diff --git a/vendor/acrios/acr-cv-101l-m-d.png b/vendor/acrios/acr-cv-101l-m-d.png deleted file mode 100644 index 42afbe75b2..0000000000 Binary files a/vendor/acrios/acr-cv-101l-m-d.png and /dev/null differ diff --git a/vendor/acrios/acr-cv-101l-m-d.yaml b/vendor/acrios/acr-cv-101l-m-d.yaml index 5efacd49dd..690d92476c 100644 --- a/vendor/acrios/acr-cv-101l-m-d.yaml +++ b/vendor/acrios/acr-cv-101l-m-d.yaml @@ -1,11 +1,14 @@ -name: M-Bus IoT converter -description: The Acrios M-Bus IoT converter is an M-Bus to LoRaWAN® converter that can be used for reading electricity meters and calorimeters. The M-Bus converter supports connections of up to 5 UL (Unit Loads) and communication is based on the EN 137 57-3 protocol. +name: M-Bus to LoRaWAN converter +description: M-Bus to LoRaWAN converter is used to retrofit ANY M-Bus meter with LoRaWAN communication + hardwareVersions: - version: 'v3.7' numeric: 1 + - version: 'ACR-CV-101L-M-DEAC_v1.1' + numeric: 2 + firmwareVersions: - - # Firmware version - version: 'e8d17c15795f' + - version: 'e8d17c15795f' numeric: 1 hardwareVersions: - 'v3.7' @@ -13,26 +16,84 @@ firmwareVersions: EU863-870: lorawanCertified: true id: acr-cv-101l-m-d-profile + - version: '2.13.18' + numeric: 2 + hardwareVersions: + - 'ACR-CV-101L-M-DEAC_v1.1' + features: + - remote rejoin + - transmission interval + profiles: + EU863-870: + vendorID: acrios + id: acr-cv-otaa-profile + lorawanCertified: true + codec: acr-cv-101l-m-x-codec + +deviceType: cots + bridgeInterfaces: - m-bus + dimensions: width: 145 length: 90 height: 55 -weight: 250 + +weight: 336 + battery: replaceable: true + type: D-Cell with JST-XH 2pin connector + operatingConditions: temperature: min: -30 max: 60 -ipCode: IP65 + relativeHumidity: + min: 0 + max: 0.85 + +ipCode: IP67 + keyProvisioning: - custom + keyProgramming: - serial + - firmware + keySecurity: read protected -productURL: https://acrios.com/m-bus-iot-prevodnik/?lang=en# -dataSheetURL: https://acrios.com/wp-content/uploads/2023/02/ACR-CV-101L-M-D.pdf + +firmwareProgramming: + - serial + - fuota lorawan + +productURL: https://www.acrios.com/converters/m-bus-lorawan +dataSheetURL: https://cdn.prod.website-files.com/66967900e67b9bbd56c4b73c/66d08c240b2ddf57a76697c6_ACR-CV-101L-M-D.pdf +# dataSheetURL: https://wiking.acrios.com/datasheets/ACR-CV-101L-M-D.pdf +# onboardingGuideURL: https://wiking.acrios.com/manuals/category/acr-cv-101l-m-x/ + +resellerURLs: + - name: 'ZENNERSHOP' + region: + - European Union + - Saudi Arabia + url: https://iot.zenner.shop/en/M-Bus-LoRa-Bridge-ACR-CV-101L-M-D/188113 + +msrp: + EUR: 192 + photos: - main: acr-cv-101l-m-d.png + main: acr-cv-101l-x-d.png + other: + - acr-cv-101l-x-d-top.png + +videos: + main: https://youtu.be/fiuiulh-8BY + +compliances: + safety: + - body: M-Bus + norm: EN + standard: 13757-3 diff --git a/vendor/acrios/acr-cv-101l-m-eac-inside.png b/vendor/acrios/acr-cv-101l-m-eac-inside.png new file mode 100644 index 0000000000..7f84c09708 Binary files /dev/null and b/vendor/acrios/acr-cv-101l-m-eac-inside.png differ diff --git a/vendor/acrios/acr-cv-101l-m-eac.yaml b/vendor/acrios/acr-cv-101l-m-eac.yaml index 348552c8d9..9903565d68 100644 --- a/vendor/acrios/acr-cv-101l-m-eac.yaml +++ b/vendor/acrios/acr-cv-101l-m-eac.yaml @@ -1,130 +1,102 @@ -name: Externally powered M-BUS to LoRaWAN® -description: 230V AC externally-powered ACRIOS Systems IoT converter is working as M-Bus to LoRaWAN® bridge with implemented LUA scripting interface. The LUA scripting interface allows for VIF DIF filtering, message buffering, message splitting, LoRaWAN communication class changes, and other operations on the hardware level. Part of the company portfolio is dedicated to enablement such as the M-Bus backend solution allowing for remote scanning and setting up the VIF DIF filters. +name: M-Bus to LoRaWAN converter, externally powered +description: M-Bus to LoRaWAN converter is used to retrofit ANY M-Bus meter with LoRaWAN communication -# Hardware versions (optional, use when you have revisions) hardwareVersions: - version: 'ACR-CV-101L-RM-D2EAC_v2.0' + numeric: 2 + - version: 'ACR-CV-101L-RM-D2EAC_v2.2' numeric: 1 -# Firmware versions (at least one is mandatory) firmwareVersions: - - # Firmware version - version: '2.5' + - version: '2.5' numeric: 1 - # Corresponding hardware versions (optional) hardwareVersions: - 'ACR-CV-101L-RM-D2EAC_v2.0' - - # Firmware features (optional) - # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how - # often he device sends a message). features: - remote rejoin - transmission interval - - # 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: - # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from - # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. - # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, - # which is verbose. - #vendorID: EU863-870: - # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) id: acr-cv-otaa-profile lorawanCertified: true + - version: '2.13.18' + numeric: 2 + hardwareVersions: + - 'ACR-CV-101L-RM-D2EAC_v2.2' + features: + - remote rejoin + - transmission interval + profiles: + EU863-870: + vendorID: acrios + id: acr-cv-otaa-profile + lorawanCertified: true + codec: acr-cv-101l-m-x-codec + +deviceType: cots -# Bridge interfaces (optional) -# Valid values are: modbus, m-bus, can bus, rs-485, sdi-12, analog. bridgeInterfaces: - m-bus -# Dimensions in mm (optional) -# Use width, height, length and/or diameter dimensions: width: 145 length: 90 height: 55 -# Weight in grams (optional) -weight: 250 +weight: 166 -# Battery information (optional) battery: replaceable: false type: Externally powered unit 85 - 305V AC -# Operating conditions (optional) operatingConditions: - # Temperature (Celsius) temperature: min: -30 max: 60 + relativeHumidity: + min: 0 + max: 0.85 -# IP rating (optional) -ipCode: IP65 +ipCode: IP67 -# Key provisioning (optional) -# Valid values are: custom (user can configure keys), join server and manifest. keyProvisioning: - custom -# Key programming (optional) -# Valid values are: bluetooth, nfc, wifi, serial (when the user has a serial interface to set the keys) -# and firmware (when the user should change the firmware to set the keys). keyProgramming: - serial - firmware -# Key security (optional) -# Valid values are: none, read protected and secure element. keySecurity: read protected -# Firmware programming (optional) -# Valid values are: serial (when the user has a serial interface to update the firmware), fuota lorawan (when the device -# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). firmwareProgramming: - serial - fuota lorawan -# Product and data sheet URLs (optional) -productURL: https://acrios.com/m-bus-iot-prevodnik/?lang=en -dataSheetURL: https://acrios.com/wp-content/uploads/2023/02/ACR-CV-101L-M-EAC.pdf +productURL: https://www.acrios.com/converters/m-bus-lorawan +# dataSheetURL: https://wiking.acrios.com/datasheets/ACR-CV-101L-M-EAC.pdf +# onboardingGuideURL: https://wiking.acrios.com/manuals/category/acr-cv-101l-m-x/ -# Commercial information resellerURLs: - - name: 'ACRIOS Systems' + - name: 'ZENNERSHOP' region: - European Union - url: https://acrios.com/?lang=en + - Saudi Arabia + url: https://iot.zenner.shop/en/M-Bus-LoRa-Bridge-ACR-CV-101L-M-D/188113 msrp: - EUR: 137 + EUR: 179 -# Photos photos: - main: zeus-2pg-rsma.png + main: acr-cv-101l-x-eac.png other: - - acr-cv-aec-angle.jpg - - acr-cv-eac-top.jpg + - acr-cv-101l-x-eac-top.png + - acr-cv-101l-m-eac-inside.png + +videos: + main: https://youtu.be/fiuiulh-8BY -# Regulatory compliances (optional) compliances: safety: - - body: IEC - norm: EN - standard: 62368-1 - # - body: IEC - # norm: EN - # standard: 137 57-3 - radioEquipment: - - body: ETSI - norm: EN - standard: 301 489-1 - version: 2.2.0 - - body: ETSI + - body: M-Bus norm: EN - standard: 301 489-3 - version: 2.1.0 + standard: 13757-3 diff --git a/vendor/acrios/acr-cv-101l-m-x-codec.yaml b/vendor/acrios/acr-cv-101l-m-x-codec.yaml new file mode 100644 index 0000000000..f128f3a614 --- /dev/null +++ b/vendor/acrios/acr-cv-101l-m-x-codec.yaml @@ -0,0 +1,37 @@ +uplinkDecoder: + fileName: acr-cv-101l-m-x.js + examples: + - description: M-Bus payload + input: + fPort: 1 + # HEX payload: 01 01 68 13 13 68 08 05 73 78 56 34 12 0a 00 e9 7e 01 00 00 00 35 01 00 00 3c 16 + bytes: [1, 1, 104, 19, 19, 104, 8, 5, 115, 120, 86, 52, 18, 10, 0, 233, 126, 1, 0, 0, 0, 53, 1, 0, 0, 60, 22] + output: + data: + a: 5 + accessN: 10 + c: 8 + cStored: Actual + ci: 115 + data: + - func: Instantaneous + id: 0 + storage: 0 + unit: l + value: 1 + - func: Instantaneous + id: 1 + storage: 1 + unit: l + value: 135 + deviceCode: 7 + deviceType: Water meter + errors: [] + fixed: true + id: 12345678 + l: 19 + len: 25 + status: 0 + type: Data + errors: [] + warnings: [] diff --git a/vendor/acrios/acr-cv-101l-m-x.js b/vendor/acrios/acr-cv-101l-m-x.js new file mode 100644 index 0000000000..5ef56ac459 --- /dev/null +++ b/vendor/acrios/acr-cv-101l-m-x.js @@ -0,0 +1,706 @@ +/** + * tmbus JavaScript Library v1.0.0 + * https://github.com/dev-lab/tmbus + * + * Copyright (c) 2023 Taras Greben + * Released under the Apache License + * https://dev-lab.github.com/tmbus/LICENSE + */ + +function ln(t) { + return t ? t.length || 0 : 0; +} + +function sNc(c, i) { + return i > 0 ? Array(i + 1).join(c) : ""; +} + +function sIn(s, i, n) { + return i ? s.slice(0, i) + n + s.slice(i) : n + s; +} + +function p10(n, e) { + if (!e) return n; + var s = ln(n); + if (!s) { + var i = parseInt(n); + if (n !== i) return isNaN(i) ? n : n * Math.pow(10, e); + } + var t = "" + n, b = (s ? t[0] == "-" : n < 0) ? 1 : 0, l = ln(t); + if (e > 0) t += sNc("0", e); + else { + e += l - b; + if (e < 0) t = sIn(t, b, sNc("0", -e)); + t = sIn(t, e <= 0 ? b : e + b, "."); + } + return s ? t : Number(t); +} + +function ha2si(a) { + var l = ln(a = a.slice()), d = [], r = a[l - 1], m = r & 128, i, f; + if (m) for (i = f = 0; i < l; ++i) if (a[i] || f) { + a[i] = 256 - a[i] - f; + f = 1; + } + for (i = l, f = 0; i;) if (a[--i]) f = 1; + if (!f) return 0; + do { + r = f = 0, i = l; + while (i) { + var n = r * 256 + a[--i]; + r = n % 10; + if (a[i] = (n - r) / 10) f = 1; + } + d.push(r); + } while (f); + for (i = ln(d); !d[--i];); + return (m ? "-" : "") + d.slice(0, ++i).reverse().join(""); +} + +function i2s(v, n) { + var r = v ? v.toString() : "0", l = ln(r); + return n ? (l < n ? sNc("0", n - l) : "") + r : r; +} + +function sum(a, b, e) { + var r = 0, i = b || 0; + while (i < (e || ln(a))) r += a[i++]; + return r & 0xFF; +} + +function parseHs(s) { + var p = s ? s.split(/[\s,]/) : [], r = [], t, i = 0; + while (i < ln(p)) if (ln(t = p[i++])) r = r.concat(t.match(/.{1,2}/g)); + return r; +} + +function hs2i(s) { + return Number("0x" + s.replace(/^#/, '')); +} + +function hs2a(s) { + var a = parseHs(s), r = [], v, i = 0; + while (i < ln(a)) { + v = hs2i(a[i++]); + if (isNaN(v) || v < 0 || v > 255) throw '"' + a[i] + '" is not a hex byte, pos ' + i; + r.push(v); + } + return r; +} + +function b2hs(i) { + i = Number(i); + return (i < 16 ? "0" : "") + i.toString(16); +} + +function ba2hs(a, s) { + var r = [], i = 0; + while (i < ln(a)) r.push(b2hs(a[i++])); + return r.join(s || ""); +} + +function ba2i(a) { + var i = ln(a); + if (!i || i > 4) return i ? a : 0; + var r = a[--i], m = i == 3 ? 0 : r & 128 ? (r &= 127, -(1 << i * 8 + 7)) : 0; + while (i) r = (r << 8) + a[--i]; + return r + m; +} + +function ba2b(a) { + var i = ln(a), r = 0; + while (i) r = (r << 8) + a[--i]; + return r; +} + +function ba2bcd(a, x) { + var r = 0, i = ln(a), v, h, l, s = "", e = 0, m = 0; + function p(c) { + if (m) c = -c; + if (c < 10) s += c; + else e = 1, s += "A-C EF".charAt(c - 10); + } + while (i) { + v = a[--i], h = (v & 0xF0) >> 4, l = v & 0xF; + if (m) h = -h, l = -l; + r = r * 100 + h * 10 + l; + p(h); + if (1 == ln(s)) { + e = 0; + if (h == 13) e = 1; + else if (h > 13) { + m = 1, l = -l, r = l; + if (h == 14) r -= 10; + } + } + p(l); + } + if (!x && e) throw s; + return e ? s : r; +} + +function i2c(i) { + return String.fromCharCode(i); +} + +function ba2s(a) { + var r = [], i = ln(a); + while (i) r.push(i2c(a[--i])); + return r.join(""); +} + +function date(y, m, d) { + return { + rawY: y, y: 1900 + y + (y < 100 ? 100 : 0), m: m, d: d, + toString: function () { + var t = this, r = i2s(d, 2) + "." + i2s(m, 2) + "." + t.y; + if (t.hr !== undefined) r += " " + i2s(t.hr, 2) + ":" + i2s(t.mi, 2) + + (t.se !== undefined ? (":" + i2s(t.se, 2)) : ""); + if (t.s) r += " (summer)"; + if (t.i) r += " (invalid)"; + return r; + } + }; +} + +function i2d(i) { + return i ? date(i >> 5 & 7 | i >> 9 & 0x78, i >> 8 & 0xF, i & 0x1F) : null; +} + +function i2t(i) { + var l = ln(i) || 0, b = l > 5 ? 1 : 0, s = b ? i[--l] : 0, i = l ? ba2b(i.slice(b, l)) : i; + if (!i) return null; + var r = i2d(i >> 16); + r.hr = i >> 8 & 0x1F; + r.mi = i & 0x3F; + if (b) r.se = s & 0x3F; + if (i & 0x8000) r.s = true; + if (i & 0x80) r.i = true; + return r; +} + +function ba2f(a) { + var l = ln(a) - 1, s = 7; + if (l == 7) s = 4; + else if (l != 3) return NaN; + var b = l - 1, m = (1 << s) - 1, f = (a[b] & m) << b * 8, h = 1 << b * 8 + s, y = 1 << 14 - s, + e = (a[b] >> s) + ((a[l] & 0x7F) << 8 - s) + 1 - y, g = a[l] >> 7 ? -1 : 1, i; + for (i = 0; i < b; ++i) f += a[i] << i * 8; + if (e == y) return g * (f ? NaN : Number.POSITIVE_INFINITY); + if (f) f = e == 1 - y ? f / (h >> 1) : (f | h) / h; + return g * f * Math.pow(2, e); +} + +function hexSum(h, c, s) { + var a = hs2a(h), l = ln(a); + if (l > 1 && l < 256 && c) { + a.push(sum(a)); + a.push(0x16); + if (l < 3) a.splice(0, 0, 0x10); + else a.splice(0, 0, 0x68, l, l, 0x68); + } + return ba2hs(a, s); +} + +function tmbus(h) { + + var a = hs2a(h), isA = Array.isArray, O = [0], MS = "Manufacturer specific", R = "Reserved", UH = "Units for H.C.A."; + while (ln(a)) if (a[0] != 255) break; else a.splice(0, 1); + var l = ln(a), e = l - 2, r = { len: l }, id = 0, n = 0, c, w; + if (!l) return r; + + function er(s) { + throw (s || "Wrong frame length") + ", pos " + n; + } + + function i() { + if (n == l) er(); + return c = a[n++]; + } + + function sl(t, s) { + var p = n, r = s + n; + if (r > e) er("Premature end of data when reading " + t + " (need " + s + ", available " + (e - n) + ")"); + n = r; + return a.slice(p, n); + } + + function ii(t, b, s) { + var r = sl(t, s || 4); + return b ? ba2i(b == 2 ? r.reverse() : r) : ba2bcd(r, 1); + } + + function aSum(b) { + if (sum(a, b, e) != a[e]) er("Check sum failed"); + } + + i(); + if (l == 1) { + c == 0xe5 ? r.type = "OK" : er("Invalid char"); + return r; + } + if (l < 5) er(); + if (a[l - 1] != 0x16) er("No Stop"); + if (c == 0x10) { + r.type = "Short"; + aSum(1); + r.c = i(); + r.a = i(); + return r; + } + if (c != 0x68) er("No Start"); + r.type = "Data"; + r.l = i(); + if (a[2] != c) er("Invalid length"); + if (a[0] != a[3]) er("Invalid format"); + if (c != l - 6) er("Wrong length"); + aSum(n = 4); + r.c = i(); + r.a = i(); + r.ci = i(); + w = r.errors = []; + if ((c & 0xFA) == 0x72) r.fixed = (c & 1) == 1; + else { + r.type = "Error"; + var s = ["Unspecified error", "Unimplemented CI-Field", "Buffer too long, truncated", "Too many records", + "Premature end of record", "More than 10 DIFE's", "More than 10 VIFE's", + R, "Application too busy for handling readout request", "Too many readouts"]; + if (c == 0x70) { + w.push(s[n == e ? 0 : i() < 10 ? c : 7]); + return r; + } + er(s[1]); + } + r.id = ii("ID"); + + var M = " meter", S = ["Heat" + M, "Cooling" + M, " (Volume measured at ", "return temperature: outlet)", "flow temperature: inlet)", "Customer unit", "Radio converter ", "Access Code "], + D = ["Other", "Oil" + M, "Electricity" + M, "Gas" + M, S[0], "Steam" + M, "Hot water" + M, "Water" + M, "Heat Cost Allocator", R, + S[0] + S[2] + S[3], "Compressed air", S[1] + S[2] + S[3], S[1] + S[2] + S[4], S[0] + S[2] + S[4], "Combined Heat / " + S[1], "Bus / System component", "Unknown device type", "Cold water" + M, "Dual water" + M, + "Pressure" + M + " / pressure device", "A/D Converter", "Warm water" + M, "Calorific value", "Smoke detector / smoke alarm device", "Room sensor", "Gas detector", "Consumption" + M, "Sensor", "Breaker (electricity)", + "Valve (gas or water)", "Switching device", S[5] + " (display device)", S[5], "Waste water" + M, "Garbage", "Carbon dioxide", "Environmental" + M, "System device", "Communication controller", + "Unidirectional repeater", "Bidirectional repeater", S[6] + "(system side)", S[6] + "(meter side)", "Wired Adapter"], + fD = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 3, 4, 5, 6, 7, 8, 9], + vD = [0, 1, 2, 3, 10, 5, 22, 7, 8, 11, 12, 13, 14, 15, 16, 17, + 27, 27, 27, 27, 23, 6, 18, 19, 20, 21, 24, 25, 26, 28, 28, 28, + 29, 30, 31, 31, 31, 32, 33, 33, 34, 35, 36, 37, 37, 37, 37, 37, + 38, 39, 40, 41, 38, 38, 42, 43, 44], + vFunc = ["Instantaneous", "Maximum", "Minimum", "During error state"]; + + function i2fu(i) { + var U = ["Wh", "kWh", "MWh", "kJ", "MJ", "GJ", "W", "kW", "MW", "kJ/h", "MJ/h", "GJ/h", "ml", "l", "m\xB3", "ml/h", "l/h", "m\xB3/h"]; + return i < 2 ? [["h,m,s", "D,M,Y"][i], 0] + : i < 0x38 ? [U[Math.floor((i - 2) / 3)], (i - 2) % 3] + : i < 0x39 ? ["\xB0C", -3] + : i < 0x3A ? [UH, 0] + : [R, 0]; + } + + function m2c(i) { + return i2c((i & 0x1F) + 64); + } + + function deManIdi(n) { + return m2c(n >> 10) + m2c(n >> 5) + m2c(n); + } + + function deManId(a, n) { + return deManIdi(ii("ManID", 1, 2)); + } + + function deD(i) { + return D[i > 0x3F ? 9 : i > 0x38 ? 38 : vD[i]]; + } + + function deS(r) { + var s = r.status; + if (r.fixed) r.cStored = s & 2 ? "At fixed date" : "Actual"; + else { + if ((s & 3) != 3) { + if (s & 1) w.push("Application Busy"); + if (s & 2) w.push("Application Error"); + } + } + if (s & 4) w.push("Power Low"); + if (s & 8) w.push("Permanent Error"); + if (s & 16) w.push("Temporary Error"); + return s & 1; + } + + function nv() { + if (!r.data) r.data = []; + var v = { id: id++ }; + r.data.push(v); + return v; + } + + function sD(d, m) { + r.deviceCode = d; + r.deviceType = m; + } + + function pF() { + r.accessN = i(); + r.status = i(); + var s = deS(r), u1 = i(), u2 = i(), m = (u1 >> 6) | (u2 >> 4 & 0xC); + sD(m, D[fD[m]]); + if (m > 9 && m < 15 && s) s = 2; + var x = nv(), y = nv(), ux = i2fu(u1 & 0x3f), vy = u2 & 0x3f, uy, v = 1; + x.storage = 0; + x.func = vFunc[0]; + x.value = p10(ii("Counter 1", s), ux[1]); + x.unit = ux[0]; + if (vy == 0x3e) uy = ux; + else { + v = 0; + if (vy != 0x3f) uy = i2fu(vy); + } + y.storage = v; + y.func = vFunc[0]; + v = ii("Counter 2", s); + y.value = uy ? p10(v, uy[1]) : v; + y.unit = uy ? uy[0] : ""; + } + + function rif(i) { + var v = ln(i); + v = v ? i[v - 1] : 128; + while (n < e && v >> 7) { + v = a[n++]; + i.push(v); + } + return i; + } + + var T = ["Reserved", "Energy", "Volume", "Mass", "On Time", "Operating Time", "Power", "Volume Flow", "Volume Flow ext.", "Mass flow", + "Flow Temperature", "Return Temperature", "Temperature Difference", "External Temperature", "Pressure", "Time Point", UH, "Averaging Duration", "Actuality Duration", "Credit", + "Debit", "Access Number", "Medium", "Manufacturer", "Parameter set id", "Model/Version", "Hardware version #", "Firmware version #", "Software version #", "Customer location", + "Customer", S[7] + "User", S[7] + "Operator", S[7] + "System Operator", S[7] + "Developer", "Password", "Error flags", "Error mask", "Digital Output", "Digital Input", + "Baudrate", "Response delay time", "Retry", "First cyclic storage #", "Last cyclic storate #", "Storage block size", "Storage interval", "Duration since last readout", "Start of tariff", "Duration of tariff", + "Period of tariff", "Voltage", "Current", "Dimensionless", "Reset counter", "Cumulation counter", "Control signal", "Day of week", "Week number", "Time point of day change", + "State of parameter activation", "Special supplier information", "Duration since last cumulation", "Operating time battery", "Battery change", "Cold/Warm Temperature Limit", "Cumul. count max power" + ], U = ["seconds", "minutes", "hours", "days", "months", "years", "Wh", "J", "m\xB3", "kg", + "W", "J/h", "m\xB3/h", "m\xB3/min", "m\xB3/s", "kg/h", "\xB0C", "K", "bar", "currency unit", + "binary", "baud", "bittimes", "V", "A", "MWh", "GJ", "t", "feet\xB3", "american gallon", + "american gallon/min", "american gallon/h", "MW", "GJ/h", "\xB0F", "revolution / measurement", "liter", "kWh", "kW", "K*l" + ]; + + function deV(v, b, n) { + v.type = T[b[0]]; + var e = b[1]; + if (ln(b) > 1) { + if (e == 5) { + e = 9; + n += 2; + } + if (e == 9) v.unit = U[n]; + else if (e == 8) { + v.type += " (" + (n ? "time & " : "") + "date)"; + v.f = n == 1 ? i2t : i2d; + } else if (e > 5) v.f = e == 7 ? deD : deManIdi; + else { + v.unit = U[b[2]]; + v.e = n + b[1]; + } + } + } + + function deVif(v, d) { + var t = d >> 3 & 0xF, n = d & 7, m = [ + [1, -3, 6], + [1, 1, 7], + [2, -6, 8], + [3, -3, 9], + [[4, 9], [5, 9]], + [6, -3, 10], + [6, 1, 11], + [7, -6, 12], + [8, -7, 13], + [8, -9, 14], + [9, -3, 15], + [[10, -3, 16], [11, -3, 16]], + [[12, -3, 17], [13, -3, 16]], + [[14, -3, 18], [[15, 8], [[16], O]]], + [[17, 9], [18, 9]]]; + if (t == 0xF) { + if (n < 3) v.type = ["Fabrication No", "(Enhanced)", "Bus Address"][n]; + } else { + var b = m[t], i = 2; + for (; isA(b[0]); n &= 0xF ^ 1 << i, b = b[d >> i-- & 1]); + deV(v, b, n); + } + } + + function deVifD(v, d) { + var t = d >> 2 & 0xF, n = d & 3, m = [ + [19, -3, 19], + [20, -3, 19], + [[21], [22, 7], [23, 6], [24]], + [[25], [26], [27], [28]], + [[29], [30], [31], [32]], + [[33], [34], [35], [36, 0, 20]], + [[37], O, [38, 0, 20], [39, 0, 20]], + [[40, 0, 21], [41, 0, 22], [42], O], + [[43], [44], [45], O], + [46, 9], + [[46, 0, 4], [46, 0, 5], O, O], + [47, 9], + [[48, 8], [49, 0, 1], [49, 0, 2], [49, 0, 3]], + [50, 9], + [[50, 0, 4], [50, 0, 5], [53], O], + O, + [[54], [55], [56], [57]], + [[58], [59], [60], [61]], + [62, 5], + [63, 5], + [[64, 8]] + ]; + if (d & 0x40) t = (t & 7) + 16; + var b = d > 0x70 ? O : m[t]; + if ((d & 0x60) == 0x40) { + t = d & 16; + n = d & 0xF; + b = t ? [52, -12, 24] : [51, -9, 23]; + } else { + if (isA(b[0])) { + b = b[n]; + n = 0; + } + } + deV(v, b, n); + } + + function deVifB(v, d) { + var t = d >> 3 & 0xF, n = d & 7, m = [ + [[[1, -1, 25]]], + [[[1, -1, 26]]], + [[[2, 2, 8]]], + [[[3, 2, 27]]], + [[[O, [2, -1, 28]], [[2, -1, 29], [2, 0, 29]]], [[[7, -3, 30], [7, 0, 30]], [[7, 0, 31], O]]], + [[[6, -1, 32]]], + [[[6, -1, 33]]], + O, + O, + O, + O, + [[10, -3, 34], [11, -3, 34]], + [[12, -3, 34], [13, -3, 34]], + O, + [[65, -3, 34], [65, -3, 16]], + [66, -3, 10]]; + var b = m[t], i = 2; + for (; isA(b[0]); n &= 0xF ^ 1 << i, b = d >> i-- & 1 ? (ln(b) < 2 ? O : b[1]) : b[0]); + deV(v, b, n); + } + + function deVife(v, d) { + var e, t = d & 7, p = "per ", m = "multiplied by sek", o = t & 2 ? "out" : "in", + w = d & 8 ? "upper" : "lower", f = d & 4 ? "last" : "first", b = d & 1 ? "end" : "begin", + D = "Duration of ", L = " limit exceed"; + e = d < 2 ? (d ? "Too many DIFE's" : e) + : d < 8 ? ["Storage number", "Unit number", "Tariff number", "Function", "Data class", "Data size"][t - 2] + " not implemented" + : d < 0xb ? e + : d < 0x10 ? ["Too many VIFE's", "Illegal VIF-Group", "Illegal VIF-Exponent", "VIF/DIF mismatch", "Unimplemented action"][t - 3] + : d < 0x15 ? e + : d < 0x19 ? ["No data available (undefined value)", "Data overflow", "Data underflow", "Data error"][t - 5] + : d < 0x1C ? "Premature end of record" + : d < 0x20 ? e + : d < 0x27 ? p + U[t].slice(0, -1) + : d < 0x28 ? p + U[35] + : d < 0x2C ? "increment per " + o + "put pulse on " + o + "put channel #" + (d & 1) + : d < 0x36 ? p + U[[36, 8, 9, 17, 37, 26, 38, 39, 23, 24][d - 0x2C]] + : d < 0x37 ? m + : d < 0x39 ? m + " / " + U[24 - (d & 1)] + : d < 0x3D ? ["start date(/time) of", "VIF contains uncorrected unit instead of corrected unit", "Accumulation only if positive contributions", + "Accumulation of abs value only if negative contributions"][t - 1] + : d < 0x40 ? T[0] + : d < 0x4A ? (t ? "# of exceeds of " + w + " limit" : w + " limit value") + : d < 0x50 ? "Date (/time) of: " + b + " of " + f + " " + w + L + : d < 0x60 ? D + f + " " + w + L + ", " + U[t & 3] + : d < 0x68 ? D + f + ", " + U[t & 3] + : d < 0x70 ? (t & 2 ? "Date (/time) of " + f + " " + b : e) + : d < 0x78 ? (v.e = (v.e || 0) + t - 6, e) + : d < 0x7C ? "Additive correction constant: 10E" + (t - 3) + "*" + v.type + " (offset)" + : d < 0x7D ? e + : d < 0x7E ? (v.e = (v.e || 0) + 3, e) + : ["future value", MS + " data next"][t & 1]; + if (e) v.typeE.push(e); + } + + function deVifs(v) { + var y = v.vif, l = ln(y), i = 0, t = y[i], m = 0x7F, d = t & m, b; + if (t == 0xFD || t == 0xFB) { + d = y[++i] & m; + (t == 0xFD ? deVifD : deVifB)(v, d); + } else if (d < 0x7C) deVif(v, d); + else if (d == 0x7C) { + b = a[(n -= l - 2) - 1]; + v.type = ba2s(sl("VIF type", b)); + y = v.vif = rif([t]); + l = ln(y); + } + if (d == m) v.type = MS; + if (!(y[i] >> 7)) return; + if (d != m) ++i; + v.typeE = []; + b = 0; + while (i < l && i < 11) { + t = y[i++], d = t & m; + b ? v.typeE.push(d) : (b = d == m, deVife(v, d)); + if (!(t & 0x80)) break; + } + if (!ln(v.typeE)) delete v.typeE; + } + + function rv(v) { + deVifs(v); + var y = v.dif, l = ln(y) - 1, p, i, d = y[0], f = d >> 4 & 3, t = d & 0xF, m, b = d & 7, u, s; + if (t == 0xD) { + p = b = a[n++]; + if (b < 0xC0) m = ba2s; + else { + b &= 0xF; + if (p > 0xEF) { + if (p < 0xFB) m = ba2f; + } else { + m = p > 0xDF ? ba2i : ba2bcd; + s = (p & 0xF0) == 0xD0; + } + } + } else { + if (b == 5) { + --b; + m = ba2f; + } else { + if (b == 7) ++b; + m = t & 8 ? ba2bcd : ba2i; + } + } + i = t = sl("Record #" + v.id, b); + if (m) { + try { + t = m(t); + } catch (e) { + v.error = true; + t = e; + } + } + if (!v.error) { + if (v.f) t = v.f(t); + m = Array.isArray(t); + if (m) t = ha2si(t); + if (s) t = m ? (t[0] == "-" ? t.slice(1) : ("-" + t)) : -t; + if (v.e) t = p10(t, v.e); + } + v.value = t; + v.rawValue = i; + v.func = vFunc[f]; + d >>= 6; f = d & 1; i = t = u = 0; + if (d & 2) { + for (; i < l; ++i) { + d = y[i + 1]; + u += (d >> 6 & 1) << i; + t += (d >> 4 & 3) << i * 2; + f += (d & 0xF) << i * 4 + 1; + } + v.device = u; + v.tariff = t; + } + v.storage = f; + delete v.f; + delete v.e; + } + + function pV() { + r.manId = deManId(a, n); + r.version = i(), i(); + sD(c, deD(c)); + r.accessN = i(); + r.status = i(); + deS(r); + n += 2; + while (n < e - 1) { + var t = a[n], v = t == 0x2F ? v : nv(); + if ((t & 0xF) == 0xF) { + t = t >> 4 & 7; ++n; + if (t < 2) { + if (t) v.request = "Readout again"; + v.type = MS; + v.value = sl(v.type, e - n); + } else if (t > 6) v.request = "Global readout"; + } else { + v.dif = rif([]); + v.vif = rif([]); + rv(v); + } + } + } + + r.fixed ? pF() : pV(); + return r; +} + +function unitConv(cfg, f) { + + var U = ["J", "Wh", "W", "J/h"], P = ["", "k", "M", "G"], k, g; + + function x(d) { + var u = d.unit, v = d.value, m; + if (u && v) { + if (m = k[u]) try { + d.value = p10(v, m[0]); + d.unit = m[1]; + } catch (e) { } + } + if (g) try { + g(d); + } catch (e) { } + } + + function p(d) { + var a, i; + if (d && (a = d.data)) for (i in a) x(a[i]); + return d; + } + + function c(d, f) { + k = {}, g = f; + var u, c, o, n, v; + if (d) for (o in d) { + c = d[o], u = U.indexOf(o), v = P.indexOf(c); + if (u >= 0 && v >= 0) for (n in P) k[P[n] + o] = [(n - v) * 3, c + o]; + } + } + + c(cfg, f); + + return { + getUnits: function () { return U.slice(); }, + getPrefixes: function () { return P.slice(); }, + config: c, + process: p + }; + +} + + +function decodeUplink(input) { + var ashex = input.bytes.reduce(function (acc, num) { + return acc + ('0' + num.toString(16)).slice(-2).toUpperCase(); + }, ''); + + var FrameIndex = parseInt(ashex.substr(0, 2), 16); + var BatchFrames = parseInt(ashex.substr(2, 2), 16); + var parsed = {}; + var errors = []; + + if (FrameIndex === 1 && BatchFrames === 1) { + parsed = tmbus(ashex.substr(4)); + } else { + errors.push("Fragmentation not supported -> use Akenza.io to decode fragmented frames"); + } + return { + data: parsed, + warnings: [], + errors: errors + }; +} diff --git a/vendor/acrios/acr-cv-101l-r-eac-inside.png b/vendor/acrios/acr-cv-101l-r-eac-inside.png new file mode 100644 index 0000000000..511ec58aac Binary files /dev/null and b/vendor/acrios/acr-cv-101l-r-eac-inside.png differ diff --git a/vendor/acrios/acr-cv-101l-r-eac.yaml b/vendor/acrios/acr-cv-101l-r-eac.yaml index 4d1c5a27a1..cf44816d80 100644 --- a/vendor/acrios/acr-cv-101l-r-eac.yaml +++ b/vendor/acrios/acr-cv-101l-r-eac.yaml @@ -1,128 +1,98 @@ -name: 230V AC externally powered RS-485 to LoRaWAN® -description: 230V AC externally-powered ACRIOS Systems IoT converter working as RS-485 to LoRaWAN® bridge with implemented LUA scripting interface. The LUA scripting interface allows for message buffering, message splitting, LoRaWAN communication class changes, implementation of custom RS485 protocols as well as Profibus, Modbus RTU, and other operations on the hardware level. +name: RS-485 to LoRaWAN converter, externally powered +description: RS-485 to LoRaWAN converter is used to retrofit ANY RS-485 meter with LoRaWAN communication -# Hardware versions (optional, use when you have revisions) hardwareVersions: - version: 'ACR-CV-101L-RM-D2EAC_v2.0' numeric: 1 + - version: 'ACR-CV-101L-RM-D2EAC_v2.2' + numeric: 2 -# Firmware versions (at least one is mandatory) firmwareVersions: - - # Firmware version - version: '2.5' + - version: '2.5' numeric: 1 - # Corresponding hardware versions (optional) hardwareVersions: - 'ACR-CV-101L-RM-D2EAC_v2.0' - - # Firmware features (optional) - # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how - # often he device sends a message). features: - remote rejoin - transmission interval - - # 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: - # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from - # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. - # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, - # which is verbose. - # vendorID: EU863-870: - # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: acr-cv-otaa-profile + lorawanCertified: true + - version: '2.13.18' + numeric: 2 + hardwareVersions: + - 'ACR-CV-101L-RM-D2EAC_v2.2' + features: + - remote rejoin + - transmission interval + profiles: + EU863-870: + vendorID: acrios id: acr-cv-otaa-profile lorawanCertified: true -# Bridge interfaces (optional) -# Valid values are: modbus, m-bus, can bus, rs-485, sdi-12, analog. +deviceType: cots + bridgeInterfaces: - modbus - rs-485 -# Dimensions in mm (optional) -# Use width, height, length and/or diameter dimensions: width: 145 length: 90 height: 55 -# Weight in grams (optional) -weight: 250 +weight: 166 -# Battery information (optional) battery: replaceable: false type: Externally powered unit 85 - 305V AC -# Operating conditions (optional) operatingConditions: - # Temperature (Celsius) temperature: min: -30 max: 60 + relativeHumidity: + min: 0 + max: 0.85 -# IP rating (optional) -ipCode: IP65 +ipCode: IP67 -# Key provisioning (optional) -# Valid values are: custom (user can configure keys), join server and manifest. keyProvisioning: - custom -# Key programming (optional) -# Valid values are: bluetooth, nfc, wifi, serial (when the user has a serial interface to set the keys) -# and firmware (when the user should change the firmware to set the keys). keyProgramming: - serial - firmware -# Key security (optional) -# Valid values are: none, read protected and secure element. keySecurity: read protected -# Firmware programming (optional) -# Valid values are: serial (when the user has a serial interface to update the firmware), fuota lorawan (when the device -# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). firmwareProgramming: - serial - fuota lorawan -# Product and data sheet URLs (optional) -productURL: https://acrios.com/rs485-iot-prevodnik/?lang=en -dataSheetURL: https://wiki.acrios.com/en/acr-cv/modbus_cv +productURL: https://www.acrios.com/converters/modbus-rs485-na-lorawan +# dataSheetURL: https://wiking.acrios.com/datasheets/ACR-CV-101L-R-EAC.pdf +# onboardingGuideURL: https://wiking.acrios.com/manuals/category/acr-cv-101l-r-x/ -# Commercial information resellerURLs: - name: 'ACRIOS Systems' region: - European Union - url: https://acrios.com/?lang=en + url: https://acrios.com/ msrp: EUR: 141 -# Photos photos: - main: zeus-2pg-rsma.png + main: acr-cv-101l-x-eac.png other: - - acr-cv-aec-angle.jpg - - acr-cv-eac-top.jpg + - acr-cv-101l-x-eac-top.png + - acr-cv-101l-r-eac-inside.png -# Regulatory compliances (optional) compliances: safety: - - body: IEC - norm: EN - standard: 62368-1 - radioEquipment: - - body: ETSI - norm: EN - standard: 301 489-1 - version: 2.2.0 - - body: ETSI + - body: M-Bus norm: EN - standard: 301 489-3 - version: 2.1.0 + standard: 13757-3 diff --git a/vendor/acrios/acr-cv-101l-x-d-top.png b/vendor/acrios/acr-cv-101l-x-d-top.png new file mode 100644 index 0000000000..ec0ab169e6 Binary files /dev/null and b/vendor/acrios/acr-cv-101l-x-d-top.png differ diff --git a/vendor/acrios/acr-cv-101l-x-d.png b/vendor/acrios/acr-cv-101l-x-d.png new file mode 100644 index 0000000000..3982a613f2 Binary files /dev/null and b/vendor/acrios/acr-cv-101l-x-d.png differ diff --git a/vendor/acrios/acr-cv-101l-x-eac-top.png b/vendor/acrios/acr-cv-101l-x-eac-top.png new file mode 100644 index 0000000000..458638327b Binary files /dev/null and b/vendor/acrios/acr-cv-101l-x-eac-top.png differ diff --git a/vendor/acrios/acr-cv-101l-x-eac.png b/vendor/acrios/acr-cv-101l-x-eac.png new file mode 100644 index 0000000000..e9c59da9c1 Binary files /dev/null and b/vendor/acrios/acr-cv-101l-x-eac.png differ diff --git a/vendor/acrios/acr-cv-101ni-w-d2-battery.png b/vendor/acrios/acr-cv-101ni-w-d2-battery.png new file mode 100644 index 0000000000..5bb7c87d6a Binary files /dev/null and b/vendor/acrios/acr-cv-101ni-w-d2-battery.png differ diff --git a/vendor/acrios/acr-cv-101ni-w-d2-inside.png b/vendor/acrios/acr-cv-101ni-w-d2-inside.png new file mode 100644 index 0000000000..b6b6ad7cb9 Binary files /dev/null and b/vendor/acrios/acr-cv-101ni-w-d2-inside.png differ diff --git a/vendor/acrios/acr-cv-101ni-w-d2-top.png b/vendor/acrios/acr-cv-101ni-w-d2-top.png new file mode 100644 index 0000000000..f7d7a17181 Binary files /dev/null and b/vendor/acrios/acr-cv-101ni-w-d2-top.png differ diff --git a/vendor/acrios/acr-cv-101ni-w-d2.png b/vendor/acrios/acr-cv-101ni-w-d2.png new file mode 100644 index 0000000000..209f796055 Binary files /dev/null and b/vendor/acrios/acr-cv-101ni-w-d2.png differ diff --git a/vendor/acrios/acr-cv-101ni-w-d2.yaml b/vendor/acrios/acr-cv-101ni-w-d2.yaml new file mode 100644 index 0000000000..280e58c622 --- /dev/null +++ b/vendor/acrios/acr-cv-101ni-w-d2.yaml @@ -0,0 +1,80 @@ +name: Wireless M-Bus to LoRaWAN converter +description: Wireless M-Bus to LoRaWAN converter is used to retrofit ANY Wireless M-Bus meter with LoRaWAN communication + +hardwareVersions: + - version: 'ACR-CV-101NI-W-D_v4.1' + numeric: 1 + +firmwareVersions: + - # Firmware version + version: '2.13.18' + numeric: 1 + hardwareVersions: + - 'ACR-CV-101NI-W-D_v4.1' + features: + - remote rejoin + - transmission interval + profiles: + EU863-870: + vendorID: acrios + id: acr-cv-otaa-profile + lorawanCertified: true + +deviceType: cots + +additionalRadios: + - cellular + +dimensions: + width: 145 + length: 90 + height: 55 + +weight: 475 + +battery: + replaceable: true + type: Double D-Cell with JST-XH 2pin connector + +operatingConditions: + temperature: + min: -30 + max: 60 + relativeHumidity: + min: 0 + max: 0.85 + +ipCode: IP67 + +keyProvisioning: + - custom + +keyProgramming: + - serial + - firmware + +keySecurity: read protected + +firmwareProgramming: + - serial + - fuota lorawan + +productURL: https://www.acrios.com/converters/wm-bus-nb-iot +# dataSheetURL: https://wiking.acrios.com/datasheets/ACR-CV-101NI-W-D2.pdf +# onboardingGuideURL: https://wiking.acrios.com/manuals/category/acr-cv-101ni-w-x/ + +resellerURLs: + - name: 'ACRIOS Systems' + region: + - European Union + url: https://www.acrios.com/ + +msrp: + EUR: 260 + +photos: + main: acr-cv-101ni-w-d2.png + other: + - acr-cv-101ni-w-d2-top.png + - acr-cv-101ni-w-d2-inside.png + - acr-cv-101ni-w-d2-battery.png diff --git a/vendor/acrios/acr-cv-aec-angle.jpg b/vendor/acrios/acr-cv-aec-angle.jpg deleted file mode 100644 index 19299c8812..0000000000 Binary files a/vendor/acrios/acr-cv-aec-angle.jpg and /dev/null differ diff --git a/vendor/acrios/acr-cv-eac-top.jpg b/vendor/acrios/acr-cv-eac-top.jpg deleted file mode 100644 index 5ab4676c62..0000000000 Binary files a/vendor/acrios/acr-cv-eac-top.jpg and /dev/null differ diff --git a/vendor/acrios/acr-cv-otaa-profile.yaml b/vendor/acrios/acr-cv-otaa-profile.yaml index 4004eef7b2..40db624af1 100644 --- a/vendor/acrios/acr-cv-otaa-profile.yaml +++ b/vendor/acrios/acr-cv-otaa-profile.yaml @@ -1,47 +1,7 @@ -# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 macVersion: 1.0.4 -# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: -# 1.0: TS001-1.0 -# 1.0.1: TS001-1.0.1 -# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB -# 1.0.3: RP001-1.0.3-RevA -# 1.0.4: RP002-1.0.0 or RP002-1.0.1 -# 1.1: RP001-1.1-RevA or RP001-1.1-RevB regionalParametersVersion: RP002-1.0.0 - -# Whether the end device supports join (OTAA) or not (ABP) supportsJoin: true -# If your device is an ABP device (supportsJoin is false), uncomment the following fields: -# RX1 delay -#rx1Delay: 5 -# RX1 data rate offset -#rx1DataRateOffset: 0 -# RX2 data rate index -#rx2DataRateIndex: 0 -# RX2 frequency (MHz) -#rx2Frequency: 869.525 -# Factory preset frequencies (MHz) -#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] - -# Maximum EIRP maxEIRP: 16 -# Whether the end device supports 32-bit frame counters supports32bitFCnt: true - -# Whether the end device supports class B supportsClassB: false -# If your device supports class B, uncomment the following fields: -# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) -#classBTimeout: 60 -# Ping slot period (seconds) -#pingSlotPeriod: 128 -# Ping slot data rate index -#pingSlotDataRateIndex: 0 -# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. -#pingSlotFrequency: 869.525 - -# Whether the end device supports class C supportsClassC: false -# If your device supports class C, uncomment the following fields: -# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) -#classCTimeout: 60 diff --git a/vendor/acrios/acr-slc-profile.yaml b/vendor/acrios/acr-slc-100l-zhaga-dali-profile.yaml similarity index 100% rename from vendor/acrios/acr-slc-profile.yaml rename to vendor/acrios/acr-slc-100l-zhaga-dali-profile.yaml diff --git a/vendor/acrios/acr-slc-100l-zhaga-dali-top.png b/vendor/acrios/acr-slc-100l-zhaga-dali-top.png new file mode 100644 index 0000000000..8d70bed026 Binary files /dev/null and b/vendor/acrios/acr-slc-100l-zhaga-dali-top.png differ diff --git a/vendor/acrios/acr-slc-100l-zhaga-dali.png b/vendor/acrios/acr-slc-100l-zhaga-dali.png index d6a9567acc..4f4bc7b39a 100644 Binary files a/vendor/acrios/acr-slc-100l-zhaga-dali.png and b/vendor/acrios/acr-slc-100l-zhaga-dali.png differ diff --git a/vendor/acrios/acr-slc-100l-zhaga-dali.yaml b/vendor/acrios/acr-slc-100l-zhaga-dali.yaml index 24b927a8bc..be65ebfaeb 100644 --- a/vendor/acrios/acr-slc-100l-zhaga-dali.yaml +++ b/vendor/acrios/acr-slc-100l-zhaga-dali.yaml @@ -1,34 +1,24 @@ name: LoRaWAN street light module (ZHAGA DALI) description: Smart street lighting module with ZHAGA socket based on the STM32WL with the 40mm enclosure in diameter is DALI and DALI-2 compatible. We can provide you with just a hardware or both with the complex solution or just a backend with API access. + hardwareVersions: - version: 'v1.0' numeric: 1 + firmwareVersions: - # Firmware version version: '1.2' numeric: 1 hardwareVersions: - 'v1.0' - # Firmware features (optional) - # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how - # often he device sends a message). features: - remote rejoin - transmission interval - profiles: EU863-870: lorawanCertified: true - id: acr-slc-profile - -# 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, smart valve, snr, so2, -# 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. + id: acr-slc-100l-zhaga-dali-profile + sensors: - light - temperature @@ -37,30 +27,34 @@ dimensions: width: 40 length: 40 height: 40 + weight: 120 + battery: replaceable: false + operatingConditions: temperature: min: -30 max: 60 + ipCode: IP67 + keyProvisioning: - custom + keyProgramming: - firmware + keySecurity: read protected -# Firmware programming (optional) -# Valid values are: serial (when the user has a serial interface to update the firmware), fuota lorawan (when the device -# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). firmwareProgramming: - fuota lorawan productURL: https://acrios.com/zhaga-lwes-modul/?lang=en + dataSheetURL: https://wiki.acrios.com/en/SLC -# Commercial information resellerURLs: - name: 'ACRIOS Systems' region: @@ -72,8 +66,9 @@ msrp: photos: main: acr-slc-100l-zhaga-dali.png + other: + - acr-slc-100l-zhaga-dali-top.png -# Regulatory compliances (optional) compliances: safety: - body: IEC diff --git a/vendor/acrios/acr-slc.png b/vendor/acrios/acr-slc.png deleted file mode 100644 index 92a7c28736..0000000000 Binary files a/vendor/acrios/acr-slc.png and /dev/null differ diff --git a/vendor/acrios/acr-slc.yaml b/vendor/acrios/acr-slc.yaml deleted file mode 100644 index 5d1cd6ee0b..0000000000 --- a/vendor/acrios/acr-slc.yaml +++ /dev/null @@ -1,90 +0,0 @@ -name: LoRaWAN street light module -description: Smart street lighting module with ZHAGA socket based on the STM32WL with the 40mm enclosure in diameter is DALI and DALI-2 compatible. We can provide you with just a hardware or both with the complex solution or just a backend with API access. -hardwareVersions: - - version: 'v1.0' - numeric: 1 -firmwareVersions: - - # Firmware version - version: '1.2' - numeric: 1 - hardwareVersions: - - 'v1.0' - # Firmware features (optional) - # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how - # often he device sends a message). - features: - - remote rejoin - - transmission interval - - profiles: - EU863-870: - lorawanCertified: true - id: acr-slc-profile - -# 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, smart valve, snr, so2, -# 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: - - light - - temperature - -dimensions: - width: 40 - length: 40 - height: 40 -weight: 120 -battery: - replaceable: false -operatingConditions: - temperature: - min: -30 - max: 60 -ipCode: IP67 -keyProvisioning: - - custom -keyProgramming: - - firmware -keySecurity: read protected - -# Firmware programming (optional) -# Valid values are: serial (when the user has a serial interface to update the firmware), fuota lorawan (when the device -# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). -firmwareProgramming: - - fuota lorawan - -productURL: https://acrios.com/zhaga-lwes-modul/?lang=en -dataSheetURL: https://wiki.acrios.com/en/SLC - -# Commercial information -resellerURLs: - - name: 'ACRIOS Systems' - region: - - European Union - url: https://acrios.com/?lang=en - -msrp: - EUR: 69 - -photos: - main: acr-slc.png - -# Regulatory compliances (optional) -compliances: - safety: - - body: IEC - norm: EN - standard: 62368-1 - radioEquipment: - - body: ETSI - norm: EN - standard: 301 489-1 - version: 2.2.0 - - body: ETSI - norm: EN - standard: 301 489-3 - version: 2.1.0 diff --git a/vendor/acrios/acrios-logo.png b/vendor/acrios/acrios-logo.png new file mode 100644 index 0000000000..baa0377198 Binary files /dev/null and b/vendor/acrios/acrios-logo.png differ diff --git a/vendor/acrios/acrioslogo.png b/vendor/acrios/acrioslogo.png deleted file mode 100644 index 4dfe4c62ca..0000000000 Binary files a/vendor/acrios/acrioslogo.png and /dev/null differ diff --git a/vendor/acrios/index.yaml b/vendor/acrios/index.yaml index fe7c7bd3be..4b4387bbf2 100644 --- a/vendor/acrios/index.yaml +++ b/vendor/acrios/index.yaml @@ -1,8 +1,9 @@ endDevices: - - acr-slc + - acr-slc-100l-zhaga-dali - acr-cv-101l-m-d - acr-cv-101l-m-eac - acr-cv-101l-r-eac + - acr-cv-101ni-w-d2 profileIDs: '1': endDeviceID: 'acr-cv-101l-r-eac' @@ -10,7 +11,7 @@ profileIDs: hardwareVersion: 'ACR-CV-101L-RM-D2EAC_v2.0' region: 'EU863-870' '2': - endDeviceID: 'acr-slc' + endDeviceID: 'acr-slc-100l-zhaga-dali' firmwareVersion: '1.2' hardwareVersion: 'v1.0' region: 'EU863-870' diff --git a/vendor/acrios/zeus-2pg-rsma.png b/vendor/acrios/zeus-2pg-rsma.png deleted file mode 100644 index 2d07f56f3e..0000000000 Binary files a/vendor/acrios/zeus-2pg-rsma.png and /dev/null differ diff --git a/vendor/atim/Produit-ACW-CTS.png b/vendor/atim/Produit-ACW-CTS.png new file mode 100644 index 0000000000..8d90c8a602 Binary files /dev/null and b/vendor/atim/Produit-ACW-CTS.png differ diff --git a/vendor/atim/acw-wl.png b/vendor/atim/acw-wl.png new file mode 100644 index 0000000000..29427341bd Binary files /dev/null and b/vendor/atim/acw-wl.png differ diff --git a/vendor/atim/decodeur.js b/vendor/atim/decodeur.js index 8a0e6ada35..2081512ec9 100644 --- a/vendor/atim/decodeur.js +++ b/vendor/atim/decodeur.js @@ -22,7 +22,8 @@ function decodeUplink(input) { errors: errors, warnings: warnings }; -}; +} + function postProcess(data, decoded) { /*gamme acw*/ @@ -41,7 +42,7 @@ function postProcess(data, decoded) { postProcessPeriode(decoded,data); postProcessTension(decoded,data); postProcessSpecifique(decoded,data); - + postProcessHistoEchan(decoded,data); /*ancien produit */ postProcessAncienCompteur(decoded,data); @@ -67,9 +68,9 @@ function postProcess(data, decoded) { function postProcessSpecifique(decoded,data){ if(decoded.wr != undefined){ if(decoded.wr[1]===0x01){ - var wr = "câble Wirecut non coupé"; + var wr = "cable Wirecut non coupé"; }else if(decoded.wr[1]===0x20){ - var wr = "câble Wirecut coupé"; + var wr = "cable Wirecut coupé"; } decoded.wr = { value : wr @@ -90,11 +91,40 @@ function postProcessTension(decoded,data){ unit : "V" }; } + if(decoded.tension != undefined){ + var valeur_echan_hist = (data.echan * data.historique); + var valeur_tension = []; + for(var i=0;i1) && (i>16 )/100 === -327.68){ - valeur_temp0 += "erreur"; + valeur_temp0.push("erreur"); }else{ - valeur_temp0 += (((decoded.temp0[1+i*2]<<8 | decoded.temp0[2+i*2])<<16>>16 )/100).toString() ; - } - - if((i%(data.echan) === (data.echan-1)) && (valeur_echan_hist != 1) && (i != (valeur_echan_hist-1))){ - valeur_temp0 += " ][ "; - }else if(i === (valeur_echan_hist-1)){ - valeur_temp0 += " ]"; - }else{ - valeur_temp0 += ' ; '; + valeur_temp0.push(((decoded.temp0[1+i*2]<<8 | decoded.temp0[2+i*2])<<16>>16 )/100) ; } } @@ -155,16 +177,9 @@ function postProcessTemp(decoded,data){ if(decoded.temp1 != undefined){ for(var i=0;i>16)/100 === -327.68){ - valeur_temp1 += "erreur"; + valeur_temp1.push("erreur"); }else{ - valeur_temp1 += (((decoded.temp1[1+i*2]<<8 | decoded.temp1[2+i*2])<<16>>16)/100).toString() ; - } - if((i%(data.echan) === (data.echan-1)) && (valeur_echan_hist != 1) && (i != (valeur_echan_hist-1))){ - valeur_temp1 += " ][ "; - }else if(i === (valeur_echan_hist-1)){ - valeur_temp1 += " ]"; - }else{ - valeur_temp1 += ' ; '; + valeur_temp1.push(((decoded.temp1[1+i*2]<<8 | decoded.temp1[2+i*2])<<16>>16)/100) ; } } decoded.temperature1 = { @@ -177,25 +192,17 @@ function postProcessTemp(decoded,data){ } function postProcessHum(decoded,data){ var j = 0; - var valeur_hum0 = "[ "; - var valeur_hum1 = "[ "; + var valeur_hum0 = []; + var valeur_hum1 = []; var valeur_echan_hist = (data.echan * data.historique); if(decoded.hum0 != undefined){ for(var i=0;i>16).toString(); - if((i%(data.echan) === (data.echan-1)) && (valeur_echan_hist != 1) && (i != (valeur_echan_hist-1))){ - valeur_dp += " ][ "; - }else if(i === (valeur_echan_hist-1)){ - valeur_dp += " ]"; - }else{ - valeur_dp += ' ; '; - } + valeur_dp.push((decoded.dp[1+i*2]<<8 | decoded.dp[2+i*2])<<16>>16); } decoded.pression_differentielle = { value : valeur_dp, @@ -253,48 +246,35 @@ function postProcessDp(decoded,data){ } } function postProcessCov(decoded,data){ - var valeur_cov = "[ "; + var valeur_cov = []; var valeur_echan_hist = (data.echan * data.historique); if(decoded.cov != undefined){ for(var i=0;i= 1 | echan >= 1){ res_str = res_str + 'ubyte[2] periode;'; - start_bcl +=2; + start_bcl += 2; + } + if(etendu){ + res_str = res_str + 'ubyte[3] histo_echan;'; + start_bcl += 3; } if(historique<1){ historique = 1; @@ -1340,6 +1319,25 @@ function decodeFrame(frame,historique,echan,Horodatage,alerte){ data.voieComptage[ctn_voie_comptage] = voie; ctn_voie_comptage++; break; + + case 0x0a: + k=1; + for(var j=0;j<(historique*echan);j++){ + i += 2; + k += 2; + } + res_str = res_str + 'ubyte['+ k +'] tension;'; + i++; + break; + case 0x0b: + k=1; + for(var j=0;j<(historique*echan);j++){ + i += 2; + k += 2; + } + res_str = res_str + 'ubyte['+ k +'] courant;'; + i++; + break; default: i++; } @@ -1562,10 +1560,18 @@ function frame_type_ancien(encoded){ frameType = "Trame alerte état câble coupé"; }else if(oct1 === 0x09){ frameType = "Trame de détection de changement d'état (TOR)"; + }else if(oct1 === 0x30){ + frameType = "Trame Compteur mode ECO (Compteur 1 22 bits et 5 deltas 32 bits LoraWan )"; }else if(oct1 === 0x31){ frameType = "Trame Test LoraWan"; + }else if(oct1 === 0x39){ + frameType = "Trame 39 Compteur mode ECO (Compteur 1 20 bits et 5 deltas 12 bits concaténés SIGFOX)"; + }else if(oct1 === 0x3a){ + frameType = "Trame 3A Compteur mode ECO (Compteur 1 20 bits et 5 deltas 12 bits concaténés SIGFOX)"; + }else if(oct1 === 0x3b){ + frameType = "Trame 3B Compteur mode ECO (Compteur 1 20 bits et 5 deltas 12 bits concaténés SIGFOX)"; }else if(oct1 === 0x18){ - frameType = "Trame de relevé périodique d'une valeur 0-10V"; + frameType = "Trame de relevé périodique d'une valeur 0-10V"; }else if(oct1 === 0x19){ frameType = "Trame de relevé périodique d'une valeur 0- 20mA"; }else if(oct1 === 0x1e){ @@ -1584,6 +1590,8 @@ function frame_type_ancien(encoded){ frameType = "Trame de fin d’alerte HAUT d’une valeur 0-10V"; }else if(oct1 === 0x25){ frameType = "Trame de fin d'alerte HAUT d'une valeur 4-20mA"; + }else{ + frameType = "Type de trame inconnu"; } return frameType; } @@ -1591,7 +1599,7 @@ function decode_trame_ancien(encoded,frame_type){ var bytes = hexToBytes(encoded); var res_str = 'byte frame_type;'; var data = {}; - switch (frameType) { + switch (frame_type) { case "Trame de vie": res_str = res_str + 'ubyte[2] tensionc;'; break; @@ -1642,9 +1650,7 @@ function decode_trame_ancien(encoded,frame_type){ for(var j=0;j> 5]; + data.heating_control.mode.active_mode.unit = "string"; + + data.heating_control.mode.holiday.is_pending = {}; + data.heating_control.mode.holiday.is_pending.value = !!(device_flags & (1 << 4)); + data.heating_control.mode.holiday.is_pending.unit = "bool"; + + data.heating_control.mode.window_open_detection.is_open = {}; + data.heating_control.mode.window_open_detection.is_open.value = !!(device_flags & (1 << 3)); + data.heating_control.mode.window_open_detection.is_open.unit = "bool"; + + data.battery_cover_locked = {}; + data.battery_cover_locked.value = !!(device_flags & (1 << 2)); + data.battery_cover_locked.unit = "bool"; + } + break; + + case "COMMAND_ID_GET_BATTERY_VOLTAGE": + data.battery_voltage = {}; + data.battery_voltage.value = ( input.bytes[idx++] * 10 + 1500).toFixed(0); + data.battery_voltage.unit = "mV"; + break; + + case "COMMAND_ID_GET_BATTTERY_COVER_LOCK_STATUS": + data.battery_cover_locked = {}; + data.battery_cover_locked.value = !!(input.bytes[idx++] & 0x01); + data.battery_cover_locked.unit = "bool"; + break; + + case "COMMAND_ID_GET_ERROR_CODE": + data.error_code = {}; + data.error_code.value = ERROR_CODE[input.bytes[idx++]]; + data.error_code.unit = "string"; + break; + + case "COMMAND_ID_GET_DEVICE_TIME": + data.device_time = data.device_time || {}; + data.device_time.local = data.device_time.local || {}; + data.device_time.local.second = {}; + data.device_time.local.minute = {}; + data.device_time.local.hour = {}; + data.device_time.local.day = {}; + data.device_time.local.weekday = {}; + data.device_time.local.month = {}; + data.device_time.local.year = {}; + data.device_time.local.is_dst = {}; + data.device_time.local.utc_offset = {}; + + data.device_time.local.second.value = input.bytes[idx++] & 0x1F; + data.device_time.local.second.unit = "s"; + + data.device_time.local.minute.value = (input.bytes[idx] >> 2) & 0x3F; + data.device_time.local.minute.unit = "min"; + + data.device_time.local.hour.value = ((input.bytes[idx++] & 0x03) << 3) + (input.bytes[idx] >> 5); + data.device_time.local.hour.unit = "h"; + + data.device_time.local.day.value = input.bytes[idx++] & 0x1F; + data.device_time.local.day.unit = "d"; + + data.device_time.local.is_dst.value = !!(input.bytes[idx] & 0x80); + data.device_time.local.is_dst.unit = "bool"; + + data.device_time.local.weekday.value = WEEKDAY[(input.bytes[idx] >> 4) & 0x07]; + data.device_time.local.weekday.unit = "string"; + + data.device_time.local.month.value = MONTH[input.bytes[idx++] & 0x0F]; + data.device_time.local.month.unit = "string"; + + data.device_time.local.year.value = input.bytes[idx++] + 2000; + data.device_time.local.year.unit = "a"; + + data.device_time.local.utc_offset.value = (input.bytes[idx++] * 0.25 - 12).toFixed(2); + data.device_time.local.utc_offset.unit = "h"; + break; + + case "COMMAND_ID_GET_DEVICE_TIME_CONFIG": + data.device_time = data.device_time || {}; + data.device_time.config = data.device_time.config || {}; + data.device_time.config.auto_time_sync_en = {}; + data.device_time.config.utc_offset = {}; + data.device_time.config.utc_dst_offset = {}; + data.device_time.config.utc_dst_begin = {}; + data.device_time.config.utc_dst_end = {}; + data.device_time.config.utc_dst_begin.week_of_month = {}; + data.device_time.config.utc_dst_end.week_of_month = {}; + data.device_time.config.utc_dst_begin.month = {}; + data.device_time.config.utc_dst_end.month = {}; + data.device_time.config.utc_dst_begin.weekday = {}; + data.device_time.config.utc_dst_end.weekday = {}; + data.device_time.config.utc_dst_begin.hour = {}; + data.device_time.config.utc_dst_end.hour = {}; + data.device_time.config.utc_dst_begin.minute = {}; + data.device_time.config.utc_dst_end.minute = {}; + + data.device_time.config.auto_time_sync_en.value = !!(input.bytes[idx] >> 7); + data.device_time.config.auto_time_sync_en.unit = "bool"; + + data.device_time.config.utc_offset.value = ((input.bytes[idx++] & 0x7F) * 0.25 - 12).toFixed(2); + data.device_time.config.utc_offset.unit = "h"; + + data.device_time.config.utc_dst_begin.week_of_month.value = WEEK_OF_MONTH[ (input.bytes[idx] >> 4) & 0x0F ]; + data.device_time.config.utc_dst_begin.week_of_month.unit = "string"; + + data.device_time.config.utc_dst_begin.month.value = MONTH[input.bytes[idx++] & 0x0F]; + data.device_time.config.utc_dst_begin.month.unit = "string"; + + data.device_time.config.utc_dst_begin.weekday.value = WEEKDAY[input.bytes[idx] >> 5]; + data.device_time.config.utc_dst_begin.weekday.unit = "string"; + + data.device_time.config.utc_dst_begin.hour.value = (input.bytes[idx++] & 0x0F); + data.device_time.config.utc_dst_begin.hour.unit = "h"; + + data.device_time.config.utc_dst_offset.value = ((input.bytes[idx++] & 0x7F) * 0.25 - 12).toFixed(2); + data.device_time.config.utc_dst_offset.unit = "h"; + + data.device_time.config.utc_dst_end.week_of_month.value = WEEK_OF_MONTH[ (input.bytes[idx] >> 4) & 0x0F ]; + data.device_time.config.utc_dst_end.week_of_month.unit = "string"; + + data.device_time.config.utc_dst_end.month.value = MONTH[input.bytes[idx++] & 0x0F]; + data.device_time.config.utc_dst_end.month.unit = "string"; + + data.device_time.config.utc_dst_end.weekday.value = WEEKDAY[input.bytes[idx] >> 5]; + data.device_time.config.utc_dst_end.weekday.unit = "string"; + + data.device_time.config.utc_dst_end.hour.value = (input.bytes[idx++] & 0x0F); + data.device_time.config.utc_dst_end.hour.unit = "h"; + + data.device_time.config.utc_dst_begin.minute.value = (input.bytes[idx] >> 4) * 5; + data.device_time.config.utc_dst_begin.minute.unit = "min"; + + data.device_time.config.utc_dst_end.minute.value = (input.bytes[idx++] & 0x0F) * 5; + data.device_time.config.utc_dst_end.minute.unit = "min"; + break; + + case "COMMAND_ID_GET_MODE_STATUS": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.active_main_mode = {}; + data.heating_control.mode.holiday = data.heating_control.mode.holiday || {}; + data.heating_control.mode.holiday.is_active = {}; + data.heating_control.mode.holiday.is_pending = {}; + data.heating_control.mode.boost = data.heating_control.mode.boost || {}; + data.heating_control.mode.boost.is_active = {}; + data.heating_control.mode.frost_protection = data.heating_control.mode.frost_protection || {}; + data.heating_control.mode.frost_protection.is_active = {}; + data.heating_control.mode.window_open_detection = data.heating_control.mode.window_open_detection || {}; + data.heating_control.mode.window_open_detection.is_active = {}; + data.heating_control.mode.emergency = data.heating_control.mode.emergency || {}; + data.heating_control.mode.emergency.is_active = {}; + data.heating_control.mode.auto = data.heating_control.mode.auto || {}; + data.heating_control.mode.auto.selected_week_program = {}; + + data.heating_control.mode.active_main_mode.value = ACTIVE_MODE[input.bytes[idx] >> 6]; + data.heating_control.mode.active_main_mode.unit = "string"; + + data.heating_control.mode.holiday.is_active.value = !!(input.bytes[idx] & (1 << 5)); + data.heating_control.mode.holiday.is_active.unit = "bool"; + + data.heating_control.mode.holiday.is_pending.value = !!(input.bytes[idx] & (1 << 4)); + data.heating_control.mode.holiday.is_pending.unit = "bool"; + + data.heating_control.mode.boost.is_active.value = !!(input.bytes[idx] & (1 << 3)); + data.heating_control.mode.boost.is_active.unit = "bool"; + + data.heating_control.mode.frost_protection.is_active.value = !!(input.bytes[idx] & (1 << 2)); + data.heating_control.mode.frost_protection.is_active.unit = "bool"; + + data.heating_control.mode.window_open_detection.is_active.value = !!(input.bytes[idx] & (1 << 1)); + data.heating_control.mode.window_open_detection.is_active.unit = "bool"; + + data.heating_control.mode.emergency.is_active.value = !!(input.bytes[idx++] & (1 << 0)); + data.heating_control.mode.emergency.is_active.uint = "bool"; + + data.heating_control.mode.auto.selected_week_program.value = (input.bytes[idx++] >> 6); + data.heating_control.mode.auto.selected_week_program.unit = "uint"; + break; + + case "COMMAND_ID_GET_HOLIDAY_MODE_CONFIG": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.holiday = data.heating_control.mode.holiday || {}; + data.heating_control.mode.holiday = {}; + data.heating_control.mode.holiday.begin = data.heating_control.mode.holiday.begin || {}; + data.heating_control.mode.holiday.end = data.heating_control.mode.holiday.end || {}; + data.heating_control.mode.holiday.begin.minute = {}; + data.heating_control.mode.holiday.begin.hour = {}; + data.heating_control.mode.holiday.begin.day = {}; + data.heating_control.mode.holiday.begin.month = {}; + data.heating_control.mode.holiday.begin.year = {}; + data.heating_control.mode.holiday.end.minute = {}; + data.heating_control.mode.holiday.end.hour = {}; + data.heating_control.mode.holiday.end.day = {}; + data.heating_control.mode.holiday.end.month = {}; + data.heating_control.mode.holiday.end.year = {}; + data.heating_control.mode.holiday.set_point_temperature = {}; + + data.heating_control.mode.holiday.begin.minute.value = ((input.bytes[idx] >> 2) & 0x0F) * 5; + data.heating_control.mode.holiday.begin.minute.unit = "min"; + + data.heating_control.mode.holiday.begin.hour.value = ((input.bytes[idx++] & 0x03) << 3) + (input.bytes[idx] >> 5); + data.heating_control.mode.holiday.begin.hour.unit = "h"; + + data.heating_control.mode.holiday.begin.day.value = input.bytes[idx++] & 0x1F; + data.heating_control.mode.holiday.begin.day.unit = "d"; + + data.heating_control.mode.holiday.end.minute.value = ((input.bytes[idx] >> 2) & 0x0F) * 5; + data.heating_control.mode.holiday.end.minute.unit = "min"; + + data.heating_control.mode.holiday.end.hour.value = ((input.bytes[idx++] & 0x03) << 3) + (input.bytes[idx] >> 5); + data.heating_control.mode.holiday.end.hour.unit = "h"; + + data.heating_control.mode.holiday.end.day.value = input.bytes[idx++] & 0x1F; + data.heating_control.mode.holiday.end.day.unit = "d"; + + data.heating_control.mode.holiday.begin.month.value = MONTH[input.bytes[idx] >> 4]; + data.heating_control.mode.holiday.begin.month.unit = "string"; + data.heating_control.mode.holiday.end.month.value = MONTH[input.bytes[idx++] &0x0F]; + data.heating_control.mode.holiday.end.month.unit = "string"; + + data.heating_control.mode.holiday.begin.year.value = input.bytes[idx++] + 2000; + data.heating_control.mode.holiday.begin.year.unit = "a"; + + data.heating_control.mode.holiday.end.year.value = input.bytes[idx++] + 2000; + data.heating_control.mode.holiday.end.year.unit = "a"; + + data.heating_control.mode.holiday.set_point_temperature.value = (input.bytes[idx++] * 0.5).toFixed(1); + data.heating_control.mode.holiday.set_point_temperature.unit = "°C"; + break; + + case "COMMAND_ID_GET_BOOST_CONFIG": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.boost = data.heating_control.mode.boost || {}; + data.heating_control.mode.boost.config = data.heating_control.mode.boost.config || {}; + + data.heating_control.mode.boost.config.duration = {}; + data.heating_control.mode.boost.config.duration.value = input.bytes[idx++] * 15; + data.heating_control.mode.boost.config.duration.unit = "s"; + + data.heating_control.mode.boost.config.valve_position = {}; + data.heating_control.mode.boost.config.valve_position.value = (input.bytes[idx++] * 0.5 ).toFixed(0); + data.heating_control.mode.boost.config.valve_position.unit = "%"; + break; + + case "COMMAND_ID_GET_WEEK_PROGRAM": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.auto = data.heating_control.mode.auto || {}; + data.heating_control.mode.auto.week_program_1 = {}; + + var week_program_nbr = (input.bytes[idx] >> 4) & 0x03; + var nbr_time_switching_points = input.bytes[idx++] & 0x0F; + + const time_switching_point = {}; + + switch(week_program_nbr) + { + case 0: + data.heating_control.mode.auto.week_program_1 = {}; + break; + + case 1: + data.heating_control.mode.auto.week_program_2 = {}; + break; + + case 2: + data.heating_control.mode.auto.week_program_3 = {}; + break; + + default: + + break; + } + + for(let i = 0; i < nbr_time_switching_points; i++) + { + + time_switching_point.minute = (input.bytes[idx] >> 4) * 5; + time_switching_point.hour = ((input.bytes[idx++] & 0x0F) << 1) + (input.bytes[idx] >> 7); + time_switching_point.weekdays = input.bytes[idx++] & 0x7F; + time_switching_point.set_point_temperature = (input.bytes[idx++] * 0.2).toFixed(1); + + switch(week_program_nbr) + { + case 0: + data.heating_control.mode.auto.week_program_1[i] = Object.assign( {}, time_switching_point); + break; + + case 1: + data.heating_control.mode.auto.week_program_2[i] = Object.assign( {}, time_switching_point); + break; + + case 2: + data.heating_control.mode.auto.week_program_3[i] = Object.assign( {}, time_switching_point); + break; + + default: + + break; + } + } + break; + + case "COMMAND_ID_GET_VALVE_POSITION": + data.heating_control = data.heating_control || {}; + data.heating_control.valve_position = {}; + + data.heating_control.valve_position.value = (input.bytes[idx++] * 0.5 ).toFixed(0); + data.heating_control.valve_position.unit = "%"; + break; + + case "COMMAND_ID_GET_VALVE_SET_POINT_POSITION": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.manu_pos = data.heating_control.mode.manu_pos ||{}; + data.heating_control.mode.manu_pos.valve_set_point_position = {}; + + data.heating_control.mode.manu_pos.valve_set_point_position.value = (input.bytes[idx++] * 0.5).toFixed(0); + data.heating_control.mode.manu_pos.valve_set_point_position.unit = "%"; + break; + + case "COMMAND_ID_GET_VALVE_OFFSET": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + data.heating_control.config.valve = data.heating_control.config.valve || {}; + + data.heating_control.config.valve.position_offset = {}; + data.heating_control.config.valve.position_offset.value = (input.bytes[idx++] * 0.5).toFixed(0); + data.heating_control.config.valve.position_offset.unit = "%"; + break; + + case "COMMAND_ID_GET_VALVE_MAXIMUM_POSITION": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + data.heating_control.config.valve = data.heating_control.config.valve || {}; + + data.heating_control.config.valve.max_position = {}; + data.heating_control.config.valve.max_position.value = (input.bytes[idx++] * 0.5).toFixed(0); + data.heating_control.config.valve.max_position.unit = "%"; + break; + case "COMMAND_ID_GET_VALVE_EMERGENCY_POSITION": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.emergency = data.heating_control.mode.emergency || {}; + data.heating_control.mode.emergency.config = data.heating_control.mode.emergency.config || {}; + data.heating_control.mode.emergency.config.valve_set_point_position = data.heating_control.mode.emergency.config.valve_set_point_position || {}; + + data.heating_control.mode.emergency.config.valve_set_point_position.value = (input.bytes[idx++] * 0.5).toFixed(0); + data.heating_control.mode.emergency.config.valve_set_point_position.unit = "%"; + break; + + case "COMMAND_ID_GET_SET_POINT_TEMPERATURE": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.manu_temp = data.heating_control.mode.manu_temp || {}; + + data.heating_control.mode.manu_temp.value = (input.bytes[idx++] * 0.5).toFixed(1); + data.heating_control.mode.manu_temp.unit = "°C"; + break; + + case "COMMAND_ID_GET_TEMPERATURE_OFFSET": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + data.heating_control.config.temperature = data.heating_control.config.temperature || {}; + data.heating_control.config.temperature.offset = data.heating_control.config.temperature.offset || {}; + + data.heating_control.config.temperature.offset.value = ((input.bytes[idx++] * 0.1) - 12.8).toFixed(1); + data.heating_control.config.temperature.offset.unit = "K"; + break; + + case "COMMAND_ID_GET_HEATING_CNTRL_INPUT_ROOM_TEMPERATURE": + data.heating_control = data.heating_control || {}; + data.heating_control.room_temperature = {}; + + data.heating_control.room_temperature.value = (input.bytes[idx++] * 0.5).toFixed(1); + data.heating_control.room_temperature.unit = "°C"; + break; + + case "COMMAND_ID_GET_HEATING_CNTRL_INPUT_SET_POINT_TEMPERATURE": + data.heating_control = data.heating_control || {}; + data.heating_control.set_point_temperature = {}; + + data.heating_control.set_point_temperature.value = (input.bytes[idx++] * 0.5).toFixed(1); + data.heating_control.set_point_temperature.unit = "°C"; + break; + + case "COMMAND_ID_GET_HEATING_CNTRL_CONFIG": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + + data.heating_control.config.adaptive_gain_adjustment_enabled = {}; + data.heating_control.config.adaptive_gain_adjustment_enabled.value = !!(input.bytes[idx] & (1 << 7)); + data.heating_control.config.adaptive_gain_adjustment_enabled.unit = "bool"; + + data.heating_control.config.controller_temperature_input_select = {}; + data.heating_control.config.controller_temperature_input_select.value = !!(input.bytes[idx++] & (1 << 6)); + data.heating_control.config.controller_temperature_input_select.unit = "bool"; + break; + + case "COMMAND_ID_GET_HEATING_CNTRL_STATIC_GAINS": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + data.heating_control.config.static_gain = data.heating_control.config.static_gain || {}; + + data.heating_control.config.static_gain.p = {}; + data.heating_control.config.static_gain.p.value = (input.bytes[idx++] << 8) + input.bytes[idx++]; + data.heating_control.config.static_gain.i = {}; + data.heating_control.config.static_gain.i.value = (input.bytes[idx++] / 1000000); + data.heating_control.config.static_gain.unit = "uint"; + break; + case "COMMAND_ID_GET_HEATING_CNTRL_INPUT_GAINS": + data.heating_control = data.heating_control || {}; + data.heating_control.input_gain = data.heating_control.input_gain || {}; + + data.heating_control.input_gain.p = {}; + data.heating_control.input_gain.p.value = (input.bytes[idx++] << 8) + input.bytes[idx++]; + data.heating_control.input_gain.i = {}; + data.heating_control.input_gain.i.value = (input.bytes[idx++] / 500000); + data.heating_control.input_gain.unit = "uint"; + break; + case "COMMAND_ID_GET_WINDOW_OPEN_STATUS": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.window_open_detection = data.heating_control.mode.window_open_detection || {}; + + data.heating_control.mode.window_open_detection.is_open = {}; + data.heating_control.mode.window_open_detection.is_open.value = !!(input.bytes[idx++] & 0x01); + data.heating_control.mode.window_open_detection.is_open.unit = "bool"; + break; + + case "COMMAND_ID_GET_WINDOW_OPEN_DETECTION_CONFIG": + data.heating_control = data.heating_control || {}; + data.heating_control.mode = data.heating_control.mode || {}; + data.heating_control.mode.window_open_detection = data.heating_control.mode.window_open_detection || {}; + data.heating_control.mode.window_open_detection.config = data.heating_control.mode.window_open_detection.config || {}; + + data.heating_control.mode.window_open_detection.config.source = {}; + data.heating_control.mode.window_open_detection.config.enable_mode = {}; + data.heating_control.mode.window_open_detection.config.open_duration = {}; + data.heating_control.mode.window_open_detection.config.temperature_delta = {}; + data.heating_control.mode.window_open_detection.config.open_temperature = {}; + + data.heating_control.mode.window_open_detection.config.source.value = !!(input.bytes[idx] & (1 << 3)); + data.heating_control.mode.window_open_detection.config.source.unit = "bool"; + + data.heating_control.mode.window_open_detection.config.enable_mode.holiday = {}; + data.heating_control.mode.window_open_detection.config.enable_mode.auto = {}; + data.heating_control.mode.window_open_detection.config.enable_mode.manu_temp = {}; + data.heating_control.mode.window_open_detection.config.enable_mode.holiday.value = !!(input.bytes[idx] & (1 << 0)); + data.heating_control.mode.window_open_detection.config.enable_mode.auto.value = !!(input.bytes[idx] & (1 << 1)); + data.heating_control.mode.window_open_detection.config.enable_mode.manu_temp.value = !!(input.bytes[idx++] & (1 << 2)); + data.heating_control.mode.window_open_detection.config.enable_mode.unit = "bool"; + + data.heating_control.mode.window_open_detection.config.open_duration.value = (input.bytes[idx] >> 5) * 10 + 10; + data.heating_control.mode.window_open_detection.config.open_duration.unit = "min"; + + data.heating_control.mode.window_open_detection.config.temperature_delta.value = ((input.bytes[idx++] & 0x1F) * 0.1 + 0.5).toFixed(1); + data.heating_control.mode.window_open_detection.config.temperature_delta.unit = "K"; + + data.heating_control.mode.window_open_detection.config.open_temperature.value = (input.bytes[idx++] * 0.5).toFixed(1); + data.heating_control.mode.window_open_detection.config.open_temperature.unit = "°C"; + break; + + case "COMMAND_ID_GET_DECALCIFICATION_CONFIG": + data.heating_control = data.heating_control || {}; + data.heating_control.config = data.heating_control.config || {}; + data.heating_control.config.decalcification_time = data.heating_control.config.decalcification_time || {}; + + data.heating_control.config.decalcification_time.weekday = {}; + data.heating_control.config.decalcification_time.week_of_month = {}; + data.heating_control.config.decalcification_time.hour = {}; + data.heating_control.config.decalcification_time.minute = {}; + + data.heating_control.config.decalcification_time.weekday.value = WEEKDAY[(input.bytes[idx] >> 4)]; + data.heating_control.config.decalcification_time.weekday.unit = "string"; + + data.heating_control.config.decalcification_time.week_of_month.value = WEEK_OF_MONTH[((input.bytes[idx] >> 1) & 0x07)]; + data.heating_control.config.decalcification_time.week_of_month.unit = "string"; + + data.heating_control.config.decalcification_time.hour.value = ((input.bytes[idx++] & 0x01) << 4) + (input.bytes[idx] >> 4); + data.heating_control.config.decalcification_time.hour.unit = "h"; + data.heating_control.config.decalcification_time.minute.value = (input.bytes[idx++] & 0x0F) * 5; + break; + + case "COMMAND_ID_COMMAND_FAILED": + data.radio = data.radio || {}; + data.radio.failed_commands = {}; + + var nbr_failed_commands = input.bytes[idx++]; + + data.radio.failed_commands.value = {}; + + for(let i = 0; i < nbr_failed_commands; i++) + { + data.radio.failed_commands.value[i] = COMMAND_ID[input.bytes[idx++]]; + } + + data.radio.failed_commands.unit = "COMMAND_ID"; + break; + + case "COMMAND_ID_GET_BUTTON_ACTION": + data.button_action = data.button_action || {}; + data.button_action.single_tap = data.button_action.single_tap || {}; + data.button_action.double_tap = data.button_action.double_tap || {}; + + data.button_action.single_tap.value = COMMAND_ID[input.bytes[idx++]]; + data.button_action.double_tap.value = COMMAND_ID[input.bytes[idx++]]; + + data.button_action.unit = "COMMAND_ID"; + break; + + case "COMMAND_ID_GET_HARDWARE_FACTORY_RESET_LOCK": + data.button_action = data.button_action || {}; + data.button_action.hw_factory_reset_locked = data.button_action.hw_factory_reset_locked || {}; + + data.button_action.hw_factory_reset_locked.value = !!(input.bytes[idx++] & (0x01)); + data.button_action.hw_factory_reset_locked.unit = "bool"; + break; + + case "COMMAND_ID_GET_DATA_RATE": + data.radio = data.radio || {}; + data.radio.data_rate = {}; + + data.radio.data_rate.value = DATA_RATE[(input.bytes[idx++] & 0x0F)]; + data.radio.data_rate.unit = "string"; + break; + + case "COMMAND_ID_GET_REMAINING_TIME_UNTIL_REJOIN": + data.radio = data.radio || {}; + data.radio.cyclic_rejoin = data.radio.cyclic_rejoin || {}; + data.radio.cyclic_rejoin.remaining_time_until_rejoin = data.radio.cyclic_rejoin.remaining_time_until_rejoin || {}; + + data.radio.cyclic_rejoin.remaining_time_until_rejoin.value = ((input.bytes[idx++] & 0x1F) << 16) + (input.bytes[idx++] << 8) + input.bytes[idx++]; + data.radio.cyclic_rejoin.remaining_time_until_rejoin.unit = "min"; + break; + + case "COMMAND_ID_GET_REJOIN_BEHAVIOR": + data.radio = data.radio || {}; + data.radio.cyclic_rejoin = data.radio.cyclic_rejoin || {}; + data.radio.cyclic_rejoin.conf = data.radio.cyclic_rejoin.conf || {}; + data.radio.cyclic_rejoin.interval = data.radio.cyclic_rejoin.interval || {}; + + data.radio.cyclic_rejoin.conf.value = REJOIN_BEHAVIOR[!(input.bytes[idx] >> 7)]; + data.radio.cyclic_rejoin.conf.unit = "string"; + + data.radio.cyclic_rejoin.interval.value = (((input.bytes[idx++] & 0x7F) * (255)) + input.bytes[idx++]); + data.radio.cyclic_rejoin.interval.unit = "h"; + break; + + case "COMMAND_ID_GET_VERSION": + data.version = data.version || {}; + data.version.hw_revision = {}; + data.version.application = {}; + data.version.bootloader = {}; + data.version.lorawan_l2 = {}; + data.version.payload_parser = {}; + + data.version.hw_revision.value = input.bytes[idx++]; + data.version.hw_revision.unit = "uint"; + + data.version.application.value = {}; + data.version.application.value[0] = input.bytes[idx++]; + data.version.application.value[1] = input.bytes[idx++]; + data.version.application.value[2] = input.bytes[idx++]; + data.version.application.unit = "uint"; + + data.version.bootloader.value = {}; + data.version.bootloader.value[0] = input.bytes[idx++]; + data.version.bootloader.value[1] = input.bytes[idx++]; + data.version.bootloader.value[2] = input.bytes[idx++]; + data.version.bootloader.unit = "uint"; + + data.version.lorawan_l2.value = {}; + data.version.lorawan_l2.value[0] = input.bytes[idx++]; + data.version.lorawan_l2.value[1] = input.bytes[idx++]; + data.version.lorawan_l2.value[2] = input.bytes[idx++]; + data.version.lorawan_l2.unit = "uint"; + + data.version.payload_parser.value = {}; + data.version.payload_parser.value[0] = payload_parser_version[0]; + data.version.payload_parser.value[1] = payload_parser_version[1]; + data.version.payload_parser.value[2] = payload_parser_version[2]; + data.version.payload_parser.unit = "uint"; + break; + + default: + break; + } + } + + return { + data: data, + warnings: [], + errors: [] + }; +} \ No newline at end of file diff --git a/vendor/dnt/dnt-lw-etrv-c.png b/vendor/dnt/dnt-lw-etrv-c.png new file mode 100644 index 0000000000..d8da6a89b0 Binary files /dev/null and b/vendor/dnt/dnt-lw-etrv-c.png differ diff --git a/vendor/dnt/dnt-lw-etrv-c.yaml b/vendor/dnt/dnt-lw-etrv-c.yaml new file mode 100644 index 0000000000..8cec647497 --- /dev/null +++ b/vendor/dnt/dnt-lw-etrv-c.yaml @@ -0,0 +1,105 @@ +name: LoRaWAN® Radiator Thermostat Controllable +description: 'The dnt® LoRaWAN® Radiator thermostat Controllable enables two ways to adjust the room temperature: directly on the device with the integrated buttons or remote control via Downlinks. It features an always-on display to show the current temperature settings, three customizable heating profiles with up to ten switching times per day, a window open detection to automatically reduce temperature and the possibility to perform a dynamic adaptive adjustment of the radiator. Because of very low energy consumption, a battery life up to 3 years can be archived.' + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '0.1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - transmission interval + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: dnt-profile + lorawanCertified: true + codec: dnt-lw-etrv-c-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, smart valve, snr, so2, +# 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: + - temperature + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 53 + length: 94 + height: 53 + +# Weight in grams (optional) +weight: 179 + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: 0 + max: 50 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0 + max: 0.97 + +# IP rating (optional) +ipCode: IP20 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - firmware + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + - fuota other + +# Product and data sheet URLs (optional) +productURL: https://www.dnt.de/ + +# Commercial information +resellerURLs: + - name: 'ELVshop' + region: + - European Union + url: https://www.dnt.de/Produkte/dnt-LoRaWAN-Heizkoerperthermostat-dnt-LW-eTRV/ +msrp: + EUR: 89.95 + +# Photos +photos: + main: dnt-lw-etrv-c.png diff --git a/vendor/dnt/dnt-lw-etrv.yaml b/vendor/dnt/dnt-lw-etrv.yaml index 0ec8eadb51..ea11748029 100644 --- a/vendor/dnt/dnt-lw-etrv.yaml +++ b/vendor/dnt/dnt-lw-etrv.yaml @@ -89,7 +89,7 @@ firmwareProgramming: - fuota other # Product and data sheet URLs (optional) -productURL: https://de.dnt.de/ +productURL: https://www.dnt.de/ # Commercial information resellerURLs: diff --git a/vendor/dnt/index.yaml b/vendor/dnt/index.yaml index b4ddecd6f9..b04effba64 100644 --- a/vendor/dnt/index.yaml +++ b/vendor/dnt/index.yaml @@ -4,3 +4,5 @@ endDevices: # Unique identifier of the end device (lowercase, alphanumeric with dashes, max 36 characters) - dnt-lw-ats # look in dnt-lw-ats.yaml for the end device definition - dnt-lw-etrv + - dnt-lw-dis + - dnt-lw-etrv-c diff --git a/vendor/ewattch/EwattchLorawanDecoder.js b/vendor/ewattch/EwattchLorawanDecoder.js new file mode 100644 index 0000000000..ee79d92cbb --- /dev/null +++ b/vendor/ewattch/EwattchLorawanDecoder.js @@ -0,0 +1,40 @@ +/* + * Lorawan Ewattch Javascript Decoder v1.1.8 + * Date : 2024-05-07 + * Author: Guillaume Caruso, Ewattch + * + * + * Decoder for Ewattch Lorawan Products, written in javascript + * + * + * BSD 3-Clause License + * + * Copyright (c) 2021, Ewattch + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +function signed16(e){return 32768&e&&(e-=65536),e}function signed8(e){return 128&e&&(e-=256),e}function float(e){var t,a=(2139095040&e)>>23;0===a?(t=!0,a=-149):(t=!1,a=a-127-23);var r=8388607&e;return!1===t&&(r|=8388608),2147483648&e?-Math.pow(2,a)*r:Math.pow(2,a)*r}function decodeUplink(e){return LoraWANEwattchDecoder(e.bytes,e.fPort,!0)}String.prototype.padStart||(String.prototype.padStart=function(e,t){return e>>=0,t=String(void 0!==t?t:" "),this.length>e?String(this):((e-=this.length)>t.length&&(t+=t.repeat(e/t.length)),t.slice(0,e)+String(this))}),LoraWANEwattchDecoder=function(e,t,a){var r={"00":"environnement","01":"presence","02":"ambiance","08":"squid",10:"impulse",20:"tyness",28:"tynode"},n={"00":[2,function(e,t,a){return{uuid:"temperature_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"temperature",value:signed16(e[0]|e[1]<<8)/100,unit:"°C"}},function(e,t){return"temperature_s"+e+"_c"+t}],"04":[1,function(e,t,a){return{uuid:"humidity_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"humidity",value:e[0]/2,unit:"%RH"}},function(e,t){return"humidity_s"+e+"_c"+t}],"08":[2,function(e,t,a){return{uuid:"C02_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"co2",value:e[0]|e[1]<<8,unit:"ppm"}},function(e,t){return"C02_s"+e+"_c"+t}],"0C":[2,function(e,t,a){return{uuid:"counter_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"counter",value:e[0]|e[1]<<8,unit:""}},function(e,t){return"counter_s"+e+"_c"+t}],"0E":[3,function(e,t,a){return{uuid:"time_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"time",value:e[0]|e[1]<<8|e[2]<<16,unit:"s"}},function(e,t){return"time_s"+e+"_c"+t}],10:[2,function(e,t,a){return{uuid:"luminosity_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"luminosity",value:e[0]|e[1]<<8,unit:"lx"}},function(e,t){return"luminosity_s"+e+"_c"+t}],14:[2,function(e,t,a){return{uuid:"motion_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"motion",value:10*(e[0]|e[1]<<8),unit:"s"}},function(e,t){return"motion_s"+e+"_c"+t}],16:[2,function(e,t,a){return{uuid:"pressure_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"pressure",value:signed16(e[0]|e[1]<<8)/100,unit:"barg"}},function(e,t){return"pressure_s"+e+"_c"+t}],18:[2,function(e,t,a){return{uuid:"flow_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"flow",value:(e[0]|e[1]<<8)/100,unit:"m3/h"}},function(e,t){return"flow_s"+e+"_c"+t}],"1A":[2,function(e,t,a){return{uuid:"volume_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"volume",value:e[0]|e[1]<<8,unit:"m3"}},function(e,t){return"volume_s"+e+"_c"+t}],"1C":[4,function(e,t,a){return{uuid:"volume_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"volume",value:float(e[0]|e[1]<<8|e[2]<<16|e[3]<<24),unit:"m3"}},function(e,t){return"volume_s"+e+"_c"+t}],20:[1,function(e,t,a){return i(e,t,a,1)},function(e,t){return"digital_input_s"+e+"_c"+t}],22:[1,function(e,t,a){return i(e,t,a,2)},function(e,t){return"digital_input_s"+e+"_c"+t}],24:[1,function(e,t,a){return i(e,t,a,4)},function(e,t){return"digital_input_s"+e+"_c"+t}],26:[1,function(e,t,a){return i(e,t,a,8)},function(e,t){return"digital_input_s"+e+"_c"+t}],28:[3,function(e,t,a){var r,n,u;r=(224&e[0])>>5?.001:.01;0==(31&e[0])?(n="mA",u="4:20"):1==(31&e[0])?(n="V",u="0:10"):2==(31&e[0])&&(n="V",u="0:24");return{uuid:"analog_input_s"+t+"_c"+a,hardwareData:{socket:t,channel:a,scale:u},type:"analogInput",value:signed16(e[1]|e[2]<<8)*r,unit:n}},function(e,t){return"analog_input_s"+e+"_c"+t}],40:[0,function(e,t,a){var r=0,n=(240&e[r])>>4,u=15&e[r],i=[];if(2===(r++,u)){for(var c=0;c>5&7,f=31&i,n.metadata.subscription=o[_.toString(16).toUpperCase().padStart(2,"0")],n.metadata.tarrifPeriod=s[f.toString(16).toUpperCase().padStart(2,"0")],r+=2,_){case 0:P=["Base"];break;case 1:P=["HC","HP"];break;case 2:P=["Heures Normales","Heures Pointe mobile"];break;case 3:P=["HC Jour bleu","HC Jour blanc","HC Jour rouge","HP Jour bleu","HP Jour blanc","HP Jour rouge"]}for(var H=0;H>4&15,f=15&i,n.metadata.subscription=d[_.toString(16).toUpperCase().padStart(2,"0")],n.metadata.tarrifPeriod=l[f.toString(16).toUpperCase().padStart(2,"0")],r++,P=["1","2","3","4"];for(H=0;H>4,o=15&e[r];switch(c){case 0:u.metadata.device_name="HEAT METER";break;case 1:u.metadata.device_name="WATER METER";break;case 2:u.metadata.device_name="ELECTRICITY METER";break;case 3:u.metadata.device_name="GAZ METER";break;default:return e.splice(0,r),u.metadata.error="Unkwown meter code 0x"+c.toString(16),u}u.metadata.device_slave_adress=i,r++,e.splice(0,r);var s=0;for(;e.length>0&&s>5,m=31&e[0],e.splice(0,1)),d=v[1](e,h,m),Array.isArray(d)?u.values=u.values.concat(d):u.values.push(d),e.splice(0,v[0]),s++}return u},function(e,t){return"mbus_s"+e+"_c"+t}],"5C":[0,function(e,t,a){var r=0,n={uuid:"modbus_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"modbus",values:[],metadata:{}};r++;var u=e[r];n.metadata.application_code=63&u,n.metadata.standardised=(64&u)>>7==1,r++;var i=e[r];switch(i){case 3:n.metadata.command="Read Holding Registers";break;case 4:n.metadata.command="Read Input Registers";break;case 8:n.metadata.command="Read Diagnostics";break;case 16:n.metadata.command="Write Multiples Registers Response";break;case 80:n.metadata.command="Master Write Multiples Registers Response";break;default:n.metadata.command="Unknown command : "+(127&i)}if(r++,3===i||4===i){n.metadata.startAdress=(e[r+1]<<8)+e[r],r+=2,n.metadata.wordCount=e[r]/2,r++;for(var c=[],o=0;oe.length);)c.push((e[r+1]<<8)+e[r]),r+=2,o++;n.values=c}return e.splice(0,r),n},function(e,t){return"modbus_s"+e+"_c"+t}],74:[1,function(e,t,a){return{uuid:"battery_s"+t+"_c"+a,hardwareData:{socket:t,channel:a},type:"battery",value:e,unit:""}},function(e,t){return"battery_s"+e+"_c"+t}]},u={"00":[1,function(e,t,a){return{value:r[e[0].toString(16).toUpperCase().padStart(2,"00")],type:"nodeType"}}],"02":[2,function(e,t,a){return{value:e[1]+"."+e[0],type:"version"}}],"04":[1,function(e,t,a){return{value:e[0],type:"batteryLevel"}}],"08":[2,function(e,t,a){return{value:10*(e[0]|e[1]<<8),type:"periodicity"}}]};function i(e,t,a,r){for(var n=[],u=e[0],i=0;i>=1;return e.splice(0,2),n}this.decode=function(e,t,a){if("string"==typeof e){for(var r=[],i=0,c=e.length;i0;){var l,p=1&e[0],v=128==(128&e[0]),h=(126&e[0]).toString(16).toUpperCase().padStart(2,"00");if(null==(o=0===s?n[h]:u[h]))return d.push({type:"error",value:"unknown object type : "+h}),{data:d};e.splice(0,1);var m=0,_=0;0===s&&p&&(m=(224&e[0])>>5,_=31&e[0],e.splice(0,1)),v?(d.push({uuid:o[2](m,_),hardwareData:{socket:m,channel:_},type:"error"}),e.splice(0,1)):(l=o[1](e,m,_),Array.isArray(l)?d=d.concat(l):d.push(l),e.splice(0,o[0]))}return{data:d}};var c={"0E":"Données erronées","0F":"Compteur Inconnu",10:"Bleu","1F":"Bleu avec defaut",20:"Jaune","2F":"Jaune avec defaut",30:"PME-PMI","3F":"PME-PMI avec defaut",40:"ICE","4E":"ICE V2.4","4F":"ICE avec defaut",50:"Linky",51:"Linky Injection","5F":"Linky avec defaut",60:"Saphir","6F":"Saphir avec defaut"},o={"00":"Base","01":"HP/HC","02":"EJP","03":"TEMPO"},s={"00":"Base","01":"HC","02":"HP","03":"EJP heures normales","04":"EJP heures de pointe mobile","05":"TEMPO HC Jour Bleu","06":"TEMPO HC Jour Blanc","07":"TEMPO HC Jour Rouge","08":"TEMPO HP Jour Bleu","09":"TEMPO HP Jour Blanc","0a":"TEMPO HP Jour Rouge"},d={"01":"Ete","02":"Hiver","03":"Pointe mobile"},l={"01":"Heures Pleines","02":"Heures Creuses","03":"Heures de pointe","04":"Heures de pointe mobile"},p={"00":"TJ MU","01":"TJ LU","02":"TJ LU-SD","03":"TJ LU-P","04":"TJ LU-PH","05":"TJ LU-CH","06":"TJ EJP","07":"TJ EJP-SD","08":"TJ EJP-PM","09":"TJ EJP-HH","0a":"TV A5 Base","0b":"TV A8 Base","0c":"BT 4 SUP36","0d":"BT 5 SUP36","0e":"HTA 5","0f":"HTA 8"},v={"00":"P","01":"PM","02":"HH","03":"HP","04":"HC","05":"HPH","06":"HCH","07":"HPE","08":"HCE","09":"HPD","0a":"HCD","0b":"JA"},h={"0a":"TV A5 Base","0b":"TV A8 Base",10:"TV A5 EJP",11:"TV A8 EJP",12:"TV A8 MOD"},m={"00":"P","01":"PM","02":"HH","03":"HP","04":"HC","05":"HPH","06":"HCH","07":"HPE","08":"HCE","09":"HPD","0a":"HCD","0b":"JA","0c":"HD","0d":"HM","0e":"DSM","0f":"SCM"};return this.decode(e,t,a)}; diff --git a/vendor/ewattch/ambiance-codec.yaml b/vendor/ewattch/ambiance-codec.yaml new file mode 100644 index 0000000000..aaf680b181 --- /dev/null +++ b/vendor/ewattch/ambiance-codec.yaml @@ -0,0 +1,5 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ewattchlorawandecoder.js + # Examples (optional) diff --git a/vendor/ewattch/ambiance.png b/vendor/ewattch/ambiance.png new file mode 100644 index 0000000000..00b744c709 Binary files /dev/null and b/vendor/ewattch/ambiance.png differ diff --git a/vendor/ewattch/ambiance.yaml b/vendor/ewattch/ambiance.yaml new file mode 100644 index 0000000000..b832dd6158 --- /dev/null +++ b/vendor/ewattch/ambiance.yaml @@ -0,0 +1,142 @@ +name: ambiance # Device name can not contain the vendor name +description: LoRa® – 5 in 1 sensor to measure Temperature, CO2, brightness, humidity and presence. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - remote rejoin + - transmission interval + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + vendorID: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: ewattch-profile-868 + lorawanCertified: true + codec: ambiance-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# 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, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - co2 + - humidity + - iaq + - battery + - light + - motion + - temperature + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 25 + length: 86 + height: 86 + +# Weight in grams (optional) +weight: 80 + +# Battery information (optional) +battery: + replaceable: true + type: AA + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: 5 + max: 60 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0.10 + max: 0.80 + +# IP rating (optional) +ipCode: IP20 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Key security (optional) +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +productURL: https://ewattch.com/en/capteurs-lora-iot/capteur-iot-lora-lorawan-ambiance/ +dataSheetURL: https://ewattch-documentation.com/?page_id=1232&lang=en + +# Photos +photos: + main: ambiance.png # Image needs to have a transparent background + +# Youtube or Vimeo Video (optional) +videos: + main: https://youtu.be/GVIfryrDYrQ + +# Regulatory compliances (optional) +compliances: + safety: + - body: IEC + norm: EN + standard: '61010' + radioEquipment: + - body: IEC + norm: EN + standard: 61000-6-2 + - body: IEC + norm: EN + standard: 61000-6-3 + - body: IEC + norm: EN + standard: '55022' + - body: IEC + norm: EN + standard: '300220' diff --git a/vendor/ewattch/ewattch-profile-868.yaml b/vendor/ewattch/ewattch-profile-868.yaml new file mode 100644 index 0000000000..b6f598ad37 --- /dev/null +++ b/vendor/ewattch/ewattch-profile-868.yaml @@ -0,0 +1,47 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.1' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'TS001-1.0.1' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 16 +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/ewattch/ewattch-profile-915.yaml b/vendor/ewattch/ewattch-profile-915.yaml new file mode 100644 index 0000000000..b6f598ad37 --- /dev/null +++ b/vendor/ewattch/ewattch-profile-915.yaml @@ -0,0 +1,47 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.1' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'TS001-1.0.1' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 16 +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/ewattch/index.yaml b/vendor/ewattch/index.yaml new file mode 100644 index 0000000000..24ad2cf4d6 --- /dev/null +++ b/vendor/ewattch/index.yaml @@ -0,0 +1,41 @@ +# This example contains just one end device: windsensor. It is referenced here in the index. + +endDevices: + # Unique identifier of the end device (lowercase, alphanumeric with dashes, max 36 characters) + - squidpro # look in squidpro.yaml for the end device definition + - ambiance # look in ambiance.yaml for the end device definition + - tynode # look in tynode.yaml for the end device definition + - squid # look in squid.yaml for the end device definition + - tyness # look in tyness.yaml for the end device definition + +# The profileIDs is a distinct value for every unique profile listed in the vendor's folder. +# This value can be freely issued by the vendor and is also used on the QR code for LoRaWAN devices, see +# https://lora-alliance.org/wp-content/uploads/2020/11/TR005_LoRaWAN_Device_Identification_QR_Codes.pdf#page=8 +# It can either be a combo of device ID + hardware version + firmware version + region, or profile ID + codec ID +# NOTE: The profileIDs is different from the vendorID. +profileIDs: + '1': + endDeviceID: 'squidpro' + firmwareVersion: '1.0' + hardwareVersion: '1.0' + region: 'EU863-870' + '2': + endDeviceID: 'ambiance' + firmwareVersion: '1.0' + hardwareVersion: '1.0' + region: 'EU863-870' + '3': + endDeviceID: 'tynode' + firmwareVersion: '1.0' + hardwareVersion: '1.0' + region: 'EU863-870' + '4': + endDeviceID: 'squid' + firmwareVersion: '1.0' + hardwareVersion: '1.0' + region: 'EU863-870' + '5': + endDeviceID: 'tyness' + firmwareVersion: '1.0' + hardwareVersion: '1.0' + region: 'EU863-870' diff --git a/vendor/ewattch/squid-codec.yaml b/vendor/ewattch/squid-codec.yaml new file mode 100644 index 0000000000..aaf680b181 --- /dev/null +++ b/vendor/ewattch/squid-codec.yaml @@ -0,0 +1,5 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ewattchlorawandecoder.js + # Examples (optional) diff --git a/vendor/ewattch/squid.png b/vendor/ewattch/squid.png new file mode 100644 index 0000000000..5086c02b00 Binary files /dev/null and b/vendor/ewattch/squid.png differ diff --git a/vendor/ewattch/squid.yaml b/vendor/ewattch/squid.yaml new file mode 100644 index 0000000000..70152a46fd --- /dev/null +++ b/vendor/ewattch/squid.yaml @@ -0,0 +1,131 @@ +name: squid # Device name can not contain the vendor name +description: The Squid sensor allows to realize the electrical sub-metering of your single-phase or three-phase installations with its 12 current clamps. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - remote rejoin + - transmission interval + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + vendorID: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: ewattch-profile-868 + lorawanCertified: true + codec: squid-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# 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, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - current + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 90 + length: 88 + height: 62 + +# Weight in grams (optional) +weight: 152 + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: 5 + max: 60 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0.10 + max: 0.80 + +# IP rating (optional) +ipCode: IP20 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Key security (optional) +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +productURL: https://ewattch.com/en/capteurs-lora-iot/capteur-iot-lora-lorawan-squid/ +dataSheetURL: https://ewattch-documentation.com/?page_id=1162&lang=en + +# Photos +photos: + main: squid.png # Image needs to have a transparent background + +# Youtube or Vimeo Video (optional) +videos: + main: https://youtu.be/d-SwS7IWEqg + +# Regulatory compliances (optional) +compliances: + safety: + - body: IEC + norm: EN + standard: '61010' + radioEquipment: + - body: IEC + norm: EN + standard: 61000-6-2 + - body: IEC + norm: EN + standard: 61000-6-3 + - body: IEC + norm: EN + standard: '55022' + - body: IEC + norm: EN + standard: '300220' diff --git a/vendor/ewattch/squidpro-codec.yaml b/vendor/ewattch/squidpro-codec.yaml new file mode 100644 index 0000000000..aaf680b181 --- /dev/null +++ b/vendor/ewattch/squidpro-codec.yaml @@ -0,0 +1,5 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ewattchlorawandecoder.js + # Examples (optional) diff --git a/vendor/ewattch/squidpro.png b/vendor/ewattch/squidpro.png new file mode 100644 index 0000000000..314dc59d6c Binary files /dev/null and b/vendor/ewattch/squidpro.png differ diff --git a/vendor/ewattch/squidpro.yaml b/vendor/ewattch/squidpro.yaml new file mode 100644 index 0000000000..647916b1e3 --- /dev/null +++ b/vendor/ewattch/squidpro.yaml @@ -0,0 +1,141 @@ +name: squid pro # Device name can not contain the vendor name +description: The Squid sensor allows to realize the electrical sub-metering of your single-phase or three-phase installations with its 12 current clamps. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - remote rejoin + - transmission interval + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + vendorID: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: ewattch-profile-868 + lorawanCertified: true + codec: squidpro-codec + US902-928: + id: ewattch-profile-915 + lorawanCertified: true + codec: squidpro-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# 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, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - energy + - power + - current + - voltage + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 90 + length: 88 + height: 62 + +# Weight in grams (optional) +weight: 152 + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: 5 + max: 60 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0.10 + max: 0.80 + +# IP rating (optional) +ipCode: IP20 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Key security (optional) +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +productURL: https://ewattch.com/en/capteurs-lora-iot/capteur-iot-lora-lorawan-squid/ +dataSheetURL: https://ewattch-documentation.com/?page_id=1165&lang=en +# Link to simple, easy onboarding instructions for the device (optional). +# Please do not use this for marketing or overly technical documents like a data sheet. +onboardingGuideURL: https://ewattch-documentation.com/wp-admin/admin-ajax.php?juwpfisadmin=false&action=wpfd&task=file.download&wpfd_category_id=116&wpfd_file_id=4817 + +# Photos +photos: + main: squidpro.png # Image needs to have a transparent background + +# Youtube or Vimeo Video (optional) +videos: + main: https://youtu.be/d-SwS7IWEqg + +# Regulatory compliances (optional) +compliances: + safety: + - body: IEC + norm: EN + standard: '61010' + radioEquipment: + - body: IEC + norm: EN + standard: 61000-6-2 + - body: IEC + norm: EN + standard: 61000-6-3 + - body: IEC + norm: EN + standard: '55022' + - body: IEC + norm: EN + standard: '300220' diff --git a/vendor/ewattch/tyness-codec.yaml b/vendor/ewattch/tyness-codec.yaml new file mode 100644 index 0000000000..aaf680b181 --- /dev/null +++ b/vendor/ewattch/tyness-codec.yaml @@ -0,0 +1,5 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ewattchlorawandecoder.js + # Examples (optional) diff --git a/vendor/ewattch/tyness-energy.png b/vendor/ewattch/tyness-energy.png new file mode 100644 index 0000000000..ab13051433 Binary files /dev/null and b/vendor/ewattch/tyness-energy.png differ diff --git a/vendor/ewattch/tyness-performance.png b/vendor/ewattch/tyness-performance.png new file mode 100644 index 0000000000..6eec7345ce Binary files /dev/null and b/vendor/ewattch/tyness-performance.png differ diff --git a/vendor/ewattch/tyness.yaml b/vendor/ewattch/tyness.yaml new file mode 100644 index 0000000000..2c41ebb787 --- /dev/null +++ b/vendor/ewattch/tyness.yaml @@ -0,0 +1,152 @@ +name: tyness # Device name can not contain the vendor name +description: IoT Sensor LoRa® modular and scalable combining several measurement acquisition and control functionalities. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - remote rejoin + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + vendorID: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: ewattch-profile-868 + lorawanCertified: true + codec: tyness-codec + US902-928: + id: ewattch-profile-915 + lorawanCertified: true + codec: tyness-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# 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, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - 4-20 ma + - analog input + - auxiliary + - battery + - current + - digital input + - pulse count + - temperature + +# Additional radios that this device has (optional) +# Valid values are: ble, nfc, wifi, cellular. +additionalRadios: + - wifi + - cellular + +# Bridge interfaces (optional) +# Valid values are: modbus, m-bus, can bus, rs-485, sdi-12, analog. +bridgeInterfaces: + - m-bus + - rs-485 + - analog + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 36 + length: 77 + height: 142 + +# Weight in grams (optional) +weight: 132 + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: 5 + max: 60 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0.10 + max: 0.80 + +# IP rating (optional) +ipCode: IP20 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Key security (optional) +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +productURL: https://ewattch.com/en/capteurs-lora-iot/capteur-iot-lora-lorawan-tyness-performance/ +dataSheetURL: https://ewattch-documentation.com/?page_id=4284&lang=en + +# Photos +photos: + main: tyness-performance.png # Image needs to have a transparent background + other: + - tyness-energy.png # Image needs to have a transparent background + +# Regulatory compliances (optional) +compliances: + safety: + - body: IEC + norm: EN + standard: '61010' + radioEquipment: + - body: IEC + norm: EN + standard: 61000-6-2 + - body: IEC + norm: EN + standard: 61000-6-3 + - body: IEC + norm: EN + standard: '55022' + - body: IEC + norm: EN + standard: '300220' diff --git a/vendor/ewattch/tynode-codec.yaml b/vendor/ewattch/tynode-codec.yaml new file mode 100644 index 0000000000..aaf680b181 --- /dev/null +++ b/vendor/ewattch/tynode-codec.yaml @@ -0,0 +1,5 @@ +# Uplink decoder decodes binary data uplink into a JSON object (optional) +# For documentation on writing encoders and decoders, see: https://www.thethingsindustries.com/docs/integrations/payload-formatters/javascript/ +uplinkDecoder: + fileName: ewattchlorawandecoder.js + # Examples (optional) diff --git a/vendor/ewattch/tynode.png b/vendor/ewattch/tynode.png new file mode 100644 index 0000000000..0bacf61cb4 Binary files /dev/null and b/vendor/ewattch/tynode.png differ diff --git a/vendor/ewattch/tynode.yaml b/vendor/ewattch/tynode.yaml new file mode 100644 index 0000000000..2baf30555d --- /dev/null +++ b/vendor/ewattch/tynode.yaml @@ -0,0 +1,140 @@ +name: tynode # Device name can not contain the vendor name +description: 'The TyNode sensor providing a choice of different measurement. 3 versions available : temperature, pulse counting or and analog measurements.' + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.0' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # Firmware features (optional) + # Valid values are: remote rejoin (trigger a join from the application layer), transmission interval (configure how + # often he device sends a message). + features: + - remote rejoin + + # 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: + # Optional identifier of the vendor of the profile. When you specify the vendorID, the profile is loaded from + # the vendorID's folder. This allows you to reuse profiles from module or LoRaWAN end device stack vendors. + # If vendorID is empty, the current vendor ID is used. In this example, the vendorID is the current vendor ID, + # which is verbose. + vendorID: + # Identifier of the profile (lowercase, alphanumeric with dashes, max 36 characters) + id: ewattch-profile-868 + lorawanCertified: true + codec: tynode-codec + +# Type of device (optional) +# Valid values are: devkit, module, cots +deviceType: cots + +# 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, +# digital output, dissolved oxygen, distance, dust, energy, gps, gyroscope, h2s, hall effect, humidity, iaq, infrared, leaf wetness, level, +# light, lightning, link, magnetometer, moisture, motion, nfc, no, no2, o3, occupancy, optical meter, particulate matter, ph, pir, +# pm2.5, pm10, potentiometer, power, precipitation, pressure, proximity, pulse count, pulse frequency, radar, rainfall, reed switch, rssi, +# sap flow, smart valve, smoke, snr, so2, solar radiation, sound, strain, surface temperature, switch, temperature, tilt, time, turbidity, +# tvoc, uv, vapor pressure, velocity, vibration, voltage, water potential, water, weight, wifi ssid, wind direction, wind speed. +sensors: + - 4-20 ma + - analog input + - battery + - digital input + - pulse count + - temperature + +# Bridge interfaces (optional) +# Valid values are: modbus, m-bus, can bus, rs-485, sdi-12, analog, ethernet. +bridgeInterfaces: + - analog + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 35 + length: 75 + height: 75 + +# Weight in grams (optional) +weight: 272 + +# Battery information (optional) +battery: + replaceable: true + type: AA + +# Operating conditions (optional) +operatingConditions: + # Temperature (Celsius) + temperature: + min: -25 + max: 70 + # Relative humidity (fraction of 1) + relativeHumidity: + min: 0.10 + max: 0.80 + +# IP rating (optional) +ipCode: IP65 + +# Key provisioning (optional) +# Valid values are: custom (user can configure keys), join server and manifest. +keyProvisioning: + - custom + - join server + +# Key programming (optional) +# Valid values are: bluetooth, nfc, wifi, ethernet (via a webpage), serial (when the user has a serial interface to set the keys) +# and firmware (when the user should change the firmware to set the keys). +keyProgramming: + - serial + +# Key security (optional) +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Firmware programming (optional) +# Valid values are: serial (when the user has a serial interface to update the firmware), ethernet, fuota lorawan (when the device +# supports LoRaWAN FUOTA via standard interfaces) and fuota other (other wireless update mechanism). +firmwareProgramming: + - serial + +# Product and data sheet URLs (optional) +dataSheetURL: https://ewattch-documentation.com/?page_id=1171&lang=en + +# Photos +photos: + main: tynode.png # Image needs to have a transparent background + +# Regulatory compliances (optional) +compliances: + safety: + - body: IEC + norm: EN + standard: '61010' + radioEquipment: + - body: IEC + norm: EN + standard: 61000-6-2 + - body: IEC + norm: EN + standard: 61000-6-3 + - body: IEC + norm: EN + standard: '55022' + - body: IEC + norm: EN + standard: '300220' diff --git a/vendor/index.yaml b/vendor/index.yaml index 2598c8c10f..b8eccbed50 100644 --- a/vendor/index.yaml +++ b/vendor/index.yaml @@ -1695,8 +1695,8 @@ vendors: - id: acrios name: ACRIOS Systems s.r.o. - website: https://acrios.com/?lang=en - logo: acrioslogo.png + website: https://acrios.com/ + logo: acrios-logo.png - id: espeasy name: ESP Easy diff --git a/vendor/netvox/index.yaml b/vendor/netvox/index.yaml index d58d385898..f0d70bbb67 100755 --- a/vendor/netvox/index.yaml +++ b/vendor/netvox/index.yaml @@ -31,6 +31,7 @@ endDevices: - r31509 - r31510 - r602a + - r603 - r711 - r711a - r718a @@ -121,6 +122,7 @@ endDevices: - r831d - ra02a - ra02c + - ra02g - ra07w - ra0715 - ra0715y diff --git a/vendor/netvox/payload/r315.js b/vendor/netvox/payload/r315.js index 57d7e4d599..c62eedf51b 100755 --- a/vendor/netvox/payload/r315.js +++ b/vendor/netvox/payload/r315.js @@ -101,9 +101,67 @@ function decodeUplink(input) { data.Humi = input.bytes[10]*0.5; } } - else if (input.bytes[2] == 0x02) - data.Illuminance = (input.bytes[4]<<8 | input.bytes[5]); - + else if (input.bytes[2] == 0x02){ + data.Illuminance = (input.bytes[4]<<8 | input.bytes[5])+"Lux"; + data.LowTemperatureAlarm = input.bytes[6] & 1; + data.HighTemperatureAlarm = input.bytes[6]>>1 & 1; + data.LowHumidityAlarm = input.bytes[6]>>2 & 1; + data.HighHumidityAlarm = input.bytes[6]>>3 & 1; + data.LowIlluminanceAlarm = input.bytes[6]>>4 & 1; + data.HighIlluminanceAlarm = input.bytes[6]>>5 & 1; + } + else if(input.bytes[2] == 0x011){ + let FunctionEnable = (input.bytes[5]<<8 |input.bytes[6]); + data.THSensor = FunctionEnable & 1; + data.LightSensor = FunctionEnable>>1 & 1; + data.PIRSensor = FunctionEnable>>2 & 1; + data.EmergenceButton = FunctionEnable>>3 & 1; + data.TiltSensor = FunctionEnable>>4 & 1; + data.InternalContactSwitch = FunctionEnable>>5 & 1; + data.ExternalContactSwitch1 = FunctionEnable>>6 & 1; + data.ExternalContactSwitch2 = FunctionEnable>>7 & 1; + data.InternalShockSensor = FunctionEnable>>8 & 1; + data.ExternalShockSensor = FunctionEnable>>9 & 1; + data.ExternalDryContactPointIN = FunctionEnable>>10 & 1; + data.DryContactPointOut = FunctionEnable>>11 & 1; + data.ExternalWaterLeakSenor1 = FunctionEnable>>12 & 1; + data.ExternalWaterLeakSenor2 = FunctionEnable>>13 & 1; + data.ExternalSeatSensor = FunctionEnable>>14 & 1; + data.ExternalGlassSensor1 = FunctionEnable>>15 & 1; + data.ExternalGlassSensor2 = input.bytes[4]& 1; + + let BinarySensorReport = (input.bytes[7]<<8 | input.bytes[8]); + data.PIRSensorState = BinarySensorReport & 1; + data.EmergenceButtonaLAlarmState = BinarySensorReport>>1 & 1; + data.TiltSensorState = BinarySensorReport>>2 & 1; + data.InternalContactSwitchSensorState = BinarySensorReport>>3 & 1; + data.ExternalContactSwitch1SensorState = BinarySensorReport>>4 & 1; + data.ExternalContactSwitch2SensorState = BinarySensorReport>>5 & 1; + data.InternalShockSensorState = BinarySensorReport>>6 & 1; + data.ExternalShockSensorState = BinarySensorReport>>7 & 1; + data.ExternalDryContactPointINState = BinarySensorReport>>8 & 1; + data.ExternalWaterLeak1SenorState = BinarySensorReport>>9 & 1; + data.ExternalWaterLeak2SenorState = BinarySensorReport>>10 & 1; + data.ExternalSeatSenorState = BinarySensorReport>>11 & 1; + data.ExternalGlassSenor1State = BinarySensorReport>>12 & 1; + data.ExternalGlassSenor2State = BinarySensorReport>>13 & 1; + } + else if(input.bytes[2] == 0x12){ + if (input.bytes[4] & 0x80){ + var tmpval = (input.bytes[4]<<8 | input.bytes[5]); + data.Temp = (0x10000 - tmpval)/100 * -1; + }else{ + data.Temp = (input.bytes[4]<<8 | input.bytes[5])/100; + } + data.Humidity = (input.bytes[6]<<8 | input.bytes[7])*0.01 +"%"; + data.Illuminance = (input.bytes[8]<<8 | input.bytes[9])+"Lux"; + data.LowTemperatureAlarm = input.bytes[10] & 1; + data.HighTemperatureAlarm = input.bytes[10]>>1 & 1; + data.LowHumidityAlarm = input.bytes[10]>>2 & 1; + data.HighHumidityAlarm = input.bytes[10]>>3 & 1; + data.LowIlluminanceAlarm = input.bytes[10]>>4 & 1; + data.HighIlluminanceAlarm = input.bytes[10]>>5 & 1; + } break; case 7: diff --git a/vendor/netvox/payload/r603.js b/vendor/netvox/payload/r603.js new file mode 100755 index 0000000000..7ac09f16f8 --- /dev/null +++ b/vendor/netvox/payload/r603.js @@ -0,0 +1,316 @@ +function getCfgCmd(cfgcmd){ + var cfgcmdlist = { + 1: "ConfigReportReq", + 129: "ConfigReportRsp", + 2: "ReadConfigReportReq", + 130: "ReadConfigReportRsp", + 3: "StartSirenReq", + + 4: "SetPeriodSirenReq", + 132: "SetPeriodSirenRsp", + 5: "GetPeriodSirenReq", + 133: "GetPeriodSirenRsp", + 6: "StopPeriodSirenReq", + 134: "StopPeriodSirenRsp", + 7: "SetLEDColorReq", + 135: "SetLEDColorRsp", + 8: "GetLEDColorReq", + 136: "GetLEDColorRsp", + 9: "SetContactSwitchTriggerAlarmReq", + 137: "SetContactSwitchTriggerAlarmRsp", + 10: "GetContactSwitchTriggerAlarmReq", + 138: "GetContactSwitchTriggerAlarmRsp", + }; + return cfgcmdlist[cfgcmd]; +} + +function getCmdToID(cmdtype){ + if (cmdtype == "ConfigReportReq") + return 1; + else if (cmdtype == "ConfigReportRsp") + return 129; + else if (cmdtype == "ReadConfigReportReq") + return 2; + else if (cmdtype == "ReadConfigReportRsp") + return 130; + else if (cmdtype == "StartSirenReq") + return 3; + + else if (cmdtype == "SetPeriodSirenReq") + return 4; + else if (cmdtype == "SetPeriodSirenRsp") + return 132; + else if (cmdtype == "GetPeriodSirenReq") + return 5; + else if (cmdtype == "GetPeriodSirenRsp") + return 133; + else if (cmdtype == "StopPeriodSirenReq") + return 6; + else if (cmdtype == "StopPeriodSirenRsp") + return 134; + else if (cmdtype == "SetLEDColorReq") + return 7; + else if (cmdtype == "SetLEDColorRsp") + return 135; + else if (cmdtype == "GetLEDColorReq") + return 8; + else if (cmdtype == "GetLEDColorRsp") + return 136; + else if (cmdtype == "SetContactSwitchTriggerAlarmReq") + return 9; + else if (cmdtype == "SetContactSwitchTriggerAlarmRsp") + return 137; + else if (cmdtype == "GetContactSwitchTriggerAlarmReq") + return 10; + else if (cmdtype == "GetContactSwitchTriggerAlarmRsp") + return 138; +} + +function getDeviceName(dev){ + var deviceName = { + 222: "R603" + }; + return deviceName[dev]; +} + +function getDeviceID(devName){ + var deviceName = { + "R603": 222 + }; + return deviceName[devName]; +} +function getSirenNoType(id){ + var type = { + 0X00:"EmergencyMode", + 0X01:"Doorbel", + 0X02:"Burglar", + 0X03:"FireMode", + 0X04:"Help", + 0X05:"No Smoking", + 0X06:"Poor Air Quality", + 0X07:"The temperature is too high", + 0X08:"Thief", + 0X09:"Welcome" + }; + return type[id]; +} +function getSirenNoTypeByName(name){ + var typeList = { + "EmergencyMode":0X00, + "Doorbel":0X01, + "Burglar":0X02, + "FireMode":0X03, + "Help":0X04, + "No Smoking":0X05, + "Poor Air Quality":0X06, + "The temperature is too high":0X07, + "Thief":0X08, + "Welcome":0X09 + }; + return typeList[name]; +} +function getStrobeModeType(id){ + var type = { + 0X00:"NoLedIndication", + 0X01:"LedBlinkMode1 in Parallel to Warning", + 0X02:"LedBlinkMode2 in Parallel to Warning" + }; + return type[id]; +} +function getStrobeModeTypeByName(name){ + var typeList = { + "NoLedIndication":0X00, + "LedBlinkMode1 in Parallel to Warning":0X01, + "LedBlinkMode2 in Parallel to Warning":0X02 + }; + return typeList[name]; +} +function padLeft(str, len) { + str = '' + str; + if (str.length >= len) { + return str; + } else { + return padLeft("0" + str, len); + } +} + +function decodeUplink(input) { + var data = {}; + switch (input.fPort) { + case 6: + if (input.bytes[2] === 0x00) + { + data.Device = getDeviceName(input.bytes[1]); + data.SWver = input.bytes[3]/10; + data.HWver = input.bytes[4]; + data.Datecode = padLeft(input.bytes[5].toString(16), 2) + padLeft(input.bytes[6].toString(16), 2) + padLeft(input.bytes[7].toString(16), 2) + padLeft(input.bytes[8].toString(16), 2); + + return { + data: data, + }; + } + + data.Device = getDeviceName(input.bytes[1]); + if (input.bytes[3] & 0x80) + { + var tmp_v = input.bytes[3] & 0x7F; + data.Volt = (tmp_v / 10).toString() + '(low battery)'; + } + else + data.Volt = input.bytes[3]/10; + + data.WarningStatus = (input.bytes[4] == 0x00) ? 'NoWarnring' : 'Warning'; + data.ContactSwitchStatus = (input.bytes[5] == 0x00) ? 'Off' : 'On'; + break; + + case 7: + data.Cmd = getCfgCmd(input.bytes[0]); + data.Device = getDeviceName(input.bytes[1]); + + if ((input.bytes[0] === getCmdToID("ConfigReportRsp")) + || (input.bytes[0] === getCmdToID("SetPeriodSirenRsp")) + || (input.bytes[0] === getCmdToID("StopPeriodSirenRsp")) + || (input.bytes[0] === getCmdToID("SetLEDColorRsp")) + || (input.bytes[0] === getCmdToID("SetContactSwitchTriggerAlarmRsp"))) + { + data.Status = (input.bytes[2] === 0x00) ? 'Success' : 'Failure'; + } + else if (input.bytes[0] === getCmdToID("ReadConfigReportRsp")) + { + data.MinTime = (input.bytes[2]<<8 | input.bytes[3]); + data.MaxTime = (input.bytes[4]<<8 | input.bytes[5]); + } + else if (input.bytes[0] === getCmdToID("GetPeriodSirenRsp")) + { + data.SirenNo = getSirenNoType(input.bytes[2]); + data.SirenLevel = input.bytes[3]; + data.StrobeMode = getStrobeModeType(input.bytes[4]); + data.Duration = (input.bytes[5]<<8 | input.bytes[6]); + data.PeriodTime = (input.bytes[7]<<8 | input.bytes[8]); + } + else if (input.bytes[0] === getCmdToID("GetLEDColorRsp")) + { + data.Red = input.bytes[2]; + data.Green = input.bytes[3]; + data.Blue = input.bytes[4]; + } + else if (input.bytes[0] === getCmdToID("GetContactSwitchTriggerAlarmRsp")) + { + data.SirenNo = getSirenNoType(input.bytes[2]); + data.SirenLevel = input.bytes[3]; + data.StrobeMode = getStrobeModeType(input.bytes[4]); + data.Duration = (input.bytes[5]<<8 | input.bytes[6]); + } + + break; + + default: + return { + errors: ['unknown FPort'], + }; + + } + + return { + data: data, + }; + } + +function encodeDownlink(input) { + var ret = []; + var devid; + var getCmdID; + + getCmdID = getCmdToID(input.data.Cmd); + devid = getDeviceID(input.data.Device); + + if (input.data.Cmd == "ConfigReportReq") + { + var mint = input.data.MinTime; + var maxt = input.data.MaxTime; + ret = ret.concat(getCmdID, devid, (mint >> 8), (mint & 0xFF), (maxt >> 8), (maxt & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if ((input.data.Cmd == "ReadConfigReportReq") + || (input.data.Cmd == "GetPeriodSirenReq") + || (input.data.Cmd == "StopPeriodSirenReq") + || (input.data.Cmd == "GetLEDColorReq")) + { + ret = ret.concat(getCmdID, devid, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if ((input.data.Cmd == "StartSirenReq") + || (input.data.Cmd == "SetContactSwitchTriggerAlarmReq") ) + { + var sirenNo = getSirenNoTypeByName(input.data.SirenNo); + var siren = input.data.SirenLevel; + var strobeMode = getStrobeModeTypeByName(input.data.StrobeMode); + var duration = input.data.Duration; + ret = ret.concat(getCmdID, devid, sirenNo, siren, strobeMode, (duration >> 8), (duration & 0xFF), 0x00, 0x00, 0x00, 0x00); + } + else if ((input.data.Cmd == "SetPeriodSirenReq") ) + { + var sirenNo = getSirenNoTypeByName(input.data.SirenNo); + var siren = input.data.SirenLevel; + var strobeMode = getStrobeModeTypeByName(input.data.StrobeMode); + var duration = input.data.Duration; + var periodTime = input.data.PeriodTime; + ret = ret.concat(getCmdID, devid, sirenNo, siren, strobeMode,(duration >> 8), (duration & 0xFF), (periodTime >> 8), (periodTime & 0xFF), 0x00, 0x00); + } + else if ((input.data.Cmd == "SetLEDColorReq") ) + { + var red = input.data.Red; + var green = input.data.Green; + var blue = input.data.Blue; + ret = ret.concat(getCmdID, devid, red, green, blue, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + + return { + fPort: 7, + bytes: ret + }; +} + +function decodeDownlink(input) { + var data = {}; + switch (input.fPort) { + case 7: + data.Cmd = getCfgCmd(input.bytes[0]); + data.Device = getDeviceName(input.bytes[1]); + if (input.bytes[0] === getCmdToID("ConfigReportReq")) + { + data.MinTime = (input.bytes[2]<<8 | input.bytes[3]); + data.MaxTime = (input.bytes[4]<<8 | input.bytes[5]); + } + else if ((input.bytes[0] === getCmdToID("StartSirenReq")) + ||(input.bytes[0] === getCmdToID("SetContactSwitchTriggerAlarmReq"))) + { + data.SirenNo= getSirenNoType(input.bytes[2]); + data.SirenLevel=input.bytes[3]; + data.StrobeMode=getStrobeModeType(input.bytes[4]) + data.Duration=(input.bytes[5]<<8 | input.bytes[6]); + } + else if (input.bytes[0] === getCmdToID("SetPeriodSirenReq")) + { + data.SirenNo= getSirenNoType(input.bytes[2]); + data.SirenLevel=input.bytes[3]; + data.StrobeMode=getStrobeModeType(input.bytes[4]) + data.Duration=(input.bytes[5]<<8 | input.bytes[6]); + data.PeriodTime=(input.bytes[7]<<8 | input.bytes[8]); + } + else if (input.bytes[0] === getCmdToID("SetLEDColorReq")) + { + data.Red= input.bytes[2]; + data.Green=input.bytes[3]; + data.Blue=input.bytes[4]; + } + break; + + default: + return { + errors: ['invalid FPort'], + }; + } + + return { + data: data, + }; +} diff --git a/vendor/netvox/payload/ra02g.js b/vendor/netvox/payload/ra02g.js new file mode 100755 index 0000000000..79993bacbe --- /dev/null +++ b/vendor/netvox/payload/ra02g.js @@ -0,0 +1,321 @@ +function getCfgCmd(cfgcmd){ + var cfgcmdlist = { + 1: "ConfigReportReq", + 129: "ConfigReportRsp", + 2: "ReadConfigReportReq", + 130: "ReadConfigReportRsp", + 3: "SetSmokeSensitivityReq", + 131: "SetSmokeSensitivityRsp", + 4: "GetSmokeSensitivityReq", + 132: "GetSmokeSensitivityRsp", + 5: "SetShockSensorSensitivityReq", + 133: "SetShockSensorSensitivityRsp", + 6: "GetShockSensorSensitivityReq", + 134: "GetShockSensorSensitivityRsp", + 7: "SetHighSoundAlarmTriggerThresholdTimeReq", + 135: "SetHighSoundAlarmTriggerThresholdTimeRsp", + 8: "GetHighSoundAlarmTriggerThresholdTimeReq", + 136: "GetHighSoundAlarmTriggerThresholdTimeRsp", + 9: "SetBeeperDurationReq", + 137: "SetBeeperDurationRsp", + 10: "GetBeeperDurationReq", + 138: "GetBeeperDurationRsp", + 11: "StopCurrentBeeperAlarmReq", + 139: "StopCurrentBeeperAlarmRsp", + 12: "SetSmokeDebounceandResumeCheckTimeReq", + 140: "SetSmokeDebounceandResumeCheckTimeRsp", + 13: "GetSmokeDebounceandResumeCheckTimeReq", + 141: "GetSmokeDebounceandResumeCheckTimeRsp" + + }; + return cfgcmdlist[cfgcmd]; +} + +function getCmdToID(cmdtype){ + if (cmdtype == "ConfigReportReq") + return 1; + else if (cmdtype == "ConfigReportRsp") + return 129; + else if (cmdtype == "ReadConfigReportReq") + return 2; + else if (cmdtype == "ReadConfigReportRsp") + return 130; + else if (cmdtype == "SetSmokeSensitivityReq") + return 3; + else if (cmdtype == "SetSmokeSensitivityRsp") + return 131; + else if (cmdtype == "GetSmokeSensitivityReq") + return 4; + else if (cmdtype == "GetSmokeSensitivityRsp") + return 132; + else if (cmdtype == "SetShockSensorSensitivityReq") + return 5; + else if (cmdtype == "SetShockSensorSensitivityRsp") + return 133; + else if (cmdtype == "GetShockSensorSensitivityReq") + return 6; + else if (cmdtype == "GetShockSensorSensitivityRsp") + return 134; + else if (cmdtype == "SetHighSoundAlarmTriggerThresholdTimeReq") + return 7; + else if (cmdtype == "SetHighSoundAlarmTriggerThresholdTimeRsp") + return 135; + else if (cmdtype == "GetHighSoundAlarmTriggerThresholdTimeReq") + return 8; + else if (cmdtype == "GetHighSoundAlarmTriggerThresholdTimeRsp") + return 136; + else if (cmdtype == "SetBeeperDurationReq") + return 9; + else if (cmdtype == "SetBeeperDurationRsp") + return 137; + else if (cmdtype == "GetBeeperDurationReq") + return 10; + else if (cmdtype == "GetBeeperDurationRsp") + return 138; + else if (cmdtype == "StopCurrentBeeperAlarmReq") + return 11; + else if (cmdtype == "StopCurrentBeeperAlarmRsp") + return 139; + else if (cmdtype == "SetSmokeDebounceandResumeCheckTimeReq") + return 12; + else if (cmdtype == "SetSmokeDebounceandResumeCheckTimeRsp") + return 140; + else if (cmdtype == "GetSmokeDebounceandResumeCheckTimeReq") + return 13; + else if (cmdtype == "GetSmokeDebounceandResumeCheckTimeRsp") + return 141; +} + +function getDeviceName(dev){ + var deviceName = { + 215: "RA02G" + }; + return deviceName[dev]; +} + +function getDeviceID(devName){ + var deviceName = { + "RA02G": 215 + }; + return deviceName[devName]; +} + +function getSmokesensorSensitivityType(id){ + var type = { + 0X00:"accroding the hardware sensitivity knob", + 0X01:"Level1", + 0X02:"Level2", + 0X03:"Level3", + 0X04:"Level4", + }; + return type[id]; +} +function getTypeByName(name){ + var typeList = { + "accroding the hardware sensitivity knob":"0X00", + "Level1":0X01, + "Level2":0X02, + "Level3":0X03, + "Level4":0X04 + }; + return typeList[name]; +} +function padLeft(str, len) { + str = '' + str; + if (str.length >= len) { + return str; + } else { + return padLeft("0" + str, len); + } +} + +function decodeUplink(input) { + var data = {}; + switch (input.fPort) { + case 6: + if (input.bytes[2] === 0x00) + { + data.Device = getDeviceName(input.bytes[1]); + data.SWver = input.bytes[3]/10; + data.HWver = input.bytes[4]; + data.Datecode = padLeft(input.bytes[5].toString(16), 2) + padLeft(input.bytes[6].toString(16), 2) + padLeft(input.bytes[7].toString(16), 2) + padLeft(input.bytes[8].toString(16), 2); + + return { + data: data, + }; + } + + data.Device = getDeviceName(input.bytes[1]); + if (input.bytes[3] & 0x80) + { + var tmp_v = input.bytes[3] & 0x7F; + data.Volt = (tmp_v / 10).toString() + '(low battery)'; + } + else + data.Volt = input.bytes[3]/10; + + data.IncenseSmokeAlarm = (input.bytes[4] == 0x00) ? 'No Alarm' : 'Alarm'; + data.HighSoundAlarm = (input.bytes[5] == 0x00) ? 'No Alarm' : 'Alarm'; + data.TemShockTamperAlarmp = (input.bytes[6] == 0x00) ? 'No Alarm' : 'Alarm'; + data.PowerOffAlarm = (input.bytes[7] == 0x00) ? 'No Alarm' : 'Alarm'; + break; + + case 7: + data.Cmd = getCfgCmd(input.bytes[0]); + data.Device = getDeviceName(input.bytes[1]); + + if ((input.bytes[0] === getCmdToID("ConfigReportRsp")) + || (input.bytes[0] === getCmdToID("SetSmokeSensitivityRsp")) + || (input.bytes[0] === getCmdToID("SetShockSensorSensitivityRsp")) + || (input.bytes[0] === getCmdToID("SetHighSoundAlarmTriggerThresholdTimeRsp")) + || (input.bytes[0] === getCmdToID("SetBeeperDurationRsp")) + || (input.bytes[0] === getCmdToID("StopCurrentBeeperAlarmRsp")) + || (input.bytes[0] === getCmdToID("SetSmokeDebounceandResumeCheckTimeRsp"))) + { + data.Status = (input.bytes[2] === 0x00) ? 'Success' : 'Failure'; + } + else if (input.bytes[0] === getCmdToID("ReadConfigReportRsp")) + { + data.MinTime = (input.bytes[2]<<8 | input.bytes[3]); + data.MaxTime = (input.bytes[4]<<8 | input.bytes[5]); + } + else if (input.bytes[0] === getCmdToID("GetSmokeSensitivityRsp")) + { + data.SmokesensorSensitivity = getSmokesensorSensitivityType(input.bytes[2]); + }else if (input.bytes[0] === getCmdToID("GetShockSensorSensitivityRsp")) + { + data.ShockSensorSensitivity = input.bytes[2]; + }else if (input.bytes[0] === getCmdToID("GetHighSoundAlarmTriggerThresholdTimeRsp")) + { + data.HighSoundAlarmTriggerThreshold = (input.bytes[2]<<8 | input.bytes[3]); + data.HighSoundAlarmTriggerDuration = (input.bytes[4]<<8 | input.bytes[5]); + }else if (input.bytes[0] === getCmdToID("GetBeeperDurationRsp")) + { + data.BeeperDuration = (input.bytes[2]<<8 | input.bytes[3]) ==0?"DisableBeeper":(input.bytes[2]<<8 | input.bytes[3]); + data.AlarmSoundLevel = input.bytes[4]; + }else if (input.bytes[0] === getCmdToID("GetSmokeDebounceandResumeCheckTimeRsp")) + { + data.SmokeDebounceTIme = (input.bytes[2]<<8 | input.bytes[3]); + data.SmokeResumeTime = input.bytes[4]; + } + + break; + + default: + return { + errors: ['unknown FPort'], + }; + + } + + return { + data: data, + }; + } + +function encodeDownlink(input) { + var ret = []; + var devid; + var getCmdID; + + getCmdID = getCmdToID(input.data.Cmd); + devid = getDeviceID(input.data.Device); + + if (input.data.Cmd == "ConfigReportReq") + { + var mint = input.data.MinTime; + var maxt = input.data.MaxTime; + ret = ret.concat(getCmdID, devid, (mint >> 8), (mint & 0xFF), (maxt >> 8), (maxt & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if ((input.data.Cmd == "ReadConfigReportReq") + ||(input.data.Cmd == "GetSmokeSensitivityReq") + ||(input.data.Cmd == "GetShockSensorSensitivityReq") + ||(input.data.Cmd == "GetHighSoundAlarmTriggerThresholdTimeReq") + ||(input.data.Cmd == "GetBeeperDurationReq") + ||(input.data.Cmd == "StopCurrentBeeperAlarmReq") + ||(input.data.Cmd == "GetSmokeDebounceandResumeCheckTimeReq")) + { + ret = ret.concat(getCmdID, devid, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if (input.data.Cmd == "SetSmokeSensitivityReq") + { + var smokesensor = getTypeByName(input.data.SmokesensorSensitivity); + ret = ret.concat(getCmdID, devid, smokesensor, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if (input.data.Cmd == "SetShockSensorSensitivityReq") + { + var shockSensor = input.data.ShockSensorSensitivity; + ret = ret.concat(getCmdID, devid, shockSensor, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if (input.data.Cmd == "SetHighSoundAlarmTriggerThresholdTimeReq") + { + var highSoundAlarmThreshold = input.data.HighSoundAlarmTriggerThreshold; + var highSoundAlarmDuration = input.data.HighSoundAlarmTriggerDuration; + ret = ret.concat(getCmdID, devid, (highSoundAlarmThreshold >> 8), (highSoundAlarmThreshold & 0xFF),(highSoundAlarmDuration >> 8), (highSoundAlarmDuration & 0xFF), 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if (input.data.Cmd == "SetBeeperDurationReq") + { + var beeper = input.data.BeeperDuration=="DisableBeeper"? 0x0000:input.data.BeeperDuration; + var alarm = input.data.AlarmSoundLevel; + ret = ret.concat(getCmdID, devid, (beeper >> 8), (beeper & 0xFF), alarm, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + else if (input.data.Cmd == "SetSmokeDebounceandResumeCheckTimeReq") + { + var debounce = input.data.SmokeDebounceTIme; + var smokeResume = input.data.SmokeResumeTime; + ret = ret.concat(getCmdID, devid, (debounce >> 8), (debounce & 0xFF), smokeResume, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + } + + return { + fPort: 7, + bytes: ret + }; +} + +function decodeDownlink(input) { + var data = {}; + switch (input.fPort) { + case 7: + data.Cmd = getCfgCmd(input.bytes[0]); + data.Device = getDeviceName(input.bytes[1]); + if (input.bytes[0] === getCmdToID("ConfigReportReq")) + { + data.MinTime = (input.bytes[2]<<8 | input.bytes[3]); + data.MaxTime = (input.bytes[4]<<8 | input.bytes[5]); + } + else if (input.bytes[0] === getCmdToID("SetSmokeSensitivityReq")) + { + data.SmokesensorSensitivity= getSmokesensorSensitivityType(input.bytes[2]); + } + else if (input.bytes[0] === getCmdToID("SetShockSensorSensitivityReq")) + { + data.ShockSensorSensitivity= input.bytes[2]; + } + else if (input.bytes[0] === getCmdToID("SetHighSoundAlarmTriggerThresholdTimeReq")) + { + data.HighSoundAlarmTriggerThreshold= (input.bytes[2]<<8 | input.bytes[3]); + data.HighSoundAlarmTriggerDuration= (input.bytes[4]<<8 | input.bytes[5]); + } + else if (input.bytes[0] === getCmdToID("SetBeeperDurationReq")) + { + data.BeeperDuration = (input.bytes[2]<<8 | input.bytes[3]) ==0?"DisableBeeper":(input.bytes[2]<<8 | input.bytes[3]); + data.AlarmSoundLevel = input.bytes[4]; + } + else if (input.bytes[0] === getCmdToID("SetSmokeDebounceandResumeCheckTimeReq")) + { + data.SmokeDebounceTIme = (input.bytes[2]<<8 | input.bytes[3]); + data.SmokeResumeTime = input.bytes[4]; + } + + break; + + default: + return { + errors: ['invalid FPort'], + }; + } + + return { + data: data, + }; +} diff --git a/vendor/netvox/photos/r603.png b/vendor/netvox/photos/r603.png new file mode 100644 index 0000000000..ec919ad859 Binary files /dev/null and b/vendor/netvox/photos/r603.png differ diff --git a/vendor/netvox/photos/ra02g.png b/vendor/netvox/photos/ra02g.png new file mode 100644 index 0000000000..deb169c093 Binary files /dev/null and b/vendor/netvox/photos/ra02g.png differ diff --git a/vendor/netvox/r315-codec.yaml b/vendor/netvox/r315-codec.yaml index 3ec0283833..4ba9466b04 100755 --- a/vendor/netvox/r315-codec.yaml +++ b/vendor/netvox/r315-codec.yaml @@ -25,6 +25,80 @@ uplinkDecoder: Temp: 27.80 Humi: 53 + - description: Status report + input: + fPort: 6 + bytes: [0x01, 0xD2, 0x02, 0x1C, 0x08, 0x03, 0x39, 0x12, 0x00, 0x00, 0x00] + output: + data: + Device: 'R315' + Volt: 2.8 + Illuminance: '2051Lux' + LowTemperatureAlarm: 1 + HighTemperatureAlarm: 0 + LowHumidityAlarm: 0 + HighHumidityAlarm: 1 + LowIlluminanceAlarm: 1 + HighIlluminanceAlarm: 1 + + - description: Status report + input: + fPort: 6 + bytes: [0x01, 0xD2, 0x011, 0x1C, 0x01, 0x03, 0x39, 0x12, 0x80, 0x00, 0x00] + output: + data: + Device: 'R315' + Volt: 2.8 + THSensor: 1 + LightSensor: 0 + PIRSensor: 0 + EmergenceButton: 1 + TiltSensor: 1 + InternalContactSwitch: 1 + ExternalContactSwitch1: 0 + ExternalContactSwitch2: 0 + InternalShockSensor: 1 + ExternalShockSensor: 1 + ExternalDryContactPointIN: 0 + DryContactPointOut: 0 + ExternalWaterLeakSenor1: 0 + ExternalWaterLeakSenor2: 0 + ExternalSeatSensor: 0 + ExternalGlassSensor1: 0 + ExternalGlassSensor2: 1 + PIRSensorState: 0 + EmergenceButtonaLAlarmState: 0 + TiltSensorState: 0 + InternalContactSwitchSensorState: 0 + ExternalContactSwitch1SensorState: 0 + ExternalContactSwitch2SensorState: 0 + InternalShockSensorState: 0 + ExternalShockSensorState: 1 + ExternalDryContactPointINState: 0 + ExternalWaterLeak1SenorState: 1 + ExternalWaterLeak2SenorState: 0 + ExternalSeatSenorState: 0 + ExternalGlassSenor1State: 1 + ExternalGlassSenor2State: 0 + + - description: Status report + input: + fPort: 6 + bytes: [0x01, 0xD2, 0x12, 0x1C, 0x03, 0x03, 0x39, 0x12, 0x39, 0x03, 0x39] + output: + data: + Device: 'R315' + Volt: 2.8 + Temp: 7.71 + Humidity: '146.1%' + Illuminance: '14595Lux' + LowTemperatureAlarm: 1 + HighTemperatureAlarm: 0 + LowHumidityAlarm: 0 + HighHumidityAlarm: 1 + LowIlluminanceAlarm: 1 + HighIlluminanceAlarm: 1 + - description: Configure report response input: fPort: 7 diff --git a/vendor/netvox/r603-codec.yaml b/vendor/netvox/r603-codec.yaml new file mode 100755 index 0000000000..cd4784253f --- /dev/null +++ b/vendor/netvox/r603-codec.yaml @@ -0,0 +1,226 @@ +uplinkDecoder: + fileName: payload/r603.js + examples: + - description: Startup version report + input: + fPort: 6 + bytes: [0x01, 0xDE, 0x00, 0x64, 0x15, 0x20, 0x20, 0x08, 0x11, 0x00, 0x00] + output: + data: + Device: 'R603' + SWver: 10 + HWver: 21 + Datecode: '20200811' + + - description: Status report + input: + fPort: 6 + bytes: [0x01, 0xDE, 0x01, 0x30, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00] + output: + data: + Device: 'R603' + Volt: 4.8 + WarningStatus: 'NoWarnring' + ContactSwitchStatus: 'On' + + - description: Configure report response + input: + fPort: 7 + bytes: [0x81, 0xDE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ConfigReportRsp' + Device: 'R603' + Status: 'Success' + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x82, 0xDE, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ReadConfigReportRsp' + Device: 'R603' + MinTime: 900 + MaxTime: 1800 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x85, 0xDE, 0x01, 0x03, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetPeriodSirenRsp' + Device: 'R603' + SirenNo: 'Doorbel' + SirenLevel: 3 + StrobeMode: 'LedBlinkMode2 in Parallel to Warning' + Duration: 2049 + PeriodTime: 0 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x86, 0xDE, 0x01, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'StopPeriodSirenRsp' + Device: 'R603' + Status: 'Failure' + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x88, 0xDE, 0x03, 0x04, 0x07, 0x08, 0x01, 0x05, 0x03, 0x00, 0x00] + output: + data: + Cmd: 'GetLEDColorRsp' + Device: 'R603' + Red: 3 + Green: 4 + Blue: 7 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x8A, 0xDE, 0x03, 0x08, 0x01, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetContactSwitchTriggerAlarmRsp' + Device: 'R603' + SirenNo: 'FireMode' + SirenLevel: 8 + StrobeMode: 'LedBlinkMode1 in Parallel to Warning' + Duration: 2049 + +downlinkDecoder: + fileName: payload/r603.js + examples: + - description: Configure report request + input: + fPort: 7 + bytes: [0x01, 0xDE, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ConfigReportReq' + Device: 'R603' + MinTime: 900 + MaxTime: 1800 + + - description: Read configure report request + input: + fPort: 7 + bytes: [0x03, 0xDE, 0x00, 0x84, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'StartSirenReq' + Device: 'R603' + SirenNo: 'EmergencyMode' + SirenLevel: 132 + StrobeMode: 'LedBlinkMode2 in Parallel to Warning' + Duration: 2049 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x04, 0xDE, 0x00, 0x84, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetPeriodSirenReq' + Device: 'R603' + SirenNo: 'EmergencyMode' + SirenLevel: 132 + StrobeMode: 'LedBlinkMode1 in Parallel to Warning' + Duration: 2049 + PeriodTime: 256 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x07, 0xDE, 0x03, 0x18, 0x07, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetLEDColorReq' + Device: 'R603' + Red: 3 + Green: 24 + Blue: 7 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x09, 0xDE, 0x03, 0x12, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetContactSwitchTriggerAlarmReq' + Device: 'R603' + SirenNo: 'FireMode' + SirenLevel: 18 + StrobeMode: 'NoLedIndication' + Duration: 2049 + +downlinkEncoder: + fileName: payload/r603.js + examples: + - description: Configure report request + input: + data: + Cmd: 'ConfigReportReq' + Device: 'R603' + MinTime: 900 + MaxTime: 1800 + output: + fPort: 7 + bytes: [0x01, 0xDE, 0x03, 0x84, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'StartSirenReq' + Device: 'R603' + SirenNo: 'EmergencyMode' + SirenLevel: 132 + StrobeMode: 'LedBlinkMode2 in Parallel to Warning' + Duration: 2049 + output: + fPort: 7 + bytes: [0x03, 0xDE, 0x00, 0x84, 0x02, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetPeriodSirenReq' + Device: 'R603' + SirenNo: 'EmergencyMode' + SirenLevel: 132 + StrobeMode: 'LedBlinkMode1 in Parallel to Warning' + Duration: 2049 + PeriodTime: 256 + output: + fPort: 7 + bytes: [0x04, 0xDE, 0x00, 0x84, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetLEDColorReq' + Device: 'R603' + Red: 3 + Green: 24 + Blue: 7 + output: + fPort: 7 + bytes: [0x07, 0xDE, 0x03, 0x18, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetContactSwitchTriggerAlarmReq' + Device: 'R603' + SirenNo: 'FireMode' + SirenLevel: 18 + StrobeMode: 'NoLedIndication' + Duration: 2049 + output: + fPort: 7 + bytes: [0x09, 0xDE, 0x03, 0x12, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] diff --git a/vendor/netvox/r603.yaml b/vendor/netvox/r603.yaml new file mode 100755 index 0000000000..757440d0e9 --- /dev/null +++ b/vendor/netvox/r603.yaml @@ -0,0 +1,63 @@ +name: R603 - Wireless Customized Voice Announcer +description: R603 is a Wireless Customized Voice Announcer. + +hardwareVersions: + - version: '21' + numeric: 21 + +firmwareVersions: + - version: '10' + numeric: 10 + hardwareVersions: + - '21' + + profiles: + EU863-870: + id: profile-eu868 + codec: r603-codec + AS923: + id: profile-as923 + codec: r603-codec + US902-928: + id: profile-us915 + codec: r603-codec + AU915-928: + id: profile-au915 + codec: r603-codec + KR920-923: + id: profile-kr920 + codec: r603-codec + IN865-867: + id: profile-in865 + codec: r603-codec + CN470-510: + id: profile-cn470 + codec: r603-codec + +dimensions: + diameter: 106 + height: 40.6 + +battery: + replaceable: true + type: 2 x1.5V AAA alkaline batteries + +operatingConditions: + temperature: + min: -20 + max: 55 + relativeHumidity: + min: 0 + max: 0.9 + +keyProvisioning: + - custom + - join server + +keySecurity: none + +productURL: http://www.netvox.com.tw/product.asp?pro=R603 +dataSheetURL: http://www.netvox.com.tw/um/R603/R603Gdatasheet.pdf + +photos: + main: photos/r603.png diff --git a/vendor/netvox/r718pa.yaml b/vendor/netvox/r718pa.yaml index 2372c9d355..078518a5d5 100755 --- a/vendor/netvox/r718pa.yaml +++ b/vendor/netvox/r718pa.yaml @@ -33,10 +33,8 @@ firmwareVersions: CN470-510: id: profile-cn470 codec: r718pa-codec - sensors: - level - dimensions: width: 88.19 length: 112 diff --git a/vendor/netvox/r718pa4.yaml b/vendor/netvox/r718pa4.yaml index b34dbdbf03..2ff45825b9 100755 --- a/vendor/netvox/r718pa4.yaml +++ b/vendor/netvox/r718pa4.yaml @@ -33,10 +33,8 @@ firmwareVersions: CN470-510: id: profile-cn470 codec: r718pa4-codec - sensors: - level - dimensions: width: 88.19 length: 112 diff --git a/vendor/netvox/r718pb.yaml b/vendor/netvox/r718pb.yaml index 90af6f6576..26f353e782 100755 --- a/vendor/netvox/r718pb.yaml +++ b/vendor/netvox/r718pb.yaml @@ -33,10 +33,8 @@ firmwareVersions: CN470-510: id: profile-cn470 codec: r718pb-codec - sensors: - level - dimensions: width: 88.19 length: 112 diff --git a/vendor/netvox/ra02g-codec.yaml b/vendor/netvox/ra02g-codec.yaml new file mode 100755 index 0000000000..5fdae9cd2e --- /dev/null +++ b/vendor/netvox/ra02g-codec.yaml @@ -0,0 +1,234 @@ +uplinkDecoder: + fileName: payload/ra02g.js + examples: + - description: Startup version report + input: + fPort: 6 + bytes: [0x01, 0xD7, 0x00, 0x64, 0x15, 0x20, 0x20, 0x08, 0x11, 0x00, 0x00] + output: + data: + Device: 'RA02G' + SWver: 10 + HWver: 21 + Datecode: '20200811' + + - description: Status report + input: + fPort: 6 + bytes: [0x01, 0xD7, 0x01, 0x30, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00] + output: + data: + Device: 'RA02G' + Volt: 4.8 + IncenseSmokeAlarm: 'No Alarm' + HighSoundAlarm: 'No Alarm' + TemShockTamperAlarmp: 'Alarm' + PowerOffAlarm: 'Alarm' + + - description: Configure report response + input: + fPort: 7 + bytes: [0x81, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ConfigReportRsp' + Device: 'RA02G' + Status: 'Success' + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x82, 0xD7, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ReadConfigReportRsp' + Device: 'RA02G' + MinTime: 900 + MaxTime: 1800 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x84, 0xD7, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetSmokeSensitivityRsp' + Device: 'RA02G' + SmokesensorSensitivity: 'Level3' + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x86, 0xD7, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetShockSensorSensitivityRsp' + Device: 'RA02G' + ShockSensorSensitivity: 3 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x88, 0xD7, 0x03, 0x04, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetHighSoundAlarmTriggerThresholdTimeRsp' + Device: 'RA02G' + HighSoundAlarmTriggerThreshold: 772 + HighSoundAlarmTriggerDuration: 1800 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x8A, 0xD7, 0x03, 0x08, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetBeeperDurationRsp' + Device: 'RA02G' + BeeperDuration: 776 + AlarmSoundLevel: 7 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x8D, 0xD7, 0x02, 0x10, 0x16, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'GetSmokeDebounceandResumeCheckTimeRsp' + Device: 'RA02G' + SmokeDebounceTIme: 528 + SmokeResumeTime: 22 + +downlinkDecoder: + fileName: payload/ra02g.js + examples: + - description: Configure report request + input: + fPort: 7 + bytes: [0x01, 0xD7, 0x03, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'ConfigReportReq' + Device: 'RA02G' + MinTime: 900 + MaxTime: 1800 + + - description: Read configure report request + input: + fPort: 7 + bytes: [0x03, 0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetSmokeSensitivityReq' + Device: 'RA02G' + SmokesensorSensitivity: 'Level1' + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x05, 0xD7, 0x13, 0x84, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetShockSensorSensitivityReq' + Device: 'RA02G' + ShockSensorSensitivity: 19 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x07, 0xD7, 0x03, 0x18, 0x07, 0x18, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetHighSoundAlarmTriggerThresholdTimeReq' + Device: 'RA02G' + HighSoundAlarmTriggerThreshold: 792 + HighSoundAlarmTriggerDuration: 1816 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x09, 0xD7, 0x03, 0x12, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetBeeperDurationReq' + Device: 'RA02G' + BeeperDuration: 786 + AlarmSoundLevel: 7 + + - description: Read configure report response + input: + fPort: 7 + bytes: [0x0C, 0xD7, 0x06, 0x04, 0x07, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00] + output: + data: + Cmd: 'SetSmokeDebounceandResumeCheckTimeReq' + Device: 'RA02G' + SmokeDebounceTIme: 1540 + SmokeResumeTime: 7 + +downlinkEncoder: + fileName: payload/ra02g.js + examples: + - description: Configure report request + input: + data: + Cmd: 'ConfigReportReq' + Device: 'RA02G' + MinTime: 900 + MaxTime: 1800 + output: + fPort: 7 + bytes: [0x01, 0xD7, 0x03, 0x84, 0x07, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetSmokeSensitivityReq' + Device: 'RA02G' + SmokesensorSensitivity: 'Level1' + output: + fPort: 7 + bytes: [0x03, 0xD7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetShockSensorSensitivityReq' + Device: 'RA02G' + ShockSensorSensitivity: 19 + output: + fPort: 7 + bytes: [0x05, 0xD7, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetHighSoundAlarmTriggerThresholdTimeReq' + Device: 'RA02G' + HighSoundAlarmTriggerThreshold: 792 + HighSoundAlarmTriggerDuration: 1816 + output: + fPort: 7 + bytes: [0x07, 0xD7, 0x03, 0x18, 0x07, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetBeeperDurationReq' + Device: 'RA02G' + BeeperDuration: 786 + AlarmSoundLevel: 7 + output: + fPort: 7 + bytes: [0x09, 0xD7, 0x03, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] + + - description: Read configure report request + input: + data: + Cmd: 'SetSmokeDebounceandResumeCheckTimeReq' + Device: 'RA02G' + SmokeDebounceTIme: 1540 + SmokeResumeTime: 7 + output: + fPort: 7 + bytes: [0x0C, 0xD7, 0x06, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] diff --git a/vendor/netvox/ra02g.yaml b/vendor/netvox/ra02g.yaml new file mode 100755 index 0000000000..d9fd8bea3f --- /dev/null +++ b/vendor/netvox/ra02g.yaml @@ -0,0 +1,63 @@ +name: RA02G - Wireless Smoking Warning +description: RA02G is a Wireless Smoking Warning. + +hardwareVersions: + - version: '21' + numeric: 21 + +firmwareVersions: + - version: '10' + numeric: 10 + hardwareVersions: + - '21' + + profiles: + EU863-870: + id: profile-eu868 + codec: ra02g-codec + AS923: + id: profile-as923 + codec: ra02g-codec + US902-928: + id: profile-us915 + codec: ra02g-codec + AU915-928: + id: profile-au915 + codec: ra02g-codec + KR920-923: + id: profile-kr920 + codec: ra02g-codec + IN865-867: + id: profile-in865 + codec: ra02g-codec + CN470-510: + id: profile-cn470 + codec: ra02g-codec + +dimensions: + diameter: 106 + height: 40.6 + +battery: + replaceable: true + type: 2 x1.5V AAA alkaline batteries + +operatingConditions: + temperature: + min: -20 + max: 55 + relativeHumidity: + min: 0 + max: 0.9 + +keyProvisioning: + - custom + - join server + +keySecurity: none + +productURL: http://www.netvox.com.tw/product.asp?pro=RA02G +dataSheetURL: http://www.netvox.com.tw/um/RA02G/RA02Gdatasheet.pdf + +photos: + main: photos/ra02g.png diff --git a/vendor/netvox/rp02.yaml b/vendor/netvox/rp02.yaml index 92a59377f7..03c773d37d 100755 --- a/vendor/netvox/rp02.yaml +++ b/vendor/netvox/rp02.yaml @@ -33,11 +33,9 @@ firmwareVersions: CN470-510: id: profile-cn470 codec: rp02-codec - sensors: - current - voltage - dimensions: width: 88.19 length: 112 diff --git a/vendor/rakwireless/decoder-qingping.js b/vendor/rakwireless/decoder-qingping.js new file mode 100644 index 0000000000..a0c60adbba --- /dev/null +++ b/vendor/rakwireless/decoder-qingping.js @@ -0,0 +1,62 @@ +function Decoder(bytes, port) { + + var i = 0; + var output = {}; + var device_address = data[i++]; + var function_code = data[i++]; + var data_length = data[i++]; + var data_type = data[i++]; + + // Parsing only real time data from sensor + if ((0x41 == function_code) && (0x01 == data_type)) { + + // id + output.device = device_address; + + // timestamp + output.timestamp = (data[i] << 24) + (data[i+1] << 16) + (data[i+2] << 8) + data[i+3]; + i+=4; + + // temperature + output.temperature = ((data[i] * 16) + (data[i+1] >> 4) - 500) / 10.0; + output.humidity = (256 * (data[i+1] & 0x0F) + data[i+2]) / 10.0; + output.co2 = (data[i+3] << 8) + data[i+4]; + i+=5; + + // battery + output.battery = data[i]; + + } + + return output; + +} + +function bytesToHex(bytes) { + + var hexArray = []; + for (var i = 0; i < bytes.length; i++) { + var hex = (bytes[i] & 0xff).toString(16).toUpperCase(); + if (hex.length === 1) { + hex = '0' + hex; + } + hexArray.push(hex); + } + return hexArray.join(''); + +} + +function decodeUplink(input) { + + bytes = input.bytes; + fPort = input.fPort; + + return { + data: Decoder(bytes, fPort), + warnings: [], + errors: [] + }; + +} + + diff --git a/vendor/rakwireless/index.yaml b/vendor/rakwireless/index.yaml index 753bfbf7d8..ff7e393e9c 100644 --- a/vendor/rakwireless/index.yaml +++ b/vendor/rakwireless/index.yaml @@ -6,3 +6,5 @@ endDevices: - wisblock-kit4 - rak2270 - rak2560 + - qingping-t-h + - qingping-co2-t-h diff --git a/vendor/rakwireless/qingping-co2-t-h-868-profile.yaml b/vendor/rakwireless/qingping-co2-t-h-868-profile.yaml new file mode 100644 index 0000000000..e087bb591f --- /dev/null +++ b/vendor/rakwireless/qingping-co2-t-h-868-profile.yaml @@ -0,0 +1,48 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.3' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'RP001-1.0.3-RevA' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 16 + +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/rakwireless/qingping-co2-t-h-915-profile.yaml b/vendor/rakwireless/qingping-co2-t-h-915-profile.yaml new file mode 100644 index 0000000000..9a2d8a9bf8 --- /dev/null +++ b/vendor/rakwireless/qingping-co2-t-h-915-profile.yaml @@ -0,0 +1,48 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.3' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'RP001-1.0.3-RevA' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 22 + +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/rakwireless/qingping-co2-t-h-codec.yaml b/vendor/rakwireless/qingping-co2-t-h-codec.yaml new file mode 100644 index 0000000000..e0b8487080 --- /dev/null +++ b/vendor/rakwireless/qingping-co2-t-h-codec.yaml @@ -0,0 +1,2 @@ +uplinkDecoder: + fileName: decoder-qingping.js diff --git a/vendor/rakwireless/qingping-co2-t-h.png b/vendor/rakwireless/qingping-co2-t-h.png new file mode 100644 index 0000000000..f3a1620350 Binary files /dev/null and b/vendor/rakwireless/qingping-co2-t-h.png differ diff --git a/vendor/rakwireless/qingping-co2-t-h.yaml b/vendor/rakwireless/qingping-co2-t-h.yaml new file mode 100644 index 0000000000..45c02746ec --- /dev/null +++ b/vendor/rakwireless/qingping-co2-t-h.yaml @@ -0,0 +1,74 @@ +name: QingPing CO2 & Temperature & Humidity Monitor for LoRaWAN +description: The QingPing LoRaWAN CO2 monitor Sensor is a remote monitoring device that uses nondispersive infrared (NDIR) spectral analysis to accurately measure CO2 levels. Aside from CO2 levels, it also monitors temperature and relative humidity, providing a comprehensive overview of the indoor environment in real time. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.3.4' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # 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: + id: qingping-co2-t-h-868-profile + lorawanCertified: false + codec: qingping-co2-t-h-codec + US902-928: + id: qingping-co2-t-h-915-profile + lorawanCertified: false + codec: qingping-co2-t-h-codec + +sensors: + - temperature + - humidity + - co2 + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 77 + length: 77 + height: 28 + +# Weight in grams (optional) +#weight: 10 + +operatingConditions: + temperature: + min: -10 + max: 50 + +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Product and data sheet URLs (optional) +productURL: https://store.rakwireless.com/products/qingping-lorawan-co2-monitoring-sensor +dataSheetURL: https://downloads.rakwireless.com/IoT-Marketplace/Qingping/Indoor%20CO2%20Monitoring%20Solution/QingPing%20LoRaWAN%20CO2%20Sensor%20Datasheet.pdf + +# Photos +photos: + main: qingping-co2-t-h.png +#videos: +# main: https://www.youtube.com/watch?v=XVRR7Akyy8M + +# Regulatory compliances (optional) +#compliances: +# emc: +# - body: ETSI +# norm: EN +# standard: 301 489-1 +# version: 2.2.3 +# radio: +# - body: ETSI +# norm: EN +# standard: 300 220-2 +# version: 3.2.1 diff --git a/vendor/rakwireless/qingping-t-h-868-profile.yaml b/vendor/rakwireless/qingping-t-h-868-profile.yaml new file mode 100644 index 0000000000..e087bb591f --- /dev/null +++ b/vendor/rakwireless/qingping-t-h-868-profile.yaml @@ -0,0 +1,48 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.3' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'RP001-1.0.3-RevA' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 16 + +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/rakwireless/qingping-t-h-915-profile.yaml b/vendor/rakwireless/qingping-t-h-915-profile.yaml new file mode 100644 index 0000000000..9a2d8a9bf8 --- /dev/null +++ b/vendor/rakwireless/qingping-t-h-915-profile.yaml @@ -0,0 +1,48 @@ +# LoRaWAN MAC version: 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4 or 1.1 +macVersion: '1.0.3' +# LoRaWAN Regional Parameters version. Values depend on the LoRaWAN version: +# 1.0: TS001-1.0 +# 1.0.1: TS001-1.0.1 +# 1.0.2: RP001-1.0.2 or RP001-1.0.2-RevB +# 1.0.3: RP001-1.0.3-RevA +# 1.0.4: RP002-1.0.0 or RP002-1.0.1 +# 1.1: RP001-1.1-RevA or RP001-1.1-RevB +regionalParametersVersion: 'RP001-1.0.3-RevA' + +# Whether the end device supports join (OTAA) or not (ABP) +supportsJoin: true +# If your device is an ABP device (supportsJoin is false), uncomment the following fields: +# RX1 delay +#rx1Delay: 5 +# RX1 data rate offset +#rx1DataRateOffset: 0 +# RX2 data rate index +#rx2DataRateIndex: 0 +# RX2 frequency (MHz) +#rx2Frequency: 869.525 +# Factory preset frequencies (MHz) +#factoryPresetFrequencies: [868.1, 868.3, 868.5, 867.1, 867.3, 867.5, 867.7, 867.9] + +# Maximum EIRP +maxEIRP: 22 + +# Whether the end device supports 32-bit frame counters +supports32bitFCnt: true + +# Whether the end device supports class B +supportsClassB: false +# If your device supports class B, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classBTimeout: 60 +# Ping slot period (seconds) +#pingSlotPeriod: 128 +# Ping slot data rate index +#pingSlotDataRateIndex: 0 +# Ping slot frequency (MHz). Set to 0 if the band supports ping slot frequency hopping. +#pingSlotFrequency: 869.525 + +# Whether the end device supports class C +supportsClassC: false +# If your device supports class C, uncomment the following fields: +# Maximum delay for the end device to answer a MAC request or confirmed downlink frame (seconds) +#classCTimeout: 60 diff --git a/vendor/rakwireless/qingping-t-h-codec.yaml b/vendor/rakwireless/qingping-t-h-codec.yaml new file mode 100644 index 0000000000..e0b8487080 --- /dev/null +++ b/vendor/rakwireless/qingping-t-h-codec.yaml @@ -0,0 +1,2 @@ +uplinkDecoder: + fileName: decoder-qingping.js diff --git a/vendor/rakwireless/qingping-t-h.png b/vendor/rakwireless/qingping-t-h.png new file mode 100644 index 0000000000..216569175c Binary files /dev/null and b/vendor/rakwireless/qingping-t-h.png differ diff --git a/vendor/rakwireless/qingping-t-h.yaml b/vendor/rakwireless/qingping-t-h.yaml new file mode 100644 index 0000000000..03c8490dca --- /dev/null +++ b/vendor/rakwireless/qingping-t-h.yaml @@ -0,0 +1,73 @@ +name: QingPing Temperature & Humidity Monitor for LoRaWAN +description: The QingPing Temp & RH Monitor Pro S is a professional-grade sensor designed for precise monitoring of temperature and humidity levels. It is specifically tailored for greenhouse applications and can withstand extreme environmental conditions. With its precision accuracy, the monitor ensures optimal growing conditions for plants, enabling users to achieve maximum productivity. + +# Hardware versions (optional, use when you have revisions) +hardwareVersions: + - version: '1.0' + numeric: 1 + +# Firmware versions (at least one is mandatory) +firmwareVersions: + - # Firmware version + version: '1.3.4' + numeric: 1 + # Corresponding hardware versions (optional) + hardwareVersions: + - '1.0' + + # 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: + id: qingping-t-h-868-profile + lorawanCertified: false + codec: qingping-t-h-codec + US902-928: + id: qingping-t-h-915-profile + lorawanCertified: false + codec: qingping-t-h-codec + +sensors: + - temperature + - humidity + +# Dimensions in mm (optional) +# Use width, height, length and/or diameter +dimensions: + width: 77 + length: 77 + height: 28 + +# Weight in grams (optional) +#weight: 10 + +operatingConditions: + temperature: + min: -20 + max: 50 + +# Valid values are: none, read protected and secure element. +keySecurity: none + +# Product and data sheet URLs (optional) +productURL: https://store.rakwireless.com/products/advanced-greenhouse-temperature-humidity-sensor-with-display +dataSheetURL: https://downloads.rakwireless.com/IoT-Marketplace/Qingping/Indoor%20Temperature%20and%20Humidity%20Monitoring%20Solution/Qingping%20Temperature%20%26%20RH%20Monitor%20Pro%20S%20Datasheet.pdf + +# Photos +photos: + main: qingping-t-h.png +#videos: +# main: https://www.youtube.com/watch?v=XVRR7Akyy8M + +# Regulatory compliances (optional) +#compliances: +# emc: +# - body: ETSI +# norm: EN +# standard: 301 489-1 +# version: 2.2.3 +# radio: +# - body: ETSI +# norm: EN +# standard: 300 220-2 +# version: 3.2.1