Examples

Data Manipulation and Events

Example 1 - Create the sum of analog1 and analog2 values and send the new value as cp1. Also monitor the sum against predefined thresholds. If a threshold is exceeded, dispatch an event. Note that it is also good practice to check the analog values exist (and are a ‘number’ type) before trying to use them, or the script will fail.:

load('senquip.js');
let ALARM_THRESHOLD = 55;
let WARN_THRESHOLD = 20;

SQ.set_data_handler(function(data) {
  let obj = JSON.parse(data);
  if ((typeof obj.analog1 === "number") && (typeof obj.analog2 === "number")) {
    let sum = obj.analog1 + obj.analog2;
    SQ.dispatch(1, sum);
    if (sum >= ALARM_THRESHOLD) {
      SQ.dispatch_event(1, SQ.ALARM, "Sum critical");
    } else if (sum >= WARN_THRESHOLD) {
      SQ.dispatch_event(1, SQ.WARNING, "Sum high");
    }
  } else {
    SQ.dispatch_event(1, SQ.INFO, "No Data");
  }
}, null);

Example 2 - Scale and offset values current1 and current2, and send them as the new values cp1 and cp5 with varying precision:

load('senquip.js');

SQ.set_data_handler(function(data) {
  let obj = JSON.parse(data);
  SQ.dispatch_double(1, 42.1*obj.current1 + 1.51, 0); // No decimal
  SQ.dispatch_double(5, -3.1416*obj.current2 + 9, 3); // 3 decimal places
}, null);

Filtering & Persistent Variables

Example 3 - Implementation an exponential moving average across consecutive measurement cycles. Highlights the use of global variables to store information between measurement cycles:

load('senquip.js');
let filtered_value = 0;

SQ.set_data_handler(function(data) {
  let obj = JSON.parse(data);
  let alpha = 0.3;
  let new_sample = obj.current1;
  filtered_value = (alpha * new_sample) + (1 - alpha)*filtered_value;
  SQ.dispatch(1, filtered_value);
}, null);

Note

The above example using global variables will only work if the device is set to ‘Always On’. Information in global variables is lost when the device sleeps or resets.

Example 4 - Persist variables when the device goes to sleep.

Coming soon!

Parsing CAN Data

Example 5 - Look for a specific PGN, parse the first 2 bytes of CAN data from Hex format, then apply a fixed scale and offset to the result:

load('senquip.js');

SQ.set_data_handler(function(data) {
  let obj = JSON.parse(data);
  for (let i = 0; i < obj.can1.length; i++) {
    // Look for the specific PGN
    if (obj.can1[i].id === 0x18FF1CF2) {
      // Extract the first 4 Hex characters (2 bytes)
      let d = SQ.parse(obj.can1[i].data, 0, 4, 16);
      SQ.dispatch_double(1, d * 0.125 + 4.5, 1);

      // Extract the next 4 Hex characters and reverse the byte order
      let e = SQ.parse(obj.can1[i].data, 4, 8, -16);
      SQ.dispatch_double(2, e * 0.5, 1);
    }
  }
}, null);

Use of Triggers

Example 6 - Set up a trigger handler to respond to button presses from the Senquip Portal.

load('senquip.js');

SQ.set_trigger_handler(function(tp) {
  if (tp === 1) SQ.set_output(1, 1, 5);  // Turn on Output 1 for 5s
  if (tp === 2) SQ.set_output(1, 0, 0);  // Turn Output 1 off forever
  if (tp === 3) {
    let s = "HELLO WORLD!";
    SQ.serial_write(1, s, s.length);  // Send string over serial port (RS232 or RS485)
  }
  if (tp === 4) SQ.serial_write(1, "\x48\x45\x58", 3);  // Send 3 bytes in HEX format
}, null);

String Enumerations

Example 7 - Send a string enumeration based on an analog voltage measurement. It also gracefully handles the case where ‘analog1’ does not exist in the data message, in which case ‘typeof obj.analog1’ would have the value ‘undefined’ (rather than ‘number’):

load('senquip.js');

SQ.set_data_handler(function(data) {
  let obj = JSON.parse(data);
  let s = "No Signal";
  if (typeof obj.analog1 === "number") {
    if (obj.analog1 >= 4.5) { s = "Error"; }
    else if (obj.analog1 >= 3.5) { s = "High"; }
    else if (obj.analog1 >= 2.5) { s = "Normal"; }
    else { s = "Low"; }
  }
  SQ.dispatch(1, s);
}, null);