Language Reference

Built-In Functions

let value = JSON.parse(str);

Parse JSON string and return parsed value. Can also be used to convert a string to a number.

// Convert string to a number
let n = JSON.parse("-37.165345");

// Convert JSON string to an object
let obj = JSON.parse("{key1: \"value1\"}");
let value = obj.key1;
let str = JSON.stringify(value);

Get string representation of the mJS value.

let proto = {foo: 1}; let o = Object.create(proto);

Create an object with the provided prototype.

'some_string'.slice(start, end);

Return a substring between two indices. Example: ‘abcdef’.slice(1,3) === ‘bc’;

'abc'.at(0);

Return numeric byte value at given string index. Example: ‘abc’.at(0) === 0x61;

'abc'.indexOf(substr[, fromIndex]);

Return index of first occurence of substr within the string or -1 if not found. ‘abc’.indexOf(‘bc’) === 1;

chr(n);

Return 1-byte string whose ASCII code is the integer n. If n is not numeric or outside of 0-255 range, null is returned. Example: chr(0x61) === ‘a’;

let a = [1,2,3,4,5]; a.splice(start, deleteCount, ...);

Change the contents of an array by removing existing elements and/or adding new elements. Example: let a = [1,2,3,4,5]; a.splice(1, 2, 100, 101, 102); a === [1,100,101,102,4,5];

let s = mkstr(ptrVar, length);

Create a string backed by a C memory chunk. A string s starts at memory location ptrVar, and is length bytes long.

let s = mkstr(ptrVar, offset, length, copy = false);

Like mkstr(ptrVar, length), but string s starts at memory location ptrVar + offset, and the caller can specify whether the string needs to be copied to the internal mjs buffer. By default it’s not copied.

System

Required library: load('api_sys.js');

void * Sys.malloc(int size)

Allocate a memory region. Memory allocated this way must be explicitly released with free().

Sys.free(void *memory_pointer)

Free memory previously allocated with malloc.

Sys.total_ram()

Return total available RAM in bytes.

Sys.free_ram()

Return free available RAM in bytes.

Sys.reboot(ms)

Reboot the system after ms milliseconds.

Sys.uptime()

Return number of seconds since last reboot.

Sys.usleep(microseconds)

Delay execution the given number of microseconds.

Config

Set and get values from the device’s config.

Required library: load('api_config.js');

Cfg.get(path)
Get a value from the device’s configuration.
path: the JSON path (using dot notation) of the setting to get.
Examples:
Cfg.get('device.id');          // returns a string
Cfg.get('accel.interval');     // returns an integer
Cfg.get('ambient.available');  // returns a boolean
Cfg.set(obj)
Set part of the device’s configuration. The new value is written to the internal FLASH configuration file which persists between power cycles.
obj: the JSON object to set.
Examples:
Cfg.set({input2: {digital: {alert: {enable: false}}}});

Warning

Incorrect use of the Cfg.set() function may lead to corruption of critical parameters, and result in bricking of the device. Use with caution.

Warning

Excessive use of Cfg.Set() will wear internal FLASH memory. The FLASH memory can typically endure 100 000 write cycles.

Timers

Timers and time related functions.

Required library: load('api_timer.js');

Timer.set(milliseconds, flags, handler, userdata)
Setup timer with milliseconds timeout and handler as a callback. flags can be either 0 or Timer.REPEAT. In the latter case, the call will be repeated indefinitely (but can be cancelled with Timer.del()), otherwise it’s a one-off. Returns a numeric timer ID.

Example:

Timer.set(1000, Timer.REPEAT, function() {
  // This will repeat every second
  let s = "HELLO";
  SERIAL.write(1, s, s.length);
}, null);

Warning

Be conscious of accidentally setting repeating timers from a function that itself is repeating (for instance from SQ.set_data_handler), as you will quickly run out of memory.

Timer.del(id)
Cancel a previously installed timer with given id.
let id = Timer.set( ... );  // Set timer, store the id
...
Timer.del(id);    // Cancel the previously set timer
id = 0;           // Explicitly clear the stored id (Important!)
Timer.now()
Return current time as double value, UNIX epoch (seconds since 1970).
Timer.fmt(fmt, time)
Formats the time time according to the strftime-like format specification fmt. The strftime reference can be found here.

Example:

let now = Timer.now();
let s = Timer.fmt("ISO8601 Time is: %FT%TZ", now);
dispatch(1, s); // Example output: "ISO8601 Time is: 2021-04-13T10:17:32Z"

Math

General mathematical functions.

Required library: load('api_math.js');

Math.ceil(x)
Rounds x upward, returning the smallest integral value that is not less than x.
Math.floor(x)
Rounds x downward, returning the largest integral value that is not greater than x.
Math.round(x)
Returns the integral value that is nearest to x, with halfway cases rounded away from zero.
Math.max(x, y)
Returns the larger of its arguments: either x or y. If one of the arguments is NaN, the other is returned.
Math.min(x, y)
Returns the smaller of its arguments: either x or y. If one of the arguments is NaN, the other is returned.
Math.abs(x)
Returns the absolute value of x.
Math.sqrt(x)
Returns the square root of x.
Math.exp(x)
Returns the base-e exponential function of x, which is e raised to the power x.
Math.log(x)
Returns the natural logarithm of x.
Math.pow(base, exponent)
Returns base raised to the power exponent
Math.sin(x)
Returns the sine of an angle of x radians.
Math.asin(x)
Returns the inverse sine of an angle of x radians.
Math.cos(x)
Returns the cosine of an angle of x radians.
Math.acos(x)
Returns the inverse cosine of an angle of x radians.
Math.random()
Returns a pseudo-random number from 0.0 to 1.0

Senquip

Functions for interacting with data collection and the device’s peripherals.

Required library: load('senquip.js');

Constants:
  • SQ.INFO: 10

  • SQ.ALERT: 20

  • SQ.WARNING: 30

  • SQ.ALARM: 40

  • SQ.ON: 1

  • SQ.OFF: 0

Encoding Type Constants:
  • SQ.U8 - Unsigned 8 bits.

  • SQ.S8 - Signed 8 bits.

  • SQ.U16 - Unsigned 16 bits.

  • SQ.S16 - Signed 16 bits.

  • SQ.U32 - Unsigned 32 bits.

  • SQ.S32 - Signed 32 bits.

  • SQ.FLOAT - 4 byte floating point.

  • SQ.DOUBLE - 8 byte floating point.

SQ.set_data_handler(function, userdata)
Registers a callback function that allows creation of new data parameters collected by the device.
function: A callback function, invoked when a measurement cycle is completed. The completed JSON data structure is passed to the callback function.
userdata: Some user data that is passed to the callback function. Set null if unused.

Note

All SQ.dispatch functions below can only be called from inside the SQ.set_data_handler callback function. Calling them outside the data handler, such as from timers or the trigger handler will not work.

SQ.dispatch_double(index, value, precision)
Add new value to the device’s data message. If called multiple times for the same index value, only the first call will be written to the outgoing data message.
index: The index of the data parameter, starting from 1.
value: The numerical value of the data to be added.
precision: The number of decimal places to send in the data message. The value must be between 0 and 8 (inclusive). 0 means no decimal places.
SQ.dispatch_string(index, string, length)
Add a new string to the device’s data message. If called multiple times for the same index value, only the first call will be written to the outgoing data message.
index: The index of the data parameter, starting from 1.
string: The string to be added.
length: The number of characters in the string. Maximum 50.
SQ.dispatch_event(index, severity, message)
Add an event (alert, warning, alarm) to the device’s data message.
index: The index on the data parameter, starting from 1.
severity: The severity of the event. Should be one of SQ.INFO, SQ.ALERT, SQ.WARNING or SQ.ALARM
message: The event message string. Maximum 30 characters.
SQ.dispatch(index, value, len)
Helper function to dispatch either a number or string. If the len parameter is omitted, a default is used. The function consists of the following mJS code:
function dispatch(index, value, len) {
  if (typeof value === 'string') {
    if (typeof len === 'undefined') { len = value.length; }
    this.dispatch_string(index, value, len);
  }
  else if (typeof value === 'number') {
    if (typeof len === 'undefined') { len = 1; }
    this.dispatch_double(index, value, len);
  }
}
SQ.set_trigger_handler(function, userdata)
Registers a callback function that is called when a trigger button is activated from the Senquip Portal.
function: A callback function, invoked when a trigger button event occurs. The trigger parameter index number is passed into the callback function. For example: 5 is passed in for tp5.
userdata: Some user data that is passed to the callback function. Set null if unused.
SQ.set_output(channel, state, time_s)
Set the device’s output channel to the given state, for the given time.
channel: Output channel index. (1 for Output 1)
state: The new state of the output, the value passed should be either SQ.ON or SQ.OFF
time_s: The time to stay in the new state. Use 0 for a permanent state change. (5 = 5 seconds)
SQ.set_current(channel, state)
Set the device’s current source channel to the given state. When ON, the SRC1 or SRC2 terminal will be internally connected to 12V. The channel remains in the given state until the device goes to sleep. If the Current Loop interval is enabled, the next measurement cycle will also modify the state.
channel: Current source channel index. (1 for SRC1, 2 for SRC2)
state: The new state. The value passed should be either SQ.ON or SQ.OFF
SQ.read_analog(channel)
Read the analog input value in volts for the given channel.
channel: Analog channel index:
0: Supply Voltage
1: Input 1
2: Input 2
Returns a voltage, or NaN on error.
SQ.parse(string, start, length, base, type)
Convert a string to a number using the base given.
string: The string to parse.
start: The starting character index. (0 = the first character in the string).
length: The number of characters in the string to parse from the start position.
base: The numerical base used when parsing the string. (10 = Decimal, 16 = Hexadecimal). A special case applies when when base is (-16): the byte order will be reversed.
type: (Optional) The number type used to interpret the parsed data. This parameter should be one of the encoding type constants. Default: SQ.S64
Returns the parsed number, or 0 on error.
SQ.encode(number, type)
Convert a number into a binary string representation of the given type.
number: The number to encode.
type: The number format to use when encoding into Big Endian binary. This parameter should be one of the encoding type constants. A negative sign in front of the type will reverse the byte order and encode into Little Endian binary.
Returns a string containing the binary representation of the given number.
Example: SQ.encode(1075, -SQ.U16) returns \x33\x04
SQ.atob(string)
Decodes and returns the base 64 encoded input string.
string: A base 64 encoded string. The maximum input string length is 256 characters.
Returns the decoded string.
SQ.split(string, separator)
Takes an input string and splits it into parts using the seperator character.
string: The string to split
separator: The seperator character.
Returns the split up array of strings.
Example: SQ.split('1,2,,4', ',') returns ['1', '2', undefined, '4']
SQ.crc(data, length, algorithm_id)
Calculates a CRC on the specified input data and returns the CRC as an integer. The length parameter is optional, but should be specified if data contains a null character. The algorithm_id is optional, by default the Modbus CRC16 is calculated.
data: The input string.
length: (Optional) Number of bytes of the input data to use in the calculation. Default: data.length
algorithm_id: (Optional) An integer to specify the algorithm. Default: 1 (Modbus CRC16)
Returns the CRC as an integer.
Example: SQ.crc('Hello'); returns 62327
SQ.clear_pulse_count(channel)
Reset the device’s pulse counter on the given channel to zero.
channel: Pulse channel index. (1 for Pulse 1)
SQ.hourmeter_set(channel, hours)
Set the hourmeter channel to the given number of hours.
channel: Hourmeter channel index. According to table below:
SQ.VIBRATION: Vibration Hours
SQ.SUPPLY: Supply Voltage Hours
SQ.MOVEMENT: GPS Movement Hours
SQ.DIGITAL1: Digital 1 Hours
SQ.DIGITAL2: Digital 2 Hours
SQ.DIGITAL3: Digital 3 Hours
SQ.STATE1: State 1 Hours
SQ.STATE2: State 2 Hours
SQ.STATE3: State 3 Hours
SQ.STATE4: State 4 Hours
SQ.STATE5: State 5 Hours
SQ.STATE6: State 6 Hours
hours: The new decimal value in hours. (Example: 3.75 = 3hrs 45min)
Example: reset supply hours to zero: SQ.hourmeter_set(SQ.SUPPLY, 0);
SQ.set_state(number)
Set the current state of the device. State hours are calculated based on based on how long a device stays in each state. See operation section for more info.
number: New state (0 to 6 inclusive)
SQ.distance(latitude, longitude)
Calculate the distance between the device and the given position. The device’s GPS must be enabled and it must have a valid position fix.
latitude: Latitude of given position in signed decimal format.
longitude: Longitude of given position in signed decimal format.
Returns the distance in meters or NaN on error.
Example: let meters = SQ.distance(-32.93197, 151.77883);
SQ.wifi_connected()
Returns true if the device is currently connected via WiFi.
SQ.lte_connected()
Returns true if the device is currently connected via 4G LTE.
SQ.hibernate_mode()
Returns true if the device is currently in hibernate mode.
SQ.keep_awake(seconds)
Keeps the device from sleeping for the given number of seconds. Useful for custom control logic where the device may need to occasionally stay awake outside the normal cycle.
seconds: Number of seconds to remain awake.

CAN

Functions for reading/writing CAN data. All settings for the CAN interface are inherited from the device’s main configuration, and the CAN Interval setting must be non-zero.

Required library: load('senquip.js');

Constants:
  • CAN.STD: 0

  • CAN.EXT: 1

CAN.tx(channel, id, data, length, flags)
Send a CAN message with the given id, data and data length. See Examples section for usage.
channel: CAN channel to use. (1 = CAN1)
id: CAN message identifier, 29-bits for Extended CAN.
data: A string of up to 8 bytes for the message payload.
length: Number of data bytes. The valid range is 0 to 8.
flags: Message options. Set frame type (standard 11-bit or extended 29-bit) using: CAN.STD or CAN.EXT
Returns true on success, or false on error.
Example: CAN.tx(1, 0x18FB1055, "\x54\x82\x13", 3, CAN.EXT);

BLE

Bluetooth functions. All settings for the BLE interface are inherited from the device’s main configuration.

Required library: load('senquip.js');

BLE.set_adv_data(data, length)
Set the raw advertising data with length. Only sets the intended payload, does not start advertising. Active advertisements must be stopped before the advertising data is updated. See Examples section for usage.
data: A string of up to 31 bytes for the raw BLE message payload.
length: Number of data bytes. The valid range is 1 to 32.
Example: BLE.set_adv_data("\x54\x82\x13", 3);

Note

Note this function sets the raw advertising message. If the BLE specification is not followed for bytes in the message (such as adding length and type), other devices may not correctly detect the message.

BLE.adv_enable(enable)
Stop or start BLE advertising using previously set data. Note: advertising must be stopped before the advertising data can be updated.
enable: true to start advertising broadcast, false to stop.
BLE.sq_adv(data, length)
Helper function which immediately starts advertising a ‘Manufacturer Specific’ BLE message (according to the Bluetooth Spec) using the provided data.
data: A string of up to 27 bytes for the ‘Manufacturer Specific’ message payload.
length: (Optional) Number of data bytes, defaults to data.length. The valid range is 1 to 27.
The helper function consists of the following code:
function sq_adv(data, len) {
  if (typeof len !== 'number') { len = data.length; }
  // Create a Manufacturer Specific message with Senquip's ID
  if (len>27) len = 27;
  let s = chr(len+3) + "\xff\x71\x0a" + data;
  this.adv_enable(false);
  this.set_adv_data(s, s.length);
  this.adv_enable(true);
}

Serial

Functions for reading/writing serial data over the RS232/RS485 interface. All settings for the serial port are inherited from the device’s main configuration, and the Serial 1 Interval setting must be non-zero.

Required library: load('api_serial.js');

SERIAL.write(channel, string, length)
Write serial data out to the device’s RS232/RS485 port. This call can be used in all modes (Capture, Modbus and Scripted), however if the serial port is in use the string data will be queued until the port is available.
channel: Serial channel index. (1 = Serial 1)
string: The string to write.
length: The number of characters in the string. Maximum length is 256 bytes.
SERIAL.read(channel)
Read serial data from the device’s input buffer. This function is only guaranteed to work correctly when the Serial port is configured as ‘Scripting’ mode.
channel: Serial channel index. (1 = Serial 1)
SERIAL.read_avail(channel)
Return number of bytes received and waiting in the input buffer.
channel: Serial channel index. (1 = Serial 1)
SERIAL.set_handler(channel, function, userdata)
Registers a callback function that is called when there is a new data in the input buffer or when space becomes available on the output buffer.
channel: Serial channel index. (1 = Serial 1)
function: The callback function which receives the following arguments: (channel, userdata).
userdata: Some user data that is passed to the callback function. Set null if unused.

Example:

let data = "";
SERIAL.set_handler(1, function(channel) {
  // Keep adding to data string as characters arrive
  data = data + SERIAL.read(channel);
  // Process data string here
  // ...
  // Clear data string when completed
  data = "";
}, null);

Endpoint

Functions for sending data to custom endpoints.

Required library: load('api_endpoint.js');

MQTT.pub(topic, message, length)
Publish the given message on the topic for the MQTT Endpoint connection.
topic: The MQTT topic to publish on.
message: The message string to publish.
length: (Optional) The number of bytes in the message string. Default: message.length
Example: MQTT.pub('data/topic', 'Message to publish')
HTTP.post(body, headers)
Publish the body and extra headers in a HTTP POST request to the url specified in the HTTP Endpoint settings.
body: The data string to put in the message body.
headers: (Optional) A string of extra HTTP Headers. Each header must end with \r\n.
Example: HTTP.post('Hello World!')

Warning

Custom HTTP POST requests from the script are not retried or buffered if they fail.

UDP.send(data, length)
Send the data in a UDP message to the url specified in the UDP Endpoint settings.
data: The data string to put in the message.
length: (Optional) Number of bytes of data to send. Default: data.length
Example: UDP.send('Hello World!')

Files

Functions for reading/writing files on the device.

Required library: load('api_file.js');

File.write(string, filename, mode)
Write string data to a file on the device. If the file does not exist, it is created. The mode parameter specifies if existing data should be deleted or appended to.
string: The string to write.
filename: The file name to write to. Allowed special characters: ._-()
mode: (Optional) File mode. ‘w’: previous content is deleted. ‘a’: append to existing content. Default: ‘w’.
Returns: number of bytes written, or zero on error.
Example: let bytes = File.write('Hello World!', 'test.csv', 'a')

Warning

Excessive use of File.write() will wear internal FLASH memory. The FLASH memory can typically endure 100 000 write cycles.

File.read(filename)
Read from a file on the device and return the whole file as a string. If the file does not exist an empty string is returned.
filename: The file name to read from.
Returns: contents of the file as a string.
Example: let file_data = File.read('test.csv')

Warning

Reading large files may fail if the device is low on RAM, as the entire file is placed into device memory as a string.