UNPKG

node-red-contrib-mysensors

Version:

Mysensors related nodes, for decoding / encoding mysensors serial protocol and MQTT topic, and wrapping arbitrary messages into mysensors compatible messages

254 lines (213 loc) 8.31 kB
import { expect } from 'chai'; import { useSinonSandbox } from '../../test/sinon'; import { MysensorsController } from './mysensors-controller'; import { IMysensorsMsg, IStrongMysensorsMsg, MsgOrigin } from './mysensors-msg'; import { mysensor_command, mysensor_internal } from './mysensors-types'; describe('Controller test', () => { const sinon = useSinonSandbox(); function setupTest(timeZone = 'CET') { const storage = { getFreeNodeId: sinon.stub().resolves(777), getChild: sinon.stub().resolves(''), getNodeList: sinon.stub().resolves(''), child: sinon.stub().resolves(), childHeard: sinon.stub(), close: sinon.stub(), nodeHeard: sinon.stub(), setBatteryLevel: sinon.stub(), setParent: sinon.stub(), sketchName: sinon.stub(), sketchVersion: sinon.stub(), }; return { storage, controller: new MysensorsController( storage, true, true, timeZone, 'M', 'mys-out', false, ), }; } it('should not respond to an id request if no id can be retrieved', async () => { const { controller, storage } = setupTest(); storage.getFreeNodeId.resolves(undefined); const input: IMysensorsMsg = { _msgid: '', payload: '', topic: 'mys-in/255/255/3/0/3', origin: MsgOrigin.serial, }; const result = await controller.messageHandler(input); expect(result).to.equal(undefined); }); it('should respond to a mqtt id request with a new id', async () => { const { controller } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: '', topic: 'mys-in/255/255/3/0/3', }; const expected: IMysensorsMsg = { _msgid: '', payload: '777', subType: mysensor_internal.I_ID_RESPONSE, topicRoot: 'mys-out', }; const result = await controller.messageHandler(input); expect(result).to.include(expected); }); describe('sketch details', () => { it('should handle sketch name', async () => { const { controller, storage } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: '123', topic: 'mys-in/255/255/3/0/11' }; const result = await controller.messageHandler(input); sinon.assert.called(storage.sketchName); expect(result).to.equal(undefined); }); it('should handle sketch version', async () => { const { controller, storage } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: '123', topic: 'mys-in/255/255/3/0/12' }; const result = await controller.messageHandler(input); sinon.assert.called(storage.sketchVersion); expect(result).to.equal(undefined); }); }); it('should handle battery message', async () => { const { controller, storage } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: '123', topic: 'mys-in/255/255/3/0/0' }; const result = await controller.messageHandler(input); sinon.assert.called(storage.setBatteryLevel); expect(result).to.equal(undefined); }); describe('parrent node', () => { it('should not set parent node if incorrect debug message is received', async () => { const { controller, storage } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: 'TSF:MSG:WRITE,1-2-3', topic: 'mys-in/255/255/3/0/9' }; const result = await controller.messageHandler(input); sinon.assert.notCalled(storage.setParent); expect(result).to.equal(undefined); }); it('should set parent when correct debug message is received', async () => { const { controller, storage } = setupTest(); const input: IMysensorsMsg = { _msgid: '', payload: 'TSF:MSG:READ,1-2-3', topic: 'mys-in/255/255/3/0/9' }; const result = await controller.messageHandler(input); sinon.assert.calledWith(storage.setParent, 1, 2); expect(result).to.equal(undefined); }); }); it('should handle config request from UART message', async () => { const { controller } = setupTest(); const expected: IMysensorsMsg = { _msgid: '', payload: '255;255;3;0;6;M', }; const request: IMysensorsMsg = { payload: '255;255;3;0;6;0', _msgid: '', }; const result = await controller.messageHandler(request); expect(result).to.include(expected); }); it('should decoded time request CET zone', async () => { const { controller } = setupTest(); sinon.clock.setSystemTime(new Date('2023-01-01 00:00Z')); const request: IMysensorsMsg = { _msgid: '', ack: 0, childSensorId: 255, messageType: mysensor_command.C_INTERNAL, nodeId: 10, payload: '', subType: mysensor_internal.I_TIME, }; const expected: IStrongMysensorsMsg<mysensor_command.C_INTERNAL> = { _msgid: '', payload: '1672534800', ack: 0, childSensorId: 255, messageType: mysensor_command.C_INTERNAL, nodeId: 10, origin: 0, subType: mysensor_internal.I_TIME, }; const result = await controller.messageHandler(request); expect(result).to.deep.equal(expected); }); it('should decoded time request ZULU zone', async () => { const { controller } = setupTest('Z'); sinon.clock.setSystemTime(new Date('2023-01-01 00:00Z')); const request: IMysensorsMsg = { _msgid: '', ack: 0, childSensorId: 255, messageType: mysensor_command.C_INTERNAL, nodeId: 10, payload: '', subType: mysensor_internal.I_TIME, }; const expected: IStrongMysensorsMsg<mysensor_command.C_INTERNAL> = { _msgid: '', payload: '1672531200', ack: 0, childSensorId: 255, messageType: mysensor_command.C_INTERNAL, nodeId: 10, origin: 0, subType: mysensor_internal.I_TIME, }; const result = await controller.messageHandler(request); expect(result).to.deep.equal(expected); }); it('should call last heard when message is received', async () => { const { controller, storage } = setupTest(); await controller.messageHandler({ payload: '10;255;3;0;6;0', _msgid: '', }); sinon.assert.called(storage.nodeHeard); }); it('should return undefined without processing if message is not decodable', async () => { const { controller, storage } = setupTest(); const result = await controller.messageHandler({payload: 'no-valid', _msgid: ''}); expect(result).to.equal(undefined); sinon.assert.notCalled(storage.child); sinon.assert.notCalled(storage.childHeard); sinon.assert.notCalled(storage.getFreeNodeId); sinon.assert.notCalled(storage.sketchName); sinon.assert.notCalled(storage.sketchVersion); }); it('should handle presentation message', async () => { const {controller, storage} = setupTest(); const testData: IMysensorsMsg = { _msgid: '', payload: '10;255;0;0;0;100' }; const result = await controller.messageHandler(testData); sinon.assert.calledOnce(storage.child); expect(result).to.equal(undefined); }); });