test(modbus): add parser tests for 4-byte and legacy-wrap decoding #1
@@ -0,0 +1,89 @@
|
||||
package home.automation.modbus;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class ModbusParserTests {
|
||||
|
||||
private ModbusRtuTcpRepository createRepo() {
|
||||
return new ModbusRtuTcpRepository(new Connection() {
|
||||
@Override
|
||||
public com.serotonin.modbus4j.ModbusMaster getConnection() {
|
||||
throw new UnsupportedOperationException("not used in parser tests");
|
||||
}
|
||||
}, java.util.Collections.emptyList());
|
||||
}
|
||||
|
||||
private String invokeDecode(ModbusRtuTcpRepository repo, short[] data, String dataType, Double scale, Boolean legacy) throws Exception {
|
||||
Method m = ModbusRtuTcpRepository.class.getDeclaredMethod("decodeValueFromShorts", short[].class, String.class, Double.class, Boolean.class);
|
||||
m.setAccessible(true);
|
||||
return (String) m.invoke(repo, (Object) data, dataType, scale, legacy);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeFourByteFloat() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
float value = 12.34f;
|
||||
int bits = Float.floatToIntBits(value);
|
||||
short high = (short) ((bits >>> 16) & 0xFFFF);
|
||||
short low = (short) (bits & 0xFFFF);
|
||||
String decoded = invokeDecode(repo, new short[]{high, low}, "FOUR_BYTE_FLOAT", 1.0, null);
|
||||
assertEquals("12.34", decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeFourByteFloatSwapped() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
float value = -5.5f;
|
||||
int bits = Float.floatToIntBits(value);
|
||||
short high = (short) ((bits >>> 16) & 0xFFFF);
|
||||
short low = (short) (bits & 0xFFFF);
|
||||
// swapped: pass low first, then high and use SWAPPED dataType
|
||||
String decoded = invokeDecode(repo, new short[]{low, high}, "FOUR_BYTE_FLOAT_SWAPPED", 1.0, null);
|
||||
// rounding to 2 decimals expected by implementation
|
||||
assertEquals("-5.5", decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeFourByteUnsignedInt() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
long unsignedVal = 3000000000L; // > 2^31
|
||||
int bits = (int) unsignedVal; // low 32 bits
|
||||
short high = (short) ((bits >>> 16) & 0xFFFF);
|
||||
short low = (short) (bits & 0xFFFF);
|
||||
String decoded = invokeDecode(repo, new short[]{high, low}, "FOUR_BYTE_INT_UNSIGNED", 1.0, null);
|
||||
assertEquals((double) unsignedVal, Double.parseDouble(decoded), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeFourByteSignedInt() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
int signedVal = -12345678;
|
||||
int bits = signedVal;
|
||||
short high = (short) ((bits >>> 16) & 0xFFFF);
|
||||
short low = (short) (bits & 0xFFFF);
|
||||
String decoded = invokeDecode(repo, new short[]{high, low}, "FOUR_BYTE_INT_SIGNED", 1.0, null);
|
||||
assertEquals((double) signedVal, Double.parseDouble(decoded), 0.0001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeTwoByteSignedLegacyWrap() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
short s = (short) (-32760); // near legacy wrap sentinel
|
||||
String decoded = invokeDecode(repo, new short[]{s}, "TWO_BYTE_INT_SIGNED", 1.0, true);
|
||||
// calculation: -(s + 32768) * scale -> -( -32760 + 32768) = -8
|
||||
assertEquals("-8.0", decoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
void decodeTwoByteNormal() throws Exception {
|
||||
ModbusRtuTcpRepository repo = createRepo();
|
||||
short s = (short) (123);
|
||||
String decoded = invokeDecode(repo, new short[]{s}, "TWO_BYTE_INT_SIGNED", 0.1, false);
|
||||
// 123 * 0.1 = 12.3
|
||||
assertEquals("12.3", decoded);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user