Language Reference ================== Recommended Optimisations -------------------------- * Variable names of 5 characters or less take significantly less resources, so keep variable names short. * Comments have no impact, other that taking filesystem space. * Avoid intermediate variables. Example: write ``print(a+b)`` rather than ``let c = a+b; print(c);`` * Generally: use small functions, with as few variables as possible. Built-In Functions ------------------ ``print(arg1, arg2, ...);`` Print arguments to stdout, separated by space. ``load('file.js', obj);`` Execute file file.js. obj paramenter is optional. obj is a global namespace object. If not specified, a current global namespace is passed to the script, which allows file.js to modify the current namespace. ``die(message);`` Exit interpreter with the given error message ``let value = JSON.parse(str);`` Parse JSON string and return parsed value. ``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()*. ``void Sys.free(void *memory_pointer)`` Free memory. ``int Sys.total_ram()`` Return total available RAM in bytes. ``int Sys.free_ram()`` Return free available RAM in bytes. ``void Sys.reboot(int ms)`` Reboot the system after `ms` milliseconds. ``double Sys.uptime()`` Return number of seconds since last reboot. ``void Sys.usleep(int microseconds)`` Sleep 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. | **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. Math ---- General mathematical functions. Required library: ``load('api_math.js');`` ``double Math.ceil(double x)`` | Rounds *x* upward, returning the smallest integral value that is not less than x. ``double Math.floor(double x)`` | Rounds *x* downward, returning the largest integral value that is not greater than x. ``double Math.round(double x)`` | Returns the integral value that is nearest to *x*, with halfway cases rounded away from zero. ``double Math.max(double x, double y)`` | Returns the larger of its arguments: either *x* or *y*. If one of the arguments is NaN, the other is returned. ``double Math.min(double x, double y)`` | Returns the smaller of its arguments: either *x* or *y*. If one of the arguments is NaN, the other is returned. ``double Math.abs(double x)`` | Returns the absolute value of *x*. ``double Math.sqrt(double x)`` | Returns the square root of *x*. ``double Math.exp(double x)`` | Returns the base-e exponential function of *x*, which is e raised to the power *x*. ``double Math.log(double x)`` | Returns the natural logarithm of *x*. ``double Math.pow(double base, double exponent)`` | Returns `base` raised to the power `exponent` ``double Math.sin(double x)`` | Returns the sine of an angle of *x* radians. ``double Math.cos(double x)`` | Returns the cosine of an angle of *x* radians. ``double 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`` ``void 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. ``void SQ.dispatch_double(int index, double value, int 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 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. ``void SQ.dispatch_string(int index, char *str, int 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. | **str**: The string to be added. | **length**: The number of characters in the string. Maximum 50. ``void SQ.dispatch_event(int index, int severity, char *str)`` | 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 | **str**: The event message. Maximum 30 characters. ``double SQ.parse(char *str, int start, int length, int base)`` | Convert a string to a double using the *base* given. | **str**: 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. | Returns the parsed number, or 0 on error. ``void 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. ``void SQ.set_output(int channel, int state, int 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. (0 = OFF, 1 = ON) | **time_s**: The time to stay in the new state. Use 0 for a permanent state change. (5 = 5 seconds) ``void SQ.serial_write(int channel, char *str, int length)`` | Write serial data out to the device's RS232/RS485 port. All settings for the serial port are inherited from the device's main configuration, and the Serial 1 `Interval` setting must be non-zero. This call can be used in both `Capture` and `Modbus` modes, however if the serial port is in use the string data will be queued until the port is available. | **channel**: Output channel index. (1 for Serial 1) | **str**: The string to write. | **length**: The number of characters in the string. ``void 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: .. code-block:: js 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); } }