Guten Morgen zusammen,
ich habe vor einiger Zeit herausgefunden, dass ich meinen HiFi Receiver per TCP steuern kann.
Dass es mit einer App geht, war mir schon klar. Jedoch bin ich von etwas mehr Sicherheit im Protokoll ausgegangen
Nun habe ich eine .Net Anwendung in C#, welche alles empfängt, was der Receiver so tut. Lautstärke- oder Kanaländerungen, Anzeige auf dem Display, Album-Cover, Songtitel, usw.
Steuern ist ebenfalls möglich.
Ziel ist es, mit 2-3 Buttons feste Szenarien auszuführen: Per 433mhz den Subwoofer anschalten. Den Receiver aktivieren, einen bestimmten Eingang wählen und die Lautstärke festlegen. Je nach Uhrzeit sich vielleicht noch um die Beleuchtung kümmern.
Nun zurück zum Titel:
Die C# Anwendung verwendet Sockets
private static Socket _sock;
private static void Connect()
{
try
{
if (_sock == null)
_sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) { ReceiveTimeout = 1000 };
if (!_sock.Connected)
_sock.Connect(DeviceIp, DevicePort);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
private static void Send(string packet)
{
if (_sock != null && _sock.Connected)
{
var bytes = packet.GetBytes();
_sock.Send(bytes, 0, bytes.Length, SocketFlags.None);
var str = Encoding.UTF8.GetString(bytes);
System.Diagnostics.Debug.WriteLine("Send:\t" + Helper.Converter.ByteToString(bytes));
}
}
Ein Nachrichtenpaket besteht aus einem Header, ein paar Platzhaltern und dann einer Nachricht mit abschließendem Footer (CarriageReturn).
Meine Umsetzung für den ESP sieht wie folgt aus:
WiFiClient client;
bool ClientConnected= false;
bool ConnectToDevice(){
if (!client.connect(host, port)) {
Serial.println("connection failed");
ClientConnected = false;
}
else
ClientConnected = true;
return ClientConnected;
}
void SendDataToDevice(uint8_t *bts){
if(!ClientConnected)
if(!ConnectToDevice())
return;
for(int i = 0; i < sizeof(bts); i++){
client.write(bts[i]);
if(bts[i] == packetFooter[sizeof(packetFooter)-1]) //ToDo: Geht schöner...
break;
}
ReadResponse();
}
void ReadResponse(){
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
while(client.available()){
String line = client.readStringUntil('\r');
Serial.print(line);
}
}
void StopConnection(){
client.stop();
}
Sie empfängt auch jede Statusänderung, analog zu meiner .Net Applikation. Nur das Versenden macht nix.
- Der Receiver reagiert nicht.
- Es kommt keine Antwort (Client Timeout)
Die Nachricht ist absolut identisch. Habe ich mir mehrfach ausgegeben lassen (Hyperterminal/Debugger) und verglichen:
C#
ISCP\0\0\0\u0010\0\0\0\b\u0001\0\0\0!1MVLUP\r
Arduino
ISCP\0\0\016\0\0\0\b1\0\0\0!1MVLUP\r
\u00XX steht für unicode 10hex == 16dec (Header-Länge)
\b ist BS 08hex, 08dec (Nachrichten-Länge [inkl. CR])
Daher tippe ich darauf, dass zwischen den .Net Sockets und dem WiFiClient noch irgendein Unterschied herrscht :
Vielleicht hat jemand von Euch da eine Vermutung, bzw. eine Idee was ich noch testen könnte?!?