diff --git a/lib/payload.json b/lib/payload.json index 428f4c3d61..e13714211e 100644 --- a/lib/payload.json +++ b/lib/payload.json @@ -56,6 +56,11 @@ "format": "date-time", "description": "Date and time of the measurement (RFC3339)" }, + "battery": { + "type": "number", + "description": "Voltage (V)", + "minimum": 0 + }, "soil": { "type": "object", "properties": { @@ -99,6 +104,11 @@ "air": { "type": "object", "properties": { + "location": { + "type": "string", + "enum": ["indoor", "outdoor"], + "description": "Specifies whether the measurement was taken indoors or outdoors." + }, "temperature": { "description": "Air temperature (°C)", "$ref": "#/definitions/temperature" @@ -137,6 +147,55 @@ } }, "additionalProperties": false + }, + "water": { + "type": "object", + "properties": { + "leak": { + "type": "boolean", + "description": "Leak detected" + } + }, + "additionalProperties": false + }, + "action": { + "type": "object", + "properties": { + "motion": { + "type": "object", + "properties": { + "detected": { + "type": "boolean", + "description": "Motion detected" + }, + "count": { + "type": "number", + "description": "Number of motion events (count)" + } + }, + "additionalProperties": false + }, + "contactState": { + "type": "string", + "description": "State of a contact sensor", + "enum": ["OPEN", "CLOSED"] + } + }, + "additionalProperties": false + }, + "position": { + "type": "object", + "properties": { + "latitude": { + "type": "number", + "description": "Horizontal distance from equator (°)" + }, + "longitude": { + "type": "number", + "description": "Vertical distance from prime meridian (°)" + } + }, + "additionalProperties": false } }, "additionalProperties": false diff --git a/vendor/browan/tbdw100-codec.yaml b/vendor/browan/tbdw100-codec.yaml index dc4035d15d..676b0d264a 100644 --- a/vendor/browan/tbdw100-codec.yaml +++ b/vendor/browan/tbdw100-codec.yaml @@ -12,6 +12,14 @@ uplinkDecoder: status: 0 temperatureBoard: 21 time: 0 + normalizedOutput: + data: + - action: + motion: + detected: false + air: + temperature: 21 + battery: 3.6 - description: Unknown FPort input: fPort: 42 diff --git a/vendor/browan/tbdw100.js b/vendor/browan/tbdw100.js index 4edc6ebd79..a8f1e65616 100644 --- a/vendor/browan/tbdw100.js +++ b/vendor/browan/tbdw100.js @@ -24,3 +24,19 @@ function decodeUplink(input) { }; } } + +function normalizeUplink(input) { + return { + data: { + action: { + motion: { + detected: input.data.status > 0, + } + }, + air: { + temperature: input.data.temperatureBoard, + }, + battery: input.data.battery, + } + }; +} diff --git a/vendor/browan/tbms100-codec.yaml b/vendor/browan/tbms100-codec.yaml index 63a1c88d15..d294b1a0f1 100644 --- a/vendor/browan/tbms100-codec.yaml +++ b/vendor/browan/tbms100-codec.yaml @@ -12,6 +12,14 @@ uplinkDecoder: status: 1 temperatureBoard: 20 time: 4 + normalizedOutput: + data: + - action: + motion: + detected: true + air: + temperature: 20 + battery: 3.6 - description: Unknown FPort input: fPort: 42 diff --git a/vendor/browan/tbms100.js b/vendor/browan/tbms100.js index 64bc65693c..9953606462 100644 --- a/vendor/browan/tbms100.js +++ b/vendor/browan/tbms100.js @@ -24,3 +24,19 @@ function decodeUplink(input) { }; } } + +function normalizeUplink(input) { + return { + data: { + action: { + motion: { + detected: input.data.status > 0, + } + }, + air: { + temperature: input.data.temperatureBoard, + }, + battery: input.data.battery, + }, + }; +} diff --git a/vendor/dragino/index.yaml b/vendor/dragino/index.yaml index fb37db16b2..f71664b9a4 100644 --- a/vendor/dragino/index.yaml +++ b/vendor/dragino/index.yaml @@ -35,3 +35,4 @@ endDevices: - sw3l - lht52 - trackerd + - lwl03a diff --git a/vendor/dragino/lht52-codec.yaml b/vendor/dragino/lht52-codec.yaml index f268a0adfa..b18ff12e75 100644 --- a/vendor/dragino/lht52-codec.yaml +++ b/vendor/dragino/lht52-codec.yaml @@ -7,6 +7,25 @@ uplinkDecoder: bytes: [0x0B, 0x88, 0x01, 0x00, 0x25, 0x00, 0x01] output: data: { 'Bat_mV': 1, 'Firmware_Version': '8801', 'Freq_Band': 0, 'Sensor_Model': 11, 'Sub_Band': 37 } + normalizedOutput: + data: + - battery: 1 + + - description: Temperature & Humidity + input: + fPort: 2 + bytes: [0x08, 0xCD, 0x02, 0x20, 0x7F, 0xFF, 0x01, 0x61, 0xCD, 0x4E, 0xDD] + output: + data: { 'Ext': 1, 'Hum_SHT': 54.4, 'Systimestamp': 1640845021, 'TempC_DS': 327.67, 'TempC_SHT': 22.53 } + normalizedOutput: + data: + - air: + location: 'indoor' + temperature: 22.53 + relativeHumidity: 54.4 + - air: + location: 'outdoor' + temperature: 327.67 - description: Unknown FPort input: diff --git a/vendor/dragino/lht52.js b/vendor/dragino/lht52.js index 1f139a19a6..0c78189e89 100644 --- a/vendor/dragino/lht52.js +++ b/vendor/dragino/lht52.js @@ -67,4 +67,35 @@ function decodeUplink(input) { errors: ["unknown FPort"] } } -} \ No newline at end of file +} + +function normalizeUplink(input) { + var data = []; + + if (input.data.TempC_SHT) { + data.push({ + air: { + location: "indoor", + temperature: input.data.TempC_SHT, + relativeHumidity: input.data.Hum_SHT, + } + }); + } + + if (input.data.TempC_DS) { + data.push({ + air: { + location: "outdoor", + temperature: input.data.TempC_DS + } + }); + } + + if (input.data.Bat_mV) { + data.push({ + battery: input.data.Bat_mV + }); + } + + return { data: data }; +} diff --git a/vendor/dragino/lht65-codec.yaml b/vendor/dragino/lht65-codec.yaml index bcfdd9d45e..cf0df18be6 100644 --- a/vendor/dragino/lht65-codec.yaml +++ b/vendor/dragino/lht65-codec.yaml @@ -7,6 +7,16 @@ uplinkDecoder: bytes: [0xCB, 0xF6, 0x0B, 0x0D, 0x03, 0x76, 0x01, 0x0A, 0xDD, 0x7F, 0xFF] output: data: { 'BatV': 3.062, 'Bat_status': 3, 'Ext_sensor': 'Temperature Sensor', 'Hum_SHT': 88.6, 'TempC_DS': 27.81, 'TempC_SHT': 28.29 } + normalizedOutput: + data: + - air: + location: 'indoor' + temperature: 28.29 + relativeHumidity: 88.6 + - air: + location: 'outdoor' + temperature: 27.81 + battery: 3.062 - description: Unknown FPort input: diff --git a/vendor/dragino/lht65.js b/vendor/dragino/lht65.js index 5a48beaa10..76cad8a068 100644 --- a/vendor/dragino/lht65.js +++ b/vendor/dragino/lht65.js @@ -99,4 +99,25 @@ default: } -} \ No newline at end of file +} + +function normalizeUplink(input) { + return { + data: [ + { + air: { + location: "indoor", + temperature: input.data.TempC_SHT, + relativeHumidity: input.data.Hum_SHT, + } + }, + { + air: { + location: "outdoor", + temperature: input.data.TempC_DS, + }, + battery: input.data.BatV + } + ] + }; +} diff --git a/vendor/dragino/lse01-codec.yaml b/vendor/dragino/lse01-codec.yaml index aa14041666..d64df580bd 100644 --- a/vendor/dragino/lse01-codec.yaml +++ b/vendor/dragino/lse01-codec.yaml @@ -7,7 +7,15 @@ uplinkDecoder: bytes: [0xCE, 0x29, 0x00, 0xF1, 0x07, 0xA5, 0x09, 0x9B, 0x6E, 0x28, 0x90] output: data: { 'Bat': 3.625, 'TempC_DS18B20': '24.1', 'conduct_SOIL': 28200, 'temp_SOIL': '24.59', 'water_SOIL': '19.57' } - + normalizedOutput: + data: + - air: + temperature: 24.1 + soil: + temperature: 24.59 + moisture: 19.57 + ec: 28.2 + battery: 3.625 - description: Unknown FPort input: fPort: 42 diff --git a/vendor/dragino/lse01.js b/vendor/dragino/lse01.js index 76086ec091..bc906fb882 100644 --- a/vendor/dragino/lse01.js +++ b/vendor/dragino/lse01.js @@ -32,4 +32,20 @@ switch (input.fPort) { errors: ["unknown FPort"] } } -} \ No newline at end of file +} + +function normalizeUplink(input) { + return { + data: { + air: { + temperature: Number(input.data.TempC_DS18B20), + }, + soil: { + temperature: Number(input.data.temp_SOIL), + moisture: Number(input.data.water_SOIL), + ec: input.data.conduct_SOIL / 1000, + }, + battery: input.data.Bat, + } + }; +} diff --git a/vendor/dragino/lsn50-v2-codec.yaml b/vendor/dragino/lsn50-v2-codec.yaml index 2da95cb942..141944d640 100644 --- a/vendor/dragino/lsn50-v2-codec.yaml +++ b/vendor/dragino/lsn50-v2-codec.yaml @@ -7,6 +7,14 @@ uplinkDecoder: bytes: [0x0B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x05] output: data: { 'ADC_CH0V': 0, 'BatV': 2.9, 'Digital_IStatus': 'L', 'Door_status': 'OPEN', 'EXTI_Trigger': 'FALSE', 'Hum_SHT': 51.7, 'TempC1': 0, 'TempC_SHT': 25.2, 'Work_mode': 'IIC' } + normalizedOutput: + data: + - air: + temperature: 25.2 + relativeHumidity: 51.7 + action: + contactState: 'OPEN' + battery: 2.9 - description: Unknown FPort input: diff --git a/vendor/dragino/lsn50-v2.js b/vendor/dragino/lsn50-v2.js index 49b6a9a761..c26628505c 100644 --- a/vendor/dragino/lsn50-v2.js +++ b/vendor/dragino/lsn50-v2.js @@ -196,4 +196,19 @@ default: errors: ["unknown FPort"] } } -} \ No newline at end of file +} + +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.TempC_SHT, + relativeHumidity: input.data.Hum_SHT, + }, + action: { + contactState: input.data.Door_status === "CLOSE" ? "CLOSED" : input.data.Door_status === "OPEN" ? "OPEN" : undefined + }, + battery: input.data.BatV, + } + }; +} diff --git a/vendor/dragino/lsn50v2-s31-codec.yaml b/vendor/dragino/lsn50v2-s31-codec.yaml index 4bf4c13e62..e8607533d9 100644 --- a/vendor/dragino/lsn50v2-s31-codec.yaml +++ b/vendor/dragino/lsn50v2-s31-codec.yaml @@ -7,7 +7,14 @@ uplinkDecoder: bytes: [0x0B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x02, 0x05] output: data: { 'ADC_CH0V': 0, 'BatV': 2.9, 'Digital_IStatus': 'L', 'Door_status': 'OPEN', 'EXTI_Trigger': 'FALSE', 'Hum_SHT': 51.7, 'TempC1': 0, 'TempC_SHT': 25.2, 'Work_mode': 'IIC' } - + normalizedOutput: + data: + - air: + temperature: 25.2 + relativeHumidity: 51.7 + action: + contactState: 'OPEN' + battery: 2.9 - description: Unknown FPort input: fPort: 42 diff --git a/vendor/dragino/lsn50v2-s31.js b/vendor/dragino/lsn50v2-s31.js index 577df8e5ed..9fef4d0eb1 100644 --- a/vendor/dragino/lsn50v2-s31.js +++ b/vendor/dragino/lsn50v2-s31.js @@ -97,4 +97,19 @@ default: errors: ["unknown FPort"] } } -} \ No newline at end of file +} + +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.TempC_SHT, + relativeHumidity: input.data.Hum_SHT + }, + action: { + contactState: input.data.Door_status === "CLOSE" ? "CLOSED" : input.data.Door_status === "OPEN" ? "OPEN" : undefined + }, + battery: input.data.BatV, + } + }; +} diff --git a/vendor/dragino/lwl03a-codec.yaml b/vendor/dragino/lwl03a-codec.yaml new file mode 100644 index 0000000000..c8b82784bf --- /dev/null +++ b/vendor/dragino/lwl03a-codec.yaml @@ -0,0 +1,13 @@ +uplinkDecoder: + fileName: lwl03a.js + examples: + - description: Distance Detection + input: + fPort: 2 + bytes: [0x01, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x0A, 0x63, 0x5C, 0xD2, 0xF2] + output: + data: { 'TDC': 'NO', 'ALARM': 'FALSE', 'WATER_LEAK_STATUS': 'LEAK', 'WATER_LEAK_TIMES': 10, 'LAST_WATER_LEAK_DURATION': 10, 'TIME': '2022-10-29 07:14:58' } + normalizedOutput: + data: + - water: + leak: true diff --git a/vendor/dragino/lwl03a.js b/vendor/dragino/lwl03a.js new file mode 100644 index 0000000000..8ce825c681 --- /dev/null +++ b/vendor/dragino/lwl03a.js @@ -0,0 +1,167 @@ +function datalog(i,bytes){ + var aa=(bytes[0+i]&0x02)?"TRUE":"FALSE"; + var bb=(bytes[0+i]&0x01)?"LEAK":"NO LEAK"; + var cc=(bytes[1+i]<<16 | bytes[2+i]<<8 | bytes[3+i]).toString(10); + var dd=(bytes[4+i]<<16 | bytes[5+i]<<8 | bytes[6+i]).toString(10); + var ee= getMyDate((bytes[7+i]<<24 | bytes[8+i]<<16 | bytes[9+i]<<8 | bytes[10+i]).toString(10)); + var string='['+aa+','+bb+','+cc+','+dd+','+ee+']'+','; + return string; +} + +function getzf(c_num){ + if(parseInt(c_num) < 10) + c_num = '0' + c_num; + return c_num; +} + +function getMyDate(str) { + var c_Date; + if (str > 9999999999) { + c_Date = new Date(parseInt(str)); + } else { + c_Date = new Date(parseInt(str) * 1000); + } + var c_Year = c_Date.getUTCFullYear(), + c_Month = c_Date.getUTCMonth() + 1, + c_Day = c_Date.getUTCDate(), + c_Hour = c_Date.getUTCHours(), + c_Min = c_Date.getUTCMinutes(), + c_Sen = c_Date.getUTCSeconds(); + var c_Time = c_Year + '-' + getzf(c_Month) + '-' + getzf(c_Day) + ' ' + getzf(c_Hour) + ':' + getzf(c_Min) + ':' + getzf(c_Sen); + return c_Time; +} + + +function Decoder(bytes, port) { + if(port==0x03) + { + for(var i=0;i>4&0x0f)+'.'+(bytes[2]&0x0f); + var bat= (bytes[5]<<8 | bytes[6])/1000; + + return { + SENSOR_MODEL:sensor, + FIRMWARE_VERSION:firm_ver, + FREQUENCY_BAND:freq_band, + SUB_BAND:sub_band, + BAT:bat, + }; + } + else + { + var tdc_interval=(bytes[0]&0x04)?"YES":"NO"; + var alarm=(bytes[0]&0x02)?"TRUE":"FALSE"; + var leak_status=(bytes[0]&0x01)?"LEAK":"NO LEAK"; + var leak_times=bytes[1]<<16 | bytes[2]<<8 | bytes[3]; + var leak_duration=bytes[4]<<16 | bytes[5]<<8 | bytes[6]; + var data_time= getMyDate((bytes[7]<<24 | bytes[8]<<16 | bytes[9]<<8 | bytes[10]).toString(10)); + + if(bytes.length==11) + { + return { + TDC:tdc_interval, + ALARM:alarm, + WATER_LEAK_STATUS:leak_status, + WATER_LEAK_TIMES:leak_times, + LAST_WATER_LEAK_DURATION:leak_duration, + TIME:data_time + }; + } + } +} + +function decodeUplink(input) { + return { + data : Decoder(input.bytes, input.fPort), + }; +} + +function normalizeUplink(input) { + var data = []; + + if (input.data.WATER_LEAK_STATUS) { + data.push({ + water: { + leak: input.data.WATER_LEAK_STATUS === "LEAK" + } + }); + } + + if (input.data.BAT) { + data.push({ + battery: input.data.BAT + }); + } + + return { data: data }; +} diff --git a/vendor/dragino/lwl03a.png b/vendor/dragino/lwl03a.png new file mode 100644 index 0000000000..1cbd41576f Binary files /dev/null and b/vendor/dragino/lwl03a.png differ diff --git a/vendor/dragino/lwl03a.yaml b/vendor/dragino/lwl03a.yaml new file mode 100644 index 0000000000..9a9dca3911 --- /dev/null +++ b/vendor/dragino/lwl03a.yaml @@ -0,0 +1,112 @@ +name: LWL03A - None-Position Rope Type Water Leak Controller +description: The Dragino LWL03A is a LoRaWAN None-Position Rope Type Water Leak Controller. User can lay the LWL03A + Water Leak Cable on the ground to detect water leakage. + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + + # LoRaWAN Device Profiles per region + # Supported regions are EU863-870, US902-928, AU915-928, AS923, CN779-787, EU433, CN470-510, KR920-923, IN865-867, RU864-870 + profiles: + EU863-870: + # Unique identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: eu868-profile + lorawanCertified: true + codec: lwl03a-codec + EU433: + id: eu433-profile + lorawanCertified: true + codec: lwl03a-codec + US902-928: + id: us915-profile + lorawanCertified: true + codec: lwl03a-codec + KR920-923: + id: kr920-profile + lorawanCertified: true + codec: lwl03a-codec + AU915-928: + id: au915-profile + lorawanCertified: true + codec: lwl03a-codec + RU864-870: + id: ru864-profile + lorawanCertified: true + codec: lwl03a-codec + IN865-867: + id: in865-profile + lorawanCertified: true + codec: lwl03a-codec + CN470-510: + id: cn470-profile + lorawanCertified: true + codec: lwl03a-codec + AS923: + id: as923-profile + lorawanCertified: true + codec: lwl03a-codec + + - version: 'lwl03a abp' + numeric: 2 + profiles: + EU863-870: + id: eu868-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + EU433: + id: eu433-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + US902-928: + id: us915-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + AU915-928: + id: au915-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + AS923: + id: as923-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + CN470-510: + id: cn470-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + IN865-867: + id: in865-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + KR920-923: + id: kr920-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec + RU864-870: + id: ru864-a-abp-profile + lorawanCertified: true + codec: lwl03a-codec +# Sensors that this device features (optional) +# Valid values are: +# 4-20 ma, accelerometer, altitude, analog input, auxiliary, barometer, battery, button, bvoc, co, co2, conductivity, +# current, digital input, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, humidity, iaq, level, light, +# lightning, link, magnetometer, moisture, motion, no, no2, o3, particulate matter, ph, pir, pm2.5, pm10, potentiometer, +# power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, rssi, snr, solar radiation, +# sound, strain, surface temperature, temperature, tilt, time, tvoc, uv, vapor pressure, velocity, vibration, voltage, +# water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - water + +# Product and data sheet URLs (optional) +productURL: https://www.dragino.com/products/lorawan-nb-iot-door-sensor-water-leak/item/241-lwl03a.html +dataSheetURL: http://wiki.dragino.com/xwiki/bin/view/Main/User%20Manual%20for%20LoRaWAN%20End%20Nodes/LWL03A%20%E2%80%93%20LoRaWAN%20None-Position%20Rope%20Type%20Water%20Leak%20Controller%20User%20Manual/ +sellerURLs: + - name: 'Dragino' + region: + - China + url: http://www.dragino.com/ + +# Photos +photos: + main: lwl03a.png diff --git a/vendor/elsys/elsys.js b/vendor/elsys/elsys.js index b992c7130f..9d74d7c1b7 100644 --- a/vendor/elsys/elsys.js +++ b/vendor/elsys/elsys.js @@ -237,3 +237,38 @@ function decodeUplink(input) { "data": DecodeElsysPayload(input.bytes) } } + +function normalizeUplink(input) { + var data = {}; + var air = {}; + var action = {}; + var motion = {}; + + if (input.data.temperature) { + air.temperature = input.data.temperature; + } + + if (input.data.humidity) { + air.relativeHumidity = input.data.humidity; + } + + if (input.data.light) { + air.lightIntensity = input.data.light; + } + + if (input.data.motion) { + motion.detected = input.data.motion > 0; + motion.count = input.data.motion; + action.motion = motion; + } + + if (Object.keys(air).length > 0) { + data.air = air; + } + + if (Object.keys(action).length > 0) { + data.action = action; + } + + return { data: data }; +} diff --git a/vendor/elsys/ems-desk-codec.yaml b/vendor/elsys/ems-desk-codec.yaml index 8ceeb900ea..a73bb270ff 100644 --- a/vendor/elsys/ems-desk-codec.yaml +++ b/vendor/elsys/ems-desk-codec.yaml @@ -16,3 +16,8 @@ uplinkDecoder: y: 39 z: 5 occupancy: 2 + normalizedOutput: + data: + - air: + temperature: 22.6 + relativeHumidity: 41 diff --git a/vendor/elsys/ers-co2-codec.yaml b/vendor/elsys/ers-co2-codec.yaml index 9d585e71d2..3efab2ef0b 100644 --- a/vendor/elsys/ers-co2-codec.yaml +++ b/vendor/elsys/ers-co2-codec.yaml @@ -15,3 +15,13 @@ uplinkDecoder: light: 39 motion: 6 co2: 776 + normalizedOutput: + data: + - air: + temperature: 22.6 + relativeHumidity: 41 + lightIntensity: 39 + action: + motion: + detected: true + count: 6 diff --git a/vendor/elsys/ers-codec.yaml b/vendor/elsys/ers-codec.yaml index dcd5afc555..2ef694561a 100644 --- a/vendor/elsys/ers-codec.yaml +++ b/vendor/elsys/ers-codec.yaml @@ -14,3 +14,13 @@ uplinkDecoder: humidity: 41 light: 39 motion: 6 + normalizedOutput: + data: + - air: + temperature: 22.6 + relativeHumidity: 41 + lightIntensity: 39 + action: + motion: + detected: true + count: 6 diff --git a/vendor/laird/rs1xx-temp-rh-sensor-codec.yaml b/vendor/laird/rs1xx-temp-rh-sensor-codec.yaml index b6af7e7d07..d6725186dd 100644 --- a/vendor/laird/rs1xx-temp-rh-sensor-codec.yaml +++ b/vendor/laird/rs1xx-temp-rh-sensor-codec.yaml @@ -16,6 +16,11 @@ uplinkDecoder: humidity: 52.33 alarmMsgCount: 256 backlogMsgCount: 1 + normalizedOutput: + data: + - air: + temperature: 98.67 + relativeHumidity: 52.33 - description: Send Temp and RH Aggregated Data Notification input: diff --git a/vendor/laird/rs1xx-temp-rh-sensor.js b/vendor/laird/rs1xx-temp-rh-sensor.js index 89485b2a1e..88c8a2b850 100644 --- a/vendor/laird/rs1xx-temp-rh-sensor.js +++ b/vendor/laird/rs1xx-temp-rh-sensor.js @@ -3481,3 +3481,13 @@ function decodeUplink(input) { return(result); } +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.temperature, + relativeHumidity: input.data.humidity, + } + } + } +} diff --git a/vendor/mclimate/vicki-codec.yaml b/vendor/mclimate/vicki-codec.yaml index 31b4c5e05c..ead089ff88 100644 --- a/vendor/mclimate/vicki-codec.yaml +++ b/vendor/mclimate/vicki-codec.yaml @@ -25,3 +25,11 @@ uplinkDecoder: antiFreezeProtection: false motorOpenness: 17 targetTemperatureFloat: '29.00' + normalizedOutput: + data: + - air: + temperature: 18.01 + relativeHumidity: 46.88 + battery: 3.5 + warnings: + - 'childLock: true' diff --git a/vendor/mclimate/vicki.js b/vendor/mclimate/vicki.js index e83d78f7e1..03730aa621 100644 --- a/vendor/mclimate/vicki.js +++ b/vendor/mclimate/vicki.js @@ -356,4 +356,55 @@ function decodeUplink(input) { return { data: data }; -} \ No newline at end of file +} + +function normalizeUplink(input) { + const warnings = []; + + if (input.data.openWindow) { + warnings.push("openWindow: true"); + } + + if (input.data.highMotorConsumption) { + warnings.push("highMotorConsumption: true"); + } + + if (input.data.lowMotorConsumption) { + warnings.push("lowMotorConsumption: true"); + } + + if (input.data.brokenSensor) { + warnings.push("brokenSensor: true"); + } + + if (input.data.childLock) { + warnings.push("childLock: true"); + } + + if (input.data.calibrationFailed) { + warnings.push("calibrationFailed: true"); + } + + if (input.data.attachedBackplate) { + warnings.push("attachedBackplate: true"); + } + + if (input.data.perceiveAsOnline) { + warnings.push("perceiveAsOnline: true"); + } + + if (input.data.antiFreezeProtection) { + warnings.push("antiFreezeProtection: true"); + } + + return { + data: { + air: { + temperature: input.data.sensorTemperature, + relativeHumidity: input.data.relativeHumidity, + }, + battery: input.data.batteryVoltage, + }, + warnings: warnings + }; +} diff --git a/vendor/milesight-iot/em300-th-codec.yaml b/vendor/milesight-iot/em300-th-codec.yaml index 2cb65024d5..90f42e5e6a 100644 --- a/vendor/milesight-iot/em300-th-codec.yaml +++ b/vendor/milesight-iot/em300-th-codec.yaml @@ -2,3 +2,19 @@ # For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ uplinkDecoder: fileName: em300-th.js + examples: + - description: Example with battery, temperature, and humidity + input: + fPort: 1 + bytes: [0x01, 0x75, 0x32, 0x03, 0x67, 0xC8, 0x00, 0x04, 0x68, 0x3C] + output: + data: + battery: 50 + temperature: 20.0 + humidity: 30.0 + normalizedOutput: + data: + - air: + temperature: 20.0 + relativeHumidity: 30.0 + battery: 50 diff --git a/vendor/milesight-iot/em300-th.js b/vendor/milesight-iot/em300-th.js index 33ae310161..f0f9d7748d 100644 --- a/vendor/milesight-iot/em300-th.js +++ b/vendor/milesight-iot/em300-th.js @@ -1,3 +1,9 @@ +function decodeUplink(input) { + return { + data : Decoder(input.bytes, input.fPort), + }; +} + function Decoder(bytes, port) { var decoded = {}; @@ -51,6 +57,17 @@ function Decoder(bytes, port) { } +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.temperature, + relativeHumidity: input.data.humidity + }, + battery: input.data.battery, + } + }; +} /* ****************************************** @@ -73,4 +90,4 @@ function readInt16LE(bytes) { return ref > 0x7fff ? ref - 0x10000 : ref; -} \ No newline at end of file +} diff --git a/vendor/milesight-iot/ws301-codec.yaml b/vendor/milesight-iot/ws301-codec.yaml index 92a11f78af..fdac30f692 100644 --- a/vendor/milesight-iot/ws301-codec.yaml +++ b/vendor/milesight-iot/ws301-codec.yaml @@ -5,11 +5,17 @@ uplinkDecoder: - description: Magnetic Contact Switch (example 1) - Milesight IoT input: fPort: 85 - bytes: [0x03, 0x00, 0x01] + bytes: [0x01, 0x75, 0x4B, 0x03, 0x00, 0x01] output: data: - door: open - - description: Magnetic Contact Switch (example 2) - Milesgiht IoT + battery: 75 + door: 'open' + normalizedOutput: + data: + - action: + contactState: 'OPEN' + battery: 75 + - description: Magnetic Contact Switch (example 2) - Milesight IoT input: fPort: 85 bytes: [0x04, 0x00, 0x01] diff --git a/vendor/milesight-iot/ws301.js b/vendor/milesight-iot/ws301.js index f98a16c516..4d3c7f4629 100644 --- a/vendor/milesight-iot/ws301.js +++ b/vendor/milesight-iot/ws301.js @@ -43,3 +43,15 @@ function Decoder(bytes, port) { return decoded; } + + +function normalizeUplink(input) { + return { + data: { + action: { + contactState: input.data.door === "close" ? "CLOSED" : input.data.door === "open" ? "OPEN" : undefined + }, + battery: input.data.battery, + } + }; +} diff --git a/vendor/moko/lw001-bgpro-codec.yaml b/vendor/moko/lw001-bgpro-codec.yaml index 131e529f2c..87ef77dbf3 100644 --- a/vendor/moko/lw001-bgpro-codec.yaml +++ b/vendor/moko/lw001-bgpro-codec.yaml @@ -4,44 +4,56 @@ uplinkDecoder: fileName: lw001-bgpro.js # Examples (optional) -# examples: -# - description: heratbeat payload -# input: -# fPort: 1 -# bytes: [0x21, 0x1E, 0xC0, 0x01, 0x47, 0x00, 0x00, 0x00, 0x00] -# output: -# data: -# battery voltage: '3.4V' -# demolish_state: '0' -# idle_state: '0' -# lorawan_downlink_count: '0' -# low_power_state: '0' -# motion_count: '0' -# motion_state: '1' -# pack_type: 'heart' -# last_restart_reason: 'ble_cmd_restart' -# ic_temperature: '30°C' -# firmware ver: 'V1.0.7' -# work_mode: 'period' - -# - description: gps fixed payload -# input: -# fPort: 2 -# bytes: [0x01, 0x1F, 0xC0, 0x02, 0x07, 0xE6, 0x08, 0x03, 0x09, 0x0F, 0x1F, 0x00, 0x09, 0x12, 0x27, 0x88, 0x8E, 0x44, 0x3A, 0xA0, 0x50, 0x0C] -# output: -# data: -# utc_time: '2022-8-3 9:15:31 Timezone:0' -# battery voltage: '3.4V' -# demolish_state: '0' -# fix_tech: 'gps' -# fix_type: 'work_mode_fix' -# idle_state: '0' -# lat: '30.458075' -# lon: '114.4692816' -# lorawan_downlink_count: '0' -# low_power_state: '0' -# motion_state: '0' -# pack_type: 'fix_success' -# pdop: '1.2' -# ic_temperature: '31°C' -# work_mode: 'period' + examples: + - description: heartbeat payload + input: + fPort: 1 + bytes: [0x21, 0x1E, 0xC0, 0x01, 0x47, 0x00, 0x00, 0x00, 0x00] + output: + data: + battery_voltage: 3.4 + demolish_state: 0 + idle_state: 0 + lorawan_downlink_count: 0 + low_power_state: 0 + motion_count: 0 + motion_state: 1 + pack_type: 'heart' + last_restart_reason: 'ble_cmd_restart' + ic_temperature: '30°C' + firmware_ver: 'V1.0.7' + work_mode: 'period mode' + normalizedOutput: + data: + - action: + motion: + detected: true + count: 0 + battery: 3.4 + - description: gps fixed payload + input: + fPort: 2 + bytes: [0x01, 0x1F, 0xC0, 0x02, 0x07, 0xE6, 0x08, 0x03, 0x09, 0x0F, 0x1F, 0x00, 0x09, 0x12, 0x27, 0x88, 0x8E, 0x44, 0x3A, 0xA0, 0x50, 0x0C] + output: + data: + utc_time: '2022-8-3 9:15:31 TZ:0' + battery_voltage: 3.4 + demolish_state: 0 + fix_tech: 'gps' + fix_type: 'work_mode_fix' + idle_state: 0 + lat: 30.458075 + lon: 114.4692816 + lorawan_downlink_count: 0 + low_power_state: 0 + motion_state: 0 + pack_type: 'fix_success' + pdop: 1.2 + ic_temperature: '31°C' + work_mode: 'period mode' + normalizedOutput: + data: + - position: + latitude: 30.458075 + longitude: 114.4692816 + battery: 3.4 diff --git a/vendor/moko/lw001-bgpro.js b/vendor/moko/lw001-bgpro.js index e29f65fde9..21c25c4927 100644 --- a/vendor/moko/lw001-bgpro.js +++ b/vendor/moko/lw001-bgpro.js @@ -41,7 +41,7 @@ function Decoder(bytes, port) } dev_info.lorawan_downlink_count = bytes[2]&0x0f; - dev_info.battery_voltage = (22+((bytes[2]>>4)&0x0f))/10 + "V"; + dev_info.battery_voltage = (22+((bytes[2]>>4)&0x0f))/10; } if(port == 1) { @@ -218,7 +218,7 @@ function Decoder(bytes, port) dev_info.fix_type = dev_fix_type[(bytes[0]>>6)&0x01]; dev_info.lorawan_downlink_count = bytes[1]&0x0f; - dev_info.battery_voltage = (22+((bytes[2]>>4)&0x0f))/10 + "V"; + dev_info.battery_voltage = (22+((bytes[2]>>4)&0x0f))/10; var parse_len = 2; lat =BytestoInt(bytes,parse_len); @@ -237,3 +237,44 @@ function Decoder(bytes, port) } return dev_info; } + +function decodeUplink(input) { + return { + data : Decoder(input.bytes, input.fPort), + }; +} + +function normalizeUplink(input) { + var data = {}; + var action = {}; + var position = {}; + var motion = {}; + + if (input.data.motion_state) { + motion.detected = input.data.motion_state > 0; + motion.count = input.data.motion_count; + action.motion = motion; + } + + if (input.data.lat) { + position.latitude = input.data.lat; + } + + if (input.data.lon) { + position.longitude = input.data.lon; + } + + if (Object.keys(action).length > 0) { + data.action = action; + } + + if (Object.keys(position).length > 0) { + data.position = position; + } + + if (input.data.battery_voltage) { + data.battery = input.data.battery_voltage; + } + + return { data: data }; +} diff --git a/vendor/sensative/strips-codec.yaml b/vendor/sensative/strips-codec.yaml index feb32e3c60..e795e99e10 100644 --- a/vendor/sensative/strips-codec.yaml +++ b/vendor/sensative/strips-codec.yaml @@ -1,2 +1,22 @@ uplinkDecoder: fileName: strips.js + examples: + - description: payload + input: + fPort: 1 + bytes: [0xFF, 0xFF, 0x01, 0x50, 0x02, 0x00, 0xEA, 0x03, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x10, 0x00] + output: + data: + battery: 80 + flood: { value: 0 } + floodAlarm: { value: false } + historySeqNr: 65535 + prevHistSeqNr: 65535 + tempAlarm: { highAlarm: false, lowAlarm: false } + temperature: { value: 23.4 } + userSwitch1Alarm: { value: false } + normalizedOutput: + data: + - air: + temperature: 23.4 + battery: 80 diff --git a/vendor/sensative/strips.js b/vendor/sensative/strips.js index e13d1d717c..5fe6191729 100644 --- a/vendor/sensative/strips.js +++ b/vendor/sensative/strips.js @@ -184,3 +184,20 @@ function Decoder(bytes, port) { } return decoded; } + +function decodeUplink(input) { + return { + data : Decoder(input.bytes, input.fPort), + }; +} + +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.temperature.value, + }, + battery: input.data.battery + } + }; + } diff --git a/vendor/tektelic/decoder_smart_room_sensor.js b/vendor/tektelic/decoder_smart_room_sensor.js index 41f4b79d84..e797f02bcf 100644 --- a/vendor/tektelic/decoder_smart_room_sensor.js +++ b/vendor/tektelic/decoder_smart_room_sensor.js @@ -2864,3 +2864,50 @@ function decodeUplink(input) { }; } + + function normalizeUplink(input) { + var data = {}; + var air = {}; + var action = {}; + var motion = {}; + + if (input.data.ambient_temperature) { + air.temperature = input.data.ambient_temperature; + } + + if (input.data.relative_humidity) { + air.relativeHumidity = input.data.relative_humidity; + } + + if (input.data.light_detected) { + air.lightIntensity = input.data.light_detected; + } + + if (input.data.motion_event_state) { + motion.detected = input.data.motion_event_state > 0; + action.motion = motion; + } + + if (input.data.motion_event_count) { + motion.count = input.data.motion_event_count; + action.motion = motion; + } + + if (input.data.reed_state) { + action.contactState = input.data.reed_state; + } + + if (Object.keys(air).length > 0) { + data.air = air; + } + + if (Object.keys(action).length > 0) { + data.action = action; + } + + if (input.data.battery_voltage) { + data.battery = input.data.battery_voltage; + } + + return { data: data }; + } diff --git a/vendor/tektelic/decoder_smart_room_sensor_pir_base.js b/vendor/tektelic/decoder_smart_room_sensor_pir_base.js index 48d6055a2e..729048a731 100644 --- a/vendor/tektelic/decoder_smart_room_sensor_pir_base.js +++ b/vendor/tektelic/decoder_smart_room_sensor_pir_base.js @@ -782,4 +782,51 @@ function decodeUplink(input) { return { data: decoded_data }; -} \ No newline at end of file +} + +function normalizeUplink(input) { + var data = {}; + var air = {}; + var action = {}; + var motion = {}; + + if (input.data.ambient_temperature) { + air.temperature = input.data.ambient_temperature; + } + + if (input.data.relative_humidity) { + air.relativeHumidity = input.data.relative_humidity; + } + + if (input.data.light_detected) { + air.lightIntensity = input.data.light_detected; + } + + if (input.data.motion_event_state) { + motion.detected = input.data.motion_event_state > 0; + action.motion = motion; + } + + if (input.data.motion_event_count) { + motion.count = input.data.motion_event_count; + action.motion = motion; + } + + if (input.data.reed_state) { + action.contactState = input.data.reed_state; + } + + if (Object.keys(air).length > 0) { + data.air = air; + } + + if (Object.keys(action).length > 0) { + data.action = action; + } + + if (input.data.battery_voltage) { + data.battery = input.data.battery_voltage; + } + + return { data: data }; + } diff --git a/vendor/tektelic/t00048xx-codec.yaml b/vendor/tektelic/t00048xx-codec.yaml index 2aa6d55a0b..73b10e2567 100644 --- a/vendor/tektelic/t00048xx-codec.yaml +++ b/vendor/tektelic/t00048xx-codec.yaml @@ -9,6 +9,11 @@ uplinkDecoder: data: ambient_temperature: 1 relative_humidity: 20 + normalizedOutput: + data: + - air: + temperature: 1 + relativeHumidity: 20 downlinkEncoder: fileName: encoder_smart_room_sensor_pir_base.js diff --git a/vendor/tektelic/t00061xx-codec.yaml b/vendor/tektelic/t00061xx-codec.yaml index ac49039067..755fcec8e6 100644 --- a/vendor/tektelic/t00061xx-codec.yaml +++ b/vendor/tektelic/t00061xx-codec.yaml @@ -12,6 +12,45 @@ uplinkDecoder: raw: '[02, 00, 01]' errors: [] warnings: [] + normalizedOutput: + data: + - air: + lightIntensity: 1 + - description: Temperature & Humidity Uplink + input: + fPort: 10 + bytes: [0x03, 0x67, 0x01, 0x26, 0x04, 0x68, 0x33, 0x00, 0xBA, 0x0B, 0xD1] + output: + data: + ambient_temperature: 29.4 + battery_voltage: 3.025 + port: '10' + raw: '[03, 67, 01, 26, 04, 68, 33, 00, BA, 0B, D1]' + relative_humidity: 25.5 + errors: [] + warnings: [] + normalizedOutput: + data: + - air: + temperature: 29.4 + relativeHumidity: 25.5 + battery: 3.025 + - description: Motion Event Uplink + input: + fPort: 10 + bytes: [0x0A, 0x00, 0xFF] + output: + data: + motion_event_state: 255 + port: '10' + raw: '[0A, 00, FF]' + errors: [] + warnings: [] + normalizedOutput: + data: + - action: + motion: + detected: true downlinkEncoder: fileName: encoder_smart_room_sensor.js diff --git a/vendor/the-things-industries/generic-node-sensor-edition-codec.js b/vendor/the-things-industries/generic-node-sensor-edition-codec.js index c5925fe3c6..155608e45b 100644 --- a/vendor/the-things-industries/generic-node-sensor-edition-codec.js +++ b/vendor/the-things-industries/generic-node-sensor-edition-codec.js @@ -9,3 +9,15 @@ function decodeUplink(input) { data: data, }; } + +function normalizeUplink(input) { + return { + data: { + air: { + temperature: input.data.temperature, + relativeHumidity: input.data.humidity, + }, + battery: input.data.batt_volt, + }, + }; +} diff --git a/vendor/the-things-industries/generic-node-sensor-edition-codec.yaml b/vendor/the-things-industries/generic-node-sensor-edition-codec.yaml index 9200cc19fc..5e44d53a4c 100644 --- a/vendor/the-things-industries/generic-node-sensor-edition-codec.yaml +++ b/vendor/the-things-industries/generic-node-sensor-edition-codec.yaml @@ -2,3 +2,21 @@ # For documentation on writing encoders and decoders, see: https://thethingsstack.io/integrations/payload-formatters/javascript/ uplinkDecoder: fileName: generic-node-sensor-edition-codec.js + # Examples (optional) + examples: + - description: Uplink example + input: + fPort: 1 + bytes: [35, 2, 216, 0, 250, 1] + output: + data: + batt_volt: 3.5 + temperature: 22.8 + humidity: 25.0 + button: 1 + normalizedOutput: + data: + - air: + temperature: 22.8 + relativeHumidity: 25.0 + battery: 3.5