inventoresed
Version:
Z-Wave driver written entirely in JavaScript/TypeScript
380 lines (343 loc) • 9.95 kB
text/typescript
import {
MeterCC,
MeterCCGet,
MeterCCReport,
MeterCCReset,
MeterCCSupportedGet,
MeterCCSupportedReport,
MeterCommand,
RateType,
} from "@zwave-js/cc";
import {
assertZWaveError,
CommandClasses,
ZWaveErrorCodes,
} from "@zwave-js/core";
import type { TestingHost } from "@zwave-js/host";
import { createTestingHost } from "@zwave-js/host";
import * as nodeUtils from "../../node/utils";
import { createTestNode, TestNode } from "../mocks";
function buildCCBuffer(payload: Buffer): Buffer {
return Buffer.concat([
Buffer.from([
CommandClasses.Meter, // CC
]),
payload,
]);
}
describe("lib/commandclass/MeterCC => ", () => {
let host: TestingHost;
let node2: TestNode;
beforeAll(
async () => {
host = createTestingHost();
node2 = createTestNode(host, { id: 2 });
await host.configManager.loadMeters();
},
// Loading configuration may take a while on CI
30000,
);
it("the Get command (V1) should serialize correctly", () => {
const cc = new MeterCCGet(host, { nodeId: 1 });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Get, // CC Command
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Get command (V2) should serialize correctly", () => {
const cc = new MeterCCGet(host, { nodeId: 1, scale: 0x03 });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Get, // CC Command
0b11_000, // Scale
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Get command (V3) should serialize correctly", () => {
const cc = new MeterCCGet(host, { nodeId: 1, scale: 0x06 });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Get, // CC Command
0b110_000, // Scale
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Get command (V4) should serialize correctly", () => {
const cc = new MeterCCGet(host, { nodeId: 1, scale: 0x0f });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Get, // CC Command
0b111_000, // Scale 1
0x1, // Scale 2
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the SupportedGet command should serialize correctly", () => {
const cc = new MeterCCSupportedGet(host, { nodeId: 1 });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.SupportedGet, // CC Command
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Reset command (V2) should serialize correctly", () => {
const cc = new MeterCCReset(host, { nodeId: 1 });
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Reset, // CC Command
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Reset command (V6) should serialize correctly", () => {
const cc = new MeterCCReset(host, {
nodeId: 1,
type: 7,
targetValue: 0x010203,
});
const expected = buildCCBuffer(
Buffer.from([
MeterCommand.Reset, // CC Command
0b100_00111, // Size, Type
0,
1,
2,
3,
]),
);
expect(cc.serialize()).toEqual(expected);
});
it("the Report command (V1) should be deserialized correctly", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0x03, // Meter type
0b001_10_001, // precision, scale, size
55, // value
]),
);
const cc = new MeterCCReport(host, { nodeId: 1, data: ccData });
expect(cc.type).toBe(3);
expect(cc.scale).toBe(2);
expect(cc.value).toBe(5.5);
expect(cc.rateType).toBe(RateType.Unspecified);
expect(cc.deltaTime).toBe(0);
expect(cc.previousValue).toBeUndefined();
});
it("the Report command (V2) should be deserialized correctly (no time delta)", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b0_10_00011, // Rate type, Meter type
0b001_10_001, // precision, scale, size
55, // value
0, // delta time
0,
]),
);
const cc = new MeterCCReport(host, { nodeId: 1, data: ccData });
expect(cc.type).toBe(3);
expect(cc.scale).toBe(2);
expect(cc.value).toBe(5.5);
expect(cc.rateType).toBe(RateType.Produced);
expect(cc.deltaTime).toBe(0);
expect(cc.previousValue).toBeUndefined();
});
it("the Report command (V2) should be deserialized correctly (with time delta)", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b0_10_00011, // Rate type, Meter type
0b001_10_001, // precision, scale, size
55, // value
0, // delta time
5,
54, // previous value
]),
);
const cc = new MeterCCReport(host, { nodeId: 1, data: ccData });
expect(cc.type).toBe(3);
expect(cc.scale).toBe(2);
expect(cc.value).toBe(5.5);
expect(cc.rateType).toBe(RateType.Produced);
expect(cc.deltaTime).toBe(5);
expect(cc.previousValue).toBe(5.4);
});
it("the Report command (V3) should be deserialized correctly", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b1_10_00001, // Scale(2), Rate type, Meter type
0b001_10_001, // precision, Scale (1:0), size
55, // value
0, // delta time
5,
54, // previous value
]),
);
const cc = new MeterCCReport(host, { nodeId: 1, data: ccData });
expect(cc.scale).toBe(6);
});
it("the Report command (V4) should be deserialized correctly", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b1_10_00001, // Scale(2), Rate type, Meter type
0b001_11_001, // precision, Scale (1:0), size
55, // value
0, // delta time
5,
54, // previous value
0b01, // Scale2
]),
);
const cc = new MeterCCReport(host, { nodeId: 1, data: ccData });
expect(cc.scale).toBe(8);
});
it("the Report command should validate that a known meter type is given", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b1_10_11111, // Scale(2), Rate type, Meter type
0b001_11_001, // precision, Scale (1:0), size
55, // value
0, // delta time
5,
54, // previous value
0b01, // Scale2
]),
);
const report = new MeterCCReport(host, { nodeId: 1, data: ccData });
// Meter type 31 (does not exist)
assertZWaveError(() => report.persistValues(host), {
errorCode: ZWaveErrorCodes.PacketFormat_InvalidPayload,
});
});
it("the Report command should validate that a known meter scale is given", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.Report, // CC Command
0b1_10_00100, // Scale(2), Rate type, Meter type
0b001_11_001, // precision, Scale (1:0), size
55, // value
0, // delta time
5,
54, // previous value
0b01, // Scale2
]),
);
const report = new MeterCCReport(host, { nodeId: 1, data: ccData });
// Meter type 4, Scale 8 (does not exist)
assertZWaveError(() => report.persistValues(host), {
errorCode: ZWaveErrorCodes.PacketFormat_InvalidPayload,
});
});
it("the value IDs should be translated correctly", () => {
expect(
nodeUtils.translateValueID(host, node2, {
commandClass: CommandClasses.Meter,
property: "value",
propertyKey: 329986,
}),
).toMatchObject({
propertyKeyName: "Cooling_Unknown (0x09)_Produced",
});
});
it("the SupportedReport command (V2/V3) should be deserialized correctly", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.SupportedReport, // CC Command
0b1_00_10101, // supports reset, type
0b01101110, // supported scales
]),
);
const cc = new MeterCCSupportedReport(host, {
nodeId: 1,
data: ccData,
});
expect(cc.type).toBe(21);
expect(cc.supportsReset).toBeTrue();
expect(cc.supportedRateTypes).toEqual([]);
expect(cc.supportedScales).toEqual([1, 2, 3, 5, 6]);
});
it("the SupportedReport command (V4/V5) should be deserialized correctly", () => {
const ccData = buildCCBuffer(
Buffer.from([
MeterCommand.SupportedReport, // CC Command
0b1_10_10101, // supports reset, rate types,type
0b1_0000001, // more scale types, supported scales
2, // scales to follow
1,
1,
]),
);
const cc = new MeterCCSupportedReport(host, {
nodeId: 1,
data: ccData,
});
expect(cc.type).toBe(21);
expect(cc.supportsReset).toBeTrue();
expect(cc.supportedRateTypes).toEqual([RateType.Produced]);
expect(cc.supportedScales).toEqual([0, 7, 15]);
});
// it("the SupportedReport command (V4/V5) should be deserialized correctly", () => {
// const ccData = buildCCBuffer(
// Buffer.from([
// MeterCommand.SupportedReport, // CC Command
// 0b1_10_10101, // supports reset, rate types,type
// 0b1_0000001, // more scale types, supported scales
// 2, // scales to follow
// 1,
// 1,
// ]),
// );
// const cc = new MeterCCSupportedReport(host, {
// nodeId: 1,
// data: ccData,
// });
// expect(cc.type).toBe(21);
// expect(cc.supportsReset).toBeTrue();
// expect(cc.supportedRateTypes).toEqual([RateType.Produced]);
// expect(cc.supportedScales).toEqual([0, 7, 15]);
// });
it("deserializing an unsupported command should return an unspecified version of MeterCC", () => {
const serializedCC = buildCCBuffer(
Buffer.from([255]), // not a valid command
);
const cc: any = new MeterCC(host, {
nodeId: 1,
data: serializedCC,
});
expect(cc.constructor).toBe(MeterCC);
});
// it("the CC values should have the correct metadata", () => {
// // Readonly, 0-99
// const currentValueMeta = getCCValueMetadata(
// CommandClasses.Meter,
// "currentValue",
// );
// expect(currentValueMeta).toMatchObject({
// readable: true,
// writeable: false,
// min: 0,
// max: 99,
// });
// // Writeable, 0-99
// const targetValueMeta = getCCValueMetadata(
// CommandClasses.Meter,
// "targetValue",
// );
// expect(targetValueMeta).toMatchObject({
// readable: true,
// writeable: true,
// min: 0,
// max: 99,
// });
// });
});