ESP8266 float to java float via WebSocket

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:

struct FloatPacket{
  uint8_t id;
  float value;
};

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

Two instances of the union:

#define PACKET_ID_PRESSURE 1
#define PACKET_ID_TEMPERATURE 2

UnionFloatPacket currentPressure;
UnionFloatPacket currentTemperature;

currentPressure.packet.id=PACKET_ID_PRESSURE;
currentTemperature.packet.id=PACKET_ID_TEMPERATURE;

Then sending of some test values from ESP8266 to java:

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

Serial.print('\t');

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

Serial.println();

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:

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

	@OnMessage
	public void handleMessage(ByteBuffer byteBuffer, Session session) {
		//	handle binary frame
		if(byteBuffer.limit()==5){
			
			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)));
			
			switch(packetId){
				case PACKET_ID_PRESSURE:
					Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("pressure: ", floatValue));
					break;
				
				case PACKET_ID_TEMPERATURE:
					Logger.getLogger(Server.class.getName()).log(Level.INFO, getString("temperature: ", floatValue));
					break;
					
				default:
					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?
Thanks.

SensorTest.ino (2.64 KB)

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.