daikin-local-control 0.2.0 → 0.3.0
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/DESIGN.md +52 -0
- package/LICENSE +21 -674
- package/README.md +45 -3
- package/UNSUPPORTED.md +10 -1
- package/dist/clients/classic.d.ts +22 -4
- package/dist/clients/classic.d.ts.map +1 -1
- package/dist/clients/classic.js +55 -8
- package/dist/clients/classic.js.map +1 -1
- package/dist/clients/client.d.ts +11 -2
- package/dist/clients/client.d.ts.map +1 -1
- package/dist/clients/dsiot.d.ts +10 -3
- package/dist/clients/dsiot.d.ts.map +1 -1
- package/dist/clients/dsiot.js +40 -5
- package/dist/clients/dsiot.js.map +1 -1
- package/dist/clients/setStateCache.d.ts +15 -0
- package/dist/clients/setStateCache.d.ts.map +1 -0
- package/dist/clients/setStateCache.js +26 -0
- package/dist/clients/setStateCache.js.map +1 -0
- package/dist/codecs/classic/capabilities.d.ts.map +1 -1
- package/dist/codecs/classic/capabilities.js +28 -1
- package/dist/codecs/classic/capabilities.js.map +1 -1
- package/dist/codecs/classic/extendedControl.d.ts +14 -1
- package/dist/codecs/classic/extendedControl.d.ts.map +1 -1
- package/dist/codecs/classic/extendedControl.js +39 -4
- package/dist/codecs/classic/extendedControl.js.map +1 -1
- package/dist/codecs/classic/keyValue.d.ts +3 -0
- package/dist/codecs/classic/keyValue.d.ts.map +1 -1
- package/dist/codecs/classic/keyValue.js +10 -0
- package/dist/codecs/classic/keyValue.js.map +1 -1
- package/dist/codecs/classic/state.d.ts +3 -2
- package/dist/codecs/classic/state.d.ts.map +1 -1
- package/dist/codecs/classic/state.js +14 -1
- package/dist/codecs/classic/state.js.map +1 -1
- package/dist/codecs/device.d.ts +10 -1
- package/dist/codecs/device.d.ts.map +1 -1
- package/dist/codecs/device.js +25 -10
- package/dist/codecs/device.js.map +1 -1
- package/dist/codecs/dsiot/capabilities.d.ts +4 -2
- package/dist/codecs/dsiot/capabilities.d.ts.map +1 -1
- package/dist/codecs/dsiot/capabilities.js +20 -4
- package/dist/codecs/dsiot/capabilities.js.map +1 -1
- package/dist/codecs/dsiot/device.d.ts +5 -0
- package/dist/codecs/dsiot/device.d.ts.map +1 -0
- package/dist/codecs/dsiot/device.js +14 -0
- package/dist/codecs/dsiot/device.js.map +1 -0
- package/dist/codecs/dsiot/multireq.d.ts +6 -4
- package/dist/codecs/dsiot/multireq.d.ts.map +1 -1
- package/dist/codecs/dsiot/multireq.js +9 -4
- package/dist/codecs/dsiot/multireq.js.map +1 -1
- package/dist/codecs/dsiot/state.d.ts +6 -2
- package/dist/codecs/dsiot/state.d.ts.map +1 -1
- package/dist/codecs/dsiot/state.js +12 -2
- package/dist/codecs/dsiot/state.js.map +1 -1
- package/dist/factory.d.ts +7 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +2 -2
- package/dist/factory.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/models/capabilities.d.ts +5 -1
- package/dist/models/capabilities.d.ts.map +1 -1
- package/dist/models/device.d.ts +12 -1
- package/dist/models/device.d.ts.map +1 -1
- package/dist/models/extendedControl.d.ts +2 -3
- package/dist/models/extendedControl.d.ts.map +1 -1
- package/dist/models/extendedControl.js +0 -1
- package/dist/models/extendedControl.js.map +1 -1
- package/dist/models/state.d.ts +15 -4
- package/dist/models/state.d.ts.map +1 -1
- package/dist/models/state.js +1 -0
- package/dist/models/state.js.map +1 -1
- package/package.json +2 -2
- package/src/clients/classic.ts +76 -10
- package/src/clients/client.ts +13 -1
- package/src/clients/dsiot.ts +52 -9
- package/src/clients/setStateCache.ts +28 -0
- package/src/codecs/classic/capabilities.ts +39 -0
- package/src/codecs/classic/extendedControl.ts +56 -5
- package/src/codecs/classic/keyValue.ts +10 -0
- package/src/codecs/classic/state.ts +30 -12
- package/src/codecs/device.ts +35 -10
- package/src/codecs/dsiot/capabilities.ts +27 -2
- package/src/codecs/dsiot/device.ts +20 -0
- package/src/codecs/dsiot/multireq.ts +9 -4
- package/src/codecs/dsiot/state.ts +16 -1
- package/src/factory.ts +17 -2
- package/src/index.ts +1 -0
- package/src/models/capabilities.ts +5 -0
- package/src/models/device.ts +13 -1
- package/src/models/extendedControl.ts +2 -5
- package/src/models/state.ts +18 -4
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# daikin-local-control
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/daikin-local-control)
|
|
4
|
+
[](https://github.com/cheziyi/daikin-local-control/actions/workflows/ci.yml?query=branch%3Amain)
|
|
5
|
+
[](package.json)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
3
8
|
A TypeScript and Node.js client for controlling Daikin air conditioners **over
|
|
4
9
|
the local network** (LAN), through their Wi-Fi adapters and with no cloud
|
|
5
10
|
dependency. It implements the same local-control protocol as the **DAIKIN Mobile
|
|
@@ -69,7 +74,10 @@ await client.close();
|
|
|
69
74
|
### Discovery
|
|
70
75
|
|
|
71
76
|
`discoverDevices()` resolves with one `DaikinDevice` for each adapter that
|
|
72
|
-
answered, and with an empty array when none did.
|
|
77
|
+
answered, and with an empty array when none did. Each carries the adapter's
|
|
78
|
+
`macAddress`, such as `A4:08:EA:CC:91:D4`, and `firmwareVersion`, such as
|
|
79
|
+
`1.2.51`, when the adapter reports them: key a stored device on `macAddress`,
|
|
80
|
+
because `host` changes when the adapter is given a new address.
|
|
73
81
|
|
|
74
82
|
| It | So |
|
|
75
83
|
| --- | --- |
|
|
@@ -87,6 +95,9 @@ const device: DaikinDevice = { host: "192.168.1.50", protocol: "classic" };
|
|
|
87
95
|
const client = createDaikinClient(device, { terminalUuid: savedUuid });
|
|
88
96
|
```
|
|
89
97
|
|
|
98
|
+
A device written by hand has no `macAddress` or `firmwareVersion`: read them
|
|
99
|
+
from the adapter with `await client.getDeviceInfo()`.
|
|
100
|
+
|
|
90
101
|
Set `protocol` to `dsiot` for a BRP084 and to `classic` for every other
|
|
91
102
|
adapter. A device without flags is an adapter that requires neither
|
|
92
103
|
registration nor a child lock code. If yours requires either, set
|
|
@@ -108,7 +119,7 @@ again.
|
|
|
108
119
|
```ts
|
|
109
120
|
import { randomUUID } from "node:crypto";
|
|
110
121
|
|
|
111
|
-
const savedUuid =
|
|
122
|
+
const savedUuid = loadFromConfig() ?? saveToConfig(randomUUID());
|
|
112
123
|
```
|
|
113
124
|
|
|
114
125
|
**KEY (when `device.requiresRegistration` is `true`).** These
|
|
@@ -154,6 +165,7 @@ is not your Wi-Fi or Out-of-Home password. Pass it as `localPassword` to
|
|
|
154
165
|
| `swingMode` | `off`, `vertical`, `horizontal` or `both`: `vertical` moves the air up and down, `horizontal` left and right |
|
|
155
166
|
| `verticalPosition` | `stop`, `position1` to `position5`, `swing`, `naturalWind`, `auto` or `floorWarming`, or `null` where the unit reports none |
|
|
156
167
|
| `horizontalPosition` | `stop`, `position1` to `position5`, `swing` or `auto`, or `null` where the unit reports none |
|
|
168
|
+
| `specialModes` | Those of `powerful`, `econo` and `streamer` that are on, empty when none is |
|
|
157
169
|
|
|
158
170
|
`getCapabilities()` resolves with a `DaikinCapabilities`, which lists the
|
|
159
171
|
values this unit takes under the plural of the state field each one limits:
|
|
@@ -164,12 +176,17 @@ values this unit takes under the plural of the state field each one limits:
|
|
|
164
176
|
| `fanSpeeds`, `swingModes`, `verticalPositions`, `horizontalPositions` | The values the unit takes, empty when it has no such control |
|
|
165
177
|
| `targetTemperaturesInC` | For each mode, `{ min, max, step }` in °C, or `null` where the mode has no setpoint |
|
|
166
178
|
| `targetHumidities` | For each mode, the humidity settings it takes, empty where it takes none |
|
|
179
|
+
| `specialModes` | For each mode, the special modes the unit takes, empty where it takes none |
|
|
167
180
|
| `specialOutlet`, `energyMonitoring`, `demandControl`, `scheduleTimer` | `true` when the unit has the feature |
|
|
168
181
|
| `model` | The adapter's own code for the unit's model |
|
|
169
182
|
|
|
170
183
|
`getSensors()` resolves with `indoorTemperatureInC`, `outdoorTemperatureInC`
|
|
171
184
|
and `indoorHumidityInPercent`, each `null` when the unit does not report it.
|
|
172
185
|
|
|
186
|
+
Call `getStateAndSensors()` when you want both: it resolves with
|
|
187
|
+
`{ state, sensors }`, and a DSIOT adapter answers it in one request, where
|
|
188
|
+
`getState()` then `getSensors()` sends the same request twice.
|
|
189
|
+
|
|
173
190
|
### Changing state
|
|
174
191
|
|
|
175
192
|
Pass `setState()` only the fields to change: a field left out keeps the value
|
|
@@ -186,6 +203,24 @@ given, whether or not the unit lists it.
|
|
|
186
203
|
| `fanSpeed` | In `dehumidify`, and on a DSIOT adapter in `cool` while a humidity setting is on: the fan runs on `auto` |
|
|
187
204
|
| `verticalPosition`, `horizontalPosition` | On a classic adapter, when the unit has no 3D airflow. On a DSIOT adapter, a fixed vertical position the unit lacks, and every fixed horizontal position |
|
|
188
205
|
|
|
206
|
+
`setState()` takes no `specialModes`: turn one on or off with
|
|
207
|
+
[`setSpecialMode()`](#extended-controls), which only a classic adapter has.
|
|
208
|
+
|
|
209
|
+
Pass `maxStateAgeForSetStateInMs` to `createDaikinClient` when you poll the
|
|
210
|
+
state anyway: `setState()` reads the unit before each write, and with it builds
|
|
211
|
+
the write from a `getState()` or `getStateAndSensors()` reply younger than that
|
|
212
|
+
instead. It changes no read: `getState()` asks the unit every time.
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
const client = createDaikinClient(device, {
|
|
216
|
+
terminalUuid: savedUuid,
|
|
217
|
+
maxStateAgeForSetStateInMs: 30_000, // your poll interval, in milliseconds
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
The write undoes a change made on the remote control since that reply:
|
|
222
|
+
[DESIGN.md](DESIGN.md#the-read-before-a-write) says how.
|
|
223
|
+
|
|
189
224
|
### Extended controls
|
|
190
225
|
|
|
191
226
|
Beyond core climate, `ClassicDaikinClient` exposes the adapter's other `set_*`
|
|
@@ -217,6 +252,13 @@ if (client instanceof ClassicDaikinClient) {
|
|
|
217
252
|
}
|
|
218
253
|
```
|
|
219
254
|
|
|
255
|
+
Read a setting back with the matching `get` method:
|
|
256
|
+
|
|
257
|
+
| Method | Resolves with |
|
|
258
|
+
| --- | --- |
|
|
259
|
+
| `getLed()`, `getHolidayMode()`, `getOutOfHomeAccess()` | `true` or `false`, or `null` when the adapter does not report it |
|
|
260
|
+
| `getMetadata()` | `{ name, icon, group }`, without the fields the adapter does not report |
|
|
261
|
+
|
|
220
262
|
[UNSUPPORTED.md](UNSUPPORTED.md) lists the endpoints without a typed method and
|
|
221
263
|
what is not known about each.
|
|
222
264
|
|
|
@@ -331,4 +373,4 @@ your own risk.
|
|
|
331
373
|
|
|
332
374
|
## License
|
|
333
375
|
|
|
334
|
-
[
|
|
376
|
+
[MIT](LICENSE). Copyright © 2026 the contributors.
|
package/UNSUPPORTED.md
CHANGED
|
@@ -17,7 +17,16 @@ To add one, pin down the request and reply first, then delete its row.
|
|
|
17
17
|
| Classic schedule demand mode (`mode=1`) | The full format of the weekly table it needs (`moc`..`suc`, `<day><n>_en`/`_t`/`_p`). | `ClassicDaikinClient.command()` |
|
|
18
18
|
| Classic special mode `spmode_kind=4` (heat plus) | Which units take it. | `ClassicDaikinClient.command()` |
|
|
19
19
|
| Timers, weekly programs, schedule timers (`/aircon/get_timer`, `set_timer`, `get_program`, `set_program`, `get_scdltimer_info`, `get_scdltimer_body`, `set_scdltimer_info`, `set_scdltimer_body`) | Their parameters. | `ClassicDaikinClient.command()` |
|
|
20
|
-
| Classic setting reads: `/aircon/get_demand_control`, `/aircon/get_price`, `/aircon/get_target`, `/common/get_holiday` | The reply fields. | `ClassicDaikinClient.command()` |
|
|
20
|
+
| Classic setting reads: `/aircon/get_demand_control`, `/aircon/get_price`, `/aircon/get_target`, `/common/get_holiday` | The reply fields. `getHolidayMode` reads `/common/basic_info` instead. | `ClassicDaikinClient.command()` |
|
|
21
|
+
| Classic `method` in `/common/get_remote_method` | Whether the reply carries it. `getOutOfHomeAccess` reads `/common/basic_info` instead. | `ClassicDaikinClient.command()` |
|
|
22
|
+
| Energy history: classic `/aircon/get_week_power`, `get_year_power`, `get_day_power_ex`, `get_week_power_ex`, `get_year_power_ex`, and DSIOT `adr_0100.history` | The unit of each value, and which day or month each position in a list stands for. | `ClassicDaikinClient.command()` |
|
|
23
|
+
| Power draw: classic `mompow` in `/aircon/get_sensor_info`, DSIOT `dgc_status.e_1003.e_A005.p_01` | The unit. | `ClassicDaikinClient.command()`, `DsiotDaikinClient.multireqGet()` |
|
|
24
|
+
| Compressor frequency: classic `cmpfreq` in `/aircon/get_sensor_info`, DSIOT `dgc_status.e_1003.e_2006.p_04` | The unit. | `ClassicDaikinClient.command()`, `DsiotDaikinClient.multireqGet()` |
|
|
25
|
+
| Error code: classic `err` in `/aircon/get_sensor_info` and `/common/basic_info` | Which code on the unit's display each number stands for. | `ClassicDaikinClient.command()` |
|
|
26
|
+
| Reading the settings of a DSIOT adapter: LED, holiday mode, name, icon, group | The value encoding of each `adp_d` leaf. | `DsiotDaikinClient.multireqGet()` |
|
|
27
|
+
| Special modes through `setState`, and on a DSIOT adapter at all | Whether a DSIOT adapter accepts a write to the leaves `getState` reads, and which value turns a mode on. | `ClassicDaikinClient.setSpecialMode()`, `DsiotDaikinClient.multireqUpdate()` |
|
|
28
|
+
| Classic `powerful` and `econo` on a unit whose `cpv` is not 3, or whose `cpv_minor` is `00` or missing | Whether such a unit takes them. `getCapabilities` lists neither for it, whatever its `en_spmode`. | `ClassicDaikinClient.setSpecialMode()` |
|
|
29
|
+
| `econo` in fan mode | Whether a unit takes it. `getCapabilities` lists it in every mode but fan. | `ClassicDaikinClient.setSpecialMode()` |
|
|
21
30
|
| Classic notifications, clock and account: `/common/get_notify`, `set_notify`, `set_push_notice`, `set_timezone`, `notify_date_time`, `set_account` | Their parameters. | `ClassicDaikinClient.command()` |
|
|
22
31
|
| Classic network: `/common/get_network_setting`, `set_network_setting`, `start_wifi_scan`, `get_wifi_scan_result`, `start_wifi_connection`, `permit_wifi_connection`, `set_lpw` | Their parameters. | `ClassicDaikinClient.command()` |
|
|
23
32
|
| Classic firmware update: a POST to `/dkac/system/fwupdate` | The format of the upload. | Not reachable |
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { DaikinCapabilities } from "../models/capabilities.js";
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
2
|
+
import type { DaikinDeviceInfo } from "../models/device.js";
|
|
3
|
+
import type { DemandControl, DeviceMetadata, TerminalScope } from "../models/extendedControl.js";
|
|
4
|
+
import type { DaikinControl, DaikinSensors, DaikinState, DaikinStateAndSensors, SpecialMode } from "../models/state.js";
|
|
4
5
|
import { type DaikinRequestOptions, type DaikinRetryOptions, type DaikinTransport } from "../transport.js";
|
|
5
6
|
import type { DaikinClient } from "./client.js";
|
|
6
7
|
/** Classic CGI adapter (BRP069-style). Reads and writes are HTTP GET with query
|
|
@@ -9,21 +10,35 @@ export declare class ClassicDaikinClient implements DaikinClient {
|
|
|
9
10
|
private readonly transport;
|
|
10
11
|
private readonly retryOptions?;
|
|
11
12
|
private capabilityFields;
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
private readonly setStateCache;
|
|
14
|
+
/** `close` closes `transport`, so give each client a transport of its own.
|
|
15
|
+
* `maxStateAgeForSetStateInMs` defaults to 0: see
|
|
16
|
+
* `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
|
|
17
|
+
constructor(transport: DaikinTransport, retryOptions?: DaikinRetryOptions | undefined, maxStateAgeForSetStateInMs?: number);
|
|
14
18
|
close(): Promise<void>;
|
|
19
|
+
getDeviceInfo(): Promise<DaikinDeviceInfo>;
|
|
15
20
|
getCapabilities(): Promise<DaikinCapabilities>;
|
|
16
21
|
getState(): Promise<DaikinState>;
|
|
17
22
|
setState(control: DaikinControl): Promise<void>;
|
|
18
23
|
getSensors(): Promise<DaikinSensors>;
|
|
24
|
+
getStateAndSensors(): Promise<DaikinStateAndSensors>;
|
|
25
|
+
/** Whether the adapter's status LED is on (`basic_info`): `null` when the
|
|
26
|
+
* adapter does not report it. */
|
|
27
|
+
getLed(): Promise<boolean | null>;
|
|
19
28
|
/** Adapter status LED on/off (`set_led`). */
|
|
20
29
|
setLed(on: boolean): Promise<void>;
|
|
30
|
+
/** Whether holiday mode is on (`basic_info`): `null` when the adapter does
|
|
31
|
+
* not report it. */
|
|
32
|
+
getHolidayMode(): Promise<boolean | null>;
|
|
21
33
|
/** Holiday / away mode (`set_holiday`). */
|
|
22
34
|
setHolidayMode(enabled: boolean): Promise<void>;
|
|
23
35
|
/** Demand control — cap the unit's power draw (`set_demand_control`). */
|
|
24
36
|
setDemandControl(demand: DemandControl): Promise<void>;
|
|
25
37
|
/** Powerful, econo or streamer (`set_special_mode`). */
|
|
26
38
|
setSpecialMode(mode: SpecialMode, enabled: boolean): Promise<void>;
|
|
39
|
+
/** Whether the unit can be operated from outside the home network
|
|
40
|
+
* (`basic_info`): `null` when the adapter does not report it. */
|
|
41
|
+
getOutOfHomeAccess(): Promise<boolean | null>;
|
|
27
42
|
/** Whether the unit can be operated from outside the home network
|
|
28
43
|
* (`set_remote_method`). */
|
|
29
44
|
setOutOfHomeAccess(enabled: boolean): Promise<void>;
|
|
@@ -32,6 +47,8 @@ export declare class ClassicDaikinClient implements DaikinClient {
|
|
|
32
47
|
setEnergyPrice(price: number): Promise<void>;
|
|
33
48
|
/** Energy target for the "target" feature (`set_target`). */
|
|
34
49
|
setEnergyTarget(target: number): Promise<void>;
|
|
50
|
+
/** Name / icon / group metadata (`basic_info`). */
|
|
51
|
+
getMetadata(): Promise<DeviceMetadata>;
|
|
35
52
|
/** Name / icon / group metadata (`set_name` etc.). */
|
|
36
53
|
setMetadata(metadata: DeviceMetadata): Promise<void>;
|
|
37
54
|
/** Register this client's uuid with an adapter whose
|
|
@@ -48,6 +65,7 @@ export declare class ClassicDaikinClient implements DaikinClient {
|
|
|
48
65
|
* timers, schedules, programs, network, credentials and firmware. It throws
|
|
49
66
|
* a `DaikinError` when the reply's `ret` is not `OK`. */
|
|
50
67
|
command(path: string, parameters?: Record<string, string>, { retry }?: DaikinRequestOptions): Promise<Record<string, string>>;
|
|
68
|
+
private readControlInfo;
|
|
51
69
|
private readCapabilityFields;
|
|
52
70
|
}
|
|
53
71
|
//# sourceMappingURL=classic.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classic.d.ts","sourceRoot":"","sources":["../../src/clients/classic.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"classic.d.ts","sourceRoot":"","sources":["../../src/clients/classic.ts"],"names":[],"mappings":"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"}
|
package/dist/clients/classic.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { mergeClassicCapabilityFields, parseClassicCapabilities, } from "../codecs/classic/capabilities.js";
|
|
2
|
-
import { applyClassicOutOfHomeAccess, encodeClassicDemandControl, encodeClassicEnergyPrice, encodeClassicEnergyTarget, encodeClassicGroup, encodeClassicHolidayMode, encodeClassicIcon, encodeClassicLed, encodeClassicName, encodeClassicSpecialMode, encodeClassicTerminalKey, encodeClassicTerminalScope, } from "../codecs/classic/extendedControl.js";
|
|
2
|
+
import { applyClassicOutOfHomeAccess, encodeClassicDemandControl, encodeClassicEnergyPrice, encodeClassicEnergyTarget, encodeClassicGroup, encodeClassicHolidayMode, encodeClassicIcon, encodeClassicLed, encodeClassicName, encodeClassicSpecialMode, encodeClassicTerminalKey, encodeClassicTerminalScope, parseClassicHolidayMode, parseClassicLed, parseClassicMetadata, parseClassicOutOfHomeAccess, } from "../codecs/classic/extendedControl.js";
|
|
3
3
|
import { assertClassicOk, parseClassicKeyValue, } from "../codecs/classic/keyValue.js";
|
|
4
4
|
import { applyClassicControl, parseClassicSensors, parseClassicState, } from "../codecs/classic/state.js";
|
|
5
|
+
import { parseDeviceInfo } from "../codecs/device.js";
|
|
5
6
|
import { withRetry, } from "../transport.js";
|
|
7
|
+
import { SetStateCache } from "./setStateCache.js";
|
|
6
8
|
// Classic CGI endpoints (BRP069-style). Reads and writes are both HTTP GET with
|
|
7
9
|
// query parameters; the reply is `key=value,key=value`.
|
|
8
10
|
const CLASSIC_ROUTES = {
|
|
@@ -34,34 +36,55 @@ export class ClassicDaikinClient {
|
|
|
34
36
|
// A unit's capabilities don't change, and `setState` needs them, so they are
|
|
35
37
|
// read once.
|
|
36
38
|
capabilityFields;
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
setStateCache;
|
|
40
|
+
/** `close` closes `transport`, so give each client a transport of its own.
|
|
41
|
+
* `maxStateAgeForSetStateInMs` defaults to 0: see
|
|
42
|
+
* `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
|
|
43
|
+
constructor(transport, retryOptions, maxStateAgeForSetStateInMs = 0) {
|
|
39
44
|
this.transport = transport;
|
|
40
45
|
this.retryOptions = retryOptions;
|
|
46
|
+
this.setStateCache = new SetStateCache(maxStateAgeForSetStateInMs);
|
|
41
47
|
}
|
|
42
48
|
close() {
|
|
43
49
|
return this.transport.close();
|
|
44
50
|
}
|
|
51
|
+
async getDeviceInfo() {
|
|
52
|
+
return parseDeviceInfo(await this.command(CLASSIC_ROUTES.basicInfo));
|
|
53
|
+
}
|
|
45
54
|
async getCapabilities() {
|
|
46
55
|
return parseClassicCapabilities(await this.readCapabilityFields());
|
|
47
56
|
}
|
|
48
57
|
async getState() {
|
|
49
|
-
return parseClassicState(await this.
|
|
58
|
+
return parseClassicState(await this.readControlInfo());
|
|
50
59
|
}
|
|
51
60
|
async setState(control) {
|
|
52
61
|
const capabilityFields = await this.readCapabilityFields();
|
|
53
|
-
const current =
|
|
62
|
+
const current = this.setStateCache.get() ??
|
|
63
|
+
(await this.command(CLASSIC_ROUTES.getControlInfo));
|
|
54
64
|
await this.command(CLASSIC_ROUTES.setControlInfo, applyClassicControl(current, control, capabilityFields));
|
|
55
65
|
}
|
|
56
66
|
async getSensors() {
|
|
57
67
|
return parseClassicSensors(await this.command(CLASSIC_ROUTES.getSensorInfo));
|
|
58
68
|
}
|
|
69
|
+
async getStateAndSensors() {
|
|
70
|
+
return { state: await this.getState(), sensors: await this.getSensors() };
|
|
71
|
+
}
|
|
59
72
|
// --- extended controls ---------------------------------------------------
|
|
60
|
-
// Each
|
|
73
|
+
// Each write goes to its own endpoint, not `set_control_info`.
|
|
74
|
+
/** Whether the adapter's status LED is on (`basic_info`): `null` when the
|
|
75
|
+
* adapter does not report it. */
|
|
76
|
+
async getLed() {
|
|
77
|
+
return parseClassicLed(await this.command(CLASSIC_ROUTES.basicInfo));
|
|
78
|
+
}
|
|
61
79
|
/** Adapter status LED on/off (`set_led`). */
|
|
62
80
|
async setLed(on) {
|
|
63
81
|
await this.command(CLASSIC_ROUTES.setLed, encodeClassicLed(on));
|
|
64
82
|
}
|
|
83
|
+
/** Whether holiday mode is on (`basic_info`): `null` when the adapter does
|
|
84
|
+
* not report it. */
|
|
85
|
+
async getHolidayMode() {
|
|
86
|
+
return parseClassicHolidayMode(await this.command(CLASSIC_ROUTES.basicInfo));
|
|
87
|
+
}
|
|
65
88
|
/** Holiday / away mode (`set_holiday`). */
|
|
66
89
|
async setHolidayMode(enabled) {
|
|
67
90
|
await this.command(CLASSIC_ROUTES.setHoliday, encodeClassicHolidayMode(enabled));
|
|
@@ -74,6 +97,11 @@ export class ClassicDaikinClient {
|
|
|
74
97
|
async setSpecialMode(mode, enabled) {
|
|
75
98
|
await this.command(CLASSIC_ROUTES.setSpecialMode, encodeClassicSpecialMode(mode, enabled));
|
|
76
99
|
}
|
|
100
|
+
/** Whether the unit can be operated from outside the home network
|
|
101
|
+
* (`basic_info`): `null` when the adapter does not report it. */
|
|
102
|
+
async getOutOfHomeAccess() {
|
|
103
|
+
return parseClassicOutOfHomeAccess(await this.command(CLASSIC_ROUTES.basicInfo));
|
|
104
|
+
}
|
|
77
105
|
/** Whether the unit can be operated from outside the home network
|
|
78
106
|
* (`set_remote_method`). */
|
|
79
107
|
async setOutOfHomeAccess(enabled) {
|
|
@@ -89,6 +117,10 @@ export class ClassicDaikinClient {
|
|
|
89
117
|
async setEnergyTarget(target) {
|
|
90
118
|
await this.command(CLASSIC_ROUTES.setTarget, encodeClassicEnergyTarget(target));
|
|
91
119
|
}
|
|
120
|
+
/** Name / icon / group metadata (`basic_info`). */
|
|
121
|
+
async getMetadata() {
|
|
122
|
+
return parseClassicMetadata(await this.command(CLASSIC_ROUTES.basicInfo));
|
|
123
|
+
}
|
|
92
124
|
/** Name / icon / group metadata (`set_name` etc.). */
|
|
93
125
|
async setMetadata(metadata) {
|
|
94
126
|
if (metadata.name !== undefined) {
|
|
@@ -126,8 +158,23 @@ export class ClassicDaikinClient {
|
|
|
126
158
|
path,
|
|
127
159
|
...(parameters ? { query: parameters } : {}),
|
|
128
160
|
});
|
|
129
|
-
|
|
130
|
-
|
|
161
|
+
try {
|
|
162
|
+
const fields = parseClassicKeyValue(await (retry ? withRetry(send, this.retryOptions) : send()));
|
|
163
|
+
assertClassicOk(fields);
|
|
164
|
+
return fields;
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
// Every request that changes the unit takes parameters, and any of them
|
|
168
|
+
// may change what `get_control_info` answers, even one that failed: a
|
|
169
|
+
// request that timed out may still have reached the unit.
|
|
170
|
+
if (parameters) {
|
|
171
|
+
this.setStateCache.clear();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
async readControlInfo() {
|
|
176
|
+
const fields = await this.command(CLASSIC_ROUTES.getControlInfo);
|
|
177
|
+
this.setStateCache.set(fields);
|
|
131
178
|
return fields;
|
|
132
179
|
}
|
|
133
180
|
readCapabilityFields() {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classic.js","sourceRoot":"","sources":["../../src/clients/classic.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,wBAAwB,GACzB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EACL,2BAA2B,EAC3B,0BAA0B,EAC1B,wBAAwB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,wBAAwB,EACxB,0BAA0B,
|
|
1
|
+
{"version":3,"file":"classic.js","sourceRoot":"","sources":["../../src/clients/classic.ts"],"names":[],"mappings":"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"}
|
package/dist/clients/client.d.ts
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
import type { DaikinCapabilities } from "../models/capabilities.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { DaikinDeviceInfo } from "../models/device.js";
|
|
3
|
+
import type { DaikinControl, DaikinSensors, DaikinState, DaikinStateAndSensors } from "../models/state.js";
|
|
3
4
|
/** The controls every adapter offers, whatever its wire protocol or
|
|
4
5
|
* authentication. `createDaikinClient` picks the implementation, so a caller
|
|
5
6
|
* needs the concrete class only for what one protocol adds, such as
|
|
6
7
|
* `ClassicDaikinClient.registerTerminal`. Every method rejects with a
|
|
7
8
|
* `DaikinError` when its request fails. */
|
|
8
9
|
export interface DaikinClient {
|
|
10
|
+
/** The adapter's MAC address and firmware version. */
|
|
11
|
+
getDeviceInfo(): Promise<DaikinDeviceInfo>;
|
|
9
12
|
/** The unit's supported features. */
|
|
10
13
|
getCapabilities(): Promise<DaikinCapabilities>;
|
|
11
14
|
/** Current controllable state. */
|
|
12
15
|
getState(): Promise<DaikinState>;
|
|
13
16
|
/** Change part of the state. The client reads the current state, overlays the
|
|
14
|
-
* control, and writes the whole thing back.
|
|
17
|
+
* control, and writes the whole thing back. It skips the read when it holds
|
|
18
|
+
* a reply to `getState` or `getStateAndSensors` younger than
|
|
19
|
+
* `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
|
|
15
20
|
setState(control: DaikinControl): Promise<void>;
|
|
16
21
|
/** Read-only temperature / humidity readings. */
|
|
17
22
|
getSensors(): Promise<DaikinSensors>;
|
|
23
|
+
/** What `getState` and `getSensors` resolve with, together. A DSIOT adapter
|
|
24
|
+
* answers both in one request, where calling the two sends the same request
|
|
25
|
+
* twice. A classic adapter takes one request for each. */
|
|
26
|
+
getStateAndSensors(): Promise<DaikinStateAndSensors>;
|
|
18
27
|
/** Close the connection to the adapter. */
|
|
19
28
|
close(): Promise<void>;
|
|
20
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/clients/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/clients/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAE5B;;;;2CAI2C;AAC3C,MAAM,WAAW,YAAY;IAC3B,sDAAsD;IACtD,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAE3C,qCAAqC;IACrC,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAE/C,kCAAkC;IAClC,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;IAEjC;;;iEAG6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEhD,iDAAiD;IACjD,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAAC;IAErC;;8DAE0D;IAC1D,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAErD,2CAA2C;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
|
package/dist/clients/dsiot.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { type DsiotUpdate } from "../codecs/dsiot/multireq.js";
|
|
2
2
|
import type { DaikinCapabilities } from "../models/capabilities.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { DaikinDeviceInfo } from "../models/device.js";
|
|
4
|
+
import type { DaikinControl, DaikinSensors, DaikinState, DaikinStateAndSensors } from "../models/state.js";
|
|
4
5
|
import { type DaikinRequestOptions, type DaikinRetryOptions, type DaikinTransport } from "../transport.js";
|
|
5
6
|
import type { DaikinClient } from "./client.js";
|
|
6
7
|
/** DSIOT adapter (BRP084-style). One endpoint, `/dsiot/multireq`: POST to read
|
|
@@ -8,13 +9,18 @@ import type { DaikinClient } from "./client.js";
|
|
|
8
9
|
export declare class DsiotDaikinClient implements DaikinClient {
|
|
9
10
|
private readonly transport;
|
|
10
11
|
private readonly retryOptions?;
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
private readonly setStateCache;
|
|
13
|
+
/** `close` closes `transport`, so give each client a transport of its own.
|
|
14
|
+
* `maxStateAgeForSetStateInMs` defaults to 0: see
|
|
15
|
+
* `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
|
|
16
|
+
constructor(transport: DaikinTransport, retryOptions?: DaikinRetryOptions | undefined, maxStateAgeForSetStateInMs?: number);
|
|
13
17
|
close(): Promise<void>;
|
|
18
|
+
getDeviceInfo(): Promise<DaikinDeviceInfo>;
|
|
14
19
|
getCapabilities(): Promise<DaikinCapabilities>;
|
|
15
20
|
getState(): Promise<DaikinState>;
|
|
16
21
|
setState(control: DaikinControl): Promise<void>;
|
|
17
22
|
getSensors(): Promise<DaikinSensors>;
|
|
23
|
+
getStateAndSensors(): Promise<DaikinStateAndSensors>;
|
|
18
24
|
/** Reboot the adapter (`/config/system/reboot`). */
|
|
19
25
|
reboot(): Promise<void>;
|
|
20
26
|
/** Raw multireq read of whole resources (`DSIOT_TARGETS` values or any `to`),
|
|
@@ -24,5 +30,6 @@ export declare class DsiotDaikinClient implements DaikinClient {
|
|
|
24
30
|
* on the indoor edge. Returns the reply, flattened as `multireqGet` does. */
|
|
25
31
|
multireqUpdate(updates: DsiotUpdate[], options?: DaikinRequestOptions): Promise<Record<string, string>>;
|
|
26
32
|
private multireq;
|
|
33
|
+
private readStatus;
|
|
27
34
|
}
|
|
28
35
|
//# sourceMappingURL=dsiot.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dsiot.d.ts","sourceRoot":"","sources":["../../src/clients/dsiot.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dsiot.d.ts","sourceRoot":"","sources":["../../src/clients/dsiot.ts"],"names":[],"mappings":"AAEA,OAAO,EAIL,KAAK,WAAW,EAEjB,MAAM,6BAA6B,CAAC;AAMrC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EAErB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUhD;6DAC6D;AAC7D,qBAAa,iBAAkB,YAAW,YAAY;IAOlD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IAPhC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAgB;IAE9C;;iEAE6D;IAC7D,YACmB,SAAS,EAAE,eAAe,EAC1B,YAAY,CAAC,EAAE,kBAAkB,YAAA,EAClD,0BAA0B,SAAI,EAG/B;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;IAEK,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC,CAI/C;IAEK,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAQnD;IAEK,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC,CAErC;IAEK,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpD;IAEK,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAOzC;IAEK,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAMzD;IAID,oDAAoD;IAC9C,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAK5B;IAED;4CACwC;IAClC,WAAW,CACf,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAEjC;IAED;iFAC6E;IACvE,cAAc,CAClB,OAAO,EAAE,WAAW,EAAE,EACtB,OAAO,CAAC,EAAE,oBAAoB,GAC7B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAEjC;YAEa,QAAQ;YAoBR,UAAU;CAQzB"}
|
package/dist/clients/dsiot.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { parseDsiotCapabilities } from "../codecs/dsiot/capabilities.js";
|
|
2
|
+
import { parseDsiotDeviceInfo } from "../codecs/dsiot/device.js";
|
|
2
3
|
import { buildDsiotMultireqGet, buildDsiotMultireqUpdate, DSIOT_TARGETS, parseDsiotMultireqReply, } from "../codecs/dsiot/multireq.js";
|
|
3
4
|
import { applyDsiotControl, parseDsiotSensors, parseDsiotState, } from "../codecs/dsiot/state.js";
|
|
4
5
|
import { withRetry, } from "../transport.js";
|
|
6
|
+
import { SetStateCache } from "./setStateCache.js";
|
|
5
7
|
// DSIOT endpoints (BRP084-style). Climate state is a POST (read) or PUT (write)
|
|
6
8
|
// of a JSON property tree to `multireq`.
|
|
7
9
|
const DSIOT_ROUTES = {
|
|
@@ -13,25 +15,34 @@ const DSIOT_ROUTES = {
|
|
|
13
15
|
export class DsiotDaikinClient {
|
|
14
16
|
transport;
|
|
15
17
|
retryOptions;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
setStateCache;
|
|
19
|
+
/** `close` closes `transport`, so give each client a transport of its own.
|
|
20
|
+
* `maxStateAgeForSetStateInMs` defaults to 0: see
|
|
21
|
+
* `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
|
|
22
|
+
constructor(transport, retryOptions, maxStateAgeForSetStateInMs = 0) {
|
|
18
23
|
this.transport = transport;
|
|
19
24
|
this.retryOptions = retryOptions;
|
|
25
|
+
this.setStateCache = new SetStateCache(maxStateAgeForSetStateInMs);
|
|
20
26
|
}
|
|
21
27
|
close() {
|
|
22
28
|
return this.transport.close();
|
|
23
29
|
}
|
|
30
|
+
async getDeviceInfo() {
|
|
31
|
+
return parseDsiotDeviceInfo(await this.multireqGet([DSIOT_TARGETS.adapterInfo]));
|
|
32
|
+
}
|
|
24
33
|
async getCapabilities() {
|
|
25
34
|
return parseDsiotCapabilities(await this.multireqGet([
|
|
26
35
|
DSIOT_TARGETS.adapterInfo,
|
|
27
36
|
DSIOT_TARGETS.indoorStatus,
|
|
37
|
+
DSIOT_TARGETS.outdoorStatus,
|
|
28
38
|
]));
|
|
29
39
|
}
|
|
30
40
|
async getState() {
|
|
31
|
-
return parseDsiotState(await this.
|
|
41
|
+
return parseDsiotState(await this.readStatus());
|
|
32
42
|
}
|
|
33
43
|
async setState(control) {
|
|
34
|
-
const values =
|
|
44
|
+
const values = this.setStateCache.get() ??
|
|
45
|
+
(await this.multireqGet([DSIOT_TARGETS.indoorStatus]));
|
|
35
46
|
await this.multireqUpdate(applyDsiotControl(values, control));
|
|
36
47
|
}
|
|
37
48
|
async getSensors() {
|
|
@@ -40,6 +51,13 @@ export class DsiotDaikinClient {
|
|
|
40
51
|
DSIOT_TARGETS.outdoorStatus,
|
|
41
52
|
]));
|
|
42
53
|
}
|
|
54
|
+
async getStateAndSensors() {
|
|
55
|
+
const values = await this.readStatus();
|
|
56
|
+
return {
|
|
57
|
+
state: parseDsiotState(values),
|
|
58
|
+
sensors: parseDsiotSensors(values),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
43
61
|
// --- extended controls ---------------------------------------------------
|
|
44
62
|
/** Reboot the adapter (`/config/system/reboot`). */
|
|
45
63
|
async reboot() {
|
|
@@ -60,7 +78,24 @@ export class DsiotDaikinClient {
|
|
|
60
78
|
}
|
|
61
79
|
async multireq(method, jsonBody, { retry = true } = {}) {
|
|
62
80
|
const send = () => this.transport.send({ method, path: DSIOT_ROUTES.multireq, jsonBody });
|
|
63
|
-
|
|
81
|
+
try {
|
|
82
|
+
return parseDsiotMultireqReply(await (retry ? withRetry(send, this.retryOptions) : send()));
|
|
83
|
+
}
|
|
84
|
+
finally {
|
|
85
|
+
// Even a write that failed: one that timed out may still have reached
|
|
86
|
+
// the unit.
|
|
87
|
+
if (method === "PUT") {
|
|
88
|
+
this.setStateCache.clear();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
async readStatus() {
|
|
93
|
+
const values = await this.multireqGet([
|
|
94
|
+
DSIOT_TARGETS.indoorStatus,
|
|
95
|
+
DSIOT_TARGETS.outdoorStatus,
|
|
96
|
+
]);
|
|
97
|
+
this.setStateCache.set(values);
|
|
98
|
+
return values;
|
|
64
99
|
}
|
|
65
100
|
}
|
|
66
101
|
//# sourceMappingURL=dsiot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dsiot.js","sourceRoot":"","sources":["../../src/clients/dsiot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzE,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,aAAa,EAEb,uBAAuB,GACxB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"dsiot.js","sourceRoot":"","sources":["../../src/clients/dsiot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** Caches the reply a client last read a unit's state from, for `setState`
|
|
2
|
+
* alone. A write carries more than the fields a control changes, so
|
|
3
|
+
* `setState` builds it from what the unit holds: from this reply while it is
|
|
4
|
+
* fresh, and from a read of its own otherwise. No read is answered from the
|
|
5
|
+
* cache: see DESIGN.md#the-read-before-a-write. */
|
|
6
|
+
export declare class SetStateCache {
|
|
7
|
+
private readonly maxAgeInMs;
|
|
8
|
+
private kept;
|
|
9
|
+
/** `get` answers a reply younger than `maxAgeInMs`, so 0 answers none. */
|
|
10
|
+
constructor(maxAgeInMs: number);
|
|
11
|
+
set(reply: Record<string, string>): void;
|
|
12
|
+
get(): Record<string, string> | undefined;
|
|
13
|
+
clear(): void;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=setStateCache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setStateCache.d.ts","sourceRoot":"","sources":["../../src/clients/setStateCache.ts"],"names":[],"mappings":"AAAA;;;;mDAImD;AACnD,qBAAa,aAAa;IAMZ,OAAO,CAAC,QAAQ,CAAC,UAAU;IALvC,OAAO,CAAC,IAAI,CAEE;IAEd,0EAA0E;IAC1E,YAA6B,UAAU,EAAE,MAAM,EAAI;IAEnD,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAEvC;IAED,GAAG,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAKxC;IAED,KAAK,IAAI,IAAI,CAEZ;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** Caches the reply a client last read a unit's state from, for `setState`
|
|
2
|
+
* alone. A write carries more than the fields a control changes, so
|
|
3
|
+
* `setState` builds it from what the unit holds: from this reply while it is
|
|
4
|
+
* fresh, and from a read of its own otherwise. No read is answered from the
|
|
5
|
+
* cache: see DESIGN.md#the-read-before-a-write. */
|
|
6
|
+
export class SetStateCache {
|
|
7
|
+
maxAgeInMs;
|
|
8
|
+
kept;
|
|
9
|
+
/** `get` answers a reply younger than `maxAgeInMs`, so 0 answers none. */
|
|
10
|
+
constructor(maxAgeInMs) {
|
|
11
|
+
this.maxAgeInMs = maxAgeInMs;
|
|
12
|
+
}
|
|
13
|
+
set(reply) {
|
|
14
|
+
this.kept = { reply, readAtInMs: performance.now() };
|
|
15
|
+
}
|
|
16
|
+
get() {
|
|
17
|
+
return this.kept !== undefined &&
|
|
18
|
+
performance.now() - this.kept.readAtInMs < this.maxAgeInMs
|
|
19
|
+
? this.kept.reply
|
|
20
|
+
: undefined;
|
|
21
|
+
}
|
|
22
|
+
clear() {
|
|
23
|
+
this.kept = undefined;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=setStateCache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setStateCache.js","sourceRoot":"","sources":["../../src/clients/setStateCache.ts"],"names":[],"mappings":"AAAA;;;;mDAImD;AACnD,MAAM,OAAO,aAAa;IAMK,UAAU;IAL/B,IAAI,CAEE;IAEd,0EAA0E;IAC1E,YAA6B,UAAkB;0BAAlB,UAAU;IAAW,CAAC;IAEnD,GAAG,CAAC,KAA6B;QAC/B,IAAI,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC;IACvD,CAAC;IAED,GAAG;QACD,OAAO,IAAI,CAAC,IAAI,KAAK,SAAS;YAC5B,WAAW,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU;YAC1D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;YACjB,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/codecs/classic/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../../src/codecs/classic/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAEnB,MAAM,8BAA8B,CAAC;AAwDtC;;;;yBAIyB;AACzB,wBAAgB,4BAA4B,CAC1C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACjC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CASxB;AAED;;;qBAGqB;AACrB,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,kBAAkB,CAmCpB;AAyED;wEACwE;AACxE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAE5E;AAoCD;wCACwC;AACxC,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAY7E"}
|