The bin object converts between JavaScript numbers/arrays and the packed
binary buffers used across the protocol and crypto APIs.
Data types. Valid types for packing and unpacking:
Type
Meaning
F32
IEEE 754 single-precision float
F64
IEEE 754 double-precision float
BITS
Single-bit array
RBITS
Reverse-bit-order single-bit array
U8 / S8
Unsigned / signed 8-bit integer (0β¦255 / β128β¦127)
U16 / S16
Unsigned / signed 16-bit integer (0β¦65,535 / β32,768β¦32,767)
U32 / S32
Unsigned / signed 32-bit integer
Byte order defaults to ABCD if not specified. It can be given as a
suffix on the format ("F32BADC", "U32DCBA", "U16AB") or as a separate
argument β AB (16-bit) and ABCD, BADC, DCBA, CDAB (32-bit) cover
the big-endian, little-endian and word-swapped layouts found across Modbus
devices. Bit types (BITS/RBITS) take no byte order.
Round trips.bin.fromArray β bin.toArray convert between arrays and
packed binary; bin.toHex β bin.fromHex convert between binary and hex
text β see the Binary Packing, Bits & Hex example.
Buffer objects returned by bin.alloc(), modbus.read().data and
eip.read().data carry their own cursor-based methods:
buffer.seek(byte) β set the cursor position.
buffer.read(format, [count]) β read one value (or an array of count values) and advance.
buffer.write(format, value | array) β write a value or array and advance.
Functions
bin.alloc() β Allocates a empty buffer (string) that can be used to store and read binary values.
Allocates a empty buffer (string) that can be used to store and read binary values.
Creates an empty string bytes long. String objects in mJS are byte strings,
so they can hold arbitrary binary data β null characters do not terminate
them. After any call to bin.alloc() the binary read/write cursor is
automatically positioned at the start of the new buffer.
Arguments
Name
Type
Required
Default
Description
bytes
number
yes
β
Buffer size in bytes β 4 bytes per 32-bit register/float.
Returns
string
A buffer with seek/read/write methods, cursor positioned at byte 0.
Example
let mbData = bin.alloc(20*4); // room for 20 float registers
modbus.setData(mbData); // Assign the data buffer for to modbus read and write requests.
while(run()){
mbData.write("F32ABCD",75); // Write a float32 (4 bytes) to our modbus data table
waitMS(1000);
}
There is only one string type in mJS which is used to store either textual strings or raw byte buffers.
Payload data returned from RS485 reads, CANBus messages, Http requests, Modbus Queries etc can all be directly parsed into regular numbers easily with these methods.
seek(byte) sets the position (byte 0 = start). (Always call this before .read() or .write())
read(format) returns one value; read(format, count) returns an array of count values. The cursor advances.
write(format, value) writes one value; write(format, array) appends the whole array. The cursor advances. The "BIT" format packs elements of 1/0 (or boolean) values into bits β see eip.handle() for a worked status-word example.
seek(byte) sets the position (byte 0 = start).
read(format) returns one value; read(format, count) returns an array of
count values. The cursor advances.
write(format, value) writes one value. The cursor advances.
write(format, array) appends the whole array. The cursor advances.
The "BIT" format can be used to work with individual bits which could be provided as an array of 1/0(or boolean) or individual values β seeeip.handle()` for a worked status-word example.
Arguments
Name
Type
Required
Default
Description
format
string
yes
β
Format string, e.g. "F32BADC", "U32DCBA".
count / value
number | array
optional
β
read: how many values to return. write: the value or array to pack.
Example
while(run()){
let data = bin.alloc(8); // allocate a 8 byte buffer
print(bin.toHex(data)); // print the hex for data "0000000000000000"
// Write some data to the buffer
data.seek(1); // Set our read/write pointer to start on the second byte
data.write("U8", 255); // Write a single unsigned 8 with value 255
data.write("U8", [0,1,2,3]); // Write an array of values as unsigned 8
print(bin.toHex(data)); // print the hex for data "00ff000102030000"
// Read some data back from the buffer
data.seek(1); // Set the read/write cursor position
print( data.read("U8") ); // "255"
print( string ( data.read("U8",4) ) ); // "[0,1,2,3]"
waitMS(1000);
}
bin.fromArray(array, format, [byteOrder]) β buffer
Packs an array of numbers or bits into a binary buffer.
Packs an array into binary data. For bit types ("BITS"/"RBITS") the array
holds 1/0 (or true/false) entries β 16 bits pack into two bytes.
The inverse is bin.toArray().
Arguments
Name
Type
Required
Default
Description
array
array
yes
β
Values to pack β numbers, or 1/0 / true/false for bit types.
Unpacks binary data into an array of numbers or bits.
The inverse of bin.fromArray() β interprets packed binary data as an array
of the given type. Use it on data from bin.fromHex(), Modbus reads or MQTT
binary messages.
Arguments
Name
Type
Required
Default
Description
data
buffer | binary
yes
β
The packed binary data to unpack.
format
string
yes
β
Element type β same set as bin.fromArray(), including "BITS"/"RBITS".
byteOrder
string
optional
"ABCD"
Byte order (see the class notes). Not used by bit types.
Returns
array
The unpacked values.
Example
let bytes = bin.fromHex("01fe");
let bitArray = bin.toArray(bytes, "RBITS");
print("bits:", string(bitArray));
let floats = bin.toArray(bin.fromHex("e6b74640000042c8"), "F32", "BADC");
Encrypt payloads before sending them over untrusted networks or to insure data integrity,Keys are 256-bit values β derive one from a passphrase with bin.sha256(). Decrypted results include checksum validation.
The http and udp functions can also encrypt transparently (see setEnv("enc.key", β¦)).
Data is automatically padded and will be rounded up to the nearest block size.
Arguments
Name
Type
Required
Default
Description
data
string
yes
β
Plaintext. Serialise objects first with string(obj).
key
binary
yes
β
256-bit key, e.g. from bin.sha256(passphrase).
Returns
binary
Encrypted data (slightly larger than the plaintext).
Example
let aesKey = bin.sha256("password");
let secretMsg = string({ msg: "I LOVE FLEXSCADA", code: 12.454 });
let encrypted = bin.enc(secretMsg, aesKey);
print("Size (Raw, Encrypted)", secretMsg.length, encrypted.length);
Decrypts AES-256 data and validates its checksums.
Decrypt AES256 encrypted data received from peers. Keys are 256-bit values β derive one from a passphrase with bin.sha256(). Decrypted results include checksum validation via the valid flag.
The http and udp functions can also decrypt transparently (see setEnv("aes.key", β¦)).
serial.init(2,9600);
let modbusFrame = bin.alloc(8);
modbusFrame.write("U8",3); // Slave Address
modbusFrame.write("U8",0x06); // 0x06 Function Code (Write Single Register)
modbusFrame.write("U16BA",0); // Register
modbusFrame.write("U16BA",1234); // Value
let crc = modbus.crc16(modbusFrame,6); // Generate the CRC from the first 6 bytes of our payload
modbusFrame.write("U16BA,crc); // write the CRC to the end of our message
serial.tx(2,modbusFrame); // Send the frame over the RS485 port.