homebridge-solaxcloud-api 2.5.0 → 2.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +172 -164
- package/LICENSE +175 -175
- package/README.md +223 -196
- package/config.sample +15 -15
- package/config.schema.json +113 -113
- package/dist/platformInverter.d.ts +5 -0
- package/dist/platformInverter.d.ts.map +1 -1
- package/dist/platformInverter.js +20 -7
- package/dist/platformInverter.js.map +1 -1
- package/package.json +60 -59
- package/test/batteryAccessory.test.ts +16 -16
- package/test/helpers.ts +80 -80
- package/test/lightSensorAccessory.test.ts +73 -73
- package/test/motionAccessory.test.ts +36 -36
- package/test/outletAccessory.test.ts +75 -75
- package/test/platformAccessory.test.ts +24 -24
- package/test/platformConfig.test.ts +188 -188
- package/test/platformTotalizer.test.ts +157 -123
- package/test/statistics.test.ts +50 -50
package/test/helpers.ts
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
import { API, Logging, MatterAccessory, MatterAPI } from 'homebridge';
|
|
2
|
-
import { Characteristic, Service, uuid } from '@homebridge/hap-nodejs';
|
|
3
|
-
import { createRequire } from 'module';
|
|
4
|
-
import os from 'os';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
|
|
7
|
-
const require = createRequire(import.meta.url);
|
|
8
|
-
const { CharacteristicEventTypes, Formats, Perms } = require('@homebridge/hap-nodejs');
|
|
9
|
-
|
|
10
|
-
export interface MatterApiHarness {
|
|
11
|
-
api: MatterAPI;
|
|
12
|
-
registrations: MatterAccessory[][];
|
|
13
|
-
updates: Array<{
|
|
14
|
-
uuid: string;
|
|
15
|
-
cluster: string;
|
|
16
|
-
attributes: Record<string, unknown>;
|
|
17
|
-
}>;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export function createLog(): Logging {
|
|
21
|
-
const noop = () => undefined;
|
|
22
|
-
|
|
23
|
-
return Object.assign(noop, {
|
|
24
|
-
debug: noop,
|
|
25
|
-
error: noop,
|
|
26
|
-
info: noop,
|
|
27
|
-
warn: noop,
|
|
28
|
-
log: noop,
|
|
29
|
-
prefix: '',
|
|
30
|
-
}) as unknown as Logging;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function createApi(matter?: MatterAPI): API {
|
|
34
|
-
return {
|
|
35
|
-
hap: {
|
|
36
|
-
Characteristic,
|
|
37
|
-
CharacteristicEventTypes,
|
|
38
|
-
Formats,
|
|
39
|
-
Perms,
|
|
40
|
-
Service,
|
|
41
|
-
uuid,
|
|
42
|
-
},
|
|
43
|
-
on: () => undefined,
|
|
44
|
-
user: {
|
|
45
|
-
storagePath: () => path.join(os.tmpdir(), 'homebridge-solaxcloud-api-test'),
|
|
46
|
-
},
|
|
47
|
-
matter,
|
|
48
|
-
} as unknown as API;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export function createMatterApi(): MatterApiHarness {
|
|
52
|
-
const registrations: MatterAccessory[][] = [];
|
|
53
|
-
const updates: MatterApiHarness['updates'] = [];
|
|
54
|
-
|
|
55
|
-
const api = {
|
|
56
|
-
deviceTypes: {
|
|
57
|
-
ElectricalSensor: { name: 'ElectricalSensor' },
|
|
58
|
-
},
|
|
59
|
-
clusterNames: {
|
|
60
|
-
ElectricalPowerMeasurement: 'electricalPowerMeasurement',
|
|
61
|
-
ElectricalEnergyMeasurement: 'electricalEnergyMeasurement',
|
|
62
|
-
},
|
|
63
|
-
registerPlatformAccessories: async (
|
|
64
|
-
_pluginIdentifier: string,
|
|
65
|
-
_platformName: string,
|
|
66
|
-
accessories: MatterAccessory[],
|
|
67
|
-
) => {
|
|
68
|
-
registrations.push(accessories);
|
|
69
|
-
},
|
|
70
|
-
updateAccessoryState: async (
|
|
71
|
-
uuid: string,
|
|
72
|
-
cluster: string,
|
|
73
|
-
attributes: Record<string, unknown>,
|
|
74
|
-
) => {
|
|
75
|
-
updates.push({ uuid, cluster, attributes });
|
|
76
|
-
},
|
|
77
|
-
} as unknown as MatterAPI;
|
|
78
|
-
|
|
79
|
-
return { api, registrations, updates };
|
|
80
|
-
}
|
|
1
|
+
import { API, Logging, MatterAccessory, MatterAPI } from 'homebridge';
|
|
2
|
+
import { Characteristic, Service, uuid } from '@homebridge/hap-nodejs';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
import os from 'os';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const { CharacteristicEventTypes, Formats, Perms } = require('@homebridge/hap-nodejs');
|
|
9
|
+
|
|
10
|
+
export interface MatterApiHarness {
|
|
11
|
+
api: MatterAPI;
|
|
12
|
+
registrations: MatterAccessory[][];
|
|
13
|
+
updates: Array<{
|
|
14
|
+
uuid: string;
|
|
15
|
+
cluster: string;
|
|
16
|
+
attributes: Record<string, unknown>;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function createLog(): Logging {
|
|
21
|
+
const noop = () => undefined;
|
|
22
|
+
|
|
23
|
+
return Object.assign(noop, {
|
|
24
|
+
debug: noop,
|
|
25
|
+
error: noop,
|
|
26
|
+
info: noop,
|
|
27
|
+
warn: noop,
|
|
28
|
+
log: noop,
|
|
29
|
+
prefix: '',
|
|
30
|
+
}) as unknown as Logging;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function createApi(matter?: MatterAPI): API {
|
|
34
|
+
return {
|
|
35
|
+
hap: {
|
|
36
|
+
Characteristic,
|
|
37
|
+
CharacteristicEventTypes,
|
|
38
|
+
Formats,
|
|
39
|
+
Perms,
|
|
40
|
+
Service,
|
|
41
|
+
uuid,
|
|
42
|
+
},
|
|
43
|
+
on: () => undefined,
|
|
44
|
+
user: {
|
|
45
|
+
storagePath: () => path.join(os.tmpdir(), 'homebridge-solaxcloud-api-test'),
|
|
46
|
+
},
|
|
47
|
+
matter,
|
|
48
|
+
} as unknown as API;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function createMatterApi(): MatterApiHarness {
|
|
52
|
+
const registrations: MatterAccessory[][] = [];
|
|
53
|
+
const updates: MatterApiHarness['updates'] = [];
|
|
54
|
+
|
|
55
|
+
const api = {
|
|
56
|
+
deviceTypes: {
|
|
57
|
+
ElectricalSensor: { name: 'ElectricalSensor' },
|
|
58
|
+
},
|
|
59
|
+
clusterNames: {
|
|
60
|
+
ElectricalPowerMeasurement: 'electricalPowerMeasurement',
|
|
61
|
+
ElectricalEnergyMeasurement: 'electricalEnergyMeasurement',
|
|
62
|
+
},
|
|
63
|
+
registerPlatformAccessories: async (
|
|
64
|
+
_pluginIdentifier: string,
|
|
65
|
+
_platformName: string,
|
|
66
|
+
accessories: MatterAccessory[],
|
|
67
|
+
) => {
|
|
68
|
+
registrations.push(accessories);
|
|
69
|
+
},
|
|
70
|
+
updateAccessoryState: async (
|
|
71
|
+
uuid: string,
|
|
72
|
+
cluster: string,
|
|
73
|
+
attributes: Record<string, unknown>,
|
|
74
|
+
) => {
|
|
75
|
+
updates.push({ uuid, cluster, attributes });
|
|
76
|
+
},
|
|
77
|
+
} as unknown as MatterAPI;
|
|
78
|
+
|
|
79
|
+
return { api, registrations, updates };
|
|
80
|
+
}
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
|
-
import { SolaxLightSensorAccessory } from '../src/lightSensorAccessory.js';
|
|
4
|
-
import { createApi, createLog, createMatterApi } from './helpers.js';
|
|
5
|
-
|
|
6
|
-
describe('SolaxLightSensorAccessory', () => {
|
|
7
|
-
it('stores ambient light values and applies the HomeKit minimum', () => {
|
|
8
|
-
const sensor = new SolaxLightSensorAccessory(createLog(), createApi(), 'Light sensor', 'light-1', 'Model');
|
|
9
|
-
|
|
10
|
-
sensor.setAmbientLightLevel(0);
|
|
11
|
-
sensor.getAmbientLightLevel((error, value) => {
|
|
12
|
-
assert.equal(error, null);
|
|
13
|
-
assert.equal(value, 0.1);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
sensor.setAmbientLightLevel(123);
|
|
17
|
-
sensor.getAmbientLightLevel((error, value) => {
|
|
18
|
-
assert.equal(error, null);
|
|
19
|
-
assert.equal(value, 123);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it('exposes information and light services', () => {
|
|
24
|
-
const sensor = new SolaxLightSensorAccessory(createLog(), createApi(), 'Light sensor', 'light-1', 'Model');
|
|
25
|
-
|
|
26
|
-
assert.equal(sensor.getServices().length, 2);
|
|
27
|
-
assert.equal(sensor.isMatterAccessory(), false);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('registers and updates a Matter electrical sensor', async () => {
|
|
31
|
-
const matter = createMatterApi();
|
|
32
|
-
const sensor = new SolaxLightSensorAccessory(
|
|
33
|
-
createLog(),
|
|
34
|
-
createApi(matter.api),
|
|
35
|
-
'Power sensor',
|
|
36
|
-
'power-1',
|
|
37
|
-
'Model',
|
|
38
|
-
true,
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
assert.equal(sensor.getServices().length, 1);
|
|
42
|
-
assert.equal(sensor.isMatterAccessory(), true);
|
|
43
|
-
assert.equal(matter.registrations.length, 1);
|
|
44
|
-
|
|
45
|
-
const accessory = matter.registrations[0][0];
|
|
46
|
-
assert.equal(accessory.deviceType, matter.api.deviceTypes.ElectricalSensor);
|
|
47
|
-
assert.deepEqual(accessory.clusters, {
|
|
48
|
-
electricalPowerMeasurement: { activePower: 0 },
|
|
49
|
-
electricalEnergyMeasurement: {
|
|
50
|
-
cumulativeEnergyExported: { energy: 0 },
|
|
51
|
-
},
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
sensor.setAmbientLightLevel(123.456);
|
|
55
|
-
sensor.setTotalEnergyConsumption(12.345);
|
|
56
|
-
await new Promise(resolve => setImmediate(resolve));
|
|
57
|
-
|
|
58
|
-
assert.deepEqual(matter.updates, [
|
|
59
|
-
{
|
|
60
|
-
uuid: accessory.UUID,
|
|
61
|
-
cluster: 'electricalPowerMeasurement',
|
|
62
|
-
attributes: { activePower: 123456 },
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
uuid: accessory.UUID,
|
|
66
|
-
cluster: 'electricalEnergyMeasurement',
|
|
67
|
-
attributes: {
|
|
68
|
-
cumulativeEnergyExported: { energy: 12345 },
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
]);
|
|
72
|
-
});
|
|
73
|
-
});
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
|
|
3
|
+
import { SolaxLightSensorAccessory } from '../src/lightSensorAccessory.js';
|
|
4
|
+
import { createApi, createLog, createMatterApi } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
describe('SolaxLightSensorAccessory', () => {
|
|
7
|
+
it('stores ambient light values and applies the HomeKit minimum', () => {
|
|
8
|
+
const sensor = new SolaxLightSensorAccessory(createLog(), createApi(), 'Light sensor', 'light-1', 'Model');
|
|
9
|
+
|
|
10
|
+
sensor.setAmbientLightLevel(0);
|
|
11
|
+
sensor.getAmbientLightLevel((error, value) => {
|
|
12
|
+
assert.equal(error, null);
|
|
13
|
+
assert.equal(value, 0.1);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
sensor.setAmbientLightLevel(123);
|
|
17
|
+
sensor.getAmbientLightLevel((error, value) => {
|
|
18
|
+
assert.equal(error, null);
|
|
19
|
+
assert.equal(value, 123);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('exposes information and light services', () => {
|
|
24
|
+
const sensor = new SolaxLightSensorAccessory(createLog(), createApi(), 'Light sensor', 'light-1', 'Model');
|
|
25
|
+
|
|
26
|
+
assert.equal(sensor.getServices().length, 2);
|
|
27
|
+
assert.equal(sensor.isMatterAccessory(), false);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('registers and updates a Matter electrical sensor', async () => {
|
|
31
|
+
const matter = createMatterApi();
|
|
32
|
+
const sensor = new SolaxLightSensorAccessory(
|
|
33
|
+
createLog(),
|
|
34
|
+
createApi(matter.api),
|
|
35
|
+
'Power sensor',
|
|
36
|
+
'power-1',
|
|
37
|
+
'Model',
|
|
38
|
+
true,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
assert.equal(sensor.getServices().length, 1);
|
|
42
|
+
assert.equal(sensor.isMatterAccessory(), true);
|
|
43
|
+
assert.equal(matter.registrations.length, 1);
|
|
44
|
+
|
|
45
|
+
const accessory = matter.registrations[0][0];
|
|
46
|
+
assert.equal(accessory.deviceType, matter.api.deviceTypes.ElectricalSensor);
|
|
47
|
+
assert.deepEqual(accessory.clusters, {
|
|
48
|
+
electricalPowerMeasurement: { activePower: 0 },
|
|
49
|
+
electricalEnergyMeasurement: {
|
|
50
|
+
cumulativeEnergyExported: { energy: 0 },
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
sensor.setAmbientLightLevel(123.456);
|
|
55
|
+
sensor.setTotalEnergyConsumption(12.345);
|
|
56
|
+
await new Promise(resolve => setImmediate(resolve));
|
|
57
|
+
|
|
58
|
+
assert.deepEqual(matter.updates, [
|
|
59
|
+
{
|
|
60
|
+
uuid: accessory.UUID,
|
|
61
|
+
cluster: 'electricalPowerMeasurement',
|
|
62
|
+
attributes: { activePower: 123456 },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
uuid: accessory.UUID,
|
|
66
|
+
cluster: 'electricalEnergyMeasurement',
|
|
67
|
+
attributes: {
|
|
68
|
+
cumulativeEnergyExported: { energy: 12345 },
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
|
-
import { SolaxMotionAccessory } from '../src/motionAccessory.js';
|
|
4
|
-
import { createApi, createLog } from './helpers.js';
|
|
5
|
-
|
|
6
|
-
function sleep(millis: number): Promise<void> {
|
|
7
|
-
return new Promise(resolve => setTimeout(resolve, millis));
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
describe('SolaxMotionAccessory', () => {
|
|
11
|
-
it('stores motion state and clears it after the configured timeout', async () => {
|
|
12
|
-
const motion = new SolaxMotionAccessory(createLog(), createApi(), 'Motion', 'motion-1', 'Model');
|
|
13
|
-
|
|
14
|
-
motion.setMotionTimeout(0);
|
|
15
|
-
assert.equal(motion.getMotionTimeout(), 0);
|
|
16
|
-
|
|
17
|
-
motion.setState(true);
|
|
18
|
-
motion.getState((error, value) => {
|
|
19
|
-
assert.equal(error, null);
|
|
20
|
-
assert.equal(value, true);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
await sleep(5);
|
|
24
|
-
|
|
25
|
-
motion.getState((error, value) => {
|
|
26
|
-
assert.equal(error, null);
|
|
27
|
-
assert.equal(value, false);
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('exposes information and motion services', () => {
|
|
32
|
-
const motion = new SolaxMotionAccessory(createLog(), createApi(), 'Motion', 'motion-1', 'Model');
|
|
33
|
-
|
|
34
|
-
assert.equal(motion.getServices().length, 2);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
|
|
3
|
+
import { SolaxMotionAccessory } from '../src/motionAccessory.js';
|
|
4
|
+
import { createApi, createLog } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
function sleep(millis: number): Promise<void> {
|
|
7
|
+
return new Promise(resolve => setTimeout(resolve, millis));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
describe('SolaxMotionAccessory', () => {
|
|
11
|
+
it('stores motion state and clears it after the configured timeout', async () => {
|
|
12
|
+
const motion = new SolaxMotionAccessory(createLog(), createApi(), 'Motion', 'motion-1', 'Model');
|
|
13
|
+
|
|
14
|
+
motion.setMotionTimeout(0);
|
|
15
|
+
assert.equal(motion.getMotionTimeout(), 0);
|
|
16
|
+
|
|
17
|
+
motion.setState(true);
|
|
18
|
+
motion.getState((error, value) => {
|
|
19
|
+
assert.equal(error, null);
|
|
20
|
+
assert.equal(value, true);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await sleep(5);
|
|
24
|
+
|
|
25
|
+
motion.getState((error, value) => {
|
|
26
|
+
assert.equal(error, null);
|
|
27
|
+
assert.equal(value, false);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('exposes information and motion services', () => {
|
|
32
|
+
const motion = new SolaxMotionAccessory(createLog(), createApi(), 'Motion', 'motion-1', 'Model');
|
|
33
|
+
|
|
34
|
+
assert.equal(motion.getServices().length, 2);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -1,75 +1,75 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
import { SolaxOutletAccessory } from '../src/outletAccessory.js';
|
|
3
|
-
import { createApi, createLog } from './helpers.js';
|
|
4
|
-
|
|
5
|
-
describe('SolaxOutletAccessory', () => {
|
|
6
|
-
function withOutlet(test: (outlet: SolaxOutletAccessory) => void): void {
|
|
7
|
-
const api = createApi();
|
|
8
|
-
const outlet = new SolaxOutletAccessory(createLog(), api, 'Outlet', 'outlet-1', 'Model');
|
|
9
|
-
|
|
10
|
-
try {
|
|
11
|
-
test(outlet);
|
|
12
|
-
} finally {
|
|
13
|
-
api['globalFakeGatoTimer']?.stop();
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
it('stores power values, clamps negative power, and tracks power series', () => {
|
|
18
|
-
withOutlet(outlet => {
|
|
19
|
-
outlet.setPowerConsumption(-10);
|
|
20
|
-
assert.equal(outlet.getPowerConsumptionValue(), 0);
|
|
21
|
-
|
|
22
|
-
outlet.getState((error, value) => {
|
|
23
|
-
assert.equal(error, null);
|
|
24
|
-
assert.equal(value, false);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
outlet.setPowerConsumption(42);
|
|
28
|
-
assert.equal(outlet.getPowerConsumptionValue(), 42);
|
|
29
|
-
assert.deepEqual(outlet.getPowerSeries(), [0, 42]);
|
|
30
|
-
|
|
31
|
-
outlet.getState((error, value) => {
|
|
32
|
-
assert.equal(error, null);
|
|
33
|
-
assert.equal(value, true);
|
|
34
|
-
});
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('stores total energy consumption', () => {
|
|
39
|
-
withOutlet(outlet => {
|
|
40
|
-
outlet.setTotalEnergyConsumption(12.5);
|
|
41
|
-
assert.equal(outlet.getTotalEnergyConsumptionValue(), 12.5);
|
|
42
|
-
|
|
43
|
-
outlet.getTotalEnergyConsumption((error, value) => {
|
|
44
|
-
assert.equal(error, null);
|
|
45
|
-
assert.equal(value, 12.5);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('calculates smoothed power from the stored power series', () => {
|
|
51
|
-
withOutlet(outlet => {
|
|
52
|
-
outlet.setPowerConsumption(10);
|
|
53
|
-
outlet.setPowerConsumption(20);
|
|
54
|
-
outlet.setPowerConsumption(30);
|
|
55
|
-
|
|
56
|
-
assert.equal(outlet.getSmoothPowerConsumption('sma', 3), 20);
|
|
57
|
-
assert.equal(outlet.getSmoothPowerConsumption('ema', 3), 15);
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('exposes information, outlet, and history services', () => {
|
|
62
|
-
withOutlet(outlet => {
|
|
63
|
-
assert.equal(outlet.getServices().length, 3);
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('does not create history service when history is disabled', () => {
|
|
68
|
-
const outlet = new SolaxOutletAccessory(createLog(), createApi(), 'Outlet', 'outlet-1', 'Model', false);
|
|
69
|
-
|
|
70
|
-
outlet.setPowerConsumption(42);
|
|
71
|
-
|
|
72
|
-
assert.equal(outlet.getPowerConsumptionValue(), 42);
|
|
73
|
-
assert.equal(outlet.getServices().length, 2);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
import { SolaxOutletAccessory } from '../src/outletAccessory.js';
|
|
3
|
+
import { createApi, createLog } from './helpers.js';
|
|
4
|
+
|
|
5
|
+
describe('SolaxOutletAccessory', () => {
|
|
6
|
+
function withOutlet(test: (outlet: SolaxOutletAccessory) => void): void {
|
|
7
|
+
const api = createApi();
|
|
8
|
+
const outlet = new SolaxOutletAccessory(createLog(), api, 'Outlet', 'outlet-1', 'Model');
|
|
9
|
+
|
|
10
|
+
try {
|
|
11
|
+
test(outlet);
|
|
12
|
+
} finally {
|
|
13
|
+
api['globalFakeGatoTimer']?.stop();
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
it('stores power values, clamps negative power, and tracks power series', () => {
|
|
18
|
+
withOutlet(outlet => {
|
|
19
|
+
outlet.setPowerConsumption(-10);
|
|
20
|
+
assert.equal(outlet.getPowerConsumptionValue(), 0);
|
|
21
|
+
|
|
22
|
+
outlet.getState((error, value) => {
|
|
23
|
+
assert.equal(error, null);
|
|
24
|
+
assert.equal(value, false);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
outlet.setPowerConsumption(42);
|
|
28
|
+
assert.equal(outlet.getPowerConsumptionValue(), 42);
|
|
29
|
+
assert.deepEqual(outlet.getPowerSeries(), [0, 42]);
|
|
30
|
+
|
|
31
|
+
outlet.getState((error, value) => {
|
|
32
|
+
assert.equal(error, null);
|
|
33
|
+
assert.equal(value, true);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('stores total energy consumption', () => {
|
|
39
|
+
withOutlet(outlet => {
|
|
40
|
+
outlet.setTotalEnergyConsumption(12.5);
|
|
41
|
+
assert.equal(outlet.getTotalEnergyConsumptionValue(), 12.5);
|
|
42
|
+
|
|
43
|
+
outlet.getTotalEnergyConsumption((error, value) => {
|
|
44
|
+
assert.equal(error, null);
|
|
45
|
+
assert.equal(value, 12.5);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('calculates smoothed power from the stored power series', () => {
|
|
51
|
+
withOutlet(outlet => {
|
|
52
|
+
outlet.setPowerConsumption(10);
|
|
53
|
+
outlet.setPowerConsumption(20);
|
|
54
|
+
outlet.setPowerConsumption(30);
|
|
55
|
+
|
|
56
|
+
assert.equal(outlet.getSmoothPowerConsumption('sma', 3), 20);
|
|
57
|
+
assert.equal(outlet.getSmoothPowerConsumption('ema', 3), 15);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('exposes information, outlet, and history services', () => {
|
|
62
|
+
withOutlet(outlet => {
|
|
63
|
+
assert.equal(outlet.getServices().length, 3);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('does not create history service when history is disabled', () => {
|
|
68
|
+
const outlet = new SolaxOutletAccessory(createLog(), createApi(), 'Outlet', 'outlet-1', 'Model', false);
|
|
69
|
+
|
|
70
|
+
outlet.setPowerConsumption(42);
|
|
71
|
+
|
|
72
|
+
assert.equal(outlet.getPowerConsumptionValue(), 42);
|
|
73
|
+
assert.equal(outlet.getServices().length, 2);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import assert from 'assert';
|
|
2
|
-
|
|
3
|
-
import { SolaxPlatformAccessory } from '../src/platformAccessory.js';
|
|
4
|
-
import { createApi, createLog } from './helpers.js';
|
|
5
|
-
|
|
6
|
-
describe('SolaxPlatformAccessory', () => {
|
|
7
|
-
it('exposes normalized model and stable hashed serial information', () => {
|
|
8
|
-
const accessory = new SolaxPlatformAccessory(createLog(), createApi(), 'Base accessory', 'serial-1', 'Model / 1!');
|
|
9
|
-
|
|
10
|
-
assert.equal(accessory.getModel(), 'Model 1');
|
|
11
|
-
assert.notEqual(accessory.getSerial(), 'serial-1');
|
|
12
|
-
assert.equal(accessory.getServices().length, 1);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('updates model and serial characteristics', () => {
|
|
16
|
-
const accessory = new SolaxPlatformAccessory(createLog(), createApi(), 'Base accessory', 'serial-1', 'Model');
|
|
17
|
-
|
|
18
|
-
accessory.setModel('Updated Model');
|
|
19
|
-
accessory.setSerial('updated-serial');
|
|
20
|
-
|
|
21
|
-
assert.equal(accessory.getModel(), 'Updated Model');
|
|
22
|
-
assert.equal(accessory.getSerial(), 'updated-serial');
|
|
23
|
-
});
|
|
24
|
-
});
|
|
1
|
+
import assert from 'assert';
|
|
2
|
+
|
|
3
|
+
import { SolaxPlatformAccessory } from '../src/platformAccessory.js';
|
|
4
|
+
import { createApi, createLog } from './helpers.js';
|
|
5
|
+
|
|
6
|
+
describe('SolaxPlatformAccessory', () => {
|
|
7
|
+
it('exposes normalized model and stable hashed serial information', () => {
|
|
8
|
+
const accessory = new SolaxPlatformAccessory(createLog(), createApi(), 'Base accessory', 'serial-1', 'Model / 1!');
|
|
9
|
+
|
|
10
|
+
assert.equal(accessory.getModel(), 'Model 1');
|
|
11
|
+
assert.notEqual(accessory.getSerial(), 'serial-1');
|
|
12
|
+
assert.equal(accessory.getServices().length, 1);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('updates model and serial characteristics', () => {
|
|
16
|
+
const accessory = new SolaxPlatformAccessory(createLog(), createApi(), 'Base accessory', 'serial-1', 'Model');
|
|
17
|
+
|
|
18
|
+
accessory.setModel('Updated Model');
|
|
19
|
+
accessory.setSerial('updated-serial');
|
|
20
|
+
|
|
21
|
+
assert.equal(accessory.getModel(), 'Updated Model');
|
|
22
|
+
assert.equal(accessory.getSerial(), 'updated-serial');
|
|
23
|
+
});
|
|
24
|
+
});
|