Go Down

Topic: ESP8266 float to java float via WebSocket (Read 94 times) previous topic - next topic


I have an ESP8266 with a BMP280 sensor attached.
The ESP8266 connects to a java WebSocket server running on my local network and i want to send both pressure and temperature readings from the ESP8266 to the server - where i'll insert them into a database.

I have been unable to reconstruct the ESP8266 float in java and am hoping someone can help me.
I've reduced my sketch to a minimum, the important parts are:

A custom struct and union:

Code: [Select]

struct FloatPacket{
  uint8_t id;
  float value;

union UnionFloatPacket {
  FloatPacket packet;
  uint8_t bytes[5];

Two instances of the union:

Code: [Select]


UnionFloatPacket currentPressure;
UnionFloatPacket currentTemperature;


Then sending of some test values from ESP8266 to java:

Code: [Select]

currentPressure.packet.value = 12.34F;
Serial.print("Pressure: ");
Serial.print(currentPressure.packet.value, 2);
Serial.print(" Pa");


currentTemperature.packet.value = 45.68F;
Serial.print("Temperature: ");
Serial.print(currentTemperature.packet.value, 2);
Serial.print(" C");


webSocketClient.sendBIN(currentTemperature.bytes, 5);
webSocketClient.sendBIN(currentPressure.bytes, 5);

My serial console shows the expected output:

Pressure: 12.34 Pa   Temperature: 45.68 C
Next in my java websocket server:

Code: [Select]

private String getString(Object... parts) {
StringBuilder stringBuilder = new StringBuilder();
for (Object part : parts) {
return stringBuilder.toString();

public void handleMessage(ByteBuffer byteBuffer, Session session) {
// handle binary frame

byte packetId=byteBuffer.get();

// float debug = java.nio.ByteBuffer.wrap(messageBytes, 1, 4).order(java.nio.ByteOrder.nativeOrder()).getFloat();

int floatAsInt=0;
for(int i=4; i>0; i--){
floatAsInt = (floatAsInt << 8) + (byteBuffer.get(i) & 0xff);
float floatValue=Float.intBitsToFloat(floatAsInt);

Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("bytes received: ", byteBuffer.get(0), ' ', byteBuffer.get(1), ' ', byteBuffer.get(2), ' ', byteBuffer.get(3), ' ', byteBuffer.get(4)));

Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("pressure: ", floatValue));

Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("temperature: ", floatValue));

Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("Unrecognised packet id: ", packetId));

// int pressureAsInt = (messageBytes[3] << 24) | ((messageBytes[2] & 0xff) << 16) | ((messageBytes[1] & 0xff) << 8) | (messageBytes[0] & 0xff);
// float pressure = Float.intBitsToFloat(pressureAsInt);
// int temperatureAsInt = (messageBytes[7] << 24) | ((messageBytes[6] & 0xff) << 16) | ((messageBytes[5] & 0xff) << 8) | (messageBytes[4] & 0xff);
// float temperature = Float.intBitsToFloat(temperatureAsInt);
// StringBuilder log=new StringBuilder("Pressure: ");
// log.append(pressure);
// log.append(", temperature: ");
// log.append(temperature);
// Logger.getLogger(Server.class.getName()).log(Level.INFO, log.toString());

} else {
Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("messageBytes has incorrect number of bytes: ", byteBuffer.limit()));

You can see the commented out code shows various other ways that i have tried to reconstruct my ESP8266 float in java - these methods did not work either.
The server logs currently shows:

pressure: -2.7755576E-17
bytes received: 1 0 0 0 -92
temperature: 1.37438953E11
bytes received: 2 0 0 0 82
So the ESP is sending these byte values: 0, 0, 0, -92 for float value 12.34
And byte values 0, 0, 0, 82 for float value 45.68

Where am i going wrong?


Mar 18, 2018, 11:31 am Last Edit: Mar 18, 2018, 11:38 am by wildbill
I can't read your Java code so I can only guess, but you may have endian issues q.v. Try declaring a float in Java and assign 12.34 to it and then dump the bytes that make it up out to see how they compare.

Edit: Another possibility is that you're calling getFloat on the bytes that make up a float and it's expecting a string such as "12.34" instead.


Thanks for the reply.

I have it fixed now.
The problem was using the struct within the union i think.
A google search led me to https://github.com/esp8266/Arduino/issues/1825

Where i read:

On many architectures, accessing word-sized values is only allowed when these values are aligned to word boundaries. This alignment is automatically done for structure members by the compiler.
So the bytes i was sending to the websocket server were not the bytes i wanted to send.
The compiler performed some optimisation, aligning the struct bytes on word boundaries effectively destroying my method of accessing them.

What an obscure fix for a simple problem!


I think you might as well send a float as ASCII text. Float is 4 bytes. Temp like "12.34" is 5 bytes, 6 if you need to add a "-". So it's not much more to transmit.


That is an easy fix and i had already got the values to successfully send using text.
I just wanted to learn why sending as bytes was not working - to satisfy my curiousity and for future reference.

I can now choose whether to use binary or text as i further develop my sketch.

Go Up