bt-seneca-msc
Version:
A pure Javascript API for the Seneca Multi Smart Calibrator (MSC) device, using web bluetooth.
688 lines (646 loc) • 21.8 kB
JavaScript
"use strict";
/******************************* MODBUS RTU FUNCTIONS FOR SENECA **********************/
var modbus = require("./modbusRtu");
var constants = require("./constants");
var utils = require("./utils");
const { Command } = require("./meterApi");
const { btState } = require("./classes/APIState");
var CommandType = constants.CommandType;
const SENECA_MB_SLAVE_ID = modbus.SENECA_MB_SLAVE_ID; // Modbus RTU slave ID
/*
* Modbus registers map. Each register is 2 bytes wide.
*/
const MSCRegisters = {
SerialNumber: 10,
CurrentMode: 100,
MeasureFlags: 102,
CMD: 107,
AUX1: 108,
LoadCellMeasure: 114,
TempMeasure: 120,
RtdTemperatureMeasure: 128,
RtdResistanceMeasure: 130,
FrequencyMeasure: 164,
MinMeasure: 132,
MaxMeasure: 134,
InstantMeasure: 136,
PowerOffDelay: 142,
PowerOffRemaining: 146,
PulseOFFMeasure: 150,
PulseONMeasure: 152,
Sensibility_uS_OFF: 166,
Sensibility_uS_ON: 168,
BatteryMeasure: 174,
ColdJunction: 190,
ThresholdU_Freq: 192,
GenerationFlags: 202,
GEN_CMD: 207,
GEN_AUX1: 208,
CurrentSetpoint: 210,
VoltageSetpoint: 212,
LoadCellSetpoint: 216,
ThermoTemperatureSetpoint: 220,
RTDTemperatureSetpoint: 228,
PulsesCount: 252,
FrequencyTICK1: 254,
FrequencyTICK2: 256,
GenUhighPerc: 262,
GenUlowPerc: 264
};
/**
* Generate the modbus RTU packet to read the serial number
* */
function makeSerialNumber() {
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.SerialNumber);
}
/**
* Generate the modbus RTU packet to read the current mode
* */
function makeCurrentMode() {
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 1, MSCRegisters.CurrentMode);
}
/**
* Generate the modbus RTU packet to read the current battery level
* */
function makeBatteryLevel() {
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.BatteryMeasure);
}
/**
* Parses the register with battery level
* @param {ArrayBuffer} buffer FC3 answer
* @returns {number} battery level in V
*/
function parseBattery(buffer) {
var registers = modbus.parseFC3(buffer);
return modbus.getFloat32LEBS(registers, 0);
}
/**
* Parse the Seneca MSC serial as per the UI interface
* @param {ArrayBuffer} buffer modbus answer packet (FC3)
*/
function parseSerialNumber(buffer) {
var registers = modbus.parseFC3(buffer);
if (registers.length < 4) {
throw new Error("Invalid serial number response");
}
const val1 = registers.getUint16(0, false);
const val2 = registers.getUint16(2, false);
const serial = ((val2 << 16) + val1).toString();
if (serial.length > 5) {
return serial.substr(0, 5) + "_" + serial.substr(5, serial.length - 5);
}
return serial;
}
/**
* Parses the state of the meter. May throw.
* @param {ArrayBuffer} buffer modbus answer packet (FC3)
* @param {CommandType} currentMode if the registers contains an IGNORE value, returns the current mode
* @returns {CommandType} meter mode
*/
function parseCurrentMode(buffer, currentMode) {
var registers = modbus.parseFC3(buffer);
if (registers.length < 2) {
throw new Error("Invalid mode response");
}
const val1 = registers.getUint16(0, false);
if (val1 == CommandType.RESERVED || val1 == CommandType.GEN_RESERVED || val1 == CommandType.RESERVED_2) { // Must be ignored, internal states of the meter
return currentMode;
}
const value = utils.Parse(CommandType, val1);
if (value == null)
throw new Error("Unknown meter mode : " + value);
if (val1 == constants.ContinuityImpl && btState.continuity)
{
return CommandType.Continuity;
}
return val1;
}
/**
* Sets the current mode.
* @param {number} mode
* @returns {ArrayBuffer|null}
*/
function makeModeRequest(mode) {
const value = utils.Parse(CommandType, mode);
const CHANGE_STATUS = 1;
// Filter invalid commands
if (value == null || value == CommandType.NONE_UNKNOWN) {
return null;
}
btState.continuity = false;
if (mode > CommandType.NONE_UNKNOWN && mode <= CommandType.OFF) { // Measurements
if (mode == CommandType.Continuity)
{
mode = constants.ContinuityImpl;
btState.continuity = true;
}
return modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.CMD, [CHANGE_STATUS, mode]);
}
else if (mode > CommandType.OFF && mode < CommandType.GEN_RESERVED) { // Generations
switch (mode) {
case CommandType.GEN_THERMO_B:
case CommandType.GEN_THERMO_E:
case CommandType.GEN_THERMO_J:
case CommandType.GEN_THERMO_K:
case CommandType.GEN_THERMO_L:
case CommandType.GEN_THERMO_N:
case CommandType.GEN_THERMO_R:
case CommandType.GEN_THERMO_S:
case CommandType.GEN_THERMO_T:
// Cold junction not configured
return modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.GEN_CMD, [CHANGE_STATUS, mode]);
case CommandType.GEN_Cu50_3W:
case CommandType.GEN_Cu50_2W:
case CommandType.GEN_Cu100_2W:
case CommandType.GEN_Ni100_2W:
case CommandType.GEN_Ni120_2W:
case CommandType.GEN_PT100_2W:
case CommandType.GEN_PT500_2W:
case CommandType.GEN_PT1000_2W:
default:
// All the simple cases
return modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.GEN_CMD, [CHANGE_STATUS, mode]);
}
}
return null;
}
/**
* When the meter is measuring, make the modbus request of the value
* @param {CommandType} mode
* @returns {ArrayBuffer} modbus RTU packet
*/
function makeMeasureRequest(mode) {
switch (mode) {
case CommandType.OFF:
return null;
case CommandType.THERMO_B:
case CommandType.THERMO_E:
case CommandType.THERMO_J:
case CommandType.THERMO_K:
case CommandType.THERMO_L:
case CommandType.THERMO_N:
case CommandType.THERMO_R:
case CommandType.THERMO_S:
case CommandType.THERMO_T:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.TempMeasure);
case CommandType.Continuity:
case CommandType.Cu50_2W:
case CommandType.Cu50_3W:
case CommandType.Cu50_4W:
case CommandType.Cu100_2W:
case CommandType.Cu100_3W:
case CommandType.Cu100_4W:
case CommandType.Ni100_2W:
case CommandType.Ni100_3W:
case CommandType.Ni100_4W:
case CommandType.Ni120_2W:
case CommandType.Ni120_3W:
case CommandType.Ni120_4W:
case CommandType.PT100_2W:
case CommandType.PT100_3W:
case CommandType.PT100_4W:
case CommandType.PT500_2W:
case CommandType.PT500_3W:
case CommandType.PT500_4W:
case CommandType.PT1000_2W:
case CommandType.PT1000_3W:
case CommandType.PT1000_4W:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 4, MSCRegisters.RtdTemperatureMeasure); // Temp-Ohm
case CommandType.Frequency:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.FrequencyMeasure);
case CommandType.PulseTrain:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 4, MSCRegisters.PulseOFFMeasure); // ON-OFF
case CommandType.LoadCell:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 4, MSCRegisters.LoadCell);
case CommandType.mA_passive:
case CommandType.mA_active:
case CommandType.V:
case CommandType.mV:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 6, MSCRegisters.MinMeasure); // Min-Max-Meas
default:
throw new Error("Mode not managed :" + btState.meter.mode);
}
}
/**
* Parse the measure read from the meter
* @param {ArrayBuffer} buffer modbus rtu answer (FC3)
* @param {CommandType} mode current mode of the meter
* @returns {array} an array with first element "Measure name (units)":Value, second Timestamp:acquisition
*/
function parseMeasure(buffer, mode) {
var responseFC3 = modbus.parseFC3(buffer);
var meas, meas2, min, max;
// All measures are float
if (responseFC3 == null)
return {};
switch (mode) {
case CommandType.THERMO_B:
case CommandType.THERMO_E:
case CommandType.THERMO_J:
case CommandType.THERMO_K:
case CommandType.THERMO_L:
case CommandType.THERMO_N:
case CommandType.THERMO_R:
case CommandType.THERMO_S:
meas = modbus.getFloat32LEBS(responseFC3, 0);
var value = Math.round(meas * 100) / 100;
return {
"Description": "Temperature",
"Value": value,
"Unit": "°C",
"Timestamp": new Date().toISOString()
};
case CommandType.Cu50_2W:
case CommandType.Cu50_3W:
case CommandType.Cu50_4W:
case CommandType.Cu100_2W:
case CommandType.Cu100_3W:
case CommandType.Cu100_4W:
case CommandType.Ni100_2W:
case CommandType.Ni100_3W:
case CommandType.Ni100_4W:
case CommandType.Ni120_2W:
case CommandType.Ni120_3W:
case CommandType.Ni120_4W:
case CommandType.PT100_2W:
case CommandType.PT100_3W:
case CommandType.PT100_4W:
case CommandType.PT500_2W:
case CommandType.PT500_3W:
case CommandType.PT500_4W:
case CommandType.PT1000_2W:
case CommandType.PT1000_3W:
case CommandType.PT1000_4W:
meas = modbus.getFloat32LEBS(responseFC3, 0);
meas2 = modbus.getFloat32LEBS(responseFC3, 4);
return {
"Description": "Temperature",
"Value": Math.round(meas * 10) / 10,
"Unit": "°C",
"SecondaryDescription": "Resistance",
"SecondaryValue": Math.round(meas2 * 10) / 10,
"SecondaryUnit": "Ohms",
"Timestamp": new Date().toISOString()
};
case CommandType.Continuity:
meas2 = modbus.getFloat32LEBS(responseFC3, 4);
return {
"Description": "Continuity",
"Value": (meas2 < constants.ContinuityThresholdOhms) ? 1 : 0,
"Unit": "None",
"SecondaryDescription": "Resistance",
"SecondaryValue": Math.round(meas2 * 10) / 10,
"SecondaryUnit": "Ohms",
"Timestamp": new Date().toISOString()
};
case CommandType.Frequency:
meas = modbus.getFloat32LEBS(responseFC3, 0);
// Sensibilità mancanti
return {
"Description": "Frequency",
"Value": Math.round(meas * 10) / 10,
"Unit": "Hz",
"Timestamp": new Date().toISOString()
};
case CommandType.mA_active:
case CommandType.mA_passive:
min = modbus.getFloat32LEBS(responseFC3, 0);
max = modbus.getFloat32LEBS(responseFC3, 4);
meas = modbus.getFloat32LEBS(responseFC3, 8);
return {
"Description": "Current",
"Value": Math.round(meas * 100) / 100,
"Unit": "mA",
"Minimum": Math.round(min * 100) / 100,
"Maximum": Math.round(max * 100) / 100,
"Timestamp": new Date().toISOString()
};
case CommandType.V:
min = modbus.getFloat32LEBS(responseFC3, 0);
max = modbus.getFloat32LEBS(responseFC3, 4);
meas = modbus.getFloat32LEBS(responseFC3, 8);
return {
"Description": "Voltage",
"Value": Math.round(meas * 100) / 100,
"Unit": "V",
"Minimum": Math.round(min * 100) / 100,
"Maximum": Math.round(max * 100) / 100,
"Timestamp": new Date().toISOString()
};
case CommandType.mV:
min = modbus.getFloat32LEBS(responseFC3, 0);
max = modbus.getFloat32LEBS(responseFC3, 4);
meas = modbus.getFloat32LEBS(responseFC3, 8);
return {
"Description": "Voltage",
"Value": Math.round(meas * 100) / 100,
"Unit": "mV",
"Minimum": Math.round(min * 100) / 100,
"Maximum": Math.round(max * 100) / 100,
"Timestamp": new Date().toISOString()
};
case CommandType.PulseTrain:
meas = modbus.getUint32LEBS(responseFC3, 0);
meas2 = modbus.getUint32LEBS(responseFC3, 4);
// Soglia e sensibilità mancanti
return {
"Description": "Pulse ON",
"Value": meas,
"Unit": "",
"SecondaryDescription": "Pulse OFF",
"SecondaryValue": meas2,
"SecondaryUnit": "",
"Timestamp": new Date().toISOString()
};
case CommandType.LoadCell:
meas = Math.round(modbus.getFloat32LEBS(responseFC3, 0) * 1000) / 1000;
// Kg mancanti
// Sensibilità, tara, portata mancanti
return {
"Description": "Imbalance",
"Value": meas,
"Unit": "mV/V",
"Timestamp": new Date().toISOString()
};
default:
return {
"Description": "Unknown",
"Value": Math.round(meas * 1000) / 1000,
"Unit": "?",
"Timestamp": new Date().toISOString()
};
}
}
/**
* Reads the status flags from measurement mode
* @param {CommandType} mode
* @returns {ArrayBuffer} modbus RTU request to send
*/
function makeQualityBitRequest(mode) {
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 1, MSCRegisters.MeasureFlags);
}
/**
* Checks if the error bit status
* @param {ArrayBuffer} buffer
* @returns {boolean} true if there is no error
*/
function isQualityValid(buffer) {
var responseFC3 = modbus.parseFC3(buffer);
return ((responseFC3.getUint16(0, false) & (1 << 13)) == 0);
}
/**
* Reads the generation flags status from the meter
* @param {CommandType} mode
* @returns {ArrayBuffer} modbus RTU request to send
*/
function makeGenStatusRead(mode) {
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 1, MSCRegisters.GenerationFlags);
}
/**
* Checks if the error bit is NOT set in the generation flags
* @param {ArrayBuffer} responseFC3
* @returns {boolean} true if there is no error
*/
function parseGenStatus(buffer, mode) {
var responseFC3 = modbus.parseFC3(buffer);
switch (mode) {
case CommandType.GEN_mA_active:
case CommandType.GEN_mA_passive:
return ((responseFC3.getUint16(0, false) & (1 << 15)) == 0) && // Gen error
((responseFC3.getUint16(0, false) & (1 << 14)) == 0); // Self generation I check
default:
return (responseFC3.getUint16(0, false) & (1 << 15)) == 0; // Gen error
}
}
/**
* Returns a buffer with the modbus-rtu request to be sent to Seneca
* @param {CommandType} mode generation mode
* @param {number} setpoint the value to set (mV/V/A/Hz/°C) except for pulses num_pulses
* @param {number} setpoint2 frequency in Hz
*/
function makeSetpointRequest(mode, setpoint, setpoint2) {
var TEMP, registers;
var dt = new ArrayBuffer(4);
var dv = new DataView(dt);
modbus.setFloat32LEBS(dv, 0, setpoint);
const sp = [dv.getUint16(0, false), dv.getUint16(2, false)];
var dtInt = new ArrayBuffer(4);
var dvInt = new DataView(dtInt);
modbus.setUint32LEBS(dvInt, 0, setpoint);
const spInt = [dvInt.getUint16(0, false), dvInt.getUint16(2, false)];
switch (mode) {
case CommandType.GEN_V:
case CommandType.GEN_mV:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.VoltageSetpoint, sp)]; // V / mV setpoint
case CommandType.GEN_mA_active:
case CommandType.GEN_mA_passive:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.CurrentSetpoint, sp)]; // I setpoint
case CommandType.GEN_Cu50_3W:
case CommandType.GEN_Cu50_2W:
case CommandType.GEN_Cu100_2W:
case CommandType.GEN_Ni100_2W:
case CommandType.GEN_Ni120_2W:
case CommandType.GEN_PT100_2W:
case CommandType.GEN_PT500_2W:
case CommandType.GEN_PT1000_2W:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.RTDTemperatureSetpoint, sp)]; // °C setpoint
case CommandType.GEN_THERMO_B:
case CommandType.GEN_THERMO_E:
case CommandType.GEN_THERMO_J:
case CommandType.GEN_THERMO_K:
case CommandType.GEN_THERMO_L:
case CommandType.GEN_THERMO_N:
case CommandType.GEN_THERMO_R:
case CommandType.GEN_THERMO_S:
case CommandType.GEN_THERMO_T:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.ThermoTemperatureSetpoint, sp)]; // °C setpoint
case CommandType.GEN_LoadCell:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.LoadCellSetpoint, sp)]; // mV/V setpoint
case CommandType.GEN_Frequency:
dt = new ArrayBuffer(8); // 2 Uint32
dv = new DataView(dt);
// See Senecal manual manual
// Max 20kHZ gen
TEMP = Math.round(20000 / setpoint, 0);
dv.setUint32(0, Math.floor(TEMP / 2), false); // TICK1
dv.setUint32(4, TEMP - Math.floor(TEMP / 2), false); // TICK2
// Byte-swapped little endian
registers = [dv.getUint16(2, false), dv.getUint16(0, false),
dv.getUint16(6, false), dv.getUint16(4, false)];
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.FrequencyTICK1, registers)];
case CommandType.GEN_PulseTrain:
dt = new ArrayBuffer(12); // 3 Uint32
dv = new DataView(dt);
// See Senecal manual manual
// Max 20kHZ gen
TEMP = Math.round(20000 / setpoint2, 0);
dv.setUint32(0, setpoint, false); // NUM_PULSES
dv.setUint32(4, Math.floor(TEMP / 2), false); // TICK1
dv.setUint32(8, TEMP - Math.floor(TEMP / 2), false); // TICK2
registers = [dv.getUint16(2, false), dv.getUint16(0, false)];
var p1 = modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.PulsesCount, registers); // must split in two to stay <= 20 bytes for the full rtu packet
registers = [ dv.getUint16(6, false), dv.getUint16(4, false),
dv.getUint16(10, false), dv.getUint16(8, false)];
var p2 = modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.FrequencyTICK1, registers);
return [p1, p2];
case CommandType.SET_UThreshold_F:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.ThresholdU_Freq, sp)]; // U min for freq measurement
case CommandType.SET_Sensitivity_uS:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.Sensibility_uS_OFF,
[spInt[0], spInt[1], spInt[0], spInt[1]])]; // uV for pulse train measurement to ON / OFF
case CommandType.SET_ColdJunction:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.ColdJunction, sp)]; // unclear unit
case CommandType.SET_Ulow:
modbus.setFloat32LEBS(dv, 0, setpoint / constants.MAX_U_GEN); // Must convert V into a % 0..MAX_U_GEN
var sp2 = [dv.getUint16(0, false), dv.getUint16(2, false)];
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.GenUlowPerc, sp2)]; // U low for freq / pulse gen
case CommandType.SET_Uhigh:
modbus.setFloat32LEBS(dv, 0, setpoint / constants.MAX_U_GEN); // Must convert V into a % 0..MAX_U_GEN
var sp3 = [dv.getUint16(0, false), dv.getUint16(2, false)];
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.GenUhighPerc, sp3)]; // U high for freq / pulse gen
case CommandType.SET_ShutdownDelay:
return [modbus.makeFC16(SENECA_MB_SLAVE_ID, MSCRegisters.PowerOffDelay, setpoint)]; // delay in sec
case CommandType.OFF:
return []; // No setpoint
default:
throw new Error("Not handled");
}
return [];
}
/**
* Reads the setpoint
* @param {CommandType} mode
* @returns {ArrayBuffer} modbus RTU request
*/
function makeSetpointRead(mode) {
switch (mode) {
case CommandType.GEN_V:
case CommandType.GEN_mV:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.VoltageSetpoint); // mV or V setpoint
case CommandType.GEN_mA_active:
case CommandType.GEN_mA_passive:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.CurrentSetpoint); // A setpoint
case CommandType.GEN_Cu50_3W:
case CommandType.GEN_Cu50_2W:
case CommandType.GEN_Cu100_2W:
case CommandType.GEN_Ni100_2W:
case CommandType.GEN_Ni120_2W:
case CommandType.GEN_PT100_2W:
case CommandType.GEN_PT500_2W:
case CommandType.GEN_PT1000_2W:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.RTDTemperatureSetpoint); // °C setpoint
case CommandType.GEN_THERMO_B:
case CommandType.GEN_THERMO_E:
case CommandType.GEN_THERMO_J:
case CommandType.GEN_THERMO_K:
case CommandType.GEN_THERMO_L:
case CommandType.GEN_THERMO_N:
case CommandType.GEN_THERMO_R:
case CommandType.GEN_THERMO_S:
case CommandType.GEN_THERMO_T:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.ThermoTemperatureSetpoint); // °C setpoint
case CommandType.GEN_Frequency:
case CommandType.GEN_PulseTrain:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 4, MSCRegisters.FrequencyTICK1); // Frequency setpoint (TICKS)
case CommandType.GEN_LoadCell:
return modbus.makeFC3(SENECA_MB_SLAVE_ID, 2, MSCRegisters.LoadCellSetpoint); // mV/V setpoint
case CommandType.NONE_UNKNOWN:
case CommandType.OFF:
return null;
}
throw new Error("Not handled");
}
/**
* Parses the answer about SetpointRead
* @param {ArrayBuffer} registers FC3 parsed answer
* @returns {number} the last setpoint
*/
function parseSetpointRead(buffer, mode) {
// Round to two digits
var registers = modbus.parseFC3(buffer);
var rounded = Math.round(modbus.getFloat32LEBS(registers, 0) * 100) / 100;
switch (mode) {
case CommandType.GEN_mA_active:
case CommandType.GEN_mA_passive:
return {
"Description": "Current",
"Value": rounded,
"Unit": "mA",
"Timestamp": new Date().toISOString()
};
case CommandType.GEN_V:
return {
"Description": "Voltage",
"Value": rounded,
"Unit": "V",
"Timestamp": new Date().toISOString()
};
case CommandType.GEN_mV:
return {
"Description": "Voltage",
"Value": rounded,
"Unit": "mV",
"Timestamp": new Date().toISOString()
};
case CommandType.GEN_LoadCell:
return {
"Description": "Imbalance",
"Value": rounded,
"Unit": "mV/V",
"Timestamp": new Date().toISOString()
};
case CommandType.GEN_Frequency:
case CommandType.GEN_PulseTrain:
var tick1 = modbus.getUint32LEBS(registers, 0);
var tick2 = modbus.getUint32LEBS(registers, 4);
var fON = 0.0;
var fOFF = 0.0;
if (tick1 != 0)
fON = Math.round(1 / (tick1 * 2 / 20000.0) * 10.0) / 10; // Need one decimal place for HZ
if (tick2 != 0)
fOFF = Math.round(1 / (tick2 * 2 / 20000.0) * 10.0) / 10; // Need one decimal place for HZ
return {
"Description": "Frequency ON",
"Value": fON,
"Unit": "Hz",
"SecondaryDescription": "Frequency OFF",
"SecondaryValue": fOFF,
"SecondaryUnit": "Hz",
"Timestamp": new Date().toISOString()
};
case CommandType.GEN_Cu50_2W:
case CommandType.GEN_Cu100_2W:
case CommandType.GEN_Ni100_2W:
case CommandType.GEN_Ni120_2W:
case CommandType.GEN_PT100_2W:
case CommandType.GEN_PT500_2W:
case CommandType.GEN_PT1000_2W:
case CommandType.GEN_THERMO_B:
case CommandType.GEN_THERMO_E:
case CommandType.GEN_THERMO_J:
case CommandType.GEN_THERMO_K:
case CommandType.GEN_THERMO_L:
case CommandType.GEN_THERMO_N:
case CommandType.GEN_THERMO_R:
case CommandType.GEN_THERMO_S:
case CommandType.GEN_THERMO_T:
return {
"Description": "Temperature",
"Value": rounded,
"Unit": "°C",
"Timestamp": new Date().toISOString()
};
default:
return {
"Description": "Unknown",
"Value": rounded,
"Unit": "?",
"Timestamp": new Date().toISOString()
};
}
}
module.exports = {
MSCRegisters, makeSerialNumber, makeCurrentMode, makeBatteryLevel, parseBattery, parseSerialNumber,
parseCurrentMode, makeModeRequest, makeMeasureRequest, parseMeasure, makeQualityBitRequest, isQualityValid,
makeGenStatusRead, parseGenStatus, makeSetpointRequest, makeSetpointRead, parseSetpointRead
};