CAPAUT-254 Add datapaser tests
This commit is contained in:
2941
package-lock.json
generated
2941
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -9,6 +9,9 @@
|
|||||||
"url": "bitbucket:captica-dev/de.captica.nodered.node.systacomfort2"
|
"url": "bitbucket:captica-dev/de.captica.nodered.node.systacomfort2"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
"captica",
|
||||||
|
"systacomfort",
|
||||||
|
"systacomfort2",
|
||||||
"node-red"
|
"node-red"
|
||||||
],
|
],
|
||||||
"node-red": {
|
"node-red": {
|
||||||
@@ -17,9 +20,11 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha"
|
"test": "nyc mocha"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"mocha": "^10.0.0"
|
"chai": "^4.3.6",
|
||||||
|
"mocha": "^10.0.0",
|
||||||
|
"nyc": "^15.1.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const SYSTACOMFORT_VALUES = {
|
|||||||
SYSTEM_TEMPERATURE_ROOM_TARGET: { dataPosition: 116, topic: 'system/temperature-room-target/get', description: 'Raumtemperatur (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 = {
|
const dataParser = {
|
||||||
/**
|
/**
|
||||||
* Create a two character based mac address segment
|
* Create a two character based mac address segment
|
||||||
* @param {*} segment
|
* @param {*} segment
|
||||||
@@ -109,3 +109,5 @@ module.exports = {
|
|||||||
return reply
|
return reply
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { dataParser, SYSTACOMFORT_VALUES }
|
||||||
@@ -4,9 +4,10 @@
|
|||||||
*
|
*
|
||||||
* @param {*} RED
|
* @param {*} RED
|
||||||
*/
|
*/
|
||||||
const PARADIGMA_UDP_PORT_DEFAULT = 22460
|
|
||||||
const dgram = require('node:dgram')
|
const dgram = require('node:dgram')
|
||||||
const dataParser = require('./dataparser')
|
const { dataParser } = require('./dataparser')
|
||||||
|
|
||||||
|
const PARADIGMA_UDP_PORT_DEFAULT = 22460
|
||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
|
|
||||||
|
|||||||
116
test/systacomfort2-spec.js
Normal file
116
test/systacomfort2-spec.js
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Test implementation of systacomfort2 node
|
||||||
|
*
|
||||||
|
* Project: de.captica.nodered.node.systacomfort2
|
||||||
|
* Author: Marc Böhm <marc.boehm@captica.de>
|
||||||
|
* Copyright (c) captica GmbH est. 2022 / MIT License
|
||||||
|
*/
|
||||||
|
const { expect } = require('chai')
|
||||||
|
const systaComfort2Node = require('../systacomfort2/systacomfort2')
|
||||||
|
const { dataParser, SYSTACOMFORT_VALUES } = require('../systacomfort2/dataparser')
|
||||||
|
|
||||||
|
const MESSAGE_INIT = 'AJe+LI4NzW0JCQwAMtoAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWAIAAAEAAAACAAAAAAAAADIAAAAyAAAAMgAAAGQAAAC4MP4/APgBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABqAwAAGgMAAE4DAAA8AwAAUgEAAAAAAAA5AAAAlwMAAA0AAAAAAAAAvAIAAIQDAAC8AgAAvAAAAC6TBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAy9tHAsmsAQBQAAAANwAAAAAAAAAEAAAAGgMAAGsDAABOAwAAUgEAAAAAAABrAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAruTDkA=='
|
||||||
|
const MESSAGE_INIT_ANSWER = 'AJe+LI4NzW0AAAAAAQAAABGcjK0='
|
||||||
|
const MESSAGE_DATA = 'AJe+LI4NzG0JCQwAMtoAAAEAAAAAAAAAOgEAAFYBAADU/v//SwMAAEUDAABCAwAA1P7//9T+///U/v//AAAAAAAAAABrAwAAXwIAAFoCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgCAADNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAyAAAAOYAAACgAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAA+gAAAAAAAAAGAAAAAAAAACYCAADIAAAAZAAAABQAAAB4AAAAAAAAADIAAABQAAAAZAAAAAUAAAACAAAAMgAAAB4AAAAAAAAAAAAAAAAAAAADAAAAMgAAAPQBAAAEAAAAMgAAAHISAADYAQAAAAAAAAAAAAABAAAAyAAAANwAAACWAAAAAAAAAAAAAAAAAAAAIwcAACQHAAAAAAAAXgEAAAAAAAANAAAAAAAAALwCAADIAAAAZAAAABQAAAB4AAAAAAAAAAAAAADIAAAAZAAAAAUAAAACAAAAMgAAAB4AAAAAAAAAAAAAAAAAAAADAAAAMgAAAPQBAAAEAAAAMgAAACMHAAAAAAAAAAAAAAAAAAABAAAAyAAAANwAAACWAAAAAAAAAAAAAAAAAAAAIwcAACQHAABeAQAAAAAAAA0AAAAAAAAAvAIAAMgAAABkAAAAFAAAAHgAAAAAAAAAAAAAAMgAAABkAAAABQAAAAIAAAAAAAAAAAAAAAMAAAAyAAAA9AEAAAQAAAAyAAAAIwcAAAAAAABYAgAAigIAAAEAAABkAAAAZAAAAAAAAAAyAAAAUgMAAAAAAAAFAAAAtgMAAAAAAAAyAAAAAAAAAJABAABkAAAAAQAAAAEAAAADAAAAAwAAAAMAAAAPAAAAMgAAAKQAAAAAAAAAAAAAABMAAAAFAAAAAAAAAAAAAAAjHAAAIwAAAAVZAAANAAAAEgAAAB51AAAcAAAAAAAAAAAAAAAAAAAALAEAAIoCAABkAAAAGQAAAAAAAAAAAAAA+gAAABgBAAAAAAAAAAAAAAAAAAC8AgAAAAAAAMgAAABkAAAAAgAAAMgAAAAeAAAAAAAAABQAAAAeAAAAHgAAADIAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAAAAAAAAAQAAAAEAAAAHAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/h54Ug=='
|
||||||
|
const TOPIC_PREFIX = 'my/custom/topic/prefix'
|
||||||
|
const OUTPUT_MESSAGE_PAYLOAD = {
|
||||||
|
BOILER_START_COUNTER: 22789,
|
||||||
|
BOILER_WORKING_HOURS: 7203,
|
||||||
|
BUFFER_TANK_TEMPERATURE_TOP: 83.7,
|
||||||
|
BUFFER_TANK_TEMPERATURE_BOTTOM: 83.4,
|
||||||
|
SOLAR_YIELD_CURRENT: 1.3,
|
||||||
|
SOLAR_YIELD_DAY: 18,
|
||||||
|
SOLAR_YIELD_TOTAL: 29982,
|
||||||
|
SOLAR_TEMPERATURE_COLLECTOR:87.5,
|
||||||
|
SYSTEM_TEMPERATURE_FLOW: 34.2,
|
||||||
|
SYSTEM_TEMPERATURE_FLOW_RETURN: null,
|
||||||
|
SYSTEM_TEMPERATURE_EXTERNAL: 31.4,
|
||||||
|
SYSTEM_TEMPERATURE_PROCESS_WATER_CURRENT: 84.3,
|
||||||
|
SYSTEM_TEMPERATURE_PROCESS_WATER_TARGET: 60,
|
||||||
|
SYSTEM_TEMPERATURE_ROOM_TARGET: 20.5,
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Node-RED registration/handling
|
||||||
|
*/
|
||||||
|
describe('SystaComfort2 - Node-RED node', () => {
|
||||||
|
// Check node registration first. We fake the RED-objec to capture the registration part
|
||||||
|
systaComfort2Node({
|
||||||
|
nodes: {
|
||||||
|
registerType: function(name, obj) {
|
||||||
|
it('should be registered on node-RED as a new node type', () => {
|
||||||
|
expect(name).to.equal('systacomfort2')
|
||||||
|
expect(obj).to.not.be.undefined
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data parser
|
||||||
|
*/
|
||||||
|
describe('SystaComfort2 - Data Parser', function(done) {
|
||||||
|
/**
|
||||||
|
* MAC address utils
|
||||||
|
*/
|
||||||
|
describe('#createMACPart()', () => {
|
||||||
|
it('should convert a byte into string and pad with a leading "0"', () => {
|
||||||
|
expect(dataParser.createMACPart(15)).to.equal('0f')
|
||||||
|
})
|
||||||
|
it('should convert a byte into as string and NOT pad with a leading "0"', () => {
|
||||||
|
expect(dataParser.createMACPart(255)).to.equal('ff')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Check init answer conversion
|
||||||
|
*/
|
||||||
|
describe('#createResponse()', () => {
|
||||||
|
it('should create an response data buffer based on the input message', () => {
|
||||||
|
let answerBuffer = dataParser.createResponse(Buffer.from(MESSAGE_INIT, 'base64'))
|
||||||
|
expect(answerBuffer).to.not.be.undefined
|
||||||
|
expect(answerBuffer.toString('base64')).to.equal(MESSAGE_INIT_ANSWER)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Check data parser
|
||||||
|
*/
|
||||||
|
describe('#parseData()', () => {
|
||||||
|
it('should parse the data message and return an null object because of invalid packet type != 1', () => {
|
||||||
|
let outputMsg = dataParser.parseData(Buffer.from(MESSAGE_INIT, 'base64'))
|
||||||
|
expect(outputMsg).to.be.null
|
||||||
|
})
|
||||||
|
it('should parse the data message and provide a structured output message', () => {
|
||||||
|
let outputMsg = dataParser.parseData(Buffer.from(MESSAGE_DATA, 'base64'))
|
||||||
|
expect(outputMsg).to.not.be.undefined
|
||||||
|
})
|
||||||
|
it('should parse the data message and return an structured output message where payload topic starts with: ' + TOPIC_PREFIX, () => {
|
||||||
|
let outputMsg = dataParser.parseData(Buffer.from(MESSAGE_DATA, 'base64'), TOPIC_PREFIX)
|
||||||
|
expect(outputMsg).to.not.be.undefined
|
||||||
|
expect(outputMsg).to.have.own.property('payload')
|
||||||
|
expect(outputMsg.payload).to.not.be.undefined
|
||||||
|
Object.values(outputMsg.payload).forEach(valueObj => {
|
||||||
|
expect(valueObj).to.not.be.undefined
|
||||||
|
expect(valueObj).to.have.own.property('topic')
|
||||||
|
expect(valueObj.topic).to.not.be.null
|
||||||
|
expect(valueObj.topic.startsWith(TOPIC_PREFIX)).to.be.true
|
||||||
|
})
|
||||||
|
})
|
||||||
|
/**
|
||||||
|
* Check values
|
||||||
|
*/
|
||||||
|
let outputMsg = dataParser.parseData(Buffer.from(MESSAGE_DATA, 'base64'))
|
||||||
|
Object.entries(SYSTACOMFORT_VALUES).forEach(([key, valueObj]) => {
|
||||||
|
const expectedValue = OUTPUT_MESSAGE_PAYLOAD[key]
|
||||||
|
it(`should have the value ${key} in payload object and with value ${expectedValue}, description, topic and unit`, () => {
|
||||||
|
expect(outputMsg.payload).to.have.own.property(key)
|
||||||
|
let payloadValue = outputMsg.payload[key]
|
||||||
|
expect(payloadValue).to.not.be.undefined
|
||||||
|
expect(payloadValue.value).to.be.equal(expectedValue)
|
||||||
|
expect(payloadValue.topic).to.be.equal(valueObj.topic)
|
||||||
|
expect(payloadValue.description).to.be.equal(valueObj.description)
|
||||||
|
expect(payloadValue.unit).to.be.equal(valueObj.unit)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* SystaComfort II node test
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
var assert = require('assert')
|
|
||||||
var systaComfort2Node = require('../systacomfort2/systacomfort2')
|
|
||||||
var dataParser = require('../systacomfort2/dataparser')
|
|
||||||
|
|
||||||
const RED_MOCK = {
|
|
||||||
nodes: {
|
|
||||||
registerType: function(name, obj) {
|
|
||||||
it('should be registered on node-RED as a new node type', () => {
|
|
||||||
assert.equal('systacomfort2', name)
|
|
||||||
assert.ok(obj)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('SystaComfort2 - Node-RED node', function() {
|
|
||||||
// Check node registration first
|
|
||||||
systaComfort2Node(RED_MOCK)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('SystaComfort2 - Data Parser', function() {
|
|
||||||
describe('#createMACPart()', function() {
|
|
||||||
it('should convert a byte into string and pad with a leading "0"', function() {
|
|
||||||
assert.equal(dataParser.createMACPart(15), '0f')
|
|
||||||
})
|
|
||||||
it('should convert a byte into as string and NOT pad with a leading "0"', function() {
|
|
||||||
assert.equal(dataParser.createMACPart(255), 'ff')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user