[SOLVED] Can't decode byte sent from Python socket server via WiFi

Hi. I am trying to send a single byte from a Python TCP socket server to an ESP8266 running a sketch using the Arudino IDE. I’ve seen a number of posts on serial USB communications, but I am specifically communicating via sockets over WiFi.

Python socket server:

import serial
import socket
import threading
import time
import tkinter as tk

port = 35000
total_points = [0,0,0]
habits = [20,15,10,10,10,10,5,0,-5,-5,-5,-5,0,0,0,0]

class SerialThread(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
            server_socket.bind(('0.0.0.0', port))
            server_socket.listen(1)

            print("Intialize socket server, listen port: {}".format(port))

            while True:
                print("Waiting for connection")
                conn, address = server_socket.accept()
                with conn:
                    print('Connection: ', address)
                    while True:
                        data = conn.recv(1024)
                        print("Data Received: ", data)
                        
                        if not data: break
                        if (data == b'\r\n'): break
                        
                        points = habits[int(data, base=16)]
                        total_points[0] = total_points[0] + points
                        points_bytes = points.to_bytes(1, byteorder = 'big', signed=True)
                        conn.send(points_bytes)
                        print("Data Sent: ", points_bytes)

class App(tk.Tk):
    def __init__(self):
        thread = SerialThread()
        thread.start()

app = App()
app.mainloop()

This is great. When the ESP8266 sends a byte (0x00, for example), I get:

Intialize socket server, listen port: 35000
Waiting for connection
Connection:  ('192.168.4.9', 64423)
Data Received:  b'0'
Data Sent:  b'\x14'
Data Received:  b''
Waiting for connection

On the ESP8266 side, I am using the ESP8266WiFi library to send and receive data which I believe uses the Arduino Stream class under the covers:

#include <ESP8266WiFi.h>

#define MENU_REWARDS        0
#define STASSID "[OMITTED]"
#define STAPSK  "[OMITTED]"
#define PIN_SELECT          D3

int menuItem = 0;
int whichMenu = MENU_REWARDS;

const char* ssid = STASSID;
const char* password = STAPSK;

const char* host = "192.168.4.1";
const uint16_t port = 35000;

static const byte rewardsByte[] = {
  0x00,
  0x01,
  0x02,
  0x03,
  0x04,
  0x05,
  0x06
};

static const byte penaltiesByte[] = {
  0x08,
  0x09,
  0x0A,
  0x0B
};

bool debug = true;

void setup() {
  Serial.begin(115200);
  if(debug) Serial.print("Connecting to ");
  if(debug) Serial.println(ssid);

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    if(debug) Serial.print(".");
  }

  if(debug) Serial.println("");
  if(debug) Serial.println("WiFi connected");
  if(debug) Serial.println("IP address: ");
  if(debug) Serial.println(WiFi.localIP());

  IPAddress ip = WiFi.localIP();
}

byte getMessageByte(int message) {
  return (whichMenu == 0) ? rewardsByte[message] : penaltiesByte[message];
}

char *printBytes(byte *bytes) {
  char bytesStr[10];
  sprintf(bytesStr, "%02X", bytes);
  if(debug) Serial.print("bytesStr: ");
  if(debug) Serial.println(bytesStr);  

  return bytesStr;
}

byte *communicateWifi(byte message) {
  byte response[10] = {'0x00','0x00','0x00','0x00','0x00','0x00','0x00','0x00','0x00','0x00'};
  int bytesRead = 0;
  
  if(debug) Serial.println("Connecting to " + String(host) + ":" + String(port));

  WiFiClient client;
  if (client.connect(host, port)) {
    if(debug) Serial.println("Connection failed!");

    if(debug) Serial.println("Sending data to server: " + message);
    if (client.connected()) {
      client.print(message);
    }
  
    // wait for data to be available
    unsigned long timeout = millis();
    while (client.available() == 0) {
      if (millis() - timeout > 5000) {
        if(debug) Serial.println(">>> Client Timeout !");
        client.stop();
        return response;
      }
    }
  
    if (client.available()) {
      int bytesRead = client.readBytes(response, 10);
  
      printBytes(response);
      if(debug) Serial.print("bytesRead: ");
      if(debug) Serial.println(bytesRead);
    }
    else {
      Serial.println("Client not available");
    }

    // Close the connection
    if(debug) Serial.println("Closing connection");
    client.stop();
  }
  else {
    if(debug) Serial.println("Connection failed!");
  }
  
  return response;
}

void processMenu() {
  int select = digitalRead(PIN_SELECT);

  if(select) {
    if(debug) Serial.println("SELECT");

    byte message = getMessageByte(menuItem);
    //if(debug) Serial.println("Message: " + message);
    
    byte *response = communicateWifi(message);
    char *responseStr = printBytes(response);
  }
}

void loop() {
  processMenu();
}

and here is the response I get:

Connecting to 192.168.4.1:35000
Sending data to server: 
bytesStr: 3FFFFF10
bytesRead: 1
Closing connection
bytesStr: 3FFFFF10

I don’t understand why I am not reading the byte correctly on the ESP8266 side. I have tried a number of different combinations of client.readBytes, client.read, converting everything to char * and doing client.readString – I can’t seem to decode the byte on the ESP8266 side.

What am I doing wrong? I want to be getting the b’\x14’ that the server is sending (would be even happier with 20!) but instead I am getting 3FFFFF10.

Thanks in advance for any help anyone might be willing to offer!

I discovered that the byte order of the ESP8266 is little endian, so I changed the encoding to:

points_bytes = points.to_bytes(1, byteorder = 'little', signed=True)

No difference.

SOLVED!

sprintf(bytesStr, "%02X", bytes);

should be

sprintf(bytesStr, "%02X", *bytes);

Gah!!! Pointers!!!!! %$^@%$

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.