UNPKG

iobroker.e3oncan

Version:

Collect data on CAN bus for Viessmann E3 devices, e.g. Vitocal, Vitocharge, Energy Meters E380CA and E3100CB

143 lines (122 loc) 6.34 kB
'use strict'; const { expect } = require('@iobroker/testing/node_modules/chai'); const { storageDids, storage } = require('./storage'); // storageDids and storage share the same utility methods (toHex, arr2Hex, // toByteArray, getDidStr, mergeDids). We test them through storageDids since // that's where mergeDids lives, and the hex utilities are defined there too. function makeStorageDids(device = 'default') { return new storageDids({ stateBase: 'test', device }); } // ── toHex ───────────────────────────────────────────────────────────────────── describe('storage.js => storageDids.toHex()', () => { const s = makeStorageDids(); it('formats 0 as "00"', () => { expect(s.toHex(0)).to.equal('00'); }); it('formats 255 as "ff"', () => { expect(s.toHex(255)).to.equal('ff'); }); it('formats a single-digit value with leading zero', () => { expect(s.toHex(10)).to.equal('0a'); }); it('formats 127 correctly', () => { expect(s.toHex(127)).to.equal('7f'); }); it('accepts a numeric string', () => { expect(s.toHex('16')).to.equal('10'); }); }); // ── arr2Hex ─────────────────────────────────────────────────────────────────── describe('storage.js => storageDids.arr2Hex()', () => { const s = makeStorageDids(); it('returns empty string for empty array', () => { expect(s.arr2Hex([])).to.equal(''); }); it('converts a single byte', () => { expect(s.arr2Hex([0x21])).to.equal('21'); }); it('converts multiple bytes', () => { expect(s.arr2Hex([0x21, 0xfa, 0x01, 0xb3])).to.equal('21fa01b3'); }); it('pads single-digit bytes with leading zero', () => { expect(s.arr2Hex([0x00, 0x0f])).to.equal('000f'); }); }); // ── toByteArray ─────────────────────────────────────────────────────────────── describe('storage.js => storageDids.toByteArray()', () => { const s = makeStorageDids(); it('returns empty array for empty string', () => { expect(s.toByteArray('')).to.deep.equal([]); }); it('converts a two-char hex string', () => { expect(s.toByteArray('21')).to.deep.equal([0x21]); }); it('converts a multi-byte hex string', () => { expect(s.toByteArray('21fa01b3')).to.deep.equal([0x21, 0xfa, 0x01, 0xb3]); }); it('is case-insensitive', () => { expect(s.toByteArray('FF')).to.deep.equal([255]); expect(s.toByteArray('ff')).to.deep.equal([255]); }); }); // ── arr2Hex / toByteArray round-trip ───────────────────────────────────────── describe('storage.js => arr2Hex / toByteArray round-trip', () => { const s = makeStorageDids(); it('arr2Hex → toByteArray restores original array', () => { const original = [0x00, 0x21, 0x7f, 0x80, 0xff]; expect(s.toByteArray(s.arr2Hex(original))).to.deep.equal(original); }); it('toByteArray → arr2Hex restores original string', () => { const hex = '00217f80ff'; expect(s.arr2Hex(s.toByteArray(hex))).to.equal(hex); }); }); // ── getDidStr ───────────────────────────────────────────────────────────────── describe('storage.js => storageDids.getDidStr()', () => { it('formats DID as 4-digit string with leading zeros for standard devices', () => { const s = makeStorageDids('default'); expect(s.getDidStr(1)).to.equal('0001'); expect(s.getDidStr(256)).to.equal('0256'); expect(s.getDidStr(1289)).to.equal('1289'); }); it('returns plain string without padding for e3100cb', () => { const s = makeStorageDids('e3100cb'); expect(s.getDidStr(1)).to.equal('1'); expect(s.getDidStr(256)).to.equal('256'); }); it('truncates to last 4 digits for large DID values on standard devices', () => { const s = makeStorageDids('default'); expect(s.getDidStr(12345)).to.equal('2345'); }); }); // ── mergeDids ───────────────────────────────────────────────────────────────── describe('storage.js => storageDids.mergeDids()', () => { const s = makeStorageDids(); it('returns a copy of common DIDs when device-specific list is empty', async () => { const common = { '0100': { codec: 'O3EInt8' }, '0200': { codec: 'O3EUtf8' } }; const result = await s.mergeDids(common, {}); expect(result).to.deep.equal(common); // Must be a copy, not the same reference expect(result).to.not.equal(common); }); it('device-specific DID overwrites common DID with same key', async () => { const common = { '0100': { codec: 'O3EInt8' } }; const specific = { '0100': { codec: 'O3EUtf8' } }; const result = await s.mergeDids(common, specific); expect(result['0100'].codec).to.equal('O3EUtf8'); }); it('device-specific DID is added when not in common list', async () => { const common = { '0100': { codec: 'O3EInt8' } }; const specific = { '0999': { codec: 'O3EFloat32' } }; const result = await s.mergeDids(common, specific); expect(result).to.have.property('0100'); expect(result).to.have.property('0999'); }); it('Version key from device-specific list is not carried over', async () => { const common = { '0100': { codec: 'O3EInt8' }, Version: '20240101' }; const specific = { Version: '20250101', '0999': { codec: 'O3EFloat32' } }; const result = await s.mergeDids(common, specific); // Version from specific must not overwrite or be added expect(result.Version).to.equal('20240101'); }); });