TapHome

Binary data

TapHome script functions PACKVALUE and UNPACKVALUE — read and write typed values in register and byte collections, with big-endian, little-endian and byte-swap order.

UNPACKVALUE and PACKVALUE convert between typed values — integers, floats, text — and the raw registers or bytes of a collection. They do not touch the bus, so they work in every script: on Modbus register blocks, on TCP and UDP payloads in a Packet parser listener script, or in a smart rule. The data type is one of the Modbus data types. Both functions need Core 2026.1, build 39001 or newer, and an app of build 39016 or newer.

UNPACKVALUE

UNPACKVALUE reads one typed value from a register collection (collection<uint16>) or a byte collection (collection<uint8>) at the given offset.

1
2
UNPACKVALUE(collection, offset, dataType)
UNPACKVALUE(collection, offset, String, length)
NameTypeDescription
collectioncollection<uint16> or collection<uint8>Source data. A blob is not accepted.
offsetnumberPosition of the value, from 0 — in registers for collection<uint16>, in bytes for collection<uint8>.
dataTypeModbus data typeFor example Uint16, BigEndianFloat, LittleEndianUint32.
lengthnumberRequired for String: number of registers (2 characters each) or bytes (1 character each). The text ends at the first zero byte.

Returns — a number; bool for Bool; int64 or uint64 for the 64-bit integer types; a string for String.

Remarks — RECEIVEDMSG.PAYLOAD is a blob and is not accepted. In a TCP or UDP listener script use RECEIVEDBYTES, which is a byte collection, or convert text with TOBYTES.

Example — values from one Modbus block read

collection<uint16> data := MODBUSRBLOCK(H, 100, 4);
VAR power := UNPACKVALUE(data, 0, BigEndianFloat);
VAR state := UNPACKVALUE(data, 2, Uint16);
VAR name := UNPACKVALUE(data, 0, String, 2);

Example — a number from received bytes

collection<uint8> frame := BYTECOLLECTION("01 02 00 FA");
UNPACKVALUE(frame, 2, Uint16);
# Result: 250
collection<uint8> frame := BYTECOLLECTION("FA 00 00 00");
UNPACKVALUE(frame, 0, LittleEndianUint32);
# Result: 250

Errors — UNPACKVALUE: offset N + M element(s) exceeds collection length L; UNPACKVALUE: parameter 1 must be a Collection<UInt16> or Collection<UInt8>; UNPACKVALUE: String data type must have specified length - number of registers to read.

PACKVALUE

PACKVALUE writes one typed value into a register or byte collection at the given offset and returns the same, changed collection.

1
PACKVALUE(collection, offset, dataType, value)

Remarks

  • The collection is changed in place; the return value is the same collection.
  • String is not supported.
  • Integer types round the value to a whole number. A value outside the range of the type, or NaN written to an integer type, stops the script.

Example — build a register block and write it in one transaction

collection<uint16> block := UINT16COLLECTION(4);
PACKVALUE(block, 0, BigEndianFloat, 21.5);
PACKVALUE(block, 2, Uint16, 100);
MODBUSWBLOCK(H, 200, block);

Example — bytes for a TCP or UDP command

collection<uint8> frame := BYTECOLLECTION(4);
PACKVALUE(frame, 0, Uint16, 0x0102);
PACKVALUE(frame, 2, LittleEndianUint16, 0x0304);
SENDDATA(frame);
# frame is now 01 02 04 03

Errors — PACKVALUE: String data type is not supported; PACKVALUE: Can’t write double.NaN to modbus register; Overflow when writing X as UInt16.

Byte order in collections

The same data type names describe the order of registers in a collection<uint16> and the order of bytes in a collection<uint8>.

Flagcollection<uint16> (registers)collection<uint8> (bytes)
BigEndian (default)Most significant register first.Most significant byte first.
LittleEndianRegister order reversed (word swap); for a 16-bit type the two bytes of the register are swapped.True little-endian: least significant byte first.
ByteSwapThe two bytes inside every register are swapped.The two bytes of every pair are swapped.
Data typeRegistersBytes
Bool11
Int16, Uint1612
Int32, UInt32, Float24
Int64, UInt64, Double48

Remarks — In a byte collection LittleEndian already reverses all bytes, so adding ByteSwap to it changes nothing.

See also — Modbus data types, MODBUSRBLOCK, RECEIVEDBYTES.