From 2d37fe93acffcf918cce96ca76ba08747d399266 Mon Sep 17 00:00:00 2001 From: j2 Date: Wed, 4 Oct 2023 17:01:37 +0200 Subject: [PATCH 01/10] In progress --- .../comtac/Cluey/counter_input_1.schema.json | 53 + .../comtac/Cluey/counter_input_2.schema.json | 53 + .../comtac/Cluey/counter_input_3.schema.json | 53 + .../comtac/Cluey/counter_input_4.schema.json | 53 + .../comtac/Cluey/counter_input_5.schema.json | 53 + .../comtac/Cluey/counter_input_6.schema.json | 53 + .../comtac/Cluey/counter_input_7.schema.json | 53 + .../comtac/Cluey/counter_input_8.schema.json | 53 + types/comtac/Cluey/digital_inputs.schema.json | 148 ++ types/comtac/Cluey/uplink.js | 1446 +++++++++++++---- 10 files changed, 1713 insertions(+), 305 deletions(-) create mode 100644 types/comtac/Cluey/counter_input_1.schema.json create mode 100644 types/comtac/Cluey/counter_input_2.schema.json create mode 100644 types/comtac/Cluey/counter_input_3.schema.json create mode 100644 types/comtac/Cluey/counter_input_4.schema.json create mode 100644 types/comtac/Cluey/counter_input_5.schema.json create mode 100644 types/comtac/Cluey/counter_input_6.schema.json create mode 100644 types/comtac/Cluey/counter_input_7.schema.json create mode 100644 types/comtac/Cluey/counter_input_8.schema.json create mode 100644 types/comtac/Cluey/digital_inputs.schema.json diff --git a/types/comtac/Cluey/counter_input_1.schema.json b/types/comtac/Cluey/counter_input_1.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_1.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_2.schema.json b/types/comtac/Cluey/counter_input_2.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_2.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_3.schema.json b/types/comtac/Cluey/counter_input_3.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_3.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_4.schema.json b/types/comtac/Cluey/counter_input_4.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_4.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_5.schema.json b/types/comtac/Cluey/counter_input_5.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_5.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_6.schema.json b/types/comtac/Cluey/counter_input_6.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_6.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_7.schema.json b/types/comtac/Cluey/counter_input_7.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_7.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/counter_input_8.schema.json b/types/comtac/Cluey/counter_input_8.schema.json new file mode 100644 index 00000000..d0f98aa6 --- /dev/null +++ b/types/comtac/Cluey/counter_input_8.schema.json @@ -0,0 +1,53 @@ +{ + "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "counter_input_", + "title": "Counter Inputs ", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [] +} diff --git a/types/comtac/Cluey/digital_inputs.schema.json b/types/comtac/Cluey/digital_inputs.schema.json new file mode 100644 index 00000000..bcdb06ee --- /dev/null +++ b/types/comtac/Cluey/digital_inputs.schema.json @@ -0,0 +1,148 @@ +{ + "$id": "https://akenza.io/comtac/cluey/digital_inputs.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "digital_inputs", + "title": "Digital Inputs", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput1": { + "title": "Digital input 1", + "description": "Digital input 1", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput2": { + "title": "Digital input 2", + "description": "Digital input 2", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput3": { + "title": "Digital input 3", + "description": "Digital input 3", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput4": { + "title": "Digital input 4", + "description": "Digital input 4", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput5": { + "title": "Digital input 5", + "description": "Digital input 5", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput6": { + "title": "Digital input 6", + "description": "Digital input 6", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput7": { + "title": "Digital input 7", + "description": "Digital input 7", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput8": { + "title": "Digital input 8", + "description": "Digital input 8", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput9": { + "title": "Digital input 9", + "description": "Digital input 9", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput10": { + "title": "Digital input 10", + "description": "Digital input 10", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput11": { + "title": "Digital input 11", + "description": "Digital input 11", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput12": { + "title": "Digital input 12", + "description": "Digital input 12", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput13": { + "title": "Digital input 13", + "description": "Digital input 13", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput14": { + "title": "Digital input 14", + "description": "Digital input 14", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput15": { + "title": "Digital input 15", + "description": "Digital input 15", + "type": "boolean", + "hideFromKpis": true + }, + "digitalInput16": { + "title": "Digital input 16", + "description": "Digital input 16", + "type": "boolean", + "hideFromKpis": true + } + }, + "required": [ + "digitalInput1", + "digitalInput2", + "digitalInput3", + "digitalInput4", + "digitalInput5", + "digitalInput6", + "digitalInput7", + "digitalInput8", + "digitalInput9", + "digitalInput10", + "digitalInput11", + "digitalInput12", + "digitalInput13", + "digitalInput14", + "digitalInput15", + "digitalInput16" + ] +} diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index c1c3fcff..ca199fe2 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -1,6 +1,13 @@ +/* + comtac AG + Cluey KM/AM/TM payload decoder (TTN/TTI v3). + www.comtac.ch + manuel.bruetsch@comtac.ch +*/ + // DEFINES -const PAYLOAD_DECODER_VERSION = "00.04-VW"; -const PAYLOAD_DECODER_INFO = "TTN/TTI"; +const PAYLOAD_DECODER_VERSION = "00.09"; +const PAYLOAD_DECODER_INFO = "comtac Cluey"; const DEVICE_DESIGNATION_CLUEY_KM = "Cluey-KM"; const DEVICE_DESIGNATION_CLUEY_AM = "Cluey-AM"; const DEVICE_DESIGNATION_CLUEY_TM = "Cluey-TM"; @@ -13,6 +20,8 @@ const CLUEY_TM_DEVICE_ID = 0x12; const PAYLOAD_VERSION = 0x00; // PL version 0 const FIXED_DATA_PORT = 3; // FIXED_DATA port +const MODBUS_PORT = 5; // MBS port +const MODBUS_TP_PORT = 6; // MBS TRANSPARENT port const DI_DATA_PORT = 20; // DI_DATA port const CNT_DATA_PORT = 21; // CNT_DATA port const TIMESYNC_PORT = 22; // TIMESYNC port @@ -38,78 +47,142 @@ const DS_DEFAULT_SUPPLY_MODE = 0x01; const DS_BUFFERED_OPERATION = 0x02; const DS_BUFFERED_OPERATION_SPAN = 0x03; const DS_PAYLOAD_FORMAT = 0x04; -const DS_STATIC_PAYLOAD_CONFIG = 0x05; // Timing Settings const TS_MEAS_INT_DC = 0x06; const TS_MEAS_INT_BAT = 0x07; const TS_TIMESYNC_INT = 0x08; const TS_REJOIN_INT = 0x09; -const TS_LEAP_SECONDS = 0x0a; +const TS_AI_MEAS_INT = 0x0a; +const TS_LEAP_SECONDS = 0x0b; // Input Settings -const IS_ENABLE = 0x0b; -const IS_ACTIVE = 0x0c; -const IS_INVERT = 0x0d; -const IS_DELAY_ENABLE = 0x0e; -const IS_DELAY_RISING = 0x0f; -const IS_DELAY_FALLING = 0x10; -const IS_DELAY_SCALING = 0x11; -const IS_WIPER_ENABLE = 0x12; -const IS_WIPER_CONFIRMATION_TIMEOUT = 0x13; -const IS_DEFLUTTER_ENABLE = 0x14; -const IS_DEFLUTTER_INTERVAL = 0x15; -const IS_DEFLUTTER_COUNT = 0x16; -const IS_DOUBLE_ENABLE = 0x17; -const IS_DOUBLE_INTERMEDIATE_STATE_TIMEOUT_ENABLE = 0x18; -const IS_DOUBLE_INTERMEDIATE_STATE_TIMEOUT = 0x19; -const IS_COUNTER_ENABLE = 0x1a; -const IS_COUNTER_HARDWARE = 0x1b; -const IS_COUNTER_MODE = 0x1c; -const IS_COUNTER_SCALING = 0x1d; -const IS_COUNTER_DIFF_ENABLE = 0x1e; -const IS_COUNTER_DIFF_INTERVAL = 0x1f; - -const AIS_ENABLE = 0x20; -const AIS_LIMIT_LOWER = 0x21; -const AIS_LIMIT_UPPER = 0x22; -const AIS_LIMIT_LOWER_HYST = 0x23; -const AIS_LIMIT_UPPER_HYST = 0x24; - -const ES_RISING_ENABLE = 0x25; -const ES_FALLING_ENABLE = 0x26; -const ES_BLOCKED_CHANGED = 0x27; -const ES_CYCLIC_DI_ENABLE = 0x28; -const ES_DI_CONFIRMED = 0x29; -const ES_CYCLIC_DI_INTERVAL = 0x2a; -const ES_CYCLIC_AI_ENABLE = 0x2b; -const ES_AI_CONFIRMED = 0x2c; -const ES_CYCLIC_AI_INTERVAL = 0x2d; -const ES_CYCLIC_CNT_ENABLE = 0x2e; -const ES_CNT_CONFIRMED = 0x2f; -const ES_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL = 0x30; -const ES_CYCLIC_CNT_TIMEDATE_WEEKDAY = 0x31; -const ES_CYCLIC_CNT_TIME_HOUR = 0x32; -const ES_CYCLIC_CNT_TIME_MINUTE = 0x33; -const ES_CYCLIC_CNT_TIME_INTERVAL = 0x34; -const ES_PRIORITY = 0x35; -const ES_DELAY = 0x36; - -const ACS_ENABLE = 0x37; -const ACS_ALARM_DELAY = 0x38; -const ACS_MOTION_DET_SEL = 0x39; -const ACS_KEY_SWITCH_SEL = 0x3a; -const ACS_DOOR_CONTACT_SEL = 0x3b; - -const OS_ENABLE = 0x3c; -const OS_INVERT = 0x3d; -const OS_MODE = 0x3e; -const OS_WIPER_TIME = 0x3f; - -const IOMS_OUT1 = 0x40; -const IOMS_OUT2 = 0x41; -const IOMS_OUT3 = 0x42; -const IOMS_OUT4 = 0x43; +const IS_ENABLE = 0x0c; +const IS_ACTIVE = 0x0d; +const IS_INVERT = 0x0e; +const IS_DELAY_ENABLE = 0x0f; +const IS_DELAY_RISING = 0x10; +const IS_DELAY_FALLING = 0x11; +const IS_DELAY_SCALING = 0x12; +const IS_WIPER_ENABLE = 0x13; +const IS_WIPER_CONFIRMATION_TIMEOUT = 0x14; +const IS_DEFLUTTER_ENABLE = 0x15; +const IS_DEFLUTTER_INTERVAL = 0x16; +const IS_DEFLUTTER_COUNT = 0x17; +const IS_DOUBLE_ENABLE = 0x18; +const IS_DOUBLE_INTERMEDIATE_STATE_TIMEOUT_ENABLE = 0x19; +const IS_DOUBLE_INTERMEDIATE_STATE_TIMEOUT = 0x1a; +const IS_COUNTER_ENABLE = 0x1b; +const IS_COUNTER_HARDWARE = 0x1c; +const IS_COUNTER_MODE = 0x1d; +const IS_COUNTER_SCALING = 0x1e; +const IS_COUNTER_DIFF_ENABLE = 0x1f; +const IS_COUNTER_DIFF_INTERVAL = 0x20; + +// Analog Input Settings +const AIS_ENABLE = 0x21; +const AIS_DELTA_ENABLE = 0x22; +const AIS_DELTA_VALUE = 0x23; +const AIS_LIMIT1_ENABLE = 0x24; +const AIS_LIMIT2_ENABLE = 0x25; +const AIS_LIMIT1_DELAY_ENABLE = 0x26; +const AIS_LIMIT2_DELAY_ENABLE = 0x27; +const AIS_LIMIT_DELAY_SCALING = 0x28; +const AIS_LIMIT1_DELAY_RISING = 0x29; +const AIS_LIMIT2_DELAY_RISING = 0x2a; +const AIS_LIMIT1_DELAY_FALLING = 0x2b; +const AIS_LIMIT2_DELAY_FALLING = 0x2c; +const AIS_LIMIT1_VALUE = 0x2d; +const AIS_LIMIT2_VALUE = 0x2e; +const AIS_LIMIT1_HYSTERESIS = 0x2f; +const AIS_LIMIT2_HYSTERESIS = 0x30; +const AIS_LIMIT1_DIRECTION = 0x31; +const AIS_LIMIT2_DIRECTION = 0x32; + +// Input Event Settings +const IES_RISING_ENABLE = 0x33; +const IES_FALLING_ENABLE = 0x34; +const IES_BLOCKED_CHANGED = 0x35; +const IES_PRIORITY = 0x36; +const IES_DELAY = 0x37; + +// Analog Event Settings +const AES_LIMIT1_RISING_ENABLE = 0x38; +const AES_LIMIT2_RISING_ENABLE = 0x39; +const AES_LIMIT1_FALLING_ENABLE = 0x3a; +const AES_LIMIT2_FALLING_ENABLE = 0x3b; +const AES_DELTA_ENABLE = 0x3c; +const AES_INVALID_VALUE_ENABLE = 0x3d; +const AES_OVERFLOW_VALUE_ENABLE = 0x3e; + +// Cyclic Settings +const CS_CYCLIC_DI_ENABLE = 0x3f; +const CS_DI_CONFIRMED = 0x40; +const CS_CYCLIC_DI_INTERVAL = 0x41; +const CS_CYCLIC_AI_ENABLE = 0x42; +const CS_AI_CONFIRMED = 0x43; +const CS_CYCLIC_AI_INTERVAL = 0x44; +const CS_CYCLIC_CNT_ENABLE = 0x45; +const CS_CNT_CONFIRMED = 0x46; +const CS_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL = 0x47; +const CS_CYCLIC_CNT_TIMEDATE_WEEKDAY = 0x48; +const CS_CYCLIC_CNT_TIME_HOUR = 0x49; +const CS_CYCLIC_CNT_TIME_MINUTE = 0x4a; +const CS_CYCLIC_CNT_TIME_INTERVAL = 0x4b; + +// Access Control Settings +const ACS_ENABLE = 0x4c; +const ACS_ALARM_DELAY = 0x4d; +const ACS_MOTION_DET_SEL = 0x4e; +const ACS_KEY_SWITCH_SEL = 0x4f; +const ACS_DOOR_CONTACT_SEL = 0x50; + +// Output Settings +const OS_ENABLE = 0x51; +const OS_INVERT = 0x52; +const OS_MODE = 0x53; +const OS_WIPER_TIME = 0x54; +const OS_TRIGGER_ENABLE = 0x5d; +const OS_TRIGGER_PERIOD = 0x5e; +const OS_TRIGGER_SCALING = 0x5f; + +// Input-Output Mapping Settings +const IOMS_OUT1 = 0x55; +const IOMS_OUT2 = 0x56; +const IOMS_OUT3 = 0x57; +const IOMS_OUT4 = 0x58; + +// Limit-Output Mapping Settings +const LOMS_OUT1 = 0x59; +const LOMS_OUT2 = 0x5a; +const LOMS_OUT3 = 0x5b; +const LOMS_OUT4 = 0x5c; + +// Modbus Settings +const MBS_CONFIG = 0x60; +const MBS_TRANSPARENT_DOWNLINK_ENABLE = 0x61; +const MBS_DPRATE_ENABLE = 0x62; +const MBS_DPRATE_TIMEDATE_WEEKDAY_SEL = 0x63; +const MBS_DPRATE_TIMEDATE_WEEKDAY = 0x64; +const MBS_DPRATE_TIME_HOUR = 0x65; +const MBS_DPRATE_TIME_MINUTE = 0x66; +const MBS_DPRATE_TIME_INTERVAL = 0x67; +const MBS_DP_00 = 0x68; +const MBS_DP_01 = 0x69; +const MBS_DP_02 = 0x6a; +const MBS_DP_03 = 0x6b; +const MBS_DP_04 = 0x6c; +const MBS_DP_05 = 0x6d; +const MBS_DP_06 = 0x6e; +const MBS_DP_07 = 0x6f; +const MBS_DP_08 = 0x70; +const MBS_DP_09 = 0x71; +const MBS_DP_10 = 0x72; +const MBS_DP_11 = 0x73; +const MBS_DP_12 = 0x74; +const MBS_DP_13 = 0x75; +const MBS_DP_14 = 0x76; +const MBS_DP_15 = 0x77; let pointer = 0; let deviceHeader = {}; @@ -202,6 +275,86 @@ function decodeUplink(input) { errors, }; } + if (deviceHeader.info.deviceVersion === 3) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } + if (deviceHeader.info.deviceVersion === 4) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + if (input.fPort === MODBUS_PORT) { + return decodeModbusPayload(input.bytes); + } + if (input.fPort === MODBUS_TP_PORT) { + return decodeModbusTransparentPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } errors.push("Device version not supported by this decoder"); return { data: { @@ -261,6 +414,86 @@ function decodeUplink(input) { errors, }; } + if (deviceHeader.info.deviceVersion === 3) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === AI_DATA_PORT) { + return decodeAiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } + if (deviceHeader.info.deviceVersion === 4) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === AI_DATA_PORT) { + return decodeAiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } errors.push("Device version not supported by this decoder"); return { data: { @@ -320,6 +553,86 @@ function decodeUplink(input) { errors, }; } + if (deviceHeader.info.deviceVersion === 3) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === AI_DATA_PORT) { + return decodeAiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } + if (deviceHeader.info.deviceVersion === 4) { + if (input.fPort === FIXED_DATA_PORT) { + return decodeFixedDataPayload(input.bytes); + } + if (input.fPort === DI_DATA_PORT) { + return decodeDiDataPayload(input.bytes); + } + if (input.fPort === AI_DATA_PORT) { + return decodeAiDataPayload(input.bytes); + } + if (input.fPort === CNT_DATA_PORT) { + return decodeCntDataPayload(input.bytes); + } + if (input.fPort === TIMESYNC_PORT) { + return decodeTimesyncPayload(input.bytes); + } + if (input.fPort === CONFIG_PORT) { + return decodeConfigPayload(input.bytes); + } + if (input.fPort === INFO_PORT) { + return decodeInfoPayload(input.bytes); + } + errors.push("not a valid port"); + return { + data: { + port: input.fPort, + portFunction: "unknown", + payloadLength: input.bytes.length, + payload: { + device: deviceHeader, + }, + decoder: { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }, + }, + warnings, + errors, + }; + } errors.push("Device version not supported by this decoder"); return { data: { @@ -399,15 +712,12 @@ function decodeDeviceHeader(data) { confirmationTimeout: Boolean(status & 0x80), }; - if (!data[pointer]) { - obj.batteryLevel = "external"; - } else if (data[pointer] === 255) { + if (data[pointer] === 255) { obj.batteryLevel = "error"; } else { // ((input - min) * 100) / (max - min) - obj.batteryLevel = `${Math.round( - ((data[pointer] - 1) * 100) / (254 - 1), - ).toString()}%`; + // obj.batteryLevel = (Math.round(((data[pointer] - 1) * 100) / (254 - 1))).toString() + "%"; + obj.batteryLevel = Math.round(((data[pointer] - 1) * 100) / (254 - 1)); } pointer++; return obj; @@ -416,18 +726,14 @@ function decodeDeviceHeader(data) { function decodeTimestamp(data) { const obj = {}; - let unixTimestamp; - let milliseconds; - let dateObject; - let humanDateFormat; - - unixTimestamp = data[3] + (data[2] << 8) + (data[1] << 16) + (data[0] << 24); - milliseconds = unixTimestamp * 1000; + const unixTimestamp = + data[3] + (data[2] << 8) + (data[1] << 16) + (data[0] << 24); + const milliseconds = unixTimestamp * 1000; obj.unix = unixTimestamp; - dateObject = new Date(milliseconds); - humanDateFormat = dateObject.toString(); // Wed Nov 24 2021 15:32:14 GMT+0100 (Mitteleuropäische Normalzeit) + const dateObject = new Date(milliseconds); + const humanDateFormat = dateObject.toString(); // Wed Nov 24 2021 15:32:14 GMT+0100 (Mitteleurop‰ische Normalzeit) // humanDateFormat = dateObject.toLocaleString(); //18.11.2021, 16:24:50 // humanDateFormat = dateObject.toUTCString(); //Thu, 18 Nov 2021 15:24:50 GMT @@ -438,14 +744,10 @@ function decodeTimestamp(data) { function addTimeToTimestamp(timestamp, data) { const obj = {}; - - let dateObject; - let humanDateFormat; - obj.unix = timestamp + (data[1] + (data[0] << 8)); - dateObject = new Date(obj.unix * 1000); - humanDateFormat = dateObject.toString(); // Wed Nov 24 2021 15:32:14 GMT+0100 (Mitteleuropäische Normalzeit) + const dateObject = new Date(obj.unix * 1000); + const humanDateFormat = dateObject.toString(); // Wed Nov 24 2021 15:32:14 GMT+0100 (Mitteleurop‰ische Normalzeit) // humanDateFormat = (dateObject).toLocaleString(); //18.11.2021, 16:24:50 // humanDateFormat = dateObject.toUTCString(); //Thu, 18 Nov 2021 15:24:50 GMT @@ -454,6 +756,52 @@ function addTimeToTimestamp(timestamp, data) { return obj; } +function decodeModbusState(data) { + let string; + + switch (data) { + case 0: + string = "MB_STATE_OK"; + break; + case 1: + string = "MB_STATE_NOT_INIT"; + break; + case 2: + string = "MB_STATE_BUSY"; + break; + case 3: + string = "MB_STATE_BUS_ERROR"; + break; + case 4: + string = "MB_STATE_FC_NOT_SUPPORTED"; + break; + case 5: + string = "MB_STATE_RX_TIMEOUT"; + break; + case 6: + string = "MB_STATE_RX_CHAR_TIMEOUT"; + break; + case 7: + string = "MB_STATE_RX_ERR"; + break; + case 8: + string = "MB_STATE_RX_CRC_ERR"; + break; + case 9: + string = "MB_STATE_RX_DATA_ERR"; + break; + case 10: + string = "MB_STATE_RX_EXCEPTION"; + break; + case 11: + string = "MB_STATE_WRONG_SLV_ADR"; + break; + default: + break; + } + return string; +} + function decodeCot(data) { let obj = {}; @@ -491,7 +839,6 @@ function decToInt(val) { function decodeFixedDataPayload(data) { const obj = {}; - const timestampAbsolute = {}; const warnings = []; obj.port = FIXED_DATA_PORT; @@ -506,75 +853,81 @@ function decodeFixedDataPayload(data) { obj.payload = { device: deviceHeader, data: { - config: { - timestamp: Boolean(data[pointer] & 0x01), - digitalInputs: Boolean(data[pointer] & 0x02), - values: Boolean(data[pointer] & 0x04), - }, timestamp: {}, - digitalInputs: "", - objects: [], + digitalInputs: {}, + analogInputs: {}, + counterInputs: {}, + temperatureInputs: {}, }, }; - pointer += 1; - - if (obj.payload.data.config.timestamp) { - obj.payload.data.timestamp = decodeTimestamp( - data.slice(pointer, pointer + 4), - ); - pointer += 4; - } - if (obj.payload.data.config.digitalInputs) { - pointer += 1; // Skip object type - obj.payload.data.digitalInputs = decode16BitAsBinaryString( - data.slice(pointer, pointer + 2), - ); - pointer += 2; - } - if (obj.payload.data.config.values) { - while (pointer < data.length - 1) { - switch (data[pointer] & 0xf0) { - case OBJECT_TYPE_CNT: - obj.payload.data.objects.push({ - type: "Counter", - id: data[pointer] & 0x0f, - value: - data[pointer + 3] + - (data[pointer + 2] << 8) + - (data[pointer + 1] << 16), - }); - pointer += 4; - break; - case OBJECT_TYPE_AI: - obj.payload.data.objects.push({ - type: "Analog", - id: data[pointer] & 0x0f, - status: { - "limit1:": Boolean(data[pointer + 1] & 0x01), - "limit2:": Boolean(data[pointer + 1] & 0x02), - "delta:": Boolean(data[pointer + 1] & 0x04), - }, - value: data[pointer + 3] + (data[pointer + 2] << 8), - }); - pointer += 4; - break; - case OBJECT_TYPE_TEMP: - obj.payload.data.objects.push({ - type: "Temperature", - id: data[pointer] & 0x0f, - status: { - "limit1:": Boolean(data[pointer + 1] & 0x01), - "limit2:": Boolean(data[pointer + 1] & 0x02), - "delta:": Boolean(data[pointer + 1] & 0x04), - }, - value: decToInt(data[pointer + 3] + (data[pointer + 2] << 8)) / 100, - }); - pointer += 4; - break; - default: - break; - } + obj.payload.data.timestamp = decodeTimestamp( + data.slice(pointer, pointer + 4), + ); + pointer += 4; + obj.payload.data.digital_inputs = { + cot: decodeCot(data[pointer] & 0xf0), + digitalInput1: !!(data[pointer + 2] & 0x01), + digitalInput2: !!(data[pointer + 2] & 0x02), + digitalInput3: !!(data[pointer + 2] & 0x04), + digitalInput4: !!(data[pointer + 2] & 0x08), + digitalInput5: !!(data[pointer + 2] & 0x10), + digitalInput6: !!(data[pointer + 2] & 0x20), + digitalInput7: !!(data[pointer + 2] & 0x40), + digitalInput8: !!(data[pointer + 2] & 0x80), + digitalInput9: !!(data[pointer + 1] & 0x01), + digitalInput10: !!(data[pointer + 1] & 0x02), + digitalInput11: !!(data[pointer + 1] & 0x04), + digitalInput12: !!(data[pointer + 1] & 0x08), + digitalInput13: !!(data[pointer + 1] & 0x10), + digitalInput14: !!(data[pointer + 1] & 0x20), + digitalInput15: !!(data[pointer + 1] & 0x40), + digitalInput16: !!(data[pointer + 1] & 0x80), + }; + pointer += 3; + + for (let i = 0; i < 8; i++) { + switch (data[pointer] & 0xf0) { + case OBJECT_TYPE_CNT: + obj.payload.data[`counter_input_${i + 1}`] = { + overflow: Boolean(data[pointer + 1] & 0x01), + reset: Boolean(data[pointer + 1] & 0x02), + limit: Boolean(data[pointer + 1] & 0x04), + cot: decodeCot(data[pointer + 1] & 0xf0), + value: + data[pointer + 4] + + (data[pointer + 3] << 8) + + (data[pointer + 2] << 16), + }; + pointer += 5; + break; + + case OBJECT_TYPE_AI: + obj.payload.data[`analog_input_${i + 1}`] = { + invalid: Boolean(data[pointer + 1] & 0x08), + overflow: Boolean(data[pointer + 1] & 0x04), + limit2: Boolean(data[pointer + 1] & 0x02), + limit1: Boolean(data[pointer + 1] & 0x01), + cot: decodeCot(data[pointer + 1] & 0xf0), + value: data[pointer + 4] + (data[pointer + 3] << 8), + }; + pointer += 5; + break; + case OBJECT_TYPE_TEMP: + obj.payload.data[`temperature_input_${i + 1}`] = { + invalid: Boolean(data[pointer + 1] & 0x08), + overflow: Boolean(data[pointer + 1] & 0x04), + limit2: Boolean(data[pointer + 1] & 0x02), + limit1: Boolean(data[pointer + 1] & 0x01), + cot: decodeCot(data[pointer + 1] & 0xf0), + value: decToInt(data[pointer + 4] + (data[pointer + 3] << 8)) / 100, + }; + pointer += 5; + break; + + default: + pointer += 5; + break; } } @@ -608,33 +961,25 @@ function decodeDiDataPayload(data) { pointer += 4; do { - if ((data[pointer] & 0xf0) == OBJECT_TYPE_DI) { + if ((data[pointer] & 0xf0) === OBJECT_TYPE_DI) { obj.payload.data.digitalInputs.push({ - info: { - type: "singlePointInfo", - id: data[pointer] & 0x0f, - }, + type: "singlePointInfo", + id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), - status: { - blocked: Boolean(data[pointer + 1] & 0x04), - state: data[pointer + 1] & 0x01, - }, + blocked: Boolean(data[pointer + 1] & 0x04), + state: data[pointer + 1] & 0x01, timestamp: addTimeToTimestamp( timestampAbsolute.unix, data.slice(pointer + 2, pointer + 4), ), }); - } else if ((data[pointer] & 0xf0) == OBJECT_TYPE_DBL) { + } else if ((data[pointer] & 0xf0) === OBJECT_TYPE_DBL) { obj.payload.data.digitalInputs.push({ - info: { - type: "doublePointInfo", - id: data[pointer] & 0x0f, - }, + type: "doublePointInfo", + id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), - status: { - blocked: Boolean(data[pointer + 1] & 0x04), - state: data[pointer + 1] & 0x03, - }, + blocked: Boolean(data[pointer + 1] & 0x04), + state: data[pointer + 1] & 0x03, timestamp: addTimeToTimestamp( timestampAbsolute.unix, data.slice(pointer + 2, pointer + 4), @@ -644,28 +989,6 @@ function decodeDiDataPayload(data) { pointer += 4; } while (pointer < data.length - 1); - // ------application specific assigments for digital inputs - // obj.application={}; - // obj.payload.data.digitalInputs.forEach(function (item) - // { - // switch(item.info.id) - // { - // case 5: - // obj.application.SwitchREMOTE=Boolean(item.status.state); - // break; - // case 6: - // obj.application.EndPositionOPEN=Boolean(item.status.state); - // break; - // case 7: - // obj.application.EndPositionCLOSE=Boolean(item.status.state); - // break; - // case 8: - // obj.application.EndPositionReserve=Boolean(item.status.state); - // break; - // } - // }); - // ----end of application specific assigments for digital inputs - return { data: obj, warnings, @@ -696,7 +1019,7 @@ function decodeAiDataPayload(data) { pointer += 4; do { - if ((data[pointer] & 0xf0) == OBJECT_TYPE_AI) { + if ((data[pointer] & 0xf0) === OBJECT_TYPE_AI) { // AI Type obj.payload.data.analogInputs.push({ info: { @@ -740,23 +1063,6 @@ function decodeAiDataPayload(data) { pointer += 6; } while (pointer < data.length - 1); - // ----application assigments for analog inputs - // obj.application={}; - // obj.payload.data.analogInputs.forEach(function (item) - // { - // switch(item.info.id) - // { - // case 1: - // obj.application.fuellstand=item.value; - // obj.application.fuellstandInvalid=Boolean(item.status.invalid); - // obj.application.fuellstandOverflow=Boolean(item.status.overflow); - // obj.application.fuellstandLimit1=Boolean(item.status.limit1); - // obj.application.fuellstandLimit2=Boolean(item.status.limit2); - // break; - // } - // }); - // ----end ofapplication assigments for analog inputs - return { data: obj, warnings, @@ -810,21 +1116,6 @@ function decodeCntDataPayload(data) { } } while (pointer < data.length - 1); - // ----application assigments for analog inputs - // obj.application={}; - // obj.payload.data.counters.forEach(function (item) - // { - // switch(item.info.id) - // { - // case 1: - // obj.application.counter1=item.value; - // obj.application.counter1Overflow=Boolean(item.status.overflow); - // obj.application.counter1Reset=Boolean(item.status.reset); - // obj.application.fuellstandLimit2=Boolean(item.status.limit2); - // break; - // } - // }); - // ----end ofapplication assigments for analog inputs return { data: obj, warnings, @@ -856,6 +1147,24 @@ function decodeTimesyncPayload(data) { }; } +function decodeDataPointConfig(data) { + let obj = {}; + + obj = { + name: data, + config: { + slave_address: data[pointer], + rfc: (data[pointer + 1] & 0xe0) >> 5, + register_count: data[pointer + 1] & 0x1f, + data_address: data[pointer + 3] + (data[pointer + 2] << 8), + }, + }; + + pointer += 4; + + return obj; +} + function decodeConfigPayload(data) { const obj = {}; const warnings = []; @@ -924,16 +1233,6 @@ function decodeConfigPayload(data) { value: data[pointer++] & 0x01 ? "dynamic" : "static", }); break; - case DS_STATIC_PAYLOAD_CONFIG: - obj.payload.data.parameters.push({ - name: "DS_STATIC_PAYLOAD_CONFIG", - value: { - timestamp: Boolean(data[pointer] & 0x01), - digitalInputs: Boolean(data[pointer] & 0x02), - counterValues: Boolean(data[pointer++] & 0x04), - }, - }); - break; // TS case TS_MEAS_INT_DC: @@ -1238,11 +1537,97 @@ function decodeConfigPayload(data) { ].values.push(string); } break; - case AIS_LIMIT_LOWER: + case AIS_DELTA_ENABLE: + obj.payload.data.parameters.push({ + name: "AIS_DELTA_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + break; + case AIS_DELTA_VALUE: + obj.payload.data.parameters.push({ + name: "AIS_DELTA_VALUE", + values: [], + unit: "units", + }); + for (i = 0; i < length / 2; i++) { + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(data[pointer + 1] + (data[pointer] << 8)); + pointer += 2; + } + break; + case AIS_LIMIT1_ENABLE: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_ENABLE", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + case AIS_LIMIT2_ENABLE: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT2_ENABLE", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + case AIS_LIMIT1_DELAY_ENABLE: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_DELAY_ENABLE", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + case AIS_LIMIT2_DELAY_ENABLE: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT2_DELAY_ENABLE", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + case AIS_LIMIT_DELAY_SCALING: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT_DELAY_SCALING", + values: [], + }); + for (i = 0; i < length / 2; i++) { + value = data[pointer + 1] + (data[pointer] << 8); + pointer += 2; + switch (value) { + case 0: + string = "ms"; + break; + case 1: + string = "s"; + break; + case 2: + string = "min"; + break; + case 3: + string = "h"; + break; + default: + string = "notAllowed"; + break; + } + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(string); + } + break; + case AIS_LIMIT1_DELAY_RISING: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_DELAY_RISING", + values: [], + unit: "units", + }); + for (i = 0; i < length / 2; i++) { + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(data[pointer + 1] + (data[pointer] << 8)); + pointer += 2; + } + break; + case AIS_LIMIT2_DELAY_RISING: obj.payload.data.parameters.push({ - name: "AIS_LIMIT_LOWER", + name: "AIS_LIMIT2_DELAY_RISING", values: [], - unit: "", + unit: "units", }); for (i = 0; i < length / 2; i++) { obj.payload.data.parameters[ @@ -1251,11 +1636,11 @@ function decodeConfigPayload(data) { pointer += 2; } break; - case AIS_LIMIT_UPPER: + case AIS_LIMIT1_DELAY_FALLING: obj.payload.data.parameters.push({ - name: "AIS_LIMIT_UPPER", + name: "AIS_LIMIT1_DELAY_FALLING", values: [], - unit: "", + unit: "units", }); for (i = 0; i < length / 2; i++) { obj.payload.data.parameters[ @@ -1264,11 +1649,50 @@ function decodeConfigPayload(data) { pointer += 2; } break; - case AIS_LIMIT_LOWER_HYST: + case AIS_LIMIT2_DELAY_FALLING: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT2_DELAY_FALLING", + values: [], + unit: "units", + }); + for (i = 0; i < length / 2; i++) { + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(data[pointer + 1] + (data[pointer] << 8)); + pointer += 2; + } + break; + case AIS_LIMIT1_VALUE: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_VALUE", + values: [], + unit: "units", + }); + for (i = 0; i < length / 2; i++) { + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(decToInt(data[pointer + 1] + (data[pointer] << 8))); + pointer += 2; + } + break; + case AIS_LIMIT2_VALUE: obj.payload.data.parameters.push({ - name: "AIS_LIMIT_LOWER_HYST", + name: "AIS_LIMIT2_VALUE", values: [], - unit: "", + unit: "units", + }); + for (i = 0; i < length / 2; i++) { + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(decToInt(data[pointer + 1] + (data[pointer] << 8))); + pointer += 2; + } + break; + case AIS_LIMIT1_HYSTERESIS: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_HYSTERESIS", + values: [], + unit: "units", }); for (i = 0; i < length / 2; i++) { obj.payload.data.parameters[ @@ -1277,11 +1701,11 @@ function decodeConfigPayload(data) { pointer += 2; } break; - case AIS_LIMIT_UPPER_HYST: + case AIS_LIMIT2_HYSTERESIS: obj.payload.data.parameters.push({ - name: "AIS_LIMIT_UPPER_HYST", + name: "AIS_LIMIT2_HYSTERESIS", values: [], - unit: "", + unit: "units", }); for (i = 0; i < length / 2; i++) { obj.payload.data.parameters[ @@ -1290,45 +1714,118 @@ function decodeConfigPayload(data) { pointer += 2; } break; + case AIS_LIMIT1_DIRECTION: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT1_DIRECTION", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + case AIS_LIMIT2_DIRECTION: + obj.payload.data.parameters.push({ + name: "AIS_LIMIT2_DIRECTION", + value: decode8BitAsBinaryString(data[pointer++]), + }); + break; + + // IES + case IES_RISING_ENABLE: + obj.payload.data.parameters.push({ + name: "IES_RISING_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case IES_FALLING_ENABLE: + obj.payload.data.parameters.push({ + name: "IES_FALLING_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case IES_BLOCKED_CHANGED: + obj.payload.data.parameters.push({ + name: "IES_BLOCKED_CHANGED", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case IES_PRIORITY: + obj.payload.data.parameters.push({ + name: "IES_PRIORITY", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case ES_DELAY: + obj.payload.data.parameters.push({ + name: "ES_DELAY", + value: data[pointer + 1] + (data[pointer] << 8), + unit: "ms", + }); + pointer += length; + break; - // ES - case ES_RISING_ENABLE: + // AES + case AES_LIMIT1_RISING_ENABLE: + obj.payload.data.parameters.push({ + name: "AES_LIMIT1_RISING_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case AES_LIMIT1_FALLING_ENABLE: + obj.payload.data.parameters.push({ + name: "AES_LIMIT1_FALLING_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case AES_LIMIT2_FALLING_ENABLE: + obj.payload.data.parameters.push({ + name: "AES_LIMIT2_FALLING_ENABLE", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case AES_DELTA_ENABLE: obj.payload.data.parameters.push({ - name: "ES_RISING_ENABLE", + name: "AES_DELTA_ENABLE", value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), }); pointer += length; break; - case ES_FALLING_ENABLE: + case AES_INVALID_VALUE_ENABLE: obj.payload.data.parameters.push({ - name: "ES_FALLING_ENABLE", + name: "AES_INVALID_VALUE_ENABLE", value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), }); pointer += length; break; - case ES_BLOCKED_CHANGED: + case AES_OVERFLOW_VALUE_ENABLE: obj.payload.data.parameters.push({ - name: "ES_BLOCKED_CHANGED", + name: "AES_OVERFLOW_VALUE_ENABLE", value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), }); pointer += length; break; - case ES_CYCLIC_DI_ENABLE: + + // CS + case CS_CYCLIC_DI_ENABLE: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_DI_ENABLE", + name: "CS_CYCLIC_DI_ENABLE", value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), }); pointer += length; break; - case ES_DI_CONFIRMED: + case CS_DI_CONFIRMED: obj.payload.data.parameters.push({ - name: "ES_DI_CONFIRMED", + name: "CS_DI_CONFIRMED", value: data[pointer++] & 0x01 ? "confirmed" : "unconfirmed", }); break; - case ES_CYCLIC_DI_INTERVAL: + case CS_CYCLIC_DI_INTERVAL: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_DI_INTERVAL", + name: "CS_CYCLIC_DI_INTERVAL", values: [], unit: "s", }); @@ -1339,22 +1836,22 @@ function decodeConfigPayload(data) { pointer += 2; } break; - case ES_CYCLIC_AI_ENABLE: + case CS_CYCLIC_AI_ENABLE: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_AI_ENABLE", + name: "CS_CYCLIC_AI_ENABLE", value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), }); pointer += length; break; - case ES_AI_CONFIRMED: + case CS_AI_CONFIRMED: obj.payload.data.parameters.push({ - name: "ES_AI_CONFIRMED", + name: "CS_AI_CONFIRMED", value: data[pointer++] & 0x01 ? "confirmed" : "unconfirmed", }); break; - case ES_CYCLIC_AI_INTERVAL: + case CS_CYCLIC_AI_INTERVAL: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_AI_INTERVAL", + name: "CS_CYCLIC_AI_INTERVAL", values: [], unit: "s", }); @@ -1365,67 +1862,52 @@ function decodeConfigPayload(data) { pointer += 2; } break; - case ES_CYCLIC_CNT_ENABLE: + case CS_CYCLIC_CNT_ENABLE: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_ENABLE", + name: "CS_CYCLIC_CNT_ENABLE", value: data[pointer++] & 0x01 ? "enabled" : "disabled", }); break; - case ES_CNT_CONFIRMED: + case CS_CNT_CONFIRMED: obj.payload.data.parameters.push({ - name: "ES_CNT_CONFIRMED", + name: "CS_CNT_CONFIRMED", value: data[pointer++] & 0x01 ? "confirmed" : "unconfirmed", }); break; - case ES_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL: + case CS_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL", + name: "CS_CYCLIC_CNT_TIMEDATE_WEEKDAY_SEL", value: data[pointer++] & 0x01 ? "weekday" : "date", }); break; - case ES_CYCLIC_CNT_TIMEDATE_WEEKDAY: + case CS_CYCLIC_CNT_TIMEDATE_WEEKDAY: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_TIMEDATE_WEEKDAY", + name: "CS_CYCLIC_CNT_TIMEDATE_WEEKDAY", value: data[pointer++] & 0x01, }); break; - case ES_CYCLIC_CNT_TIME_HOUR: + case CS_CYCLIC_CNT_TIME_HOUR: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_TIME_HOUR", + name: "CS_CYCLIC_CNT_TIME_HOUR", value: data[pointer++] & 0x01, }); break; - case ES_CYCLIC_CNT_TIME_MINUTE: + case CS_CYCLIC_CNT_TIME_MINUTE: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_TIME_MINUTE", + name: "CS_CYCLIC_CNT_TIME_MINUTE", value: data[pointer++] & 0x01, }); break; - case ES_CYCLIC_CNT_TIME_INTERVAL: + case CS_CYCLIC_CNT_TIME_INTERVAL: obj.payload.data.parameters.push({ - name: "ES_CYCLIC_CNT_TIME_INTERVAL", + name: "CS_CYCLIC_CNT_TIME_INTERVAL", value: data[pointer + 1] + (data[pointer] << 8), unit: "min", }); pointer += length; break; - case ES_PRIORITY: - obj.payload.data.parameters.push({ - name: "ES_PRIORITY", - value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), - }); - pointer += length; - break; - case ES_DELAY: - obj.payload.data.parameters.push({ - name: "ES_DELAY", - value: data[pointer + 1] + (data[pointer] << 8), - unit: "ms", - }); - pointer += length; - break; - // ASC + // ACS case ACS_ENABLE: obj.payload.data.parameters.push({ name: "ACS_ENABLE", @@ -1499,6 +1981,25 @@ function decodeConfigPayload(data) { pointer += 2; } break; + case OS_TRIGGER_ENABLE: + obj.payload.data.parameters.push({ + name: "OS_TRIGGER_ENABLE", + value: data[pointer++] & 0x01 ? "enabled" : "disabled", + }); + break; + case OS_TRIGGER_PERIOD: + obj.payload.data.parameters.push({ + name: "OS_TRIGGER_PERIOD", + value: decode16BitAsBinaryString(data.slice(pointer, pointer + 2)), + }); + pointer += length; + break; + case OS_TRIGGER_SCALING: + obj.payload.data.parameters.push({ + name: "OS_TRIGGER_SCALING", + value: data[pointer++] & 0x01, + }); + break; // IOMS case IOMS_OUT1: @@ -1621,6 +2122,235 @@ function decodeConfigPayload(data) { ].values.push(string); } break; + + // LOMS + case LOMS_OUT1: + obj.payload.data.parameters.push({ + name: "LOMS_OUT1", + values: [], + }); + for (i = 0; i < length / 2; i++) { + value = data[pointer + 1] + (data[pointer] << 8); + pointer += 2; + switch (value) { + case 0: + string = "disabled"; + break; + case 1: + string = "rising"; + break; + case 2: + string = "falling"; + break; + case 3: + string = "both"; + break; + default: + string = "notAllowed"; + break; + } + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(string); + } + break; + case LOMS_OUT2: + obj.payload.data.parameters.push({ + name: "LOMS_OUT2", + values: [], + }); + for (i = 0; i < length / 2; i++) { + value = data[pointer + 1] + (data[pointer] << 8); + pointer += 2; + switch (value) { + case 0: + string = "disabled"; + break; + case 1: + string = "rising"; + break; + case 2: + string = "falling"; + break; + case 3: + string = "both"; + break; + default: + string = "notAllowed"; + break; + } + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(string); + } + break; + case LOMS_OUT3: + obj.payload.data.parameters.push({ + name: "LOMS_OUT3", + values: [], + }); + for (i = 0; i < length / 2; i++) { + value = data[pointer + 1] + (data[pointer] << 8); + pointer += 2; + switch (value) { + case 0: + string = "disabled"; + break; + case 1: + string = "rising"; + break; + case 2: + string = "falling"; + break; + case 3: + string = "both"; + break; + default: + string = "notAllowed"; + break; + } + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(string); + } + break; + case LOMS_OUT4: + obj.payload.data.parameters.push({ + name: "LOMS_OUT4", + values: [], + }); + for (i = 0; i < length / 2; i++) { + value = data[pointer + 1] + (data[pointer] << 8); + pointer += 2; + switch (value) { + case 0: + string = "disabled"; + break; + case 1: + string = "rising"; + break; + case 2: + string = "falling"; + break; + case 3: + string = "both"; + break; + default: + string = "notAllowed"; + break; + } + obj.payload.data.parameters[ + obj.payload.data.parameters.length - 1 + ].values.push(string); + } + break; + case MBS_CONFIG: + obj.payload.data.parameters.push({ + name: "MBS_CONFIG", + config: { + baudrate: + data[pointer + 2] + + (data[pointer + 1] << 8) + + (data[pointer] << 16), + answer_timeout: data[pointer + 4] + (data[pointer + 3] << 8), + parity: data[pointer + 5] & 0x03, + retries: (data[pointer + 5] & 0x0c) >> 2, + }, + }); + pointer += 6; + break; + case MBS_TRANSPARENT_DOWNLINK_ENABLE: + obj.payload.data.parameters.push({ + name: "MBS_TRANSPARENT_DOWNLINK_ENABLE", + value: data[pointer++] & 0x01 ? "enabled" : "disabled", + }); + break; + case MBS_DPRATE_ENABLE: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_ENABLE", + value: data[pointer++] & 0x01 ? "enabled" : "disabled", + }); + break; + case MBS_DPRATE_TIMEDATE_WEEKDAY_SEL: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_TIMEDATE_WEEKDAY_SEL", + value: data[pointer++] & 0x01 ? "weekday" : "date", + }); + break; + case MBS_DPRATE_TIMEDATE_WEEKDAY: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_TIMEDATE_WEEKDAY", + value: data[pointer++] & 0x01, + }); + break; + case MBS_DPRATE_TIME_HOUR: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_TIME_HOUR", + value: data[pointer++] & 0x01, + }); + break; + case MBS_DPRATE_TIME_MINUTE: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_TIME_MINUTE", + value: data[pointer++] & 0x01, + }); + break; + case MBS_DPRATE_TIME_INTERVAL: + obj.payload.data.parameters.push({ + name: "MBS_DPRATE_TIME_INTERVAL", + value: data[pointer + 1] + (data[pointer] << 8), + unit: "min", + }); + pointer += length; + break; + case MBS_DP_00: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_00")); + break; + case MBS_DP_01: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_01")); + break; + case MBS_DP_02: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_02")); + break; + case MBS_DP_03: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_03")); + break; + case MBS_DP_04: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_04")); + break; + case MBS_DP_05: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_05")); + break; + case MBS_DP_06: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_06")); + break; + case MBS_DP_07: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_07")); + break; + case MBS_DP_08: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_08")); + break; + case MBS_DP_09: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_09")); + break; + case MBS_DP_10: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_10")); + break; + case MBS_DP_11: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_11")); + break; + case MBS_DP_12: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_12")); + break; + case MBS_DP_13: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_13")); + break; + case MBS_DP_14: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_14")); + break; + case MBS_DP_15: + obj.payload.data.parameters.push(decodeDataPointConfig("MBS_DP_15")); + break; default: break; } @@ -1654,6 +2384,82 @@ function decodeInfoPayload(data) { }; } +function decodeModbusPayload(data) { + const obj = {}; + const warnings = []; + + obj.port = MODBUS_PORT; + obj.portFunction = "MODBUS"; + obj.payloadLength = data.length; + + obj.decoder = { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }; + + obj.payload = { + device: deviceHeader, + datapoints: [], + }; + + do { + obj.payload.datapoints.push({ + state: decodeModbusState((data[pointer] & 0xf0) >> 4), + index: data[pointer] & 0x0f, + timestamp: decodeTimestamp(data.slice(pointer + 1, pointer + 5)), + registers: [], + }); + + for (let i = 0; i < data[pointer + 5] * 2; i++) { + obj.payload.datapoints[obj.payload.datapoints.length - 1].registers.push( + data[pointer + 6 + i], + ); + } + + pointer += 1 + 4 + 1 + data[pointer + 5] * 2; + } while (pointer - 1 < data.length - 1); + + return { + data: obj, + warnings, + }; +} + +function decodeModbusTransparentPayload(data) { + const obj = {}; + const warnings = []; + + obj.port = MODBUS_PORT; + obj.portFunction = "MODBUS TRANSPARENT"; + obj.payloadLength = data.length; + + obj.decoder = { + version: PAYLOAD_DECODER_VERSION, + info: PAYLOAD_DECODER_INFO, + }; + + obj.payload = { + device: deviceHeader, + }; + + obj.payload = { + command: { + slave_adress: data[pointer], + fc: data[pointer + 1], + answer: [], + }, + }; + + for (let i = pointer + 2; i < data.length; i++) { + obj.payload.command.answer.push(data[pointer + i]); + } + + return { + data: obj, + warnings, + }; +} + function decodeGpsPayload(data) { const obj = {}; const warnings = []; @@ -1676,14 +2482,18 @@ function decodeGpsPayload(data) { info: PAYLOAD_DECODER_INFO, }; - obj.payload.data.coordinates.latitude = parseInt( - data.slice(pointer, pointer + 4).toString("hex"), - 16, - ); - obj.payload.data.coordinates.longitude = parseInt( - data.slice(pointer + 5, pointer + 9).toString("hex"), - 16, - ); + // obj.payload.data.coordinates.latitude = parseInt(data.slice(pointer, (pointer + 4)).toString("hex"), 16); + // obj.payload.data.coordinates.longitude = parseInt(data.slice(pointer + 5, (pointer + 9)).toString("hex"), 16); + obj.payload.data.coordinates.latitude = + (((((data[pointer] << 8) + data[pointer + 1]) << 8) + data[pointer + 2]) << + 8) + + data[pointer + 3]; + obj.payload.data.coordinates.longitude = + (((((data[pointer + 4] << 8) + data[pointer + 5]) << 8) + + data[pointer + 6]) << + 8) + + data[pointer + 7]; + pointer += 8; return { data: obj, @@ -1723,9 +2533,35 @@ function consume(event) { }); const { device } = decoded.data.payload; + const type = decoded.data.portFunction; // FIXED_DATA const { data } = decoded.data.payload; const { warnings } = decoded; + switch (type) { + case "FIXED_DATA": + Object.keys(data).forEach((key) => { + data[key].limit = data[key].cot.limit; + data[key].event = data[key].cot.event; + data[key].interrogation = data[key].cot.interrogation; + data[key].cyclic = data[key].cot.cyclic; + delete data[key].cot; + + emit("sample", { data: data[key], topic: key }); + }); + break; + case "FIXED_DATA": + break; + case "FIXED_DATA": + break; + case "FIXED_DATA": + break; + case "FIXED_DATA": + break; + + default: + break; + } + // Digital inputs for (let i = 0; i < data.digitalInputs.length; i++) { const digitalInputs = {}; From 5b8b4c7f389ca2b328a14bb6af8989e087fb25f4 Mon Sep 17 00:00:00 2001 From: j2 Date: Wed, 11 Oct 2023 11:38:14 +0200 Subject: [PATCH 02/10] Finished up comtac cluey --- types/comtac/Cluey/analog_input_1.schema.json | 75 +++++ types/comtac/Cluey/analog_input_2.schema.json | 75 +++++ types/comtac/Cluey/analog_input_3.schema.json | 75 +++++ types/comtac/Cluey/analog_input_4.schema.json | 75 +++++ types/comtac/Cluey/analog_input_5.schema.json | 75 +++++ types/comtac/Cluey/analog_input_6.schema.json | 75 +++++ types/comtac/Cluey/analog_input_7.schema.json | 75 +++++ types/comtac/Cluey/analog_input_8.schema.json | 75 +++++ .../Cluey/analog_input_data.schema.json | 91 ++++++ types/comtac/Cluey/configuration.schema.json | 17 + types/comtac/Cluey/count_data.schema.json | 77 +++++ .../comtac/Cluey/counter_input_1.schema.json | 24 +- .../comtac/Cluey/counter_input_2.schema.json | 24 +- .../comtac/Cluey/counter_input_3.schema.json | 24 +- .../comtac/Cluey/counter_input_4.schema.json | 24 +- .../comtac/Cluey/counter_input_5.schema.json | 24 +- .../comtac/Cluey/counter_input_6.schema.json | 24 +- .../comtac/Cluey/counter_input_7.schema.json | 24 +- .../comtac/Cluey/counter_input_8.schema.json | 24 +- types/comtac/Cluey/error.schema.json | 17 + types/comtac/Cluey/gps.schema.json | 27 ++ types/comtac/Cluey/meta.json | 42 ++- types/comtac/Cluey/modbus.schema.json | 55 ++++ .../Cluey/modbus_transparent.schema.json | 29 ++ ...tal.schema.json => point_info.schema.json} | 71 ++-- .../Cluey/temperature_input_1.schema.json | 75 +++++ .../Cluey/temperature_input_2.schema.json | 75 +++++ .../Cluey/temperature_input_3.schema.json | 75 +++++ .../Cluey/temperature_input_4.schema.json | 75 +++++ .../Cluey/temperature_input_5.schema.json | 75 +++++ .../Cluey/temperature_input_6.schema.json | 75 +++++ .../Cluey/temperature_input_7.schema.json | 75 +++++ .../Cluey/temperature_input_8.schema.json | 75 +++++ types/comtac/Cluey/time_sync.schema.json | 17 + types/comtac/Cluey/uplink.js | 303 +++++++++++------- types/comtac/Cluey/uplink.spec.js | 84 ++--- 36 files changed, 1972 insertions(+), 250 deletions(-) create mode 100644 types/comtac/Cluey/analog_input_1.schema.json create mode 100644 types/comtac/Cluey/analog_input_2.schema.json create mode 100644 types/comtac/Cluey/analog_input_3.schema.json create mode 100644 types/comtac/Cluey/analog_input_4.schema.json create mode 100644 types/comtac/Cluey/analog_input_5.schema.json create mode 100644 types/comtac/Cluey/analog_input_6.schema.json create mode 100644 types/comtac/Cluey/analog_input_7.schema.json create mode 100644 types/comtac/Cluey/analog_input_8.schema.json create mode 100644 types/comtac/Cluey/analog_input_data.schema.json create mode 100644 types/comtac/Cluey/configuration.schema.json create mode 100644 types/comtac/Cluey/count_data.schema.json create mode 100644 types/comtac/Cluey/error.schema.json create mode 100644 types/comtac/Cluey/gps.schema.json create mode 100644 types/comtac/Cluey/modbus.schema.json create mode 100644 types/comtac/Cluey/modbus_transparent.schema.json rename types/comtac/Cluey/{digital.schema.json => point_info.schema.json} (53%) create mode 100644 types/comtac/Cluey/temperature_input_1.schema.json create mode 100644 types/comtac/Cluey/temperature_input_2.schema.json create mode 100644 types/comtac/Cluey/temperature_input_3.schema.json create mode 100644 types/comtac/Cluey/temperature_input_4.schema.json create mode 100644 types/comtac/Cluey/temperature_input_5.schema.json create mode 100644 types/comtac/Cluey/temperature_input_6.schema.json create mode 100644 types/comtac/Cluey/temperature_input_7.schema.json create mode 100644 types/comtac/Cluey/temperature_input_8.schema.json create mode 100644 types/comtac/Cluey/time_sync.schema.json diff --git a/types/comtac/Cluey/analog_input_1.schema.json b/types/comtac/Cluey/analog_input_1.schema.json new file mode 100644 index 00000000..764aaa7a --- /dev/null +++ b/types/comtac/Cluey/analog_input_1.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_1.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_1", + "title": "Analog Input 1", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_2.schema.json b/types/comtac/Cluey/analog_input_2.schema.json new file mode 100644 index 00000000..ce1944fa --- /dev/null +++ b/types/comtac/Cluey/analog_input_2.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_2.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_2", + "title": "Analog Input 2", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_3.schema.json b/types/comtac/Cluey/analog_input_3.schema.json new file mode 100644 index 00000000..c493b625 --- /dev/null +++ b/types/comtac/Cluey/analog_input_3.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_3.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_3", + "title": "Analog Input 3", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_4.schema.json b/types/comtac/Cluey/analog_input_4.schema.json new file mode 100644 index 00000000..19d9b230 --- /dev/null +++ b/types/comtac/Cluey/analog_input_4.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_4.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_4", + "title": "Analog Input 4", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_5.schema.json b/types/comtac/Cluey/analog_input_5.schema.json new file mode 100644 index 00000000..4ff66746 --- /dev/null +++ b/types/comtac/Cluey/analog_input_5.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_5.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_5", + "title": "Analog Input 5", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_6.schema.json b/types/comtac/Cluey/analog_input_6.schema.json new file mode 100644 index 00000000..1c33581a --- /dev/null +++ b/types/comtac/Cluey/analog_input_6.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_6.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_6", + "title": "Analog Input 6", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_7.schema.json b/types/comtac/Cluey/analog_input_7.schema.json new file mode 100644 index 00000000..5c1d3ee9 --- /dev/null +++ b/types/comtac/Cluey/analog_input_7.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_7.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_7", + "title": "Analog Input 7", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_8.schema.json b/types/comtac/Cluey/analog_input_8.schema.json new file mode 100644 index 00000000..6064b79b --- /dev/null +++ b/types/comtac/Cluey/analog_input_8.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_8.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_8", + "title": "Analog Input 8", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/analog_input_data.schema.json b/types/comtac/Cluey/analog_input_data.schema.json new file mode 100644 index 00000000..1bc23504 --- /dev/null +++ b/types/comtac/Cluey/analog_input_data.schema.json @@ -0,0 +1,91 @@ +{ + "$id": "https://akenza.io/comtac/cluey/analog_input_data.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "analog_input_data", + "title": "Analog Input Data", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "type": { + "title": "Type", + "description": "Type", + "type": "string", + "enum": ["ANALOG_VALUE", "TEMPERATURE_VALUE"], + "hideFromKpis": true + }, + "id": { + "title": "ID", + "description": "ID", + "type": "number", + "hideFromKpis": true + }, + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "type", + "id", + "invalid", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/configuration.schema.json b/types/comtac/Cluey/configuration.schema.json new file mode 100644 index 00000000..29f2ba21 --- /dev/null +++ b/types/comtac/Cluey/configuration.schema.json @@ -0,0 +1,17 @@ +{ + "$id": "https://akenza.io/comtac/cluey/configuration.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "configuration", + "title": "Configuration", + "properties": { + "parameters": { + "title": "Configuration Parameters", + "description": "Configuration Parameters", + "type": "array", + "hideFromKpis": true + } + }, + "required": ["parameters"] +} diff --git a/types/comtac/Cluey/count_data.schema.json b/types/comtac/Cluey/count_data.schema.json new file mode 100644 index 00000000..384c0b1f --- /dev/null +++ b/types/comtac/Cluey/count_data.schema.json @@ -0,0 +1,77 @@ +{ + "$id": "https://akenza.io/comtac/cluey/count_data.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "count_data", + "title": "Count Data", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "type": { + "title": "Type", + "description": "Type", + "type": "string", + "enum": ["COUNTER_DIFFERENCE", "COUNTER"], + "hideFromKpis": true + }, + "id": { + "title": "ID", + "description": "ID", + "type": "number", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "reset": { + "title": "Reset", + "description": "Reset", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "type", + "id", + "overflow", + "reset", + "value" + ] +} diff --git a/types/comtac/Cluey/counter_input_1.schema.json b/types/comtac/Cluey/counter_input_1.schema.json index d0f98aa6..747e4c17 100644 --- a/types/comtac/Cluey/counter_input_1.schema.json +++ b/types/comtac/Cluey/counter_input_1.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_1.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_1", + "title": "Counter Input 1", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_2.schema.json b/types/comtac/Cluey/counter_input_2.schema.json index d0f98aa6..b7506420 100644 --- a/types/comtac/Cluey/counter_input_2.schema.json +++ b/types/comtac/Cluey/counter_input_2.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_2.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_2", + "title": "Counter Input 2", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_3.schema.json b/types/comtac/Cluey/counter_input_3.schema.json index d0f98aa6..d65a2134 100644 --- a/types/comtac/Cluey/counter_input_3.schema.json +++ b/types/comtac/Cluey/counter_input_3.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_3.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_3", + "title": "Counter Input 3", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_4.schema.json b/types/comtac/Cluey/counter_input_4.schema.json index d0f98aa6..bcf9ee98 100644 --- a/types/comtac/Cluey/counter_input_4.schema.json +++ b/types/comtac/Cluey/counter_input_4.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_4.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_4", + "title": "Counter Input 4", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_5.schema.json b/types/comtac/Cluey/counter_input_5.schema.json index d0f98aa6..dc07fc9c 100644 --- a/types/comtac/Cluey/counter_input_5.schema.json +++ b/types/comtac/Cluey/counter_input_5.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_5.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_5", + "title": "Counter Input 5", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_6.schema.json b/types/comtac/Cluey/counter_input_6.schema.json index d0f98aa6..3beac6c6 100644 --- a/types/comtac/Cluey/counter_input_6.schema.json +++ b/types/comtac/Cluey/counter_input_6.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_6.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_6", + "title": "Counter Input 6", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_7.schema.json b/types/comtac/Cluey/counter_input_7.schema.json index d0f98aa6..a9afe9e8 100644 --- a/types/comtac/Cluey/counter_input_7.schema.json +++ b/types/comtac/Cluey/counter_input_7.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_7.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_7", + "title": "Counter Input 7", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/counter_input_8.schema.json b/types/comtac/Cluey/counter_input_8.schema.json index d0f98aa6..7b12a7df 100644 --- a/types/comtac/Cluey/counter_input_8.schema.json +++ b/types/comtac/Cluey/counter_input_8.schema.json @@ -1,10 +1,10 @@ { - "$id": "https://akenza.io/comtac/cluey/counter_input_.schema.json", + "$id": "https://akenza.io/comtac/cluey/counter_input_8.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "counter_input_", - "title": "Counter Inputs ", + "topic": "counter_input_8", + "title": "Counter Input 8", "properties": { "limit": { "title": "Limit", @@ -31,14 +31,14 @@ "hideFromKpis": true }, "overflow": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Overflow", + "description": "Overflow", "type": "boolean", "hideFromKpis": true }, "reset": { - "title": "Cyclic", - "description": "Cyclic", + "title": "Reset", + "description": "Reset", "type": "boolean", "hideFromKpis": true }, @@ -49,5 +49,13 @@ "hideFromKpis": true } }, - "required": [] + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "reset", + "value" + ] } diff --git a/types/comtac/Cluey/error.schema.json b/types/comtac/Cluey/error.schema.json new file mode 100644 index 00000000..81ae0c04 --- /dev/null +++ b/types/comtac/Cluey/error.schema.json @@ -0,0 +1,17 @@ +{ + "$id": "https://akenza.io/comtac/cluey/error.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "error", + "title": "Error", + "properties": { + "errors": { + "title": "Errors", + "type": "array", + "description": "List of errors", + "hideFromKpis": true + } + }, + "required": ["error"] +} diff --git a/types/comtac/Cluey/gps.schema.json b/types/comtac/Cluey/gps.schema.json new file mode 100644 index 00000000..97aafca0 --- /dev/null +++ b/types/comtac/Cluey/gps.schema.json @@ -0,0 +1,27 @@ +{ + "$id": "https://akenza.io/comtac/cluey/gps.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "gps", + "title": "GPS", + "properties": { + "latitude": { + "title": "Latitude", + "unit": "°", + "type": "number", + "description": "Latitude", + "minimum": -3276.5, + "maximum": 3276.5 + }, + "longitude": { + "title": "Longitude", + "unit": "°", + "type": "number", + "description": "Longitude", + "minimum": -3276.5, + "maximum": 3276.5 + } + }, + "required": ["latitude", "longitude"] +} diff --git a/types/comtac/Cluey/meta.json b/types/comtac/Cluey/meta.json index 546dad2c..8f0d6ae3 100644 --- a/types/comtac/Cluey/meta.json +++ b/types/comtac/Cluey/meta.json @@ -3,12 +3,48 @@ "version": "1.0.0", "manufacturer": "Comtac", "url": "https://www.comtac.ch/en/products/all-products/monitoring-ios/cluey-km.html", - "description": "For monitoring and control tasks in power, water or other infrastructure networks. Configurable to your needs", + "description": "Cluey KM / TM / AM / MB for monitoring and control tasks in power, water or other infrastructure networks. Configurable to your needs", "author": "Akenza AG", "firmwareVersion": "V1.0.0", "loraDeviceClass": "C", - "availableSensors": ["Digital"], - "outputTopics": ["digital", "lifecycle"], + "availableSensors": ["Analog", "Counter", "Digital", "GPS", "Temperature"], + "outputTopics": [ + "analog_input_1", + "analog_input_2", + "analog_input_3", + "analog_input_4", + "analog_input_5", + "analog_input_6", + "analog_input_7", + "analog_input_8", + "analog_input_data", + "configuration", + "counter_input_1", + "counter_input_2", + "counter_input_3", + "counter_input_4", + "counter_input_5", + "counter_input_6", + "counter_input_7", + "counter_input_8", + "count_data", + "digital_inputs", + "error", + "gps", + "lifecycle", + "modbus_transparent", + "modbus", + "point_info", + "temperature_input_1", + "temperature_input_2", + "temperature_input_3", + "temperature_input_4", + "temperature_input_5", + "temperature_input_6", + "temperature_input_7", + "temperature_input_8", + "time_sync" + ], "encoding": "HEX", "connectivity": "LORA" } diff --git a/types/comtac/Cluey/modbus.schema.json b/types/comtac/Cluey/modbus.schema.json new file mode 100644 index 00000000..95d61b04 --- /dev/null +++ b/types/comtac/Cluey/modbus.schema.json @@ -0,0 +1,55 @@ +{ + "$id": "https://akenza.io/comtac/cluey/modbus.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "modbus", + "title": "Modbus", + "properties": { + "modbusId": { + "title": "Modbis ID", + "description": "Modbis ID", + "type": "string", + "hideFromKpis": true + }, + "errorVerbose": { + "title": "Error Verbose", + "description": "Error Verbose", + "type": "string", + "enum": [ + "MB_STATE_OK", + "MB_STATE_NOT_INIT", + "MB_STATE_BUSY", + "MB_STATE_BUS_ERROR", + "MB_STATE_FC_NOT_SUPPORTED", + "MB_STATE_RX_TIMEOUT", + "MB_STATE_RX_CHAR_TIMEOUT", + "MB_STATE_RX_ERR", + "MB_STATE_RX_CRC_ERR", + "MB_STATE_RX_DATA_ERR", + "MB_STATE_RX_EXCEPTION", + "MB_STATE_WRONG_SLV_ADR" + ], + "hideFromKpis": true + }, + "errorCode": { + "title": "Error code", + "description": "Error code", + "type": "number", + "hideFromKpis": true + }, + "index": { + "title": "Index", + "description": "Index", + "type": "number", + "hideFromKpis": true + }, + "registers": { + "title": "Registers", + "description": "Registers", + "type": "array", + "hideFromKpis": true + } + }, + "required": ["modbusId", "errorVerbose", "errorCode", "index", "registers"] +} diff --git a/types/comtac/Cluey/modbus_transparent.schema.json b/types/comtac/Cluey/modbus_transparent.schema.json new file mode 100644 index 00000000..77ec7420 --- /dev/null +++ b/types/comtac/Cluey/modbus_transparent.schema.json @@ -0,0 +1,29 @@ +{ + "$id": "https://akenza.io/comtac/cluey/modbus_transparent.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "modbus_transparent", + "title": "Modbus Transparent", + "properties": { + "slaveAdress": { + "title": "Slave adress", + "description": "Slave adress", + "type": "number", + "hideFromKpis": true + }, + "fc": { + "title": "FC", + "description": "FC", + "type": "number", + "hideFromKpis": true + }, + "answer": { + "title": "Command answer", + "description": "Command answer", + "type": "array", + "hideFromKpis": true + } + }, + "required": ["slaveAdress", "fc", "answer"] +} diff --git a/types/comtac/Cluey/digital.schema.json b/types/comtac/Cluey/point_info.schema.json similarity index 53% rename from types/comtac/Cluey/digital.schema.json rename to types/comtac/Cluey/point_info.schema.json index d8f7db30..bbb7f328 100644 --- a/types/comtac/Cluey/digital.schema.json +++ b/types/comtac/Cluey/point_info.schema.json @@ -1,55 +1,70 @@ { - "$id": "https://akenza.io/comtac/cluey/digital.schema.json", + "$id": "https://akenza.io/comtac/cluey/point_info.schema.json", "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "processingType": "uplink_decoder", - "topic": "digital", - "title": "Digital", + "topic": "point_info", + "title": "Point Info", "properties": { - "blocked": { - "title": "Blocked", - "description": "Blocked", + "limit": { + "title": "Limit", + "description": "Limit", "type": "boolean", "hideFromKpis": true }, - "cyclic": { - "title": "Cyclic", - "description": "Cyclic", - "type": "boolean" - }, "event": { "title": "Event", "description": "Event", - "type": "boolean" - }, - "inputNr": { - "title": "Input number", - "description": "Input number", - "type": "integer" + "type": "boolean", + "hideFromKpis": true }, "interrogation": { "title": "Interrogation", "description": "Interrogation", - "type": "boolean" + "type": "boolean", + "hideFromKpis": true }, - "limit": { - "title": "Limit", - "description": "Limit", - "type": "boolean" + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "type": { + "title": "Type", + "description": "Type", + "type": "string", + "enum": ["SINGLE_POINT_INFO", "DOUBLE_POINT_INFO"], + "hideFromKpis": true + }, + "id": { + "title": "ID", + "description": "ID", + "type": "number", + "hideFromKpis": true + }, + "blocked": { + "title": "Blocked", + "description": "Blocked", + "type": "boolean", + "hideFromKpis": true }, "state": { "title": "State", "description": "State", - "type": "integer" + "type": "number", + "hideFromKpis": true } }, "required": [ - "blocked", - "cyclic", + "limit", "event", - "inputNr", "interrogation", - "limit", + "cyclic", + "type", + "id", + "blocked", "state" ] -} \ No newline at end of file +} diff --git a/types/comtac/Cluey/temperature_input_1.schema.json b/types/comtac/Cluey/temperature_input_1.schema.json new file mode 100644 index 00000000..f3fd161e --- /dev/null +++ b/types/comtac/Cluey/temperature_input_1.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_1.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_1", + "title": "Temperature Input 1", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_2.schema.json b/types/comtac/Cluey/temperature_input_2.schema.json new file mode 100644 index 00000000..a16f3af6 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_2.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_2.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_2", + "title": "Temperature Input 2", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_3.schema.json b/types/comtac/Cluey/temperature_input_3.schema.json new file mode 100644 index 00000000..c8e3ae94 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_3.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_3.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_3", + "title": "Temperature Input 3", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_4.schema.json b/types/comtac/Cluey/temperature_input_4.schema.json new file mode 100644 index 00000000..eccd16c6 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_4.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_4.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_4", + "title": "Temperature Input 4", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_5.schema.json b/types/comtac/Cluey/temperature_input_5.schema.json new file mode 100644 index 00000000..1055c5c4 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_5.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_5.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_5", + "title": "Temperature Input 5", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_6.schema.json b/types/comtac/Cluey/temperature_input_6.schema.json new file mode 100644 index 00000000..c56860c0 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_6.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_6.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_6", + "title": "Temperature Input 6", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_7.schema.json b/types/comtac/Cluey/temperature_input_7.schema.json new file mode 100644 index 00000000..95f50e24 --- /dev/null +++ b/types/comtac/Cluey/temperature_input_7.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_7.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_7", + "title": "Temperature Input 7", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/temperature_input_8.schema.json b/types/comtac/Cluey/temperature_input_8.schema.json new file mode 100644 index 00000000..d1e888fd --- /dev/null +++ b/types/comtac/Cluey/temperature_input_8.schema.json @@ -0,0 +1,75 @@ +{ + "$id": "https://akenza.io/comtac/cluey/temperature_input_8.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "temperature_input_8", + "title": "Temperature Input 8", + "properties": { + "limit": { + "title": "Limit", + "description": "Limit", + "type": "boolean", + "hideFromKpis": true + }, + "event": { + "title": "Event", + "description": "Event", + "type": "boolean", + "hideFromKpis": true + }, + "interrogation": { + "title": "Interrogation", + "description": "Interrogation", + "type": "boolean", + "hideFromKpis": true + }, + "cyclic": { + "title": "Cyclic", + "description": "Cyclic", + "type": "boolean", + "hideFromKpis": true + }, + + "invalid": { + "title": "Invalid", + "description": "Invalid", + "type": "boolean", + "hideFromKpis": true + }, + "overflow": { + "title": "Overflow", + "description": "Overflow", + "type": "boolean", + "hideFromKpis": true + }, + "limit1": { + "title": "Limit 1", + "description": "Limit 1", + "type": "boolean", + "hideFromKpis": true + }, + "limit2": { + "title": "Limit 2", + "description": "Limit 2", + "type": "boolean", + "hideFromKpis": true + }, + "value": { + "title": "Value", + "description": "Value", + "type": "number", + "hideFromKpis": true + } + }, + "required": [ + "limit", + "event", + "interrogation", + "cyclic", + "overflow", + "limit1", + "limit2", + "value" + ] +} diff --git a/types/comtac/Cluey/time_sync.schema.json b/types/comtac/Cluey/time_sync.schema.json new file mode 100644 index 00000000..6e5a6e4b --- /dev/null +++ b/types/comtac/Cluey/time_sync.schema.json @@ -0,0 +1,17 @@ +{ + "$id": "https://akenza.io/comtac/cluey/time_sync.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "time_sync", + "title": "Time Synchronization", + "properties": { + "timestamp": { + "title": "Device Timestamp", + "description": "Device Timestamp", + "type": "number", + "hideFromKpis": true + } + }, + "required": ["timestamp"] +} diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index ca199fe2..ea60c9c1 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -6,10 +6,10 @@ */ // DEFINES -const PAYLOAD_DECODER_VERSION = "00.09"; +const PAYLOAD_DECODER_VERSION = "00.11"; const PAYLOAD_DECODER_INFO = "comtac Cluey"; const DEVICE_DESIGNATION_CLUEY_KM = "Cluey-KM"; -const DEVICE_DESIGNATION_CLUEY_AM = "Cluey-AM"; +const DEVICE_DESIGNATION_CLUEY_AM = "Cluey-AM/MB"; const DEVICE_DESIGNATION_CLUEY_TM = "Cluey-TM"; const DEVICE_MANUFACTURER = "comtac AG"; @@ -220,11 +220,11 @@ function decodeUplink(input) { if (input.fPort === PING_PORT) { return decodePingPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -257,11 +257,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -294,11 +294,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -337,11 +337,11 @@ function decodeUplink(input) { if (input.fPort === MODBUS_TP_PORT) { return decodeModbusTransparentPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -355,11 +355,11 @@ function decodeUplink(input) { errors, }; } - errors.push("Device version not supported by this decoder"); + errors.push("DEVICE_VERSION_NOT_SUPPORTED"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -396,11 +396,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKNOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -436,11 +436,17 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + if (input.fPort === MODBUS_PORT) { + return decodeModbusPayload(input.bytes); + } + if (input.fPort === MODBUS_TP_PORT) { + return decodeModbusTransparentPayload(input.bytes); + } + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -476,11 +482,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -494,11 +500,11 @@ function decodeUplink(input) { errors, }; } - errors.push("Device version not supported by this decoder"); + errors.push("DEVICE_VERSION_NOT_SUPPORTED"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -535,11 +541,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -575,11 +581,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -615,11 +621,11 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("not a valid port"); + errors.push("INVALID_PORT"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -633,11 +639,11 @@ function decodeUplink(input) { errors, }; } - errors.push("Device version not supported by this decoder"); + errors.push("DEVICE_VERSION_NOT_SUPPORTED"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -651,11 +657,11 @@ function decodeUplink(input) { errors, }; } - errors.push("Device ID not supported by this decoder"); + errors.push("DEVICE_ID_NOT_SUPPORTED"); return { data: { port: input.fPort, - portFunction: "unknown", + portFunction: "UNKOWN", payloadLength: input.bytes.length, payload: { device: deviceHeader, @@ -852,13 +858,7 @@ function decodeFixedDataPayload(data) { obj.payload = { device: deviceHeader, - data: { - timestamp: {}, - digitalInputs: {}, - analogInputs: {}, - counterInputs: {}, - temperatureInputs: {}, - }, + data: {}, }; obj.payload.data.timestamp = decodeTimestamp( @@ -963,7 +963,7 @@ function decodeDiDataPayload(data) { do { if ((data[pointer] & 0xf0) === OBJECT_TYPE_DI) { obj.payload.data.digitalInputs.push({ - type: "singlePointInfo", + type: "SINGLE_POINT_INFO", id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), blocked: Boolean(data[pointer + 1] & 0x04), @@ -975,7 +975,7 @@ function decodeDiDataPayload(data) { }); } else if ((data[pointer] & 0xf0) === OBJECT_TYPE_DBL) { obj.payload.data.digitalInputs.push({ - type: "doublePointInfo", + type: "DOUBLE_POINT_INFO", id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), blocked: Boolean(data[pointer + 1] & 0x04), @@ -1022,17 +1022,13 @@ function decodeAiDataPayload(data) { if ((data[pointer] & 0xf0) === OBJECT_TYPE_AI) { // AI Type obj.payload.data.analogInputs.push({ - info: { - type: "analogValue", - id: data[pointer] & 0x0f, - }, + type: "ANALOG_VALUE", + id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), - status: { - invalid: Boolean(data[pointer + 1] & 0x08), - overflow: Boolean(data[pointer + 1] & 0x04), - limit2: Boolean(data[pointer + 1] & 0x02), - limit1: Boolean(data[pointer + 1] & 0x01), - }, + invalid: Boolean(data[pointer + 1] & 0x08), + overflow: Boolean(data[pointer + 1] & 0x04), + limit2: Boolean(data[pointer + 1] & 0x02), + limit1: Boolean(data[pointer + 1] & 0x01), value: decToInt(data[pointer + 3] + (data[pointer + 2] << 8)), timestamp: addTimeToTimestamp( timestampAbsolute.unix, @@ -1042,17 +1038,13 @@ function decodeAiDataPayload(data) { } else if ((data[pointer] & 0xf0) === OBJECT_TYPE_TEMP) { // TEMP Type obj.payload.data.analogInputs.push({ - info: { - type: "Temperature", - id: data[pointer] & 0x0f, - }, + type: "TEMPERATURE_VALUE", + id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), - status: { - invalid: Boolean(data[pointer + 1] & 0x08), - overflow: Boolean(data[pointer + 1] & 0x04), - limit2: Boolean(data[pointer + 1] & 0x02), - limit1: Boolean(data[pointer + 1] & 0x01), - }, + invalid: Boolean(data[pointer + 1] & 0x08), + overflow: Boolean(data[pointer + 1] & 0x04), + limit2: Boolean(data[pointer + 1] & 0x02), + limit1: Boolean(data[pointer + 1] & 0x01), value: decToInt(data[pointer + 3] + (data[pointer + 2] << 8)) / 100, timestamp: addTimeToTimestamp( timestampAbsolute.unix, @@ -1096,16 +1088,13 @@ function decodeCntDataPayload(data) { pointer += 4; for (let i = 0; i < objectCount; i++) { obj.payload.data.counters.push({ - info: { - type: (data[pointer] & 0xf0) === 0x50 ? "counterdiff" : "counter", - id: data[pointer] & 0x0f, - }, + type: + (data[pointer] & 0xf0) === 0x50 ? "COUNTER_DIFFERENCE" : "COUNTER", + id: data[pointer] & 0x0f, cot: decodeCot(data[pointer + 1] & 0xf0), - status: { - overflow: Boolean(data[pointer + 1] & 0x01), - reset: Boolean(data[pointer + 1] & 0x02), - limit: Boolean(data[pointer + 1] & 0x04), - }, + overflow: Boolean(data[pointer + 1] & 0x01), + reset: Boolean(data[pointer + 1] & 0x02), + limit: Boolean(data[pointer + 1] & 0x04), timestamp: timestampCommon, value: data[pointer + 4] + @@ -2399,25 +2388,33 @@ function decodeModbusPayload(data) { obj.payload = { device: deviceHeader, - datapoints: [], + datapoints: {}, }; - - do { - obj.payload.datapoints.push({ - state: decodeModbusState((data[pointer] & 0xf0) >> 4), + while (pointer <= data.length - 5) { + // there must be at leased 5 additional bytes in the payload (state(=1) + timestamp(=4) + const dpErrorCode = (data[pointer] & 0xf0) >> 4; + const keyName = `dp_${(data[pointer] & 0x0f) + .toString(10) + .padStart(2, "0")}`; + obj.payload.datapoints[keyName] = { + errorVerbose: decodeModbusState(dpErrorCode), + errorCode: dpErrorCode, index: data[pointer] & 0x0f, timestamp: decodeTimestamp(data.slice(pointer + 1, pointer + 5)), registers: [], - }); - - for (let i = 0; i < data[pointer + 5] * 2; i++) { - obj.payload.datapoints[obj.payload.datapoints.length - 1].registers.push( - data[pointer + 6 + i], - ); + }; + pointer += 5; + // datenlength & Registers only present if no error!! + if (dpErrorCode === 0) { + const regCount = data[pointer]; + for (let i = 0; i < regCount; i++) { + obj.payload.datapoints[keyName].registers.push( + (data[pointer + 1 + 2 * i] << 8) + data[pointer + 2 + 2 * i], + ); + } + pointer += 1 + regCount * 2; } - - pointer += 1 + 4 + 1 + data[pointer + 5] * 2; - } while (pointer - 1 < data.length - 1); + } return { data: obj, @@ -2430,7 +2427,7 @@ function decodeModbusTransparentPayload(data) { const warnings = []; obj.port = MODBUS_PORT; - obj.portFunction = "MODBUS TRANSPARENT"; + obj.portFunction = "MODBUS_TRANSPARENT"; obj.payloadLength = data.length; obj.decoder = { @@ -2444,7 +2441,7 @@ function decodeModbusTransparentPayload(data) { obj.payload = { command: { - slave_adress: data[pointer], + slaveAdress: data[pointer], fc: data[pointer + 1], answer: [], }, @@ -2533,9 +2530,9 @@ function consume(event) { }); const { device } = decoded.data.payload; - const type = decoded.data.portFunction; // FIXED_DATA + const type = decoded.data.portFunction; const { data } = decoded.data.payload; - const { warnings } = decoded; + const { errors } = decoded; switch (type) { case "FIXED_DATA": @@ -2549,50 +2546,120 @@ function consume(event) { emit("sample", { data: data[key], topic: key }); }); break; - case "FIXED_DATA": + case "DI_DATA": + data.digitalInputs.forEach((dataPoint) => { + let result = {}; + result.limit = dataPoint.cot.limit; + result.event = dataPoint.cot.event; + result.interrogation = dataPoint.cot.interrogation; + result.cyclic = dataPoint.cot.cyclic; + delete dataPoint.cot; + + // Timestamp + const { timestamp } = dataPoint; + delete dataPoint.timestamp; + + result = Object.assign(result, dataPoint); + + emit("sample", { + data: result, + topic: "point_info", + timestamp, + }); + }); break; - case "FIXED_DATA": + case "AI_DATA": + data.analogInputs.forEach((dataPoint) => { + const result = {}; + result.limit = dataPoint.cot.limit; + result.event = dataPoint.cot.event; + result.interrogation = dataPoint.cot.interrogation; + result.cyclic = dataPoint.cot.cyclic; + delete dataPoint.cot; + + // Timestamp + const { timestamp } = dataPoint; + delete dataPoint.timestamp; + + dataPoint = Object.assign(result, dataPoint); + + emit("sample", { data: result, topic: "analog_input_data", timestamp }); + }); break; - case "FIXED_DATA": + case "CNT_DATA": + data.digitalInputs.forEach((dataPoint) => { + const result = {}; + result.limit = dataPoint.cot.limit; + result.event = dataPoint.cot.event; + result.interrogation = dataPoint.cot.interrogation; + result.cyclic = dataPoint.cot.cyclic; + delete dataPoint.cot; + + // Timestamp + const { timestamp } = dataPoint; + delete dataPoint.timestamp; + + dataPoint = Object.assign(result, dataPoint); + + emit("sample", { data: result, topic: "count_data", timestamp }); + }); break; - case "FIXED_DATA": + case "MODBUS": { + const { datapoints } = decoded.data.payload; + Object.keys(datapoints).forEach((key) => { + let result = {}; + result.modbusId = key; + // Timestamp + const { timestamp } = datapoints[key]; + delete dataPoint.timestamp; + result = Object.assign(result, datapoints[key]); + + emit("sample", { data: result, topic: "modbus", timestamp }); + }); + break; + } + case "MODBUS_TRANSPARENT": { + const { command } = decoded.data.payload; + emit("sample", { data: command, topic: "modbus_transparent" }); + break; + } + case "TIMESYNC": + emit("sample", { data: data.data, topic: "time_sync" }); + break; + case "CONFIG": + // Could be singular datapoints instead of an array. + emit("sample", { + data: { parameters: data.parameters }, + topic: "configuration", + }); + break; + case "INFO": + // Empty + break; + case "GPS": + emit("sample", { data: data.coordinates, topic: "gps" }); + // Empty + break; + case "PING": + // Empty + break; + case "UNKNOWN": + // Empty break; - default: break; } - // Digital inputs - for (let i = 0; i < data.digitalInputs.length; i++) { - const digitalInputs = {}; - const digital = data.digitalInputs[i]; - - digitalInputs.inputNr = digital.info.id; - digitalInputs.limit = digital.cot.limit; - digitalInputs.event = digital.cot.event; - digitalInputs.interrogation = digital.cot.interrogation; - digitalInputs.cyclic = digital.cot.cyclic; - - digitalInputs.blocked = digital.status.blocked; - digitalInputs.state = digital.status.state; - - const timestamp = new Date(digital.timestamp.string); - - emit("sample", { - data: digitalInputs, - topic: "digital", - timestamp, - }); - } - // Lifecycle const lifecycle = device.deviceStatus; - lifecycle.batteryLevel = Number(device.batteryLevel.replace(/\D/g, "")); + lifecycle.batteryLevel = device.batteryLevel; emit("sample", { data: lifecycle, topic: "lifecycle" }); - // Warnings - if (warnings.length > 0) { - emit("sample", { data: warnings, topic: "warnings" }); + // Errors + if (errors !== undefined) { + if (errors.length > 0) { + emit("sample", { data: { errors }, topic: "error" }); + } } } diff --git a/types/comtac/Cluey/uplink.spec.js b/types/comtac/Cluey/uplink.spec.js index cc05814b..ee8c3105 100644 --- a/types/comtac/Cluey/uplink.spec.js +++ b/types/comtac/Cluey/uplink.spec.js @@ -5,16 +5,16 @@ const utils = require("test-utils"); const { assert } = chai; -describe("Comtac Cluey KM Uplink", () => { - let digitalSchema = null; +describe("Comtac Cluey Uplink", () => { + let digitalInputsSchema = null; let consume = null; before((done) => { const script = rewire("./uplink.js"); consume = utils.init(script); utils - .loadSchema(`${__dirname}/digital.schema.json`) + .loadSchema(`${__dirname}/digital_inputs.schema.json`) .then((parsedSchema) => { - digitalSchema = parsedSchema; + digitalInputsSchema = parsedSchema; done(); }); }); @@ -29,8 +29,18 @@ describe("Comtac Cluey KM Uplink", () => { }); }); + let pointInfoSchema = null; + before((done) => { + utils + .loadSchema(`${__dirname}/point_info.schema.json`) + .then((parsedSchema) => { + pointInfoSchema = parsedSchema; + done(); + }); + }); + describe("consume()", () => { - it("should decode the Comtac Cluey KM payload", () => { + it("should decode the Comtac Cluey point_info payload", () => { const data = { data: { port: 20, @@ -44,16 +54,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 1); + assert.equal(value.data.id, 1); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -61,16 +71,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 2); + assert.equal(value.data.id, 2); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -78,16 +88,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 3); + assert.equal(value.data.id, 3); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -95,16 +105,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 4); + assert.equal(value.data.id, 4); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -112,16 +122,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 5); + assert.equal(value.data.id, 5); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -129,16 +139,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 6); + assert.equal(value.data.id, 6); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -146,16 +156,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 7); + assert.equal(value.data.id, 7); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { @@ -163,16 +173,16 @@ describe("Comtac Cluey KM Uplink", () => { assert.isNotNull(value); assert.typeOf(value.data, "object"); - assert.equal(value.topic, "digital"); + assert.equal(value.topic, "point_info"); assert.equal(value.data.blocked, false); assert.equal(value.data.cyclic, false); assert.equal(value.data.event, false); - assert.equal(value.data.inputNr, 8); + assert.equal(value.data.id, 8); assert.equal(value.data.interrogation, true); assert.equal(value.data.limit, false); - assert.equal(value.data.state, 1); + assert.equal(value.data.type, "SINGLE_POINT_INFO"); - utils.validateSchema(value.data, digitalSchema, { throwError: true }); + utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); utils.expectEmits((type, value) => { From fb93a4a00c537bde68b4d566e2ea1c3c4233c3e6 Mon Sep 17 00:00:00 2001 From: j2 Date: Wed, 11 Oct 2023 17:32:02 +0200 Subject: [PATCH 03/10] Added multiple tests --- .../Cluey/analog_input_data.schema.json | 91 ------ types/comtac/Cluey/uplink.js | 18 +- types/comtac/Cluey/uplink.spec.js | 264 ++++++++++++++++++ 3 files changed, 274 insertions(+), 99 deletions(-) delete mode 100644 types/comtac/Cluey/analog_input_data.schema.json diff --git a/types/comtac/Cluey/analog_input_data.schema.json b/types/comtac/Cluey/analog_input_data.schema.json deleted file mode 100644 index 1bc23504..00000000 --- a/types/comtac/Cluey/analog_input_data.schema.json +++ /dev/null @@ -1,91 +0,0 @@ -{ - "$id": "https://akenza.io/comtac/cluey/analog_input_data.schema.json", - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "processingType": "uplink_decoder", - "topic": "analog_input_data", - "title": "Analog Input Data", - "properties": { - "limit": { - "title": "Limit", - "description": "Limit", - "type": "boolean", - "hideFromKpis": true - }, - "event": { - "title": "Event", - "description": "Event", - "type": "boolean", - "hideFromKpis": true - }, - "interrogation": { - "title": "Interrogation", - "description": "Interrogation", - "type": "boolean", - "hideFromKpis": true - }, - "cyclic": { - "title": "Cyclic", - "description": "Cyclic", - "type": "boolean", - "hideFromKpis": true - }, - - "type": { - "title": "Type", - "description": "Type", - "type": "string", - "enum": ["ANALOG_VALUE", "TEMPERATURE_VALUE"], - "hideFromKpis": true - }, - "id": { - "title": "ID", - "description": "ID", - "type": "number", - "hideFromKpis": true - }, - "invalid": { - "title": "Invalid", - "description": "Invalid", - "type": "boolean", - "hideFromKpis": true - }, - "overflow": { - "title": "Overflow", - "description": "Overflow", - "type": "boolean", - "hideFromKpis": true - }, - "limit1": { - "title": "Limit 1", - "description": "Limit 1", - "type": "boolean", - "hideFromKpis": true - }, - "limit2": { - "title": "Limit 2", - "description": "Limit 2", - "type": "boolean", - "hideFromKpis": true - }, - "value": { - "title": "Value", - "description": "Value", - "type": "number", - "hideFromKpis": true - } - }, - "required": [ - "limit", - "event", - "interrogation", - "cyclic", - "type", - "id", - "invalid", - "overflow", - "limit1", - "limit2", - "value" - ] -} diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index ea60c9c1..8c45418a 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -1019,11 +1019,11 @@ function decodeAiDataPayload(data) { pointer += 4; do { + const id = data[pointer] & 0x0f; if ((data[pointer] & 0xf0) === OBJECT_TYPE_AI) { // AI Type obj.payload.data.analogInputs.push({ - type: "ANALOG_VALUE", - id: data[pointer] & 0x0f, + topic: `analog_input_${id}`, cot: decodeCot(data[pointer + 1] & 0xf0), invalid: Boolean(data[pointer + 1] & 0x08), overflow: Boolean(data[pointer + 1] & 0x04), @@ -1038,8 +1038,7 @@ function decodeAiDataPayload(data) { } else if ((data[pointer] & 0xf0) === OBJECT_TYPE_TEMP) { // TEMP Type obj.payload.data.analogInputs.push({ - type: "TEMPERATURE_VALUE", - id: data[pointer] & 0x0f, + topic: `temperature_input_${id}`, cot: decodeCot(data[pointer + 1] & 0xf0), invalid: Boolean(data[pointer + 1] & 0x08), overflow: Boolean(data[pointer + 1] & 0x04), @@ -2536,6 +2535,7 @@ function consume(event) { switch (type) { case "FIXED_DATA": + delete data.timestamp; Object.keys(data).forEach((key) => { data[key].limit = data[key].cot.limit; data[key].event = data[key].cot.event; @@ -2570,20 +2570,22 @@ function consume(event) { break; case "AI_DATA": data.analogInputs.forEach((dataPoint) => { + const { topic } = dataPoint; + const { timestamp } = dataPoint; + const result = {}; result.limit = dataPoint.cot.limit; result.event = dataPoint.cot.event; result.interrogation = dataPoint.cot.interrogation; result.cyclic = dataPoint.cot.cyclic; - delete dataPoint.cot; - // Timestamp - const { timestamp } = dataPoint; + delete dataPoint.cot; + delete dataPoint.topic; delete dataPoint.timestamp; dataPoint = Object.assign(result, dataPoint); - emit("sample", { data: result, topic: "analog_input_data", timestamp }); + emit("sample", { data: result, topic, timestamp }); }); break; case "CNT_DATA": diff --git a/types/comtac/Cluey/uplink.spec.js b/types/comtac/Cluey/uplink.spec.js index ee8c3105..6aaa21af 100644 --- a/types/comtac/Cluey/uplink.spec.js +++ b/types/comtac/Cluey/uplink.spec.js @@ -39,7 +39,122 @@ describe("Comtac Cluey Uplink", () => { }); }); + let analogInput5Schema = null; + before((done) => { + utils + .loadSchema(`${__dirname}/analog_input_5.schema.json`) + .then((parsedSchema) => { + analogInput5Schema = parsedSchema; + done(); + }); + }); + + let analogInput6Schema = null; + before((done) => { + utils + .loadSchema(`${__dirname}/analog_input_6.schema.json`) + .then((parsedSchema) => { + analogInput6Schema = parsedSchema; + done(); + }); + }); + + let analogInput7Schema = null; + before((done) => { + utils + .loadSchema(`${__dirname}/analog_input_7.schema.json`) + .then((parsedSchema) => { + analogInput7Schema = parsedSchema; + done(); + }); + }); + + let analogInput8Schema = null; + before((done) => { + utils + .loadSchema(`${__dirname}/analog_input_8.schema.json`) + .then((parsedSchema) => { + analogInput8Schema = parsedSchema; + done(); + }); + }); + describe("consume()", () => { + /* + it("should decode the Comtac Cluey AI_DATA payload", () => { + const data = { + data: { + port: 23, + payloadHex: "1103040163d033a755801ee30000568900000000", + }, + }; + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_5"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, false); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, false); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 7907); + + utils.validateSchema(value.data, analogInput5Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_6"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, true); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, true); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 0); + + utils.validateSchema(value.data, analogInput6Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "lifecycle"); + assert.equal(value.data.batteryLevel, 0); + assert.equal(value.data.batteryPowered, false); + assert.equal(value.data.bufferOverflow, false); + assert.equal(value.data.configurationError, false); + assert.equal(value.data.confirmationTimeout, false); + assert.equal(value.data.deviceRestarted, false); + assert.equal(value.data.lowSupplyVoltage, false); + assert.equal(value.data.timeSynced, true); + assert.equal(value.data.txCreditsConsumed, false); + + utils.validateSchema(value.data, lifecycleSchema, { + throwError: true, + }); + }); + + consume(data); + }); + it("should decode the Comtac Cluey point_info payload", () => { const data = { data: { @@ -204,6 +319,155 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, lifecycleSchema, { throwError: true }); }); + consume(data); + }); + */ + it("should decode the Comtac Cluey interval data payload", () => { + const data = { + data: { + port: 3, + payloadHex: + "110304bc64c2376680000300000000000000000000000000000000000000005588000000568800000057880000005888000000", + }, + }; + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "digital_inputs"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.limit, false); + assert.equal(value.data.digitalInput1, true); + assert.equal(value.data.digitalInput2, true); + assert.equal(value.data.digitalInput3, false); + assert.equal(value.data.digitalInput4, false); + assert.equal(value.data.digitalInput5, false); + assert.equal(value.data.digitalInput6, false); + assert.equal(value.data.digitalInput7, false); + assert.equal(value.data.digitalInput8, false); + assert.equal(value.data.digitalInput9, false); + assert.equal(value.data.digitalInput10, false); + assert.equal(value.data.digitalInput11, false); + assert.equal(value.data.digitalInput12, false); + assert.equal(value.data.digitalInput13, false); + assert.equal(value.data.digitalInput14, false); + assert.equal(value.data.digitalInput15, false); + assert.equal(value.data.digitalInput16, false); + + utils.validateSchema(value.data, digitalInputsSchema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_5"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, true); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, false); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 0); + + utils.validateSchema(value.data, analogInput5Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_6"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, true); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, false); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 0); + + utils.validateSchema(value.data, analogInput6Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_7"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, true); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, false); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 0); + + utils.validateSchema(value.data, analogInput7Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "analog_input_8"); + assert.equal(value.data.cyclic, true); + assert.equal(value.data.event, false); + assert.equal(value.data.interrogation, false); + assert.equal(value.data.invalid, true); + assert.equal(value.data.limit, false); + assert.equal(value.data.limit1, false); + assert.equal(value.data.limit2, false); + assert.equal(value.data.overflow, false); + assert.equal(value.data.value, 0); + + utils.validateSchema(value.data, analogInput8Schema, { + throwError: true, + }); + }); + + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "lifecycle"); + assert.equal(value.data.batteryLevel, 74); + assert.equal(value.data.batteryPowered, false); + assert.equal(value.data.bufferOverflow, false); + assert.equal(value.data.configurationError, false); + assert.equal(value.data.confirmationTimeout, false); + assert.equal(value.data.deviceRestarted, false); + assert.equal(value.data.lowSupplyVoltage, false); + assert.equal(value.data.timeSynced, true); + assert.equal(value.data.txCreditsConsumed, false); + + utils.validateSchema(value.data, lifecycleSchema, { + throwError: true, + }); + }); + consume(data); }); }); From e96e1eadf7131fa9ca753fba3641b003b1198027 Mon Sep 17 00:00:00 2001 From: j2 Date: Tue, 17 Oct 2023 13:43:24 +0200 Subject: [PATCH 04/10] Removed timestamp from sample --- types/comtac/Cluey/uplink.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index 8c45418a..470eebc2 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -2564,7 +2564,6 @@ function consume(event) { emit("sample", { data: result, topic: "point_info", - timestamp, }); }); break; @@ -2585,7 +2584,7 @@ function consume(event) { dataPoint = Object.assign(result, dataPoint); - emit("sample", { data: result, topic, timestamp }); + emit("sample", { data: result, topic }); }); break; case "CNT_DATA": @@ -2603,7 +2602,7 @@ function consume(event) { dataPoint = Object.assign(result, dataPoint); - emit("sample", { data: result, topic: "count_data", timestamp }); + emit("sample", { data: result, topic: "count_data" }); }); break; case "MODBUS": { @@ -2616,7 +2615,7 @@ function consume(event) { delete dataPoint.timestamp; result = Object.assign(result, datapoints[key]); - emit("sample", { data: result, topic: "modbus", timestamp }); + emit("sample", { data: result, topic: "modbus" }); }); break; } From b9e1542b2af0c556753314761ee803ccae676be6 Mon Sep 17 00:00:00 2001 From: j2 Date: Thu, 19 Oct 2023 14:50:45 +0200 Subject: [PATCH 05/10] Fixed timestamps --- lib/test/utils.js | 7 ++++++- types/comtac/Cluey/uplink.js | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/lib/test/utils.js b/lib/test/utils.js index 1d333880..c384af27 100644 --- a/lib/test/utils.js +++ b/lib/test/utils.js @@ -2,7 +2,12 @@ const fs = require("fs"); const chai = require("chai"); const request = require("sync-request"); const { validate } = require("jsonschema"); -require('dotenv').config() + +try { + require("dotenv").config(); +} catch (ex) { + console.log("No dotenv file"); +} const { assert } = chai; const bits = require("bits"); diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index 470eebc2..1d43d44b 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -2556,7 +2556,7 @@ function consume(event) { delete dataPoint.cot; // Timestamp - const { timestamp } = dataPoint; + const timestamp = new Date(dataPoint.timestamp.unix * 1000); delete dataPoint.timestamp; result = Object.assign(result, dataPoint); @@ -2564,13 +2564,14 @@ function consume(event) { emit("sample", { data: result, topic: "point_info", + timestamp, }); }); break; case "AI_DATA": data.analogInputs.forEach((dataPoint) => { const { topic } = dataPoint; - const { timestamp } = dataPoint; + const timestamp = new Date(dataPoint.timestamp.unix * 1000); const result = {}; result.limit = dataPoint.cot.limit; @@ -2584,7 +2585,7 @@ function consume(event) { dataPoint = Object.assign(result, dataPoint); - emit("sample", { data: result, topic }); + emit("sample", { data: result, topic, timestamp }); }); break; case "CNT_DATA": @@ -2597,12 +2598,12 @@ function consume(event) { delete dataPoint.cot; // Timestamp - const { timestamp } = dataPoint; + const timestamp = new Date(dataPoint.timestamp.unix * 1000); delete dataPoint.timestamp; dataPoint = Object.assign(result, dataPoint); - emit("sample", { data: result, topic: "count_data" }); + emit("sample", { data: result, topic: "count_data", timestamp }); }); break; case "MODBUS": { @@ -2611,11 +2612,12 @@ function consume(event) { let result = {}; result.modbusId = key; // Timestamp - const { timestamp } = datapoints[key]; - delete dataPoint.timestamp; + const timestamp = new Date(datapoints[key].timestamp.unix * 1000); + + delete datapoints[key].timestamp; result = Object.assign(result, datapoints[key]); - emit("sample", { data: result, topic: "modbus" }); + emit("sample", { data: result, topic: "modbus", timestamp }); }); break; } @@ -2655,6 +2657,10 @@ function consume(event) { const lifecycle = device.deviceStatus; lifecycle.batteryLevel = device.batteryLevel; + if (lifecycle.batteryLevel === 0) { + delete lifecycle.batteryLevel; + } + emit("sample", { data: lifecycle, topic: "lifecycle" }); // Errors From 79bfa39b22d7d0409837aa9b4710721a6f56a4fb Mon Sep 17 00:00:00 2001 From: j2 Date: Wed, 25 Oct 2023 14:17:32 +0200 Subject: [PATCH 06/10] Added catch for unrealistic timestamps --- types/comtac/Cluey/lifecycle.schema.json | 3 +-- types/comtac/Cluey/uplink.js | 29 ++++++++++++++++++++---- types/comtac/Cluey/uplink.spec.js | 7 +++--- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/types/comtac/Cluey/lifecycle.schema.json b/types/comtac/Cluey/lifecycle.schema.json index 30854ce0..d5675240 100644 --- a/types/comtac/Cluey/lifecycle.schema.json +++ b/types/comtac/Cluey/lifecycle.schema.json @@ -57,7 +57,6 @@ } }, "required": [ - "batteryLevel", "batteryPowered", "bufferOverflow", "configurationError", @@ -67,4 +66,4 @@ "timeSynced", "txCreditsConsumed" ] -} \ No newline at end of file +} diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index 1d43d44b..030ecc26 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -2519,6 +2519,19 @@ function decodePingPayload(data) { }; } +function checkTimestamp(timestamp) { + let now = new Date(); + now = now.getTime(); + const sampleTime = timestamp.getTime(); + + if (sampleTime < now - 2629746000 || sampleTime > now) { + // Only give out data with a timestamp within a month + // Also if its in the future i will just use now + return new Date(); + } + return timestamp; +} + function consume(event) { const payload = event.data.payloadHex; const { port } = event.data; @@ -2556,7 +2569,9 @@ function consume(event) { delete dataPoint.cot; // Timestamp - const timestamp = new Date(dataPoint.timestamp.unix * 1000); + const timestamp = checkTimestamp( + new Date(dataPoint.timestamp.unix * 1000), + ); delete dataPoint.timestamp; result = Object.assign(result, dataPoint); @@ -2571,7 +2586,9 @@ function consume(event) { case "AI_DATA": data.analogInputs.forEach((dataPoint) => { const { topic } = dataPoint; - const timestamp = new Date(dataPoint.timestamp.unix * 1000); + const timestamp = checkTimestamp( + new Date(dataPoint.timestamp.unix * 1000), + ); const result = {}; result.limit = dataPoint.cot.limit; @@ -2598,7 +2615,9 @@ function consume(event) { delete dataPoint.cot; // Timestamp - const timestamp = new Date(dataPoint.timestamp.unix * 1000); + const timestamp = checkTimestamp( + new Date(dataPoint.timestamp.unix * 1000), + ); delete dataPoint.timestamp; dataPoint = Object.assign(result, dataPoint); @@ -2612,7 +2631,9 @@ function consume(event) { let result = {}; result.modbusId = key; // Timestamp - const timestamp = new Date(datapoints[key].timestamp.unix * 1000); + const timestamp = checkTimestamp( + new Date(datapoints[key].timestamp.unix * 1000), + ); delete datapoints[key].timestamp; result = Object.assign(result, datapoints[key]); diff --git a/types/comtac/Cluey/uplink.spec.js b/types/comtac/Cluey/uplink.spec.js index 6aaa21af..e2398347 100644 --- a/types/comtac/Cluey/uplink.spec.js +++ b/types/comtac/Cluey/uplink.spec.js @@ -80,7 +80,6 @@ describe("Comtac Cluey Uplink", () => { }); describe("consume()", () => { - /* it("should decode the Comtac Cluey AI_DATA payload", () => { const data = { data: { @@ -137,7 +136,6 @@ describe("Comtac Cluey Uplink", () => { assert.typeOf(value.data, "object"); assert.equal(value.topic, "lifecycle"); - assert.equal(value.data.batteryLevel, 0); assert.equal(value.data.batteryPowered, false); assert.equal(value.data.bufferOverflow, false); assert.equal(value.data.configurationError, false); @@ -154,7 +152,7 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); - + /* it("should decode the Comtac Cluey point_info payload", () => { const data = { data: { @@ -321,7 +319,7 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); - */ + /* it("should decode the Comtac Cluey interval data payload", () => { const data = { data: { @@ -470,5 +468,6 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); + */ }); }); From 05a261275ee350e7d7285fe8ffbbfb5678eb673a Mon Sep 17 00:00:00 2001 From: j2 Date: Fri, 27 Oct 2023 11:11:40 +0200 Subject: [PATCH 07/10] Changed according to comments and added changelog entry --- CHANGELOG.md | 16 +++++++++-- types/comtac/Cluey/analog_input_1.schema.json | 1 - types/comtac/Cluey/analog_input_2.schema.json | 1 - types/comtac/Cluey/analog_input_3.schema.json | 1 - types/comtac/Cluey/analog_input_4.schema.json | 1 - types/comtac/Cluey/analog_input_5.schema.json | 1 - types/comtac/Cluey/analog_input_6.schema.json | 1 - types/comtac/Cluey/analog_input_7.schema.json | 1 - types/comtac/Cluey/analog_input_8.schema.json | 1 - types/comtac/Cluey/count_data.schema.json | 1 - types/comtac/Cluey/gps.schema.json | 8 ++---- types/comtac/Cluey/point_info.schema.json | 1 - .../Cluey/temperature_input_1.schema.json | 1 - .../Cluey/temperature_input_2.schema.json | 1 - .../Cluey/temperature_input_3.schema.json | 1 - .../Cluey/temperature_input_4.schema.json | 1 - .../Cluey/temperature_input_5.schema.json | 1 - .../Cluey/temperature_input_6.schema.json | 1 - .../Cluey/temperature_input_7.schema.json | 1 - .../Cluey/temperature_input_8.schema.json | 1 - types/comtac/Cluey/uplink.js | 28 ++++++++++--------- 21 files changed, 31 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a06c2d50..5d95c7fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,12 +4,26 @@ All notable changes to this project will be documented in this file. --- +# [1.39.0] - 2023-10-27 + +### Added + +- Laiier - SevernWLD + +### Changed + +- Comtac - Cluey + # [1.38.0] - 2023-09-28 +### Added + - Nanothings - Nanotag # [1.38.0] - 2023-09-28 +### Added + - Integra - Aquastream - Enginko - EGK-LW22PLG - Enginko - MCF-LW12MET @@ -17,8 +31,6 @@ All notable changes to this project will be documented in this file. - Dragino - Gropoint Air - Dragino - Gropoint Air V1.1 -### Added - # [1.37.2] - 2023-08-30 ### Added diff --git a/types/comtac/Cluey/analog_input_1.schema.json b/types/comtac/Cluey/analog_input_1.schema.json index 764aaa7a..b0c3a196 100644 --- a/types/comtac/Cluey/analog_input_1.schema.json +++ b/types/comtac/Cluey/analog_input_1.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_2.schema.json b/types/comtac/Cluey/analog_input_2.schema.json index ce1944fa..dab1f87e 100644 --- a/types/comtac/Cluey/analog_input_2.schema.json +++ b/types/comtac/Cluey/analog_input_2.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_3.schema.json b/types/comtac/Cluey/analog_input_3.schema.json index c493b625..1a01cd28 100644 --- a/types/comtac/Cluey/analog_input_3.schema.json +++ b/types/comtac/Cluey/analog_input_3.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_4.schema.json b/types/comtac/Cluey/analog_input_4.schema.json index 19d9b230..01e9b2e1 100644 --- a/types/comtac/Cluey/analog_input_4.schema.json +++ b/types/comtac/Cluey/analog_input_4.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_5.schema.json b/types/comtac/Cluey/analog_input_5.schema.json index 4ff66746..8054924d 100644 --- a/types/comtac/Cluey/analog_input_5.schema.json +++ b/types/comtac/Cluey/analog_input_5.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_6.schema.json b/types/comtac/Cluey/analog_input_6.schema.json index 1c33581a..0fe1c3ec 100644 --- a/types/comtac/Cluey/analog_input_6.schema.json +++ b/types/comtac/Cluey/analog_input_6.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_7.schema.json b/types/comtac/Cluey/analog_input_7.schema.json index 5c1d3ee9..51163e0e 100644 --- a/types/comtac/Cluey/analog_input_7.schema.json +++ b/types/comtac/Cluey/analog_input_7.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/analog_input_8.schema.json b/types/comtac/Cluey/analog_input_8.schema.json index 6064b79b..f71fd055 100644 --- a/types/comtac/Cluey/analog_input_8.schema.json +++ b/types/comtac/Cluey/analog_input_8.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/count_data.schema.json b/types/comtac/Cluey/count_data.schema.json index 384c0b1f..5997f304 100644 --- a/types/comtac/Cluey/count_data.schema.json +++ b/types/comtac/Cluey/count_data.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "type": { "title": "Type", "description": "Type", diff --git a/types/comtac/Cluey/gps.schema.json b/types/comtac/Cluey/gps.schema.json index 97aafca0..9405ed4a 100644 --- a/types/comtac/Cluey/gps.schema.json +++ b/types/comtac/Cluey/gps.schema.json @@ -10,17 +10,13 @@ "title": "Latitude", "unit": "°", "type": "number", - "description": "Latitude", - "minimum": -3276.5, - "maximum": 3276.5 + "description": "Latitude" }, "longitude": { "title": "Longitude", "unit": "°", "type": "number", - "description": "Longitude", - "minimum": -3276.5, - "maximum": 3276.5 + "description": "Longitude" } }, "required": ["latitude", "longitude"] diff --git a/types/comtac/Cluey/point_info.schema.json b/types/comtac/Cluey/point_info.schema.json index bbb7f328..65fe6745 100644 --- a/types/comtac/Cluey/point_info.schema.json +++ b/types/comtac/Cluey/point_info.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "type": { "title": "Type", "description": "Type", diff --git a/types/comtac/Cluey/temperature_input_1.schema.json b/types/comtac/Cluey/temperature_input_1.schema.json index f3fd161e..be654659 100644 --- a/types/comtac/Cluey/temperature_input_1.schema.json +++ b/types/comtac/Cluey/temperature_input_1.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_2.schema.json b/types/comtac/Cluey/temperature_input_2.schema.json index a16f3af6..8ce71c07 100644 --- a/types/comtac/Cluey/temperature_input_2.schema.json +++ b/types/comtac/Cluey/temperature_input_2.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_3.schema.json b/types/comtac/Cluey/temperature_input_3.schema.json index c8e3ae94..0aea2007 100644 --- a/types/comtac/Cluey/temperature_input_3.schema.json +++ b/types/comtac/Cluey/temperature_input_3.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_4.schema.json b/types/comtac/Cluey/temperature_input_4.schema.json index eccd16c6..acda9f19 100644 --- a/types/comtac/Cluey/temperature_input_4.schema.json +++ b/types/comtac/Cluey/temperature_input_4.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_5.schema.json b/types/comtac/Cluey/temperature_input_5.schema.json index 1055c5c4..c173c929 100644 --- a/types/comtac/Cluey/temperature_input_5.schema.json +++ b/types/comtac/Cluey/temperature_input_5.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_6.schema.json b/types/comtac/Cluey/temperature_input_6.schema.json index c56860c0..594dae7b 100644 --- a/types/comtac/Cluey/temperature_input_6.schema.json +++ b/types/comtac/Cluey/temperature_input_6.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_7.schema.json b/types/comtac/Cluey/temperature_input_7.schema.json index 95f50e24..3ace4ac7 100644 --- a/types/comtac/Cluey/temperature_input_7.schema.json +++ b/types/comtac/Cluey/temperature_input_7.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/temperature_input_8.schema.json b/types/comtac/Cluey/temperature_input_8.schema.json index d1e888fd..86843b1a 100644 --- a/types/comtac/Cluey/temperature_input_8.schema.json +++ b/types/comtac/Cluey/temperature_input_8.schema.json @@ -30,7 +30,6 @@ "type": "boolean", "hideFromKpis": true }, - "invalid": { "title": "Invalid", "description": "Invalid", diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index 030ecc26..00842f1b 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -191,6 +191,7 @@ let deviceHeader = {}; function decodeUplink(input) { const warnings = []; const errors = []; + const invalidPort = "INVALID_PORT"; deviceHeader = decodeDeviceHeader(input.bytes); @@ -220,7 +221,7 @@ function decodeUplink(input) { if (input.fPort === PING_PORT) { return decodePingPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -257,7 +258,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -294,7 +295,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -337,7 +338,7 @@ function decodeUplink(input) { if (input.fPort === MODBUS_TP_PORT) { return decodeModbusTransparentPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -396,7 +397,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -442,7 +443,7 @@ function decodeUplink(input) { if (input.fPort === MODBUS_TP_PORT) { return decodeModbusTransparentPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -482,7 +483,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -541,7 +542,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -581,7 +582,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -621,7 +622,7 @@ function decodeUplink(input) { if (input.fPort === INFO_PORT) { return decodeInfoPayload(input.bytes); } - errors.push("INVALID_PORT"); + errors.push(invalidPort); return { data: { port: input.fPort, @@ -2523,10 +2524,11 @@ function checkTimestamp(timestamp) { let now = new Date(); now = now.getTime(); const sampleTime = timestamp.getTime(); + const secondsPerMonth = 2629746000; - if (sampleTime < now - 2629746000 || sampleTime > now) { - // Only give out data with a timestamp within a month - // Also if its in the future i will just use now + // Only give out data with a timestamp within a month + // Also if its in the future i will just use now + if (sampleTime < now - secondsPerMonth || sampleTime > now) { return new Date(); } return timestamp; From 27d02523972872d9e3430f8180ca39b19c886b0c Mon Sep 17 00:00:00 2001 From: j2 Date: Fri, 27 Oct 2023 15:03:50 +0200 Subject: [PATCH 08/10] Changed according to comments --- types/comtac/Cluey/event.schema.json | 31 +++++++++ types/comtac/Cluey/meta.json | 3 +- types/comtac/Cluey/uplink.js | 81 +++++++++++------------ types/comtac/Cluey/uplink.spec.js | 96 +++++++++++++++++++++++++++- 4 files changed, 165 insertions(+), 46 deletions(-) create mode 100644 types/comtac/Cluey/event.schema.json diff --git a/types/comtac/Cluey/event.schema.json b/types/comtac/Cluey/event.schema.json new file mode 100644 index 00000000..697ecdf4 --- /dev/null +++ b/types/comtac/Cluey/event.schema.json @@ -0,0 +1,31 @@ +{ + "$id": "https://akenza.io/comtac/cluey/event.schema.json", + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "processingType": "uplink_decoder", + "topic": "event", + "title": "Event", + "properties": { + "eventType": { + "title": "Event type", + "type": "string", + "description": "Event type", + "enum": [ + "FIXED_DATA", + "DI_DATA", + "AI_DATA", + "CNT_DATA", + "MODBUS", + "MODBUS_TRANSPARENT", + "TIMESYNC", + "CONFIG", + "INFO", + "GPS", + "PING", + "UNKNOWN" + ], + "hideFromKpis": true + } + }, + "required": ["eventType"] +} diff --git a/types/comtac/Cluey/meta.json b/types/comtac/Cluey/meta.json index 8f0d6ae3..c2ea04cf 100644 --- a/types/comtac/Cluey/meta.json +++ b/types/comtac/Cluey/meta.json @@ -43,7 +43,8 @@ "temperature_input_6", "temperature_input_7", "temperature_input_8", - "time_sync" + "time_sync", + "event" ], "encoding": "HEX", "connectivity": "LORA" diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index 00842f1b..e4e43f7f 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -2526,9 +2526,10 @@ function checkTimestamp(timestamp) { const sampleTime = timestamp.getTime(); const secondsPerMonth = 2629746000; - // Only give out data with a timestamp within a month - // Also if its in the future i will just use now + // Only output data with a timestamp not older than a month + // For future dates default to now if (sampleTime < now - secondsPerMonth || sampleTime > now) { + emit("log", { wrongTime: timestamp }); return new Date(); } return timestamp; @@ -2552,31 +2553,31 @@ function consume(event) { case "FIXED_DATA": delete data.timestamp; Object.keys(data).forEach((key) => { - data[key].limit = data[key].cot.limit; - data[key].event = data[key].cot.event; - data[key].interrogation = data[key].cot.interrogation; - data[key].cyclic = data[key].cot.cyclic; - delete data[key].cot; - - emit("sample", { data: data[key], topic: key }); + const result = Object.assign({}, data[key]); + result.limit = result.cot.limit; + result.event = result.cot.event; + result.interrogation = result.cot.interrogation; + result.cyclic = result.cot.cyclic; + delete result.cot; + + emit("sample", { data: result, topic: key }); }); break; case "DI_DATA": data.digitalInputs.forEach((dataPoint) => { - let result = {}; - result.limit = dataPoint.cot.limit; - result.event = dataPoint.cot.event; + const result = Object.assign({}, dataPoint); + result.limit = result.cot.limit; + result.event = result.cot.event; result.interrogation = dataPoint.cot.interrogation; result.cyclic = dataPoint.cot.cyclic; - delete dataPoint.cot; // Timestamp const timestamp = checkTimestamp( - new Date(dataPoint.timestamp.unix * 1000), + new Date(result.timestamp.unix * 1000), ); - delete dataPoint.timestamp; - result = Object.assign(result, dataPoint); + delete result.cot; + delete result.timestamp; emit("sample", { data: result, @@ -2592,37 +2593,33 @@ function consume(event) { new Date(dataPoint.timestamp.unix * 1000), ); - const result = {}; - result.limit = dataPoint.cot.limit; - result.event = dataPoint.cot.event; - result.interrogation = dataPoint.cot.interrogation; - result.cyclic = dataPoint.cot.cyclic; + const result = Object.assign({}, dataPoint); + result.limit = result.cot.limit; + result.event = result.cot.event; + result.interrogation = result.cot.interrogation; + result.cyclic = result.cot.cyclic; - delete dataPoint.cot; - delete dataPoint.topic; - delete dataPoint.timestamp; - - dataPoint = Object.assign(result, dataPoint); + delete result.cot; + delete result.topic; + delete result.timestamp; emit("sample", { data: result, topic, timestamp }); }); break; case "CNT_DATA": data.digitalInputs.forEach((dataPoint) => { - const result = {}; - result.limit = dataPoint.cot.limit; - result.event = dataPoint.cot.event; - result.interrogation = dataPoint.cot.interrogation; - result.cyclic = dataPoint.cot.cyclic; - delete dataPoint.cot; + const result = Object.assign({}, dataPoint); + result.limit = result.cot.limit; + result.event = result.cot.event; + result.interrogation = result.cot.interrogation; + result.cyclic = result.cot.cyclic; + delete result.cot; // Timestamp const timestamp = checkTimestamp( - new Date(dataPoint.timestamp.unix * 1000), + new Date(result.timestamp.unix * 1000), ); - delete dataPoint.timestamp; - - dataPoint = Object.assign(result, dataPoint); + delete result.timestamp; emit("sample", { data: result, topic: "count_data", timestamp }); }); @@ -2630,15 +2627,14 @@ function consume(event) { case "MODBUS": { const { datapoints } = decoded.data.payload; Object.keys(datapoints).forEach((key) => { - let result = {}; + const result = Object.assign({}, datapoints[key]); result.modbusId = key; + // Timestamp const timestamp = checkTimestamp( - new Date(datapoints[key].timestamp.unix * 1000), + new Date(result.timestamp.unix * 1000), ); - - delete datapoints[key].timestamp; - result = Object.assign(result, datapoints[key]); + delete result.timestamp; emit("sample", { data: result, topic: "modbus", timestamp }); }); @@ -2664,7 +2660,6 @@ function consume(event) { break; case "GPS": emit("sample", { data: data.coordinates, topic: "gps" }); - // Empty break; case "PING": // Empty @@ -2676,6 +2671,8 @@ function consume(event) { break; } + emit("sample", { data: { eventType: type }, topic: "event" }); + // Lifecycle const lifecycle = device.deviceStatus; lifecycle.batteryLevel = device.batteryLevel; diff --git a/types/comtac/Cluey/uplink.spec.js b/types/comtac/Cluey/uplink.spec.js index e2398347..be05b4d8 100644 --- a/types/comtac/Cluey/uplink.spec.js +++ b/types/comtac/Cluey/uplink.spec.js @@ -19,6 +19,14 @@ describe("Comtac Cluey Uplink", () => { }); }); + let eventSchema = null; + before((done) => { + utils.loadSchema(`${__dirname}/event.schema.json`).then((parsedSchema) => { + eventSchema = parsedSchema; + done(); + }); + }); + let lifecycleSchema = null; before((done) => { utils @@ -88,6 +96,10 @@ describe("Comtac Cluey Uplink", () => { }, }; + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -109,6 +121,10 @@ describe("Comtac Cluey Uplink", () => { }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -130,6 +146,19 @@ describe("Comtac Cluey Uplink", () => { }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "event"); + assert.equal(value.data.eventType, "AI_DATA"); + + utils.validateSchema(value.data, eventSchema, { + throwError: true, + }); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -152,7 +181,7 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); - /* + it("should decode the Comtac Cluey point_info payload", () => { const data = { data: { @@ -161,6 +190,12 @@ describe("Comtac Cluey Uplink", () => { "100128df5fee66011141000012410000134100001441000015410000164100001741000018410000", }, }; + const script = rewire("./uplink.js"); + consume = utils.init(script); + + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); utils.expectEmits((type, value) => { assert.equal(type, "sample"); @@ -179,6 +214,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -196,6 +235,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -213,6 +256,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -230,6 +277,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -247,6 +298,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -264,6 +319,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -281,6 +340,10 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "log"); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -298,6 +361,19 @@ describe("Comtac Cluey Uplink", () => { utils.validateSchema(value.data, pointInfoSchema, { throwError: true }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "event"); + assert.equal(value.data.eventType, "DI_DATA"); + + utils.validateSchema(value.data, eventSchema, { + throwError: true, + }); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -319,7 +395,7 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); - /* + it("should decode the Comtac Cluey interval data payload", () => { const data = { data: { @@ -328,6 +404,8 @@ describe("Comtac Cluey Uplink", () => { "110304bc64c2376680000300000000000000000000000000000000000000005588000000568800000057880000005888000000", }, }; + const script = rewire("./uplink.js"); + consume = utils.init(script); utils.expectEmits((type, value) => { assert.equal(type, "sample"); @@ -445,6 +523,19 @@ describe("Comtac Cluey Uplink", () => { }); }); + utils.expectEmits((type, value) => { + assert.equal(type, "sample"); + assert.isNotNull(value); + assert.typeOf(value.data, "object"); + + assert.equal(value.topic, "event"); + assert.equal(value.data.eventType, "FIXED_DATA"); + + utils.validateSchema(value.data, eventSchema, { + throwError: true, + }); + }); + utils.expectEmits((type, value) => { assert.equal(type, "sample"); assert.isNotNull(value); @@ -468,6 +559,5 @@ describe("Comtac Cluey Uplink", () => { consume(data); }); - */ }); }); From 06a713de6e6e7c325d8718c8ff2d6e32157ecd2a Mon Sep 17 00:00:00 2001 From: j2 Date: Fri, 27 Oct 2023 15:04:56 +0200 Subject: [PATCH 09/10] Changed eslintconfig to disable automated object spread --- .eslintrc.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.eslintrc.json b/.eslintrc.json index 8e3742a1..f3779e4a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -24,6 +24,7 @@ "object": true } ], + "prefer-object-spread": "off", "no-bitwise": "off", "no-plusplus": "off", "curly": "error", From 280dd7f39ee80313bb559fc3626492aabf1d5aea Mon Sep 17 00:00:00 2001 From: j2 Date: Fri, 27 Oct 2023 16:21:01 +0200 Subject: [PATCH 10/10] shortet Object assigns --- types/comtac/Cluey/uplink.js | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/types/comtac/Cluey/uplink.js b/types/comtac/Cluey/uplink.js index e4e43f7f..7017d748 100644 --- a/types/comtac/Cluey/uplink.js +++ b/types/comtac/Cluey/uplink.js @@ -2553,11 +2553,7 @@ function consume(event) { case "FIXED_DATA": delete data.timestamp; Object.keys(data).forEach((key) => { - const result = Object.assign({}, data[key]); - result.limit = result.cot.limit; - result.event = result.cot.event; - result.interrogation = result.cot.interrogation; - result.cyclic = result.cot.cyclic; + const result = Object.assign({}, data[key], data[key].cot); delete result.cot; emit("sample", { data: result, topic: key }); @@ -2565,18 +2561,13 @@ function consume(event) { break; case "DI_DATA": data.digitalInputs.forEach((dataPoint) => { - const result = Object.assign({}, dataPoint); - result.limit = result.cot.limit; - result.event = result.cot.event; - result.interrogation = dataPoint.cot.interrogation; - result.cyclic = dataPoint.cot.cyclic; + const result = Object.assign({}, dataPoint, dataPoint.cot); + delete result.cot; // Timestamp const timestamp = checkTimestamp( new Date(result.timestamp.unix * 1000), ); - - delete result.cot; delete result.timestamp; emit("sample", { @@ -2593,12 +2584,7 @@ function consume(event) { new Date(dataPoint.timestamp.unix * 1000), ); - const result = Object.assign({}, dataPoint); - result.limit = result.cot.limit; - result.event = result.cot.event; - result.interrogation = result.cot.interrogation; - result.cyclic = result.cot.cyclic; - + const result = Object.assign({}, dataPoint, dataPoint.cot); delete result.cot; delete result.topic; delete result.timestamp; @@ -2608,11 +2594,7 @@ function consume(event) { break; case "CNT_DATA": data.digitalInputs.forEach((dataPoint) => { - const result = Object.assign({}, dataPoint); - result.limit = result.cot.limit; - result.event = result.cot.event; - result.interrogation = result.cot.interrogation; - result.cyclic = result.cot.cyclic; + const result = Object.assign({}, dataPoint, dataPoint.cot); delete result.cot; // Timestamp