daikin-local-control 0.2.1 → 0.3.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/DESIGN.md +52 -0
- package/README.md +39 -2
- 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 +43 -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 +11 -1
- package/dist/codecs/device.d.ts.map +1 -1
- package/dist/codecs/device.js +26 -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 +7 -0
- package/dist/codecs/dsiot/device.d.ts.map +1 -0
- package/dist/codecs/dsiot/device.js +18 -0
- package/dist/codecs/dsiot/device.js.map +1 -0
- package/dist/codecs/dsiot/multireq.d.ts +7 -4
- package/dist/codecs/dsiot/multireq.d.ts.map +1 -1
- package/dist/codecs/dsiot/multireq.js +10 -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 +15 -2
- 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 +1 -1
- package/src/clients/classic.ts +76 -10
- package/src/clients/client.ts +13 -1
- package/src/clients/dsiot.ts +55 -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 +36 -10
- package/src/codecs/dsiot/capabilities.ts +27 -2
- package/src/codecs/dsiot/device.ts +24 -0
- package/src/codecs/dsiot/multireq.ts +10 -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 +16 -2
- package/src/models/extendedControl.ts +2 -5
- package/src/models/state.ts +18 -4
package/DESIGN.md
CHANGED
|
@@ -23,6 +23,36 @@ one that landed changes nothing. `reboot()` passes `{ retry: false }`, as should
|
|
|
23
23
|
any caller of `command()`, `multireqGet()` or `multireqUpdate()` whose request
|
|
24
24
|
is not safe to repeat.
|
|
25
25
|
|
|
26
|
+
## The read before a write
|
|
27
|
+
|
|
28
|
+
`setState` takes only the fields to change, but a write carries more than
|
|
29
|
+
those. So `setState` first reads what the unit holds, and builds the write from
|
|
30
|
+
that reply:
|
|
31
|
+
|
|
32
|
+
| Adapter | A write carries | The reply supplies |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| Classic | Every control field the unit takes, on each `set_control_info`: `pow`, `mode`, `stemp`, `shum`, `f_rate` and the direction fields. Whether the adapter takes a request without one of them is not known, so none is left out. | Each field the control leaves out. On a mode change, the values the adapter remembers for the target mode: `dt3`, `dh3`, `dfr3` and `dfd3` for cool. |
|
|
35
|
+
| DSIOT | The power, the power transition and the mode on each write, then only the leaves the control changes | The power the unit holds, which decides the transition. The mode, when the control sets none. The `md` of the louver and humidity leaves, which a position and a percentage are encoded from. |
|
|
36
|
+
|
|
37
|
+
With `maxStateAgeForSetStateInMs` set, `setState` skips that read while the
|
|
38
|
+
client's `SetStateCache` holds a reply to `getState` or `getStateAndSensors`
|
|
39
|
+
younger than that. A caller that polls sets it to its poll interval, and a
|
|
40
|
+
write then costs one request where it cost two. No read is answered from the
|
|
41
|
+
cache: `getState` asks the unit every time.
|
|
42
|
+
|
|
43
|
+
The default is 0, because a write built from an old reply undoes a change made
|
|
44
|
+
on the remote control since that reply. Someone switches the unit to heat on
|
|
45
|
+
the remote, the caller sets 23 °C from a reply read before that, and the write
|
|
46
|
+
puts the unit back in cool.
|
|
47
|
+
|
|
48
|
+
Every write through the client clears the cache, `command()` with parameters
|
|
49
|
+
and `multireqUpdate()` included, so the `setState` after a write reads first.
|
|
50
|
+
|
|
51
|
+
Rejected: `setState` taking a whole `DaikinState` from the caller in place of
|
|
52
|
+
the read. A `DaikinState` holds the current mode's values alone: it has neither
|
|
53
|
+
the values a classic adapter remembers for the other modes nor the `md` of a
|
|
54
|
+
DSIOT leaf, so the client would still need the reply.
|
|
55
|
+
|
|
26
56
|
## Capabilities
|
|
27
57
|
|
|
28
58
|
`DaikinCapabilities` lists what a unit accepts in the vocabulary of `DaikinState`:
|
|
@@ -96,3 +126,25 @@ Rejected: positions as the numbers 0 to 25, typed `number`, with
|
|
|
96
126
|
- A caller learned of a mistyped number only when the call ran.
|
|
97
127
|
- The `Error` was the one failure of `setState` that was not a
|
|
98
128
|
`DaikinError`.
|
|
129
|
+
|
|
130
|
+
## Special modes
|
|
131
|
+
|
|
132
|
+
`DaikinState.specialModes` lists the special modes that are on, and `getState`
|
|
133
|
+
reads it on both protocols. `DaikinControl` leaves it out, so `setState` is
|
|
134
|
+
never handed a field it cannot write: UNSUPPORTED.md says what is not known.
|
|
135
|
+
|
|
136
|
+
Rejected: a `getSpecialModes` on `ClassicDaikinClient`, beside `setSpecialMode`.
|
|
137
|
+
|
|
138
|
+
- A classic adapter reports the modes in `adv`, in the `get_control_info` reply
|
|
139
|
+
`getState` already reads, so the method sent a second request for a reply the
|
|
140
|
+
caller had.
|
|
141
|
+
- A DSIOT adapter reports them in its `dgc_status` trees, and a method on
|
|
142
|
+
`ClassicDaikinClient` gave a caller no way to read those.
|
|
143
|
+
|
|
144
|
+
`DaikinCapabilities.specialModes` lists the special modes a unit takes mode by
|
|
145
|
+
mode, as `targetHumidities` does.
|
|
146
|
+
|
|
147
|
+
Rejected: one list for the whole unit.
|
|
148
|
+
|
|
149
|
+
- Econo is not known to be taken in fan mode, so the one list offered it in a
|
|
150
|
+
mode where UNSUPPORTED.md lists it as unknown.
|
package/README.md
CHANGED
|
@@ -74,7 +74,10 @@ await client.close();
|
|
|
74
74
|
### Discovery
|
|
75
75
|
|
|
76
76
|
`discoverDevices()` resolves with one `DaikinDevice` for each adapter that
|
|
77
|
-
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.
|
|
78
81
|
|
|
79
82
|
| It | So |
|
|
80
83
|
| --- | --- |
|
|
@@ -92,6 +95,9 @@ const device: DaikinDevice = { host: "192.168.1.50", protocol: "classic" };
|
|
|
92
95
|
const client = createDaikinClient(device, { terminalUuid: savedUuid });
|
|
93
96
|
```
|
|
94
97
|
|
|
98
|
+
A device written by hand has no `name`, `macAddress` or `firmwareVersion`: read
|
|
99
|
+
them from the adapter with `await client.getDeviceInfo()`.
|
|
100
|
+
|
|
95
101
|
Set `protocol` to `dsiot` for a BRP084 and to `classic` for every other
|
|
96
102
|
adapter. A device without flags is an adapter that requires neither
|
|
97
103
|
registration nor a child lock code. If yours requires either, set
|
|
@@ -113,7 +119,7 @@ again.
|
|
|
113
119
|
```ts
|
|
114
120
|
import { randomUUID } from "node:crypto";
|
|
115
121
|
|
|
116
|
-
const savedUuid =
|
|
122
|
+
const savedUuid = loadFromConfig() ?? saveToConfig(randomUUID());
|
|
117
123
|
```
|
|
118
124
|
|
|
119
125
|
**KEY (when `device.requiresRegistration` is `true`).** These
|
|
@@ -159,6 +165,7 @@ is not your Wi-Fi or Out-of-Home password. Pass it as `localPassword` to
|
|
|
159
165
|
| `swingMode` | `off`, `vertical`, `horizontal` or `both`: `vertical` moves the air up and down, `horizontal` left and right |
|
|
160
166
|
| `verticalPosition` | `stop`, `position1` to `position5`, `swing`, `naturalWind`, `auto` or `floorWarming`, or `null` where the unit reports none |
|
|
161
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 |
|
|
162
169
|
|
|
163
170
|
`getCapabilities()` resolves with a `DaikinCapabilities`, which lists the
|
|
164
171
|
values this unit takes under the plural of the state field each one limits:
|
|
@@ -169,12 +176,17 @@ values this unit takes under the plural of the state field each one limits:
|
|
|
169
176
|
| `fanSpeeds`, `swingModes`, `verticalPositions`, `horizontalPositions` | The values the unit takes, empty when it has no such control |
|
|
170
177
|
| `targetTemperaturesInC` | For each mode, `{ min, max, step }` in °C, or `null` where the mode has no setpoint |
|
|
171
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 |
|
|
172
180
|
| `specialOutlet`, `energyMonitoring`, `demandControl`, `scheduleTimer` | `true` when the unit has the feature |
|
|
173
181
|
| `model` | The adapter's own code for the unit's model |
|
|
174
182
|
|
|
175
183
|
`getSensors()` resolves with `indoorTemperatureInC`, `outdoorTemperatureInC`
|
|
176
184
|
and `indoorHumidityInPercent`, each `null` when the unit does not report it.
|
|
177
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
|
+
|
|
178
190
|
### Changing state
|
|
179
191
|
|
|
180
192
|
Pass `setState()` only the fields to change: a field left out keeps the value
|
|
@@ -191,6 +203,24 @@ given, whether or not the unit lists it.
|
|
|
191
203
|
| `fanSpeed` | In `dehumidify`, and on a DSIOT adapter in `cool` while a humidity setting is on: the fan runs on `auto` |
|
|
192
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 |
|
|
193
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
|
+
|
|
194
224
|
### Extended controls
|
|
195
225
|
|
|
196
226
|
Beyond core climate, `ClassicDaikinClient` exposes the adapter's other `set_*`
|
|
@@ -222,6 +252,13 @@ if (client instanceof ClassicDaikinClient) {
|
|
|
222
252
|
}
|
|
223
253
|
```
|
|
224
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
|
+
|
|
225
262
|
[UNSUPPORTED.md](UNSUPPORTED.md) lists the endpoints without a typed method and
|
|
226
263
|
what is not known about each.
|
|
227
264
|
|
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, 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":"AAgCA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,aAAa,EACb,cAAc,EACd,aAAa,EACd,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,WAAW,EACX,qBAAqB,EACrB,WAAW,EACZ,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;AA2BhD;oDACoD;AACpD,qBAAa,mBAAoB,YAAW,YAAY;IAUpD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;IARhC,OAAO,CAAC,gBAAgB,CAA8C;IACtE,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,CAE/C;IAEK,eAAe,IAAI,OAAO,CAAC,kBAAkB,CAAC,CAEnD;IAEK,QAAQ,IAAI,OAAO,CAAC,WAAW,CAAC,CAErC;IAEK,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CASpD;IAEK,UAAU,IAAI,OAAO,CAAC,aAAa,CAAC,CAIzC;IAEK,kBAAkB,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAEzD;IAKD;qCACiC;IAC3B,MAAM,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAEtC;IAED,6CAA6C;IACvC,MAAM,CAAC,EAAE,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvC;IAED;wBACoB;IACd,cAAc,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAI9C;IAED,2CAA2C;IACrC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAKpD;IAED,yEAAyE;IACnE,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAK3D;IAED,wDAAwD;IAClD,cAAc,CAAC,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAKvE;IAED;qEACiE;IAC3D,kBAAkB,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAIlD;IAED;gCAC4B;IACtB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxD;IAED;gCAC4B;IACtB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjD;IAED,6DAA6D;IACvD,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKnD;IAED,mDAAmD;IAC7C,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC,CAE3C;IAED,sDAAsD;IAChD,WAAW,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBzD;IAED;;+EAE2E;IACrE,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAKjD;IAED;+BAC2B;IACrB,kBAAkB,CAAC,KAAK,GAAE,aAAsB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKrE;IAED,qCAAqC;IAC/B,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAE5B;IAED;;;6DAGyD;IACnD,OAAO,CACX,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,EAAE,KAAY,EAAE,GAAE,oBAAyB,GAC1C,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAqBjC;YAEa,eAAe;IAM7B,OAAO,CAAC,oBAAoB;CAY7B"}
|
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 name, 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,4DAA4D;IAC5D,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,CAO/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,37 @@ 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([
|
|
32
|
+
DSIOT_TARGETS.adapterInfo,
|
|
33
|
+
DSIOT_TARGETS.adapterSettings,
|
|
34
|
+
]));
|
|
35
|
+
}
|
|
24
36
|
async getCapabilities() {
|
|
25
37
|
return parseDsiotCapabilities(await this.multireqGet([
|
|
26
38
|
DSIOT_TARGETS.adapterInfo,
|
|
27
39
|
DSIOT_TARGETS.indoorStatus,
|
|
40
|
+
DSIOT_TARGETS.outdoorStatus,
|
|
28
41
|
]));
|
|
29
42
|
}
|
|
30
43
|
async getState() {
|
|
31
|
-
return parseDsiotState(await this.
|
|
44
|
+
return parseDsiotState(await this.readStatus());
|
|
32
45
|
}
|
|
33
46
|
async setState(control) {
|
|
34
|
-
const values =
|
|
47
|
+
const values = this.setStateCache.get() ??
|
|
48
|
+
(await this.multireqGet([DSIOT_TARGETS.indoorStatus]));
|
|
35
49
|
await this.multireqUpdate(applyDsiotControl(values, control));
|
|
36
50
|
}
|
|
37
51
|
async getSensors() {
|
|
@@ -40,6 +54,13 @@ export class DsiotDaikinClient {
|
|
|
40
54
|
DSIOT_TARGETS.outdoorStatus,
|
|
41
55
|
]));
|
|
42
56
|
}
|
|
57
|
+
async getStateAndSensors() {
|
|
58
|
+
const values = await this.readStatus();
|
|
59
|
+
return {
|
|
60
|
+
state: parseDsiotState(values),
|
|
61
|
+
sensors: parseDsiotSensors(values),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
43
64
|
// --- extended controls ---------------------------------------------------
|
|
44
65
|
/** Reboot the adapter (`/config/system/reboot`). */
|
|
45
66
|
async reboot() {
|
|
@@ -60,7 +81,24 @@ export class DsiotDaikinClient {
|
|
|
60
81
|
}
|
|
61
82
|
async multireq(method, jsonBody, { retry = true } = {}) {
|
|
62
83
|
const send = () => this.transport.send({ method, path: DSIOT_ROUTES.multireq, jsonBody });
|
|
63
|
-
|
|
84
|
+
try {
|
|
85
|
+
return parseDsiotMultireqReply(await (retry ? withRetry(send, this.retryOptions) : send()));
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
// Even a write that failed: one that timed out may still have reached
|
|
89
|
+
// the unit.
|
|
90
|
+
if (method === "PUT") {
|
|
91
|
+
this.setStateCache.clear();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async readStatus() {
|
|
96
|
+
const values = await this.multireqGet([
|
|
97
|
+
DSIOT_TARGETS.indoorStatus,
|
|
98
|
+
DSIOT_TARGETS.outdoorStatus,
|
|
99
|
+
]);
|
|
100
|
+
this.setStateCache.set(values);
|
|
101
|
+
return values;
|
|
64
102
|
}
|
|
65
103
|
}
|
|
66
104
|
//# 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"}
|