Hallo! bin grade an einem Projekt dran wo ich an einen Dimmer auf ESP8266 Basis (Arduino Framework) über eine PHP Website mit TCP Sockets ein Bytearray senden will. Mit VB.NET klappt das schon sehr gut, allerdings ist mein PHP Wissen extrem eingerostet (zuletzt mit PHP4 gearbeitet). Im Wesentlichen hab ich ein Commandbyte, z.B. 0x20 und dann z.B. 12 Bit PWM Werte die unter VB.NET als unsigned 16 Bit Integer abgebildet, per Bitshifting in zwei einzelne Bytes zerlegt und dann ins Bytearray gepackt und versendet werden. Genau hier scheitert es bei PHP bei mir. Habe schon die pack() Funktion gefunden und konnte auch schon einzelne Bytes versenden (sind auch richtig angekommen). Sobald es jedoch darum ging, unsigned 16 Bit Integer und unsigned 8 Bit Integer auf einmal zu versenden, also mit einem pack() in eine Variable zu speichern um diese dann zu verschicken, kam nur Müll an. Habe es mit Little und Big Endian probiert. Bin einfach überfordert und konnte trotz stundenlanger Recherche und Kopfzerbrechen nicht zu einer Lösung finden. Für manche Dinge bin ich wohl einfach zu blöd bzw. verstehe sie erst, wenn ich die Lösung vor den Augen habe (sprich: wenn es mir jemand vorgekaut hat). Bitte um Nachsicht diesbezüglich, habe mir echt schon die Doku u.a. von pack, unpack, ... reingezogen und etliche Threads auf stackoverflow umgegraben, verstehe es trotzdem nicht. Danke für eure Hinweise!
Lucas N. schrieb: > Im Wesentlichen hab ich ein Commandbyte, z.B. 0x20 und dann z.B. 12 Bit > PWM Werte die unter VB.NET als unsigned 16 Bit Integer abgebildet, per > Bitshifting in zwei einzelne Bytes zerlegt und dann ins Bytearray > gepackt und versendet werden. Das kannst Du genauso auch in PHP machen. Am besten zeigst Du mal den funktionierenden VB-Code.
Danke dass du dir Zeit nimmst!
1 | Private Sub SendColors() |
2 | Dim ByteArray(17) As Byte |
3 | ByteArray(0) = &H20 |
4 | ByteArray(1) = CByte(BitConverter.GetBytes(ch1.Value)(0)) |
5 | ByteArray(2) = CByte(BitConverter.GetBytes(ch1.Value)(1)) |
6 | ByteArray(3) = CByte(BitConverter.GetBytes(ch2.Value)(0)) |
7 | ByteArray(4) = CByte(BitConverter.GetBytes(ch2.Value)(1)) |
8 | ByteArray(5) = CByte(BitConverter.GetBytes(ch3.Value)(0)) |
9 | ByteArray(6) = CByte(BitConverter.GetBytes(ch3.Value)(1)) |
10 | ByteArray(7) = CByte(BitConverter.GetBytes(ch4.Value)(0)) |
11 | ByteArray(8) = CByte(BitConverter.GetBytes(ch4.Value)(1)) |
12 | ByteArray(9) = CByte(BitConverter.GetBytes(ch5.Value)(0)) |
13 | ByteArray(10) = CByte(BitConverter.GetBytes(ch5.Value)(1)) |
14 | ByteArray(11) = CByte(BitConverter.GetBytes(ch6.Value)(0)) |
15 | ByteArray(12) = CByte(BitConverter.GetBytes(ch6.Value)(1)) |
16 | ByteArray(13) = CByte(BitConverter.GetBytes(ch7.Value)(0)) |
17 | ByteArray(14) = CByte(BitConverter.GetBytes(ch7.Value)(1)) |
18 | ByteArray(15) = CByte(BitConverter.GetBytes(ch8.Value)(0)) |
19 | ByteArray(16) = CByte(BitConverter.GetBytes(ch8.Value)(1)) |
20 | ExecQuery(ByteArray) |
21 | End Sub |
22 | |
23 | Private Sub ExecQuery(data As Byte()) |
24 | Dim tcpClient As New System.Net.Sockets.TcpClient() |
25 | tcpClient.Connect(txtIP.Text, 5160) |
26 | |
27 | Dim networkStream As NetworkStream = tcpClient.GetStream() |
28 | |
29 | If networkStream.CanWrite And networkStream.CanRead Then |
30 | ' Do a simple write. |
31 | Dim numberOfBytesRead As Integer = 0 |
32 | |
33 | Dim ResponseBytes(18) As Byte |
34 | |
35 | Dim ReceiveBuffer(0) As Byte |
36 | |
37 | networkStream.Write(data, 0, data.Length) |
38 | |
39 | Dim TimeOut As DateTime |
40 | TimeOut = DateTime.Now |
41 | |
42 | While (networkStream.DataAvailable Or DateTime.Now.Subtract(TimeOut).Seconds <= 2) |
43 | networkStream.Read(ReceiveBuffer, 0, 1) |
44 | ResponseBytes(numberOfBytesRead) = ReceiveBuffer(0) |
45 | numberOfBytesRead += 1 |
46 | TimeOut = DateTime.Now |
47 | If numberOfBytesRead > 0 Then |
48 | If ResponseBytes(0) = &HF0 Or ResponseBytes(0) = &H95 And numberOfBytesRead = 9 Then |
49 | Exit While |
50 | End If |
51 | End If |
52 | End While |
53 | ' Do stuff |
54 | |
55 | Else |
56 | If Not networkStream.CanRead Then |
57 | Console.WriteLine("cannot not write data to this stream") |
58 | tcpClient.Close() |
59 | Else |
60 | If Not networkStream.CanWrite Then |
61 | Console.WriteLine("cannot read data from this stream") |
62 | tcpClient.Close() |
63 | End If |
64 | End If |
65 | End If |
66 | tcpClient.Close() |
67 | |
68 | End Sub |
Edit: der Microcontrollerteil am ESP8266 schaut in C so aus:
1 | if (client.available() > 16) |
2 | {
|
3 | client.readBytes(tcpServerInputBuffer, 17); |
4 | client.flush(); |
5 | |
6 | ....
|
7 | |
8 | if (tcpServerInputBuffer[0] == TCP_CHANNELS_SET) |
9 | {
|
10 | poweredOn = true; |
11 | pwm_channels[0] = tcpServerInputBuffer[1] | uint16_t(tcpServerInputBuffer[2]) << 8; |
12 | pwm_channels[1] = tcpServerInputBuffer[3] | uint16_t(tcpServerInputBuffer[4]) << 8; |
13 | pwm_channels[2] = tcpServerInputBuffer[5] | uint16_t(tcpServerInputBuffer[6]) << 8; |
14 | pwm_channels[3] = tcpServerInputBuffer[7] | uint16_t(tcpServerInputBuffer[8]) << 8; |
15 | |
16 | pwm_channels[4] = tcpServerInputBuffer[9] | uint16_t(tcpServerInputBuffer[10]) << 8; |
17 | pwm_channels[5] = tcpServerInputBuffer[11] | uint16_t(tcpServerInputBuffer[12]) << 8; |
18 | pwm_channels[6] = tcpServerInputBuffer[13] | uint16_t(tcpServerInputBuffer[14]) << 8; |
19 | pwm_channels[7] = tcpServerInputBuffer[15] | uint16_t(tcpServerInputBuffer[16]) << 8; |
20 | client.write(0xF0); |
21 | }
|
22 | |
23 | ...
|
24 | }
|
:
Bearbeitet durch User
Das Schreiben müsste folgendermaßen funktionieren:
1 | $host = "127.0.0.1"; |
2 | $port = 5160; |
3 | |
4 | $packet = pack("CSSSSSSSS", 0x20, $ch1, $ch2, $ch3, $ch4, $ch5, $ch6, $ch7, $ch8); |
5 | |
6 | $socket = socket_create(AF_INET, SOCK_STREAM, 0); |
7 | socket_connect($socket, $host, $port); |
8 | socket_write($socket, $packet, 17); |
Danach muss man dann die Antwort lesen. In dem ESP-Beispiel-Code wird nur ein Byte (nämlich 0xF0) zurückgegeben, im VB-Code sehe ich irgendwelche möglichen Werte mit mit Datenlänge 9. Du kannst ja mal selbst schauen, lesen der Antwort geht mit:
1 | $maxlen = 9; // oder ein anderer Wert |
2 | $result = socket_read ($socket, $maxlen); |
Notfalls machst Du auch eine Schleife über Read jedes einzelnen Zeichens:
1 | $result = socket_read ($socket, 1); |
Googlen nach "socket_read php" hilft weiter.
:
Wiederhergestellt durch Moderator
Frank M. schrieb: > $packet = pack("CSSSSSSSS", 0x20, $ch1, $ch2, $ch3, $ch4, $ch5, $ch6, > $ch7, $ch8); "CSSSS..." war die ausschlaggebende Information, vielen Dank! Könnte mir auf den Kopf greifen, das ist ja eh ähnlich wie printf in C. > Danach muss man dann die Antwort lesen. In dem ESP-Beispiel-Code wird > nur ein Byte (nämlich 0xF0) zurückgegeben, im VB-Code sehe ich > irgendwelche möglichen Werte mit mit Datenlänge 9. Die Länge der Antwort hängt vom Kommando ab. Manche Kommandos bekommen nur 0xF0 zurück (einfaches ACK), manche bekommen eine komplette Antwort inkl. Daten retour. > Du kannst ja mal selbst schauen, lesen der Antwort geht mit:$maxlen = 9; > // oder ein anderer Wert > $result = socket_read ($socket, $maxlen); > Notfalls machst Du auch eine Schleife über Read jedes einzelnen > Zeichens:$result = socket_read ($socket, 1); > > Googlen nach "socket_read php" hilft weiter. Danke, hast mir jedenfalls schon sehr weitergeholfen. Da hätte ich wieder mal echt selbst draufkommen können. Mein Code hat, bis auf das von dir gelieferte "CSSSSSSSS" so ausgesehen, habe das mit fsockopen statt mit socket_create und socket_connect gemacht. Wo liegt denn da der Unterschied? Habe irgendwo gelesen, dass fsockopen viel langsamer sein soll, kann ich aber irgendwie nicht ganz glauben...
1 | <?php
|
2 | $output = pack("CSSSSSSSS", 0x20, $r, $g, $b, 0, $r, $g, $b, 0); |
3 | $socket = fsockopen("192.168.25.158", 5160); |
4 | fwrite($socket, $output, 17); |
5 | fclose($fp); |
6 | ?>
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.