homebridge-solaxcloud-api 2.3.3 → 2.4.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +150 -131
  2. package/LICENSE +175 -175
  3. package/README.md +1 -0
  4. package/config.sample +15 -15
  5. package/config.schema.json +113 -106
  6. package/dist/batteryAccessory.d.ts +70 -70
  7. package/dist/batteryAccessory.d.ts.map +1 -1
  8. package/dist/batteryAccessory.js +124 -123
  9. package/dist/batteryAccessory.js.map +1 -1
  10. package/dist/index.d.ts +6 -6
  11. package/dist/index.js +6 -6
  12. package/dist/lightSensorAccessory.d.ts +34 -34
  13. package/dist/lightSensorAccessory.js +58 -58
  14. package/dist/motionAccessory.d.ts +53 -53
  15. package/dist/motionAccessory.js +93 -93
  16. package/dist/outletAccessory.d.ts +104 -100
  17. package/dist/outletAccessory.d.ts.map +1 -1
  18. package/dist/outletAccessory.js +196 -187
  19. package/dist/outletAccessory.js.map +1 -1
  20. package/dist/platform.d.ts +67 -56
  21. package/dist/platform.d.ts.map +1 -1
  22. package/dist/platform.js +320 -265
  23. package/dist/platform.js.map +1 -1
  24. package/dist/platformAccessory.d.ts +70 -70
  25. package/dist/platformAccessory.js +102 -102
  26. package/dist/platformInverter.d.ts +180 -176
  27. package/dist/platformInverter.d.ts.map +1 -1
  28. package/dist/platformInverter.js +348 -343
  29. package/dist/platformInverter.js.map +1 -1
  30. package/dist/platformMeters.d.ts +68 -68
  31. package/dist/platformMeters.js +2 -2
  32. package/dist/settings.d.ts +8 -8
  33. package/dist/settings.js +11 -11
  34. package/dist/solaxcloudfetch.d.ts +1 -1
  35. package/dist/solaxcloudfetch.js +21 -21
  36. package/dist/solaxcloudfetch.js.map +1 -1
  37. package/dist/statistics.d.ts +36 -36
  38. package/dist/statistics.js +88 -88
  39. package/dist/util.d.ts +23 -23
  40. package/dist/util.js +42 -42
  41. package/package.json +55 -54
  42. package/test/batteryAccessory.test.ts +16 -0
  43. package/test/helpers.ts +36 -0
  44. package/test/lightSensorAccessory.test.ts +28 -0
  45. package/test/motionAccessory.test.ts +36 -0
  46. package/test/outletAccessory.test.ts +75 -0
  47. package/test/platformAccessory.test.ts +24 -0
  48. package/test/platformConfig.test.ts +188 -0
  49. package/test/platformTotalizer.test.ts +97 -0
  50. package/config.json +0 -16
  51. package/dist/solaxcloudapi.d.ts +0 -163
  52. package/dist/solaxcloudapi.d.ts.map +0 -1
  53. package/dist/solaxcloudapi.js +0 -226
  54. package/dist/solaxcloudapi.js.map +0 -1
  55. package/test/solaxcloudapi.test.ts +0 -164
package/dist/util.js CHANGED
@@ -1,43 +1,43 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Util = void 0;
4
- /**
5
- * Utility class.
6
- */
7
- class Util {
8
- /**
9
- * Calculates 32 bit hash from a string.
10
- * @param s {string} String to calculate 32 bit hash from.
11
- * @returns {number} The 32 bit hash from the string.
12
- */
13
- static hash32(s) {
14
- let hash = 0;
15
- if (s.length === 0) {
16
- return hash;
17
- }
18
- for (let i = 0; i < s.length; i++) {
19
- const chr = s.charCodeAt(i);
20
- hash = ((hash << 5) - hash) + chr;
21
- hash |= 0; // Convert to 32bit integer
22
- }
23
- return hash;
24
- }
25
- /**
26
- * Removes non-standard alphanumeric characters from string.
27
- * @param {string} s The original string.
28
- * @returns {string} Resulting string without any non-standard chars.
29
- */
30
- static normalizeName(s) {
31
- return s.replace(/[^-_ a-zA-Z0-9]/gi, '');
32
- }
33
- /**
34
- * Returns whether an array has duplicates or not.
35
- * @param {unknown[]} array The array to check for duplicates.
36
- * @returns {boolean} Whether the array has duplicates.
37
- */
38
- static arrayHasDuplicates(array) {
39
- return (new Set(array)).size !== array.length;
40
- }
41
- }
42
- exports.Util = Util;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Util = void 0;
4
+ /**
5
+ * Utility class.
6
+ */
7
+ class Util {
8
+ /**
9
+ * Calculates 32 bit hash from a string.
10
+ * @param s {string} String to calculate 32 bit hash from.
11
+ * @returns {number} The 32 bit hash from the string.
12
+ */
13
+ static hash32(s) {
14
+ let hash = 0;
15
+ if (s.length === 0) {
16
+ return hash;
17
+ }
18
+ for (let i = 0; i < s.length; i++) {
19
+ const chr = s.charCodeAt(i);
20
+ hash = ((hash << 5) - hash) + chr;
21
+ hash |= 0; // Convert to 32bit integer
22
+ }
23
+ return hash;
24
+ }
25
+ /**
26
+ * Removes non-standard alphanumeric characters from string.
27
+ * @param {string} s The original string.
28
+ * @returns {string} Resulting string without any non-standard chars.
29
+ */
30
+ static normalizeName(s) {
31
+ return s.replace(/[^-_ a-zA-Z0-9]/gi, '');
32
+ }
33
+ /**
34
+ * Returns whether an array has duplicates or not.
35
+ * @param {unknown[]} array The array to check for duplicates.
36
+ * @returns {boolean} Whether the array has duplicates.
37
+ */
38
+ static arrayHasDuplicates(array) {
39
+ return (new Set(array)).size !== array.length;
40
+ }
41
+ }
42
+ exports.Util = Util;
43
43
  //# sourceMappingURL=util.js.map
package/package.json CHANGED
@@ -1,54 +1,55 @@
1
- {
2
- "private": false,
3
- "displayName": "Homebridge Solax Cloud API",
4
- "name": "homebridge-solaxcloud-api",
5
- "version": "2.3.3",
6
- "description": "Integrates solar production info using public Solax/QCells Cloud API into Homebridge accessories.",
7
- "license": "Apache-2.0",
8
- "repository": {
9
- "type": "git",
10
- "url": "git://github.com/AllMightySauron/homebride-solaxcloud-api.git"
11
- },
12
- "bugs": {
13
- "url": "https://github.com/AllMightySauron/homebride-solaxcloud-api/issues"
14
- },
15
- "engines": {
16
- "node": ">=14.18.1",
17
- "homebridge": ">=1.3.8"
18
- },
19
- "main": "dist/index.js",
20
- "scripts": {
21
- "test": "mocha --require ts-node/register test/**/*.test.ts",
22
- "lint": "eslint src/**.ts --max-warnings=0",
23
- "watch": "npm run build && npm link && nodemon",
24
- "build": "rimraf ./dist && tsc",
25
- "prepublishOnly": "npm run lint && npm run build"
26
- },
27
- "keywords": [
28
- "homebridge",
29
- "homebridge-plugin",
30
- "solax",
31
- "qcells",
32
- "solaxcloud"
33
- ],
34
- "dependencies": {
35
- "fakegato-history": "^0.6.4",
36
- "homebridge-lib": "^5.7.2",
37
- "jshint": "^2.13.6",
38
- "string-hash-64": "^1.0.3",
39
- "sync-fetch": "^0.3.1"
40
- },
41
- "devDependencies": {
42
- "@types/mocha": "^9.0.0",
43
- "@types/node": "^16.10.9",
44
- "@typescript-eslint/eslint-plugin": "^5.0.0",
45
- "@typescript-eslint/parser": "^5.0.0",
46
- "eslint": "^8.0.1",
47
- "homebridge": "^1.7.0",
48
- "mocha": "^9.2.2",
49
- "nodemon": "^3.1.0",
50
- "rimraf": "^3.0.2",
51
- "ts-node": "^10.3.0",
52
- "typescript": "^4.4.4"
53
- }
54
- }
1
+ {
2
+ "private": false,
3
+ "displayName": "Homebridge Solax Cloud API",
4
+ "name": "homebridge-solaxcloud-api",
5
+ "version": "2.4.1",
6
+ "description": "Integrates solar production info using public Solax/QCells Cloud API into Homebridge accessories.",
7
+ "license": "Apache-2.0",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git://github.com/AllMightySauron/homebride-solaxcloud-api.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/AllMightySauron/homebride-solaxcloud-api/issues"
14
+ },
15
+ "engines": {
16
+ "node": ">=14.18.1",
17
+ "homebridge": ">=1.3.8"
18
+ },
19
+ "main": "dist/index.js",
20
+ "scripts": {
21
+ "test": "mocha --exit --require ts-node/register test/**/*.test.ts",
22
+ "lint": "eslint src/**.ts --max-warnings=0",
23
+ "watch": "npm run build && npm link && nodemon",
24
+ "build": "rimraf ./dist && tsc",
25
+ "prepublishOnly": "npm run lint && npm run build"
26
+ },
27
+ "keywords": [
28
+ "homebridge",
29
+ "homebridge-plugin",
30
+ "solax",
31
+ "qcells",
32
+ "solaxcloud"
33
+ ],
34
+ "dependencies": {
35
+ "fakegato-history": "^0.6.7",
36
+ "homebridge-lib": "^5.7.2",
37
+ "jshint": "^2.13.6",
38
+ "string-hash-64": "^1.0.3",
39
+ "sync-fetch": "^0.3.1",
40
+ "solax-cloud-api": "^0.2.0"
41
+ },
42
+ "devDependencies": {
43
+ "@types/mocha": "^9.0.0",
44
+ "@types/node": "^16.10.9",
45
+ "@typescript-eslint/eslint-plugin": "^5.0.0",
46
+ "@typescript-eslint/parser": "^5.0.0",
47
+ "eslint": "^8.0.1",
48
+ "homebridge": "^1.7.0",
49
+ "mocha": "^11.0.1",
50
+ "nodemon": "^3.1.0",
51
+ "rimraf": "^3.0.2",
52
+ "ts-node": "^10.3.0",
53
+ "typescript": "^4.4.4"
54
+ }
55
+ }
@@ -0,0 +1,16 @@
1
+ import assert = require('assert');
2
+
3
+ import { BATTERY_CHARGING_STATE, SolaxBatteryAccessory } from '../src/batteryAccessory';
4
+ import { createApi, createLog } from './helpers';
5
+
6
+ describe('SolaxBatteryAccessory', () => {
7
+ it('keeps charge state getter in sync after updates', () => {
8
+ const battery = new SolaxBatteryAccessory(createLog(), createApi(), 'Battery', 'bat-test', 'Test Model');
9
+
10
+ battery.setChargeState(BATTERY_CHARGING_STATE.CHARGING);
11
+ assert.equal(battery.getChargeStateValue(), BATTERY_CHARGING_STATE.CHARGING);
12
+
13
+ battery.setChargeState(BATTERY_CHARGING_STATE.NOT_CHARGEABLE);
14
+ assert.equal(battery.getChargeStateValue(), BATTERY_CHARGING_STATE.NOT_CHARGEABLE);
15
+ });
16
+ });
@@ -0,0 +1,36 @@
1
+ import { API, Logging } from 'homebridge';
2
+ import { Characteristic, Service } from 'hap-nodejs';
3
+ import os from 'os';
4
+ import path from 'path';
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
7
+ const { CharacteristicEventTypes, Formats, Perms } = require('hap-nodejs');
8
+
9
+ export function createLog(): Logging {
10
+ const noop = () => undefined;
11
+
12
+ return Object.assign(noop, {
13
+ debug: noop,
14
+ error: noop,
15
+ info: noop,
16
+ warn: noop,
17
+ log: noop,
18
+ prefix: '',
19
+ }) as unknown as Logging;
20
+ }
21
+
22
+ export function createApi(): API {
23
+ return {
24
+ hap: {
25
+ Characteristic,
26
+ CharacteristicEventTypes,
27
+ Formats,
28
+ Perms,
29
+ Service,
30
+ },
31
+ on: () => undefined,
32
+ user: {
33
+ storagePath: () => path.join(os.tmpdir(), 'homebridge-solaxcloud-api-test'),
34
+ },
35
+ } as unknown as API;
36
+ }
@@ -0,0 +1,28 @@
1
+ import assert = require('assert');
2
+
3
+ import { SolaxLightSensorAccessory } from '../src/lightSensorAccessory';
4
+ import { createApi, createLog } from './helpers';
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
+ });
28
+ });
@@ -0,0 +1,36 @@
1
+ import assert = require('assert');
2
+
3
+ import { SolaxMotionAccessory } from '../src/motionAccessory';
4
+ import { createApi, createLog } from './helpers';
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
+ });
@@ -0,0 +1,75 @@
1
+ import assert = require('assert');
2
+ import { SolaxOutletAccessory } from '../src/outletAccessory';
3
+ import { createApi, createLog } from './helpers';
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
+ });
@@ -0,0 +1,24 @@
1
+ import assert = require('assert');
2
+
3
+ import { SolaxPlatformAccessory } from '../src/platformAccessory';
4
+ import { createApi, createLog } from './helpers';
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
+ });
@@ -0,0 +1,188 @@
1
+ import { Logging, PlatformConfig } from 'homebridge';
2
+
3
+ import assert = require('assert');
4
+
5
+ import { SolaxCloudAPIPlatform } from '../src/platform';
6
+
7
+ interface TestLog extends Logging {
8
+ errors: string[];
9
+ }
10
+
11
+ function createLog(): TestLog {
12
+ const noop = () => undefined;
13
+ const log = Object.assign(noop, {
14
+ debug: noop,
15
+ info: noop,
16
+ warn: noop,
17
+ log: noop,
18
+ prefix: '',
19
+ errors: [] as string[],
20
+ error(message: string) {
21
+ this.errors.push(message);
22
+ },
23
+ }) as unknown as TestLog;
24
+
25
+ return log;
26
+ }
27
+
28
+ function createConfig(pollingFrequency = 300): PlatformConfig {
29
+ return {
30
+ platform: 'SolaxCloudAPI',
31
+ inverters: [
32
+ {
33
+ brand: 'solax',
34
+ tokenId: '20200722185111234567890',
35
+ name: 'Test inverter',
36
+ sn: 'ABCDEFGHIJ',
37
+ },
38
+ ],
39
+ pollingFrequency,
40
+ };
41
+ }
42
+
43
+ function createPlatformForConfigCheck(log: Logging): SolaxCloudAPIPlatform {
44
+ const platform = Object.create(SolaxCloudAPIPlatform.prototype);
45
+
46
+ platform.log = log;
47
+
48
+ return platform as SolaxCloudAPIPlatform;
49
+ }
50
+
51
+ describe('SolaxCloudAPIPlatform config checks', () => {
52
+ [
53
+ {
54
+ name: 'missing inverters',
55
+ config: { platform: 'SolaxCloudAPI' } as PlatformConfig,
56
+ error: 'mandatory parameter "inverters"',
57
+ },
58
+ {
59
+ name: 'non-array inverters',
60
+ config: { ...createConfig(), inverters: 'invalid' },
61
+ error: 'Incorrect type for mandatory parameter "inverters"',
62
+ },
63
+ {
64
+ name: 'inverter missing mandatory fields',
65
+ config: { ...createConfig(), inverters: [{ brand: 'solax', name: 'Test inverter', sn: 'ABCDEFGHIJ' }] },
66
+ error: 'Invalid type for inverter under "inverters"',
67
+ },
68
+ {
69
+ name: 'null inverter entry',
70
+ config: { ...createConfig(), inverters: [null] },
71
+ error: 'Invalid type for inverter under "inverters"',
72
+ },
73
+ {
74
+ name: 'unsupported inverter brand',
75
+ config: {
76
+ ...createConfig(),
77
+ inverters: [
78
+ {
79
+ brand: 'unsupported',
80
+ tokenId: '20200722185111234567890',
81
+ name: 'Test inverter',
82
+ sn: 'ABCDEFGHIJ',
83
+ },
84
+ ],
85
+ },
86
+ error: 'Invalid type for inverter under "inverters"',
87
+ },
88
+ {
89
+ name: 'duplicate inverter names',
90
+ config: {
91
+ ...createConfig(),
92
+ inverters: [
93
+ {
94
+ brand: 'solax',
95
+ tokenId: '20200722185111234567890',
96
+ name: 'Test inverter',
97
+ sn: 'ABCDEFGHIJ',
98
+ },
99
+ {
100
+ brand: 'qcells',
101
+ tokenId: '20200722185111234567891',
102
+ name: 'Test inverter',
103
+ sn: 'KLMNOPQRST',
104
+ },
105
+ ],
106
+ },
107
+ error: 'Duplicate inverter names',
108
+ },
109
+ {
110
+ name: 'duplicate inverter serial numbers',
111
+ config: {
112
+ ...createConfig(),
113
+ inverters: [
114
+ {
115
+ brand: 'solax',
116
+ tokenId: '20200722185111234567890',
117
+ name: 'Test inverter 1',
118
+ sn: 'ABCDEFGHIJ',
119
+ },
120
+ {
121
+ brand: 'qcells',
122
+ tokenId: '20200722185111234567891',
123
+ name: 'Test inverter 2',
124
+ sn: 'ABCDEFGHIJ',
125
+ },
126
+ ],
127
+ },
128
+ error: 'Duplicate inverter SNs',
129
+ },
130
+ ].forEach(testCase => {
131
+ it(`rejects invalid config: ${testCase.name}`, () => {
132
+ const log = createLog();
133
+ const platform = createPlatformForConfigCheck(log);
134
+
135
+ assert.equal(platform['checkConfig'](testCase.config as PlatformConfig), false);
136
+ assert.equal(log.errors.length, 1);
137
+ assert.match(log.errors[0], new RegExp(testCase.error));
138
+ });
139
+ });
140
+
141
+ it('rejects polling frequencies that would produce an empty smoothing window', () => {
142
+ const log = createLog();
143
+ const platform = createPlatformForConfigCheck(log);
144
+ const config = createConfig(901);
145
+
146
+ assert.throws(
147
+ () => platform['checkConfig'](config),
148
+ /Polling frequency cannot be higher than 900 seconds/,
149
+ );
150
+ assert.equal(log.errors.length, 1);
151
+ });
152
+
153
+ it('accepts the largest polling frequency that keeps one smoothing period', () => {
154
+ const log = createLog();
155
+ const platform = createPlatformForConfigCheck(log);
156
+ const config = createConfig(900);
157
+
158
+ assert.equal(platform['checkConfig'](config), true);
159
+ assert.equal(config.pollingFrequency, 900);
160
+ });
161
+
162
+ it('defaults history to enabled when not configured', () => {
163
+ const log = createLog();
164
+ const platform = createPlatformForConfigCheck(log);
165
+ const config = createConfig();
166
+
167
+ assert.equal(platform['checkConfig'](config), true);
168
+ assert.equal(config.enableHistory, true);
169
+ });
170
+
171
+ it('keeps history disabled when configured', () => {
172
+ const log = createLog();
173
+ const platform = createPlatformForConfigCheck(log);
174
+ const config = { ...createConfig(), enableHistory: false };
175
+
176
+ assert.equal(platform['checkConfig'](config), true);
177
+ assert.equal(config.enableHistory, false);
178
+ });
179
+
180
+ it('defaults invalid history config to enabled', () => {
181
+ const log = createLog();
182
+ const platform = createPlatformForConfigCheck(log);
183
+ const config = { ...createConfig(), enableHistory: 'invalid' };
184
+
185
+ assert.equal(platform['checkConfig'](config), true);
186
+ assert.equal(config.enableHistory, true);
187
+ });
188
+ });