From b9d57735525c119f612d9a3eb4aa7692f8460868 Mon Sep 17 00:00:00 2001 From: Marc Boehm Date: Wed, 27 Jul 2022 17:13:33 +0200 Subject: [PATCH 1/5] CAPAUT-253 FIrst stable implementation --- LICENSE | 19 ++++ README.md | 36 +++++++ img/captica_favicon.png | Bin 0 -> 16727 bytes img/captica_logo.svg | 1 + package.json | 19 ++++ systacomfort2/icons/captica.png | Bin 0 -> 71703 bytes systacomfort2/systacomfort2.html | 39 +++++++ systacomfort2/systacomfort2.js | 169 +++++++++++++++++++++++++++++++ 8 files changed, 283 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 img/captica_favicon.png create mode 100644 img/captica_logo.svg create mode 100644 package.json create mode 100644 systacomfort2/icons/captica.png create mode 100644 systacomfort2/systacomfort2.html create mode 100644 systacomfort2/systacomfort2.js diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..b5ca2ca --- /dev/null +++ b/LICENSE @@ -0,0 +1,19 @@ +MIT Licence Copyright (c) captica GmbH - Marc Böhm (marc.boehm@captica.de) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8ed156e --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ + +

+ +# captica: Node-RED Node for SystaComfort II + +Receive data from SysteComfort II devices in Node-RED flows + +This Node-RED node is capturing the packets from a SysteComfort II device and prepares the data for further processing. + +## Supported values + +|Value-Key|Description| +|--|--| +|BOILER_START_COUNTER|Starts of boiler gas unit| +|BOILER_WORKING_HOURS|Overall working hours of boiler| +|BUFFER_TANK_TEMPERATURE_TOP|Top temperature of buffer tank| +|BUFFER_TANK_TEMPERATURE_BOTTOM|Bottom temperature of buffer tank| +|SOLAR_YIELD_CURRENT|Current yield of solar| +|SOLAR_YIELD_DAY|Day yield of solar| +|SOLAR_YIELD_TOTAL|Total yield of solar| +|SOLAR_TEMPERATURE_COLLECTOR|Current temperature of solar collector| +|SYSTEM_TEMPERATURE_FLOW|Current temperature of system flow| +|SYSTEM_TEMPERATURE_FLOW_RETURN|Current temperature of system flow (return)| +|SYSTEM_TEMPERATURE_EXTERNAL|External temperature of system| +|SYSTEM_TEMPERATURE_PROCESS_WATER_CURRENT|Current temperature of system process water| +|SYSTEM_TEMPERATURE_PROCESS_WATER_TARGET|Target temperature of system process water| +|SYSTEM_TEMPERATURE_ROOM_TARGET|Target room temperature| + +## Compatible SystaComfort II devices + +|Device|Software-Version|Hardware-Version|Basis-System|Compatible?| +|--|--|--|--|--| +|Systa Comfort 2|V1.16|V1.21|V1.13|yes - except flow return value is not available| + +## Connectivity +To capture the published data you have to redirect the traffic which sent by the SysteComfort II device to the official remote portal. If you have an local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. diff --git a/img/captica_favicon.png b/img/captica_favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..11bddba5db817e8b434890db4e834f34373d286f GIT binary patch literal 16727 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 literal 0 HcmV?d00001 diff --git a/img/captica_logo.svg b/img/captica_logo.svg new file mode 100644 index 0000000..7dea9c6 --- /dev/null +++ b/img/captica_logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1f3d11d --- /dev/null +++ b/package.json @@ -0,0 +1,19 @@ +{ + "name": "@captica/node-red-systacomfort2", + "version": "1.0.0", + "description": "Node-RED node to connect and read data from SystaComfort II heating/solar systems", + "author": "Marc Böhm (marc.boehm@captica.de)", + "homepage": "http://www.captica.de", + "repository": { + "type": "bitbucked", + "url": "https://bitbucket.org/captica-dev/de.captica.nodered.node.systacomfort2" + }, + "dependencies": { + }, + "keywords": [ "node-red" ], + "node-red" : { + "nodes": { + "systacomfort2": "systacomfort2/systacomfort2.js" + } + } +} \ No newline at end of file diff --git a/systacomfort2/icons/captica.png b/systacomfort2/icons/captica.png new file mode 100644 index 0000000000000000000000000000000000000000..bacad4c40ab7144364bd79771024b6d4214f3564 GIT binary patch literal 71703 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 + RED.nodes.registerType('systacomfort2', { + category: 'captica', + color: '#37BEE4', + defaults: { + name: {value:""}, + topicPrefix: {value:""}, + listenPort: {value:""} + }, + inputs: 0, + outputs: 1, + icon: 'captica.png', + label: function () { + return this.name || 'SystaComfort2' + }, + outputLabels: 'data' + }) + + + + + \ No newline at end of file diff --git a/systacomfort2/systacomfort2.js b/systacomfort2/systacomfort2.js new file mode 100644 index 0000000..5462503 --- /dev/null +++ b/systacomfort2/systacomfort2.js @@ -0,0 +1,169 @@ + +/** + * SystaComfort II node implementation + * + * @param {*} RED + */ +const DGRAM = require('node:dgram') +const BITMASK_2_BYTES = 0xFF +const BITMASK_4_BYTES = 0xFFFF +const PARADIGMA_EMPTY_VALUE = -300 +const PARADIGMA_OFFSET_COUNTER_REPLY = 0x3FBF +const PARADIGMA_OFFSET_MAC_REPLY = 0x8E83 +const PARADIGMA_REPLY_BYTE_12 = 0x01 +const PARADIGMA_UDP_PORT_DEFAULT = 22460 +const REPLY_LENGTH = 20 +const MAC_UNKNOWN_SEGEMENT = '??' + +// Enumeration of available data channels +const SYSTACOMFORT_VALUES = { + BOILER_START_COUNTER: { dataPosition: 748, topic: 'boiler/starts/get', description: 'Starts Brenner', unit: null, valueDivider: 1 }, + BOILER_WORKING_HOURS: { dataPosition: 740, topic: 'boiler/workinghours/get', description: 'Betriebsstunden Brenner', unit: 'h', valueDivider: 1 }, + BUFFER_TANK_TEMPERATURE_TOP: { dataPosition: 40, topic: 'buffer/temperature-top/get', description: 'Temperatur Pufferspeicher oben (TPO)', unit: '°C', valueDivider: 10 }, + BUFFER_TANK_TEMPERATURE_BOTTOM: { dataPosition: 44, topic: 'buffer/temperature-bottom/get', description: 'Temperatur Pufferspeicher unten (TPU)', unit: '°C', valueDivider: 10 }, + SOLAR_YIELD_CURRENT: { dataPosition: 752, topic: 'solar/yield-current/get', description: 'Solargewinn aktuell', unit: 'kW', valueDivider: 10 }, + SOLAR_YIELD_DAY: { dataPosition: 756, topic: 'solar/yield-day/get', description: 'Solargewinn pro Tag', unit: 'kWh', valueDivider: 1 }, + SOLAR_YIELD_TOTAL: { dataPosition: 760, topic: 'solar/yield-overall/get', description: 'Solargewinn gesamt', unit: 'kWh', valueDivider: 1 }, + SOLAR_TEMPERATURE_COLLECTOR: { dataPosition: 68, topic: 'solar/temperature-collector/get', description: 'Kollektortemperatur', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_FLOW: { dataPosition: 28, topic: 'system/temperature-flow/get', description: 'Vorlauftemperatur Heizung (Ist)', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_FLOW_RETURN: { dataPosition: 32, topic: 'system/temperature-flowreturn/get', description: 'Rücklauftemperatur Heizung', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_EXTERNAL: { dataPosition: 24, topic: 'system/temperature-external/get', description: 'Außentemperatur', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_PROCESS_WATER_CURRENT: { dataPosition: 36, topic: 'system/temperature-processwater-current/get', description: 'Warmwassertemperatur (Ist / TWO)', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_PROCESS_WATER_TARGET: { dataPosition: 112, topic: 'system/temperature-processwater-target/get', description: 'Warmwassertemperatur (Soll)', unit: '°C', valueDivider: 10 }, + SYSTEM_TEMPERATURE_ROOM_TARGET: { dataPosition: 116, topic: 'system/temperature-room-target/get', description: 'Raumtemperatur (Soll)', unit: '°C', valueDivider: 10 } +} + +module.exports = function(RED) { + + /** + * Create a two character based mac address segment + * @param {*} segment + * @returns + */ + function createMACPart(segment) { + return ( segment === null ? MAC_UNKNOWN_SEGEMENT : segment.toString(16).padStart(2,'0') ) + } + + /** + * Parse datagram message recieved on upd socket from systa device + * @param {*} data + * @returns + */ + function parseData(data, topicPrefix) { + // Create mac address from first 5 bytes (reorder) + let deviceAddress = `${createMACPart(data[3])}:${createMACPart(data[2])}:${createMACPart(data[1])}:${createMACPart(data[0])}:${createMACPart(data[5])}:${createMACPart(data[4])}` + // Message type + let packetType = data[16]; + // Calculate counter from two bytes + let counter = ( ( data[6] & BITMASK_2_BYTES ) << 0 ) | ( ( data[7] & BITMASK_2_BYTES ) << 8 ); + // Process message of type 1 only + if ( packetType == 0x01 ) { + let resultMessage = { + payload: {}, + deviceAddress: deviceAddress, + messageCounter: counter, + packetType: packetType + } + + Object.entries(SYSTACOMFORT_VALUES).forEach( ([key, valueDescriptor]) => { + let dataValue = null + let startPosition = valueDescriptor.dataPosition + if ( data.length > startPosition ) { + let dataValueRaw = null + dataValueRaw = ((data[startPosition] & BITMASK_2_BYTES)) | + ((data[startPosition+1] & BITMASK_2_BYTES) << 8 ) | + ((data[startPosition+2] & BITMASK_2_BYTES) << 16 ) | + ((data[startPosition+3] & BITMASK_2_BYTES) << 24 ) + if ( dataValueRaw != PARADIGMA_EMPTY_VALUE ) { + dataValue = (dataValueRaw / valueDescriptor.valueDivider) + } + let topic = valueDescriptor.topic + // Add prefix if necessar + if ( topicPrefix ) { + topic = topicPrefix + (topicPrefix.endsWith('/') ? '' : '/') + valueDescriptor.topic + } + resultMessage.payload[key] = { value: dataValue, topic: topic, description: valueDescriptor.description, unit: valueDescriptor.unit } + } + }) + return resultMessage + } + return null + } + + /** + * Create reply message to answer based on incoming data + * @param {*} msg + */ + function createResponse(data) { + let reply = Buffer.alloc(REPLY_LENGTH) + // Initialize the first 8 bytes by copy the recieved one. Fill all others with 0 + for ( let i = 0; i < REPLY_LENGTH; i++) { + reply[i] = ( i < 8 ? data[i] : 0x00 ) + } + // Static part of reply, always 1 + reply[12] = PARADIGMA_REPLY_BYTE_12 + // Generate a mac id. Using as first byte the second last mac byte and the second byte is the last mac byte + // Adding an offset and forcing 4 bytes (0xFFFF) mask + let macID = ( ( data[4] & BITMASK_2_BYTES ) + ( data[5] << 8 ) + PARADIGMA_OFFSET_MAC_REPLY ) & BITMASK_4_BYTES + // first (right) byte is used on position 16, second (left) byte on 17. using bit shifting to force 1 byte + reply[16] = macID & BITMASK_2_BYTES + reply[17] = macID >> 8 + // Generate a counter id. Sum the counter bytes and add a static offset + // Adding an offset and forcing 4 bytes (0xFFFF) mask + let counterReply = ( ( data[6] & BITMASK_2_BYTES ) + ( data[7] << 8 ) + PARADIGMA_OFFSET_COUNTER_REPLY ) & BITMASK_4_BYTES + reply[18] = counterReply & BITMASK_2_BYTES + reply[19] = counterReply >> 8 + return reply + } + + /** + * Node object function + * @param {*} config + */ + function systaComfort2Device(config) { + RED.nodes.createNode(this, config) + const node = this + const udpServer = DGRAM.createSocket('udp4') + // Handle exceptions on server + udpServer.on('error', (err) => { + node.error(`SysteComfort2: Error on udp server connection: ${err.stack}`) + node.status({ fill: 'red', shape: 'ring', text: 'Error on udp server connection' }) + udpServer.close() + }) + // Handle messages + udpServer.on('message', (data, rinfo) => { + node.log(`Recieved message from ${rinfo.address}:${rinfo.port} at ${new Date().toLocaleString()}`) + node.status({ fill: 'green', shape: 'dot', text: `Recieved message from ${rinfo.address}:${rinfo.port} at ${new Date().toLocaleString()}` }) + // Create response and send back to client + let responseData = createResponse(data) + const client = DGRAM.createSocket('udp4') + client.send(responseData, rinfo.port, rinfo.address, (err) => { + client.close() + }) + // Parse data receieved from syste comfort device + let msgData = parseData(data, config.topicPrefix) + if ( msgData ) { + msgData.deviceIP = rinfo.address + msgData.devicePort = rinfo.port + node.send(msgData) + } + }) + // Handle listen state + udpServer.on('listening', () => { + const address = udpServer.address() + node.status({ fill: 'green', shape: 'dot', text: `Server is listening: ${address.address}:${address.port}` }) + }) + udpServer.bind(config.listenPort || PARADIGMA_UDP_PORT_DEFAULT) + // Cleanup hooks + node.on('close', () => { + if ( udpServer ) { + udpServer.close() + } + }) + } + + /** + * Register node object to Node-RED instance + */ + RED.nodes.registerType('systacomfort2', systaComfort2Device) +} \ No newline at end of file From 1e4d215a7ddae0f545d3084403a220af7d2ab7df Mon Sep 17 00:00:00 2001 From: Marc Boehm Date: Wed, 27 Jul 2022 17:24:44 +0200 Subject: [PATCH 2/5] CAPAUT-253 Fix labels, extend readme, add pipeline --- README.md | 11 +++++++++-- bitbucket-pipelines.yml | 30 ++++++++++++++++++++++++++++++ systacomfort2/systacomfort2.html | 2 +- 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 bitbucket-pipelines.yml diff --git a/README.md b/README.md index 8ed156e..0413dba 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,14 @@ This Node-RED node is capturing the packets from a SysteComfort II device and pr |Device|Software-Version|Hardware-Version|Basis-System|Compatible?| |--|--|--|--|--| -|Systa Comfort 2|V1.16|V1.21|V1.13|yes - except flow return value is not available| +|SystaComfort II|V1.16|V1.21|V1.13|yes - except SYSTEM_TEMPERATURE_FLOW_RETURN is not available| + +## Node Parameters +|Parameter|Description| +|--|--| +|Name|Name of node on flow| +|Topic Prefix|Prefix will be added to topic property on output message payload| +|Listen Port|Port of UDP Server to listen on. Useful on multiple devices| ## Connectivity -To capture the published data you have to redirect the traffic which sent by the SysteComfort II device to the official remote portal. If you have an local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. +To capture the published data from your SysteComfort II device you have to redirect the traffic on your local network. If you have an local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml new file mode 100644 index 0000000..ec8d213 --- /dev/null +++ b/bitbucket-pipelines.yml @@ -0,0 +1,30 @@ +image: node:16 + +definitions: + steps: + # Build nodes + - step: &step-build-nodes + name: Build + caches: + - node + script: + - npm install + - npm test + + # Publish node + - step: &step-publish-nodes + name: Publish Nodes + script: + - pipe: atlassian/npm-publish:0.3.2 + variables: + NPM_TOKEN: $CAPTICA_NPM_TOKEN + FOLDER: './' + EXTRA_ARGS: '--access public' +pipelines: + default: + - step: *step-build-nodes + + tags: + v*: + - step: *step-build-nodes + - step: *step-publish-nodes \ No newline at end of file diff --git a/systacomfort2/systacomfort2.html b/systacomfort2/systacomfort2.html index aa785b1..275c040 100644 --- a/systacomfort2/systacomfort2.html +++ b/systacomfort2/systacomfort2.html @@ -27,7 +27,7 @@
- +
From e8fcce9496f4c2468bd512fef12e56b964054832 Mon Sep 17 00:00:00 2001 From: Marc Boehm Date: Wed, 27 Jul 2022 20:36:48 +0200 Subject: [PATCH 3/5] CAPAUT-253 Fix review findings --- README.md | 6 +++--- package.json | 4 ++-- systacomfort2/systacomfort2.html | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 0413dba..a5738bb 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ # captica: Node-RED Node for SystaComfort II -Receive data from SysteComfort II devices in Node-RED flows +Receive data from SystaComfort II devices in Node-RED flows -This Node-RED node is capturing the packets from a SysteComfort II device and prepares the data for further processing. +This Node-RED node is capturing the packets from a SystaComfort II device and prepares the data for further processing. ## Supported values @@ -40,4 +40,4 @@ This Node-RED node is capturing the packets from a SysteComfort II device and pr |Listen Port|Port of UDP Server to listen on. Useful on multiple devices| ## Connectivity -To capture the published data from your SysteComfort II device you have to redirect the traffic on your local network. If you have an local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. +To capture the published data from your SysteComfort II device you have to redirect the traffic on your local network. If you have a local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. diff --git a/package.json b/package.json index 1f3d11d..dbfaa32 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "author": "Marc Böhm (marc.boehm@captica.de)", "homepage": "http://www.captica.de", "repository": { - "type": "bitbucked", - "url": "https://bitbucket.org/captica-dev/de.captica.nodered.node.systacomfort2" + "type": "git", + "url": "bitbucket:captica-dev/de.captica.nodered.node.systacomfort2" }, "dependencies": { }, diff --git a/systacomfort2/systacomfort2.html b/systacomfort2/systacomfort2.html index 275c040..1a63ee6 100644 --- a/systacomfort2/systacomfort2.html +++ b/systacomfort2/systacomfort2.html @@ -34,6 +34,6 @@ \ No newline at end of file From 3703ebb00692f637cc5f86000d2616e1f2e73629 Mon Sep 17 00:00:00 2001 From: Marc Boehm Date: Wed, 27 Jul 2022 20:54:18 +0200 Subject: [PATCH 4/5] CAPAUT-253 Add topics to readme, fix pipeline --- README.md | 32 ++++++++++++++++---------------- bitbucket-pipelines.yml | 3 +-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index a5738bb..210d1cb 100644 --- a/README.md +++ b/README.md @@ -9,22 +9,22 @@ This Node-RED node is capturing the packets from a SystaComfort II device and pr ## Supported values -|Value-Key|Description| -|--|--| -|BOILER_START_COUNTER|Starts of boiler gas unit| -|BOILER_WORKING_HOURS|Overall working hours of boiler| -|BUFFER_TANK_TEMPERATURE_TOP|Top temperature of buffer tank| -|BUFFER_TANK_TEMPERATURE_BOTTOM|Bottom temperature of buffer tank| -|SOLAR_YIELD_CURRENT|Current yield of solar| -|SOLAR_YIELD_DAY|Day yield of solar| -|SOLAR_YIELD_TOTAL|Total yield of solar| -|SOLAR_TEMPERATURE_COLLECTOR|Current temperature of solar collector| -|SYSTEM_TEMPERATURE_FLOW|Current temperature of system flow| -|SYSTEM_TEMPERATURE_FLOW_RETURN|Current temperature of system flow (return)| -|SYSTEM_TEMPERATURE_EXTERNAL|External temperature of system| -|SYSTEM_TEMPERATURE_PROCESS_WATER_CURRENT|Current temperature of system process water| -|SYSTEM_TEMPERATURE_PROCESS_WATER_TARGET|Target temperature of system process water| -|SYSTEM_TEMPERATURE_ROOM_TARGET|Target room temperature| +|Value-Key|Topic|Description| +|--|--|--| +|BOILER_START_COUNTER|boiler/starts/get|Starts of boiler gas unit| +|BOILER_WORKING_HOURS|boiler/workinghours/get|Overall working hours of boiler| +|BUFFER_TANK_TEMPERATURE_TOP|buffer/temperature-top/get|Top temperature of buffer tank| +|BUFFER_TANK_TEMPERATURE_BOTTOM|buffer/temperature-bottom/get|Bottom temperature of buffer tank| +|SOLAR_YIELD_CURRENT|solar/yield-current/get|Current yield of solar| +|SOLAR_YIELD_DAY|solar/yield-day/get|Day yield of solar| +|SOLAR_YIELD_TOTAL|solar/yield-total/get|Total yield of solar| +|SOLAR_TEMPERATURE_COLLECTOR|solar/temperature-collector/get|Current temperature of solar collector| +|SYSTEM_TEMPERATURE_FLOW|system/temperature-flow/get|Current temperature of system flow| +|SYSTEM_TEMPERATURE_FLOW_RETURN|system/temperature-flowreturn/get|Current temperature of system flow (return)| +|SYSTEM_TEMPERATURE_EXTERNAL|system/temperature-external/get|External temperature of system| +|SYSTEM_TEMPERATURE_PROCESS_WATER_CURRENT|system/temperature-processwater-current/get|Current temperature of system process water| +|SYSTEM_TEMPERATURE_PROCESS_WATER_TARGET|system/temperature-processwater-target/get|Target temperature of system process water| +|SYSTEM_TEMPERATURE_ROOM_TARGET|system/temperature-room-target/get|Target room temperature| ## Compatible SystaComfort II devices diff --git a/bitbucket-pipelines.yml b/bitbucket-pipelines.yml index ec8d213..4740195 100644 --- a/bitbucket-pipelines.yml +++ b/bitbucket-pipelines.yml @@ -8,8 +8,7 @@ definitions: caches: - node script: - - npm install - - npm test + - npm install # Publish node - step: &step-publish-nodes From 2bb4711468d60a94a87db5b95b7f3e788ec1aa12 Mon Sep 17 00:00:00 2001 From: Marc Boehm Date: Wed, 27 Jul 2022 21:04:04 +0200 Subject: [PATCH 5/5] CAPAUT-253 Fix typos --- README.md | 2 +- systacomfort2/systacomfort2.js | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 210d1cb..22bf44d 100644 --- a/README.md +++ b/README.md @@ -40,4 +40,4 @@ This Node-RED node is capturing the packets from a SystaComfort II device and pr |Listen Port|Port of UDP Server to listen on. Useful on multiple devices| ## Connectivity -To capture the published data from your SysteComfort II device you have to redirect the traffic on your local network. If you have a local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. +To capture the published data from your SystaComfort II device you have to redirect the traffic on your local network. If you have a local DNS Forwarder you can just create a static host override. The domain `pradigma.remoteportal.de` needs to be resolved to your internal Node-RED ip address. diff --git a/systacomfort2/systacomfort2.js b/systacomfort2/systacomfort2.js index 5462503..3700127 100644 --- a/systacomfort2/systacomfort2.js +++ b/systacomfort2/systacomfort2.js @@ -23,7 +23,7 @@ const SYSTACOMFORT_VALUES = { BUFFER_TANK_TEMPERATURE_BOTTOM: { dataPosition: 44, topic: 'buffer/temperature-bottom/get', description: 'Temperatur Pufferspeicher unten (TPU)', unit: '°C', valueDivider: 10 }, SOLAR_YIELD_CURRENT: { dataPosition: 752, topic: 'solar/yield-current/get', description: 'Solargewinn aktuell', unit: 'kW', valueDivider: 10 }, SOLAR_YIELD_DAY: { dataPosition: 756, topic: 'solar/yield-day/get', description: 'Solargewinn pro Tag', unit: 'kWh', valueDivider: 1 }, - SOLAR_YIELD_TOTAL: { dataPosition: 760, topic: 'solar/yield-overall/get', description: 'Solargewinn gesamt', unit: 'kWh', valueDivider: 1 }, + SOLAR_YIELD_TOTAL: { dataPosition: 760, topic: 'solar/yield-total/get', description: 'Solargewinn gesamt', unit: 'kWh', valueDivider: 1 }, SOLAR_TEMPERATURE_COLLECTOR: { dataPosition: 68, topic: 'solar/temperature-collector/get', description: 'Kollektortemperatur', unit: '°C', valueDivider: 10 }, SYSTEM_TEMPERATURE_FLOW: { dataPosition: 28, topic: 'system/temperature-flow/get', description: 'Vorlauftemperatur Heizung (Ist)', unit: '°C', valueDivider: 10 }, SYSTEM_TEMPERATURE_FLOW_RETURN: { dataPosition: 32, topic: 'system/temperature-flowreturn/get', description: 'Rücklauftemperatur Heizung', unit: '°C', valueDivider: 10 }, @@ -68,9 +68,8 @@ module.exports = function(RED) { Object.entries(SYSTACOMFORT_VALUES).forEach( ([key, valueDescriptor]) => { let dataValue = null let startPosition = valueDescriptor.dataPosition - if ( data.length > startPosition ) { - let dataValueRaw = null - dataValueRaw = ((data[startPosition] & BITMASK_2_BYTES)) | + if ( data.length > startPosition ) { + let dataValueRaw = ((data[startPosition] & BITMASK_2_BYTES)) | ((data[startPosition+1] & BITMASK_2_BYTES) << 8 ) | ((data[startPosition+2] & BITMASK_2_BYTES) << 16 ) | ((data[startPosition+3] & BITMASK_2_BYTES) << 24 ) @@ -126,7 +125,7 @@ module.exports = function(RED) { const udpServer = DGRAM.createSocket('udp4') // Handle exceptions on server udpServer.on('error', (err) => { - node.error(`SysteComfort2: Error on udp server connection: ${err.stack}`) + node.error(`SystaComfort2: Error on udp server connection: ${err.stack}`) node.status({ fill: 'red', shape: 'ring', text: 'Error on udp server connection' }) udpServer.close() }) @@ -140,7 +139,7 @@ module.exports = function(RED) { client.send(responseData, rinfo.port, rinfo.address, (err) => { client.close() }) - // Parse data receieved from syste comfort device + // Parse data receieved from systa comfort device let msgData = parseData(data, config.topicPrefix) if ( msgData ) { msgData.deviceIP = rinfo.address