daikin-local-control 0.4.0 → 0.5.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.
Files changed (96) hide show
  1. package/DESIGN.md +47 -4
  2. package/README.md +154 -46
  3. package/UNSUPPORTED.md +27 -2
  4. package/dist/clients/airbase.d.ts +64 -0
  5. package/dist/clients/airbase.d.ts.map +1 -0
  6. package/dist/clients/airbase.js +175 -0
  7. package/dist/clients/airbase.js.map +1 -0
  8. package/dist/clients/client.d.ts +3 -2
  9. package/dist/clients/client.d.ts.map +1 -1
  10. package/dist/codecs/airbase/capabilities.d.ts +23 -0
  11. package/dist/codecs/airbase/capabilities.d.ts.map +1 -0
  12. package/dist/codecs/airbase/capabilities.js +108 -0
  13. package/dist/codecs/airbase/capabilities.js.map +1 -0
  14. package/dist/codecs/airbase/state.d.ts +29 -0
  15. package/dist/codecs/airbase/state.d.ts.map +1 -0
  16. package/dist/codecs/airbase/state.js +166 -0
  17. package/dist/codecs/airbase/state.js.map +1 -0
  18. package/dist/codecs/airbase/tables.d.ts +7 -0
  19. package/dist/codecs/airbase/tables.d.ts.map +1 -0
  20. package/dist/codecs/airbase/tables.js +27 -0
  21. package/dist/codecs/airbase/tables.js.map +1 -0
  22. package/dist/codecs/airbase/zone.d.ts +12 -0
  23. package/dist/codecs/airbase/zone.d.ts.map +1 -0
  24. package/dist/codecs/airbase/zone.js +50 -0
  25. package/dist/codecs/airbase/zone.js.map +1 -0
  26. package/dist/codecs/classic/tables.d.ts +2 -0
  27. package/dist/codecs/classic/tables.d.ts.map +1 -1
  28. package/dist/codecs/classic/tables.js +2 -0
  29. package/dist/codecs/classic/tables.js.map +1 -1
  30. package/dist/codecs/device.d.ts +7 -1
  31. package/dist/codecs/device.d.ts.map +1 -1
  32. package/dist/codecs/device.js +14 -2
  33. package/dist/codecs/device.js.map +1 -1
  34. package/dist/codecs/dsiot/tables.d.ts +3 -0
  35. package/dist/codecs/dsiot/tables.d.ts.map +1 -1
  36. package/dist/codecs/dsiot/tables.js +3 -0
  37. package/dist/codecs/dsiot/tables.js.map +1 -1
  38. package/dist/discovery.d.ts +20 -10
  39. package/dist/discovery.d.ts.map +1 -1
  40. package/dist/discovery.js +96 -30
  41. package/dist/discovery.js.map +1 -1
  42. package/dist/factory.d.ts +8 -5
  43. package/dist/factory.d.ts.map +1 -1
  44. package/dist/factory.js +13 -3
  45. package/dist/factory.js.map +1 -1
  46. package/dist/index.d.ts +6 -0
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +6 -0
  49. package/dist/index.js.map +1 -1
  50. package/dist/models/device.d.ts +3 -2
  51. package/dist/models/device.d.ts.map +1 -1
  52. package/dist/models/device.js +1 -1
  53. package/dist/models/device.js.map +1 -1
  54. package/dist/models/zone.d.ts +9 -0
  55. package/dist/models/zone.d.ts.map +1 -0
  56. package/dist/models/zone.js +2 -0
  57. package/dist/models/zone.js.map +1 -0
  58. package/dist/simulators/airbase.d.ts +82 -0
  59. package/dist/simulators/airbase.d.ts.map +1 -0
  60. package/dist/simulators/airbase.js +352 -0
  61. package/dist/simulators/airbase.js.map +1 -0
  62. package/dist/simulators/classic.d.ts.map +1 -1
  63. package/dist/simulators/classic.js +2 -2
  64. package/dist/simulators/classic.js.map +1 -1
  65. package/dist/simulators/index.d.ts +1 -0
  66. package/dist/simulators/index.d.ts.map +1 -1
  67. package/dist/simulators/index.js +1 -0
  68. package/dist/simulators/index.js.map +1 -1
  69. package/dist/simulators/simulator.d.ts +11 -10
  70. package/dist/simulators/simulator.d.ts.map +1 -1
  71. package/dist/simulators/simulator.js +2 -2
  72. package/dist/simulators/simulator.js.map +1 -1
  73. package/dist/transport.d.ts +3 -2
  74. package/dist/transport.d.ts.map +1 -1
  75. package/dist/transport.js +4 -1
  76. package/dist/transport.js.map +1 -1
  77. package/package.json +7 -3
  78. package/src/clients/airbase.ts +274 -0
  79. package/src/clients/client.ts +3 -2
  80. package/src/codecs/airbase/capabilities.ts +150 -0
  81. package/src/codecs/airbase/state.ts +223 -0
  82. package/src/codecs/airbase/tables.ts +32 -0
  83. package/src/codecs/airbase/zone.ts +62 -0
  84. package/src/codecs/classic/tables.ts +3 -0
  85. package/src/codecs/device.ts +18 -2
  86. package/src/codecs/dsiot/tables.ts +4 -0
  87. package/src/discovery.ts +101 -32
  88. package/src/factory.ts +21 -5
  89. package/src/index.ts +6 -0
  90. package/src/models/device.ts +3 -2
  91. package/src/models/zone.ts +8 -0
  92. package/src/simulators/airbase.ts +495 -0
  93. package/src/simulators/classic.ts +2 -1
  94. package/src/simulators/index.ts +1 -0
  95. package/src/simulators/simulator.ts +13 -12
  96. package/src/transport.ts +7 -3
@@ -11,7 +11,7 @@ export interface DaikinSimulatorRequest {
11
11
  headers: IncomingHttpHeaders;
12
12
  body: string;
13
13
  }
14
- /** What `startClassicSimulator` and `startDsiotSimulator` both resolve with. */
14
+ /** What every simulator resolves with. */
15
15
  export interface DaikinSimulator {
16
16
  /** `<address>:<port>`, as `DaikinDevice.host` takes it: `127.0.0.1`, unless
17
17
  * the simulator was started at another `address`, and a port that was free
@@ -40,9 +40,10 @@ export interface DaikinSimulatorTemperatures {
40
40
  min: number;
41
41
  max: number;
42
42
  }
43
- /** What a simulated unit has, where both protocols can say it. Anything else
44
- * about a unit is set in the adapter's own terms: `modelInfo` on a classic
45
- * simulator, and `leaves` on a DSIOT one. */
43
+ /** What a simulated unit has, where the classic and the DSIOT protocol can
44
+ * both say it. Anything else about a unit is set in the adapter's own terms:
45
+ * `modelInfo` on a classic simulator, and `leaves` on a DSIOT one. An Airbase
46
+ * simulator takes an `AirbaseSimulatorUnit` instead. */
46
47
  export interface DaikinSimulatorUnit {
47
48
  /** A unit that only cools offers dehumidify, cool and fan. Defaults to
48
49
  * false: a heat pump, which offers auto and heat as well. */
@@ -63,10 +64,9 @@ export interface DaikinSimulatorUnit {
63
64
  * classic one. */
64
65
  heatTemperaturesInC?: DaikinSimulatorTemperatures;
65
66
  }
66
- /** The options `startClassicSimulator` and `startDsiotSimulator` both take.
67
- * A simulator applies `deviceInfo`, `state` and `sensors` after the fields
68
- * given in the adapter's own terms, so they replace a field given both
69
- * ways. */
67
+ /** The options every simulator takes. A simulator applies `deviceInfo`,
68
+ * `state` and `sensors` after the fields given in the adapter's own terms, so
69
+ * they replace a field given both ways. */
70
70
  export interface StartSimulatorOptions {
71
71
  /** The adapter's name, MAC address and firmware version, as
72
72
  * `getDeviceInfo` reads them back. A field left out keeps its default.
@@ -78,7 +78,8 @@ export interface StartSimulatorOptions {
78
78
  state?: Partial<DaikinState>;
79
79
  /** What the unit's sensors read at the start: see
80
80
  * `DaikinSimulator.setSensors`. Defaults to 26 °C and 55 % indoors, and
81
- * 30 °C outdoors. */
81
+ * 30 °C outdoors. An Airbase simulator reports no humidity unless it is
82
+ * given one. */
82
83
  sensors?: Partial<DaikinSensors>;
83
84
  /** How long, in milliseconds, the adapter takes to answer a request. It
84
85
  * answers one request at a time, in the order they arrive, so a request
@@ -96,7 +97,7 @@ export interface StartSimulatorOptions {
96
97
  answersDiscovery?: boolean;
97
98
  }
98
99
  /** What `startSimulator` resolves with: the part of a `DaikinSimulator` that
99
- * is the same for both protocols. */
100
+ * is the same for every protocol. */
100
101
  export type SimulatorServer = Pick<DaikinSimulator, "host" | "requests" | "stop">;
101
102
  export interface SimulatorReply {
102
103
  statusCode: number;
@@ -1 +1 @@
1
- {"version":3,"file":"simulator.d.ts","sourceRoot":"","sources":["../../src/simulators/simulator.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAEnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAC5D,OAAO,KAAK,EACV,aAAa,EACb,WAAW,EACX,WAAW,EACZ,MAAM,oBAAoB,CAAC;AAU5B,6CAA6C;AAC7C,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,mBAAmB,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B;;0BAEsB;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;4CAEwC;IACxC,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,EAAE,CAAC;IAC5C;;;;;8EAK0E;IAC1E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI,CAAC;IAC5C;2DACuD;IACvD,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC;IAClD;yBACqB;IACrB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,aAAa;AACb,MAAM,WAAW,2BAA2B;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;6CAE6C;AAC7C,MAAM,WAAW,mBAAmB;IAClC;iEAC6D;IAC7D,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,0DAA0D;IAC1D,GAAG,CAAC,EAAE,OAAO,CAAC;IACd;uEACmE;IACnE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACrC,+DAA+D;IAC/D,YAAY,CAAC,EAAE,SAAS,WAAW,EAAE,CAAC;IACtC;;sBAEkB;IAClB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;IAClD;;sBAEkB;IAClB,mBAAmB,CAAC,EAAE,2BAA2B,CAAC;CACnD;AAED;;;WAGW;AACX,MAAM,WAAW,qBAAqB;IACpC;;4CAEwC;IACxC,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B;;iCAE6B;IAC7B,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7B;;yBAEqB;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACjC;;0EAEsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;oDAEgD;IAChD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;+DAI2D;IAC3D,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED;qCACqC;AACrC,MAAM,MAAM,eAAe,GAAG,IAAI,CAChC,eAAe,EACf,MAAM,GAAG,UAAU,GAAG,MAAM,CAC7B,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;4EAC4E;AAC5E,wBAAgB,UAAU,CAAC,OAAO,EAAE,sBAAsB,GAAG,cAAc,CAK1E;AAED;yDACyD;AACzD,wBAAgB,cAAc,CAC5B,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAClC,MAAM,CAIR;AAED;;;2DAG2D;AAC3D,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,EAC9B,MAAM,EAAE,CAAC,OAAO,EAAE,sBAAsB,KAAK,cAAc,EAC3D,eAAe,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5C,OAAO,CAAC,eAAe,CAAC,CA6E1B"}
1
+ {"version":3,"file":"simulator.d.ts","sourceRoot":"","sources":["../../src/simulators/simulator.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { createSocket } from "node:dgram";
2
2
  import { once } from "node:events";
3
3
  import { createServer } from "node:http";
4
- // What the classic and the DSIOT simulator share: the HTTP server, and the
5
- // reply to a discovery probe, which both adapters send in the same form.
4
+ // What the simulators share: the HTTP server, and the reply to a discovery
5
+ // probe, which every adapter sends in the same form.
6
6
  const DISCOVERY_PROBE = "DAIKIN_UDP/common/basic_info";
7
7
  const DISCOVERY_PORT = 30050;
8
8
  const DEFAULT_ADDRESS = "127.0.0.1";
@@ -1 +1 @@
1
- {"version":3,"file":"simulator.js","sourceRoot":"","sources":["../../src/simulators/simulator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"simulator.js","sourceRoot":"","sources":["../../src/simulators/simulator.ts"],"names":[],"mappings":"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"}
@@ -29,8 +29,9 @@ export interface DaikinTransportOptions {
29
29
  /** HTTPS (a Marvell adapter in secure mode). */
30
30
  usesHttps?: boolean;
31
31
  /** The terminal uuid, sent as `X-Daikin-uuid` on every call: 32 lowercase
32
- * hexadecimal digits, a UUID without its dashes. */
33
- terminalUuid: string;
32
+ * hexadecimal digits, a UUID without its dashes. Without one the header is
33
+ * left out, as an Airbase adapter takes it. */
34
+ terminalUuid?: string;
34
35
  authentication?: DaikinAuthentication;
35
36
  /** How long, in milliseconds, to wait for each of the connection, the
36
37
  * reply's headers and the reply's body before `send` throws a
@@ -1 +1 @@
1
- {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAIhE,MAAM,WAAW,oBAAoB;IACnC;6CACyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC;;oEAEgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAID;;wBAEwB;AACxB,wBAAsB,SAAS,CAAC,OAAO,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EACjC,EAAE,UAAuC,EAAE,GAAE,kBAAuB,GACnE,OAAO,CAAC,OAAO,CAAC,CAYlB;AAoBD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC/B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;wDACoD;IACpD,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC;;2DAEuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;wDAEwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B;mFAC+E;IAC/E,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED;;;;;;;gBAOgB;AAChB,qBAAa,eAAe;IAQd,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyB;IAE7D;;0DAEsD;IACtD,YAA6B,OAAO,EAAE,sBAAsB,EAa3D;IAED;;;;;;;2BAOuB;IACjB,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAoDlD;IAED,2CAA2C;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;CACF"}
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAIhE,MAAM,WAAW,oBAAoB;IACnC;6CACyC;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC;;oEAEgE;IAChE,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACvB;AAID;;wBAEwB;AACxB,wBAAsB,SAAS,CAAC,OAAO,EACrC,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,EACjC,EAAE,UAAuC,EAAE,GAAE,kBAAuB,GACnE,OAAO,CAAC,OAAO,CAAC,CAYlB;AAoBD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,KAAK,CAAC;IAC/B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;mDAE+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,oBAAoB,CAAC;IACtC;;2DAEuD;IACvD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACxB;AAED;;wDAEwD;AACxD,MAAM,WAAW,gBAAgB;IAC/B;mFAC+E;IAC/E,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACtB;AAED;;;;;;;gBAOgB;AAChB,qBAAa,eAAe;IAQd,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAyB;IAE7D;;0DAEsD;IACtD,YAA6B,OAAO,EAAE,sBAAsB,EAgB3D;IAED;;;;;;;2BAOuB;IACjB,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAoDlD;IAED,2CAA2C;IACrC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3B;CACF"}
package/dist/transport.js CHANGED
@@ -52,7 +52,10 @@ export class DaikinTransport {
52
52
  constructor(options) {
53
53
  this.options = options;
54
54
  // Before the Client, so a uuid that throws leaves no connection open.
55
- this.terminalUuidHeaders = encodeTerminalUuid(options.terminalUuid);
55
+ this.terminalUuidHeaders =
56
+ options.terminalUuid === undefined
57
+ ? {}
58
+ : encodeTerminalUuid(options.terminalUuid);
56
59
  const scheme = options.usesHttps ? "https" : "http";
57
60
  this.origin = `${scheme}://${options.host.replace(/\/+$/, "")}`;
58
61
  const timeoutInMs = options.timeoutInMs ?? DEFAULT_TIMEOUT_IN_MS;
@@ -1 +1 @@
1
- {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "daikin-local-control",
3
- "version": "0.4.0",
4
- "description": "Unofficial Node.js and TypeScript client for controlling Daikin air conditioners over the local network (LAN), with no cloud. Supports classic (BRP069, BRP072) and DSIOT (BRP084) Wi-Fi adapters.",
3
+ "version": "0.5.0",
4
+ "description": "Unofficial Node.js and TypeScript client for controlling Daikin air conditioners over the local network (LAN), with no cloud. Supports classic (BRP069, BRP072), DSIOT (BRP084) and Airbase (BRP15B61) Wi-Fi adapters.",
5
5
  "keywords": [
6
6
  "daikin",
7
7
  "daikin-ac",
8
8
  "daikin-api",
9
9
  "daikin-mobile-controller",
10
+ "daikin-airbase",
11
+ "onecta",
10
12
  "air-conditioner",
11
13
  "air-conditioning",
12
14
  "aircon",
@@ -19,6 +21,7 @@
19
21
  "brp072a42",
20
22
  "brp072c42",
21
23
  "brp084",
24
+ "brp15b61",
22
25
  "dsiot",
23
26
  "skyair",
24
27
  "home-automation",
@@ -31,7 +34,8 @@
31
34
  "taiwan",
32
35
  "philippines",
33
36
  "australia",
34
- "new-zealand"
37
+ "new-zealand",
38
+ "europe"
35
39
  ],
36
40
  "license": "MIT",
37
41
  "homepage": "https://github.com/cheziyi/daikin-local-control#readme",
@@ -0,0 +1,274 @@
1
+ import {
2
+ mergeAirbaseCapabilityFields,
3
+ parseAirbaseCapabilities,
4
+ parseAirbaseZoneCount,
5
+ takesAirbaseAirside,
6
+ takesAirbaseFanAuto,
7
+ } from "../codecs/airbase/capabilities.js";
8
+ import {
9
+ applyAirbaseAirside,
10
+ applyAirbaseControl,
11
+ applyAirbaseFanAuto,
12
+ parseAirbaseAirside,
13
+ parseAirbaseFanAuto,
14
+ parseAirbaseSensors,
15
+ parseAirbaseState,
16
+ } from "../codecs/airbase/state.js";
17
+ import { applyAirbaseZone, parseAirbaseZones } from "../codecs/airbase/zone.js";
18
+ import {
19
+ assertClassicOk,
20
+ isClassicOk,
21
+ parseClassicKeyValue,
22
+ } from "../codecs/classic/keyValue.js";
23
+ import { parseDeviceInfo } from "../codecs/device.js";
24
+ import { DaikinError } from "../error.js";
25
+ import type { DaikinCapabilities } from "../models/capabilities.js";
26
+ import type { DaikinDeviceInfo } from "../models/device.js";
27
+ import type {
28
+ DaikinControl,
29
+ DaikinSensors,
30
+ DaikinState,
31
+ DaikinStateAndSensors,
32
+ SpecialMode,
33
+ } from "../models/state.js";
34
+ import type { DaikinZone } from "../models/zone.js";
35
+ import {
36
+ type DaikinRequestOptions,
37
+ type DaikinRetryOptions,
38
+ type DaikinTransport,
39
+ withRetry,
40
+ } from "../transport.js";
41
+ import type { DaikinClient } from "./client.js";
42
+ import { SetStateCache } from "./setStateCache.js";
43
+
44
+ // An Airbase adapter answers the endpoints of a classic adapter under this
45
+ // path, and HTTP 404 at the paths a classic adapter answers.
46
+ const AIRBASE_ROOT = "/skyfi";
47
+
48
+ const AIRBASE_ROUTES = {
49
+ basicInfo: "/common/basic_info",
50
+ getModelInfo: "/aircon/get_model_info",
51
+ getControlInfo: "/aircon/get_control_info",
52
+ setControlInfo: "/aircon/set_control_info",
53
+ getSensorInfo: "/aircon/get_sensor_info",
54
+ getZoneSetting: "/aircon/get_zone_setting",
55
+ setZoneSetting: "/aircon/set_zone_setting",
56
+ } as const;
57
+
58
+ const NOT_FOUND = 404;
59
+
60
+ /** Whether the adapter `transport` reaches is an Airbase adapter: one that
61
+ * answers HTTP 404 at `/common/basic_info`, where a classic adapter answers,
62
+ * and `ret=OK` at `/skyfi/common/basic_info`. It sends the second request
63
+ * only after that 404, and retries a refused or dropped connection as
64
+ * `withRetry` does by default: an adapter drops one while it answers another
65
+ * caller. It resolves with `false` when either request fails any other way.
66
+ * `discoverDevices` calls it, and `src/index.ts` does not export it. */
67
+ export async function isAirbaseAdapter(
68
+ transport: DaikinTransport,
69
+ ): Promise<boolean> {
70
+ const get = (path: string) =>
71
+ withRetry(() => transport.send({ method: "GET", path }));
72
+ try {
73
+ await get(AIRBASE_ROUTES.basicInfo);
74
+ return false;
75
+ } catch (error) {
76
+ if (!(error instanceof DaikinError) || error.httpStatusCode !== NOT_FOUND) {
77
+ return false;
78
+ }
79
+ }
80
+ try {
81
+ return isClassicOk(
82
+ parseClassicKeyValue(
83
+ await get(`${AIRBASE_ROOT}${AIRBASE_ROUTES.basicInfo}`),
84
+ ),
85
+ );
86
+ } catch {
87
+ return false;
88
+ }
89
+ }
90
+
91
+ /** Airbase adapter (BRP15B61), on a ducted unit. Reads and writes are HTTP GET
92
+ * with query parameters, as on a classic adapter, at paths under `/skyfi`.
93
+ * It takes no terminal uuid and no local password. */
94
+ export class AirbaseDaikinClient implements DaikinClient {
95
+ // A unit's capabilities don't change, so they are read once.
96
+ private capabilityFields: Promise<Record<string, string>> | undefined;
97
+ private readonly setStateCache: SetStateCache;
98
+
99
+ /** `close` closes `transport`, so give each client a transport of its own.
100
+ * `maxStateAgeForSetStateInMs` defaults to 0: see
101
+ * `CreateDaikinClientOptions.maxStateAgeForSetStateInMs`. */
102
+ constructor(
103
+ private readonly transport: DaikinTransport,
104
+ private readonly retryOptions?: DaikinRetryOptions,
105
+ maxStateAgeForSetStateInMs = 0,
106
+ ) {
107
+ this.setStateCache = new SetStateCache(maxStateAgeForSetStateInMs);
108
+ }
109
+
110
+ close(): Promise<void> {
111
+ return this.transport.close();
112
+ }
113
+
114
+ async getDeviceInfo(): Promise<DaikinDeviceInfo> {
115
+ return parseDeviceInfo(await this.command(AIRBASE_ROUTES.basicInfo));
116
+ }
117
+
118
+ async getCapabilities(): Promise<DaikinCapabilities> {
119
+ return parseAirbaseCapabilities(await this.readCapabilityFields());
120
+ }
121
+
122
+ async getState(): Promise<DaikinState> {
123
+ return parseAirbaseState(await this.readControlInfo());
124
+ }
125
+
126
+ async setState(control: DaikinControl): Promise<void> {
127
+ const current =
128
+ this.setStateCache.get() ??
129
+ (await this.command(AIRBASE_ROUTES.getControlInfo));
130
+ await this.command(
131
+ AIRBASE_ROUTES.setControlInfo,
132
+ applyAirbaseControl(current, control),
133
+ );
134
+ }
135
+
136
+ async getSensors(): Promise<DaikinSensors> {
137
+ return parseAirbaseSensors(
138
+ await this.command(AIRBASE_ROUTES.getSensorInfo),
139
+ );
140
+ }
141
+
142
+ async getStateAndSensors(): Promise<DaikinStateAndSensors> {
143
+ return { state: await this.getState(), sensors: await this.getSensors() };
144
+ }
145
+
146
+ /** Rejects with a `DaikinError` whose status is 501: an Airbase adapter has
147
+ * no known request for a special mode. */
148
+ async setSpecialMode(_mode: SpecialMode, _enabled: boolean): Promise<void> {
149
+ throw new DaikinError("An Airbase adapter takes no special mode", 501);
150
+ }
151
+
152
+ // --- extended controls ---------------------------------------------------
153
+
154
+ /** Whether fan auto is on: the unit then picks the fan speed itself, up to
155
+ * the one that is set. `null` on a unit that takes no fan auto. */
156
+ async getFanAuto(): Promise<boolean | null> {
157
+ return takesAirbaseFanAuto(await this.readCapabilityFields())
158
+ ? parseAirbaseFanAuto(await this.readControlInfo())
159
+ : null;
160
+ }
161
+
162
+ /** Switches fan auto on or off. It switches airside off, and keeps the fan
163
+ * speed. Check `getFanAuto` first: the client sends it to any unit. */
164
+ async setFanAuto(enabled: boolean): Promise<void> {
165
+ await this.command(
166
+ AIRBASE_ROUTES.setControlInfo,
167
+ applyAirbaseFanAuto(
168
+ await this.command(AIRBASE_ROUTES.getControlInfo),
169
+ enabled,
170
+ ),
171
+ );
172
+ }
173
+
174
+ /** Whether airside is on. `null` on a unit that takes no airside. */
175
+ async getAirside(): Promise<boolean | null> {
176
+ return takesAirbaseAirside(await this.readCapabilityFields())
177
+ ? parseAirbaseAirside(await this.readControlInfo())
178
+ : null;
179
+ }
180
+
181
+ /** Switches airside on or off. Switching it on switches fan auto off and
182
+ * sets the lowest fan speed. Check `getAirside` first: the client sends it
183
+ * to any unit. */
184
+ async setAirside(enabled: boolean): Promise<void> {
185
+ await this.command(
186
+ AIRBASE_ROUTES.setControlInfo,
187
+ applyAirbaseAirside(
188
+ await this.command(AIRBASE_ROUTES.getControlInfo),
189
+ enabled,
190
+ ),
191
+ );
192
+ }
193
+
194
+ /** The unit's zones, in the unit's order; empty on a unit without zones,
195
+ * which is not asked for any. */
196
+ async getZones(): Promise<DaikinZone[]> {
197
+ const capabilityFields = await this.readCapabilityFields();
198
+ return parseAirbaseZones(
199
+ await this.readZoneSetting(capabilityFields),
200
+ capabilityFields,
201
+ );
202
+ }
203
+
204
+ /** Opens or closes the zone at `index` in `getZones`, counted from 0. It
205
+ * rejects with an `Error` for an index the unit has no zone at. */
206
+ async setZone(index: number, enabled: boolean): Promise<void> {
207
+ const capabilityFields = await this.readCapabilityFields();
208
+ const current = await this.readZoneSetting(capabilityFields);
209
+ await this.command(
210
+ AIRBASE_ROUTES.setZoneSetting,
211
+ applyAirbaseZone(current, capabilityFields, index, enabled),
212
+ );
213
+ }
214
+
215
+ /** Calls any endpoint by its path below `/skyfi`, such as
216
+ * `/aircon/get_control_info`, with query parameters, and returns the reply's
217
+ * `key=value` fields. It throws a `DaikinError` when the reply's `ret` is
218
+ * not `OK`. */
219
+ async command(
220
+ path: string,
221
+ parameters?: Record<string, string>,
222
+ { retry = true }: DaikinRequestOptions = {},
223
+ ): Promise<Record<string, string>> {
224
+ const send = () =>
225
+ this.transport.send({
226
+ method: "GET",
227
+ path: `${AIRBASE_ROOT}${path}`,
228
+ ...(parameters ? { query: parameters } : {}),
229
+ });
230
+ try {
231
+ const fields = parseClassicKeyValue(
232
+ await (retry ? withRetry(send, this.retryOptions) : send()),
233
+ );
234
+ assertClassicOk(fields);
235
+ return fields;
236
+ } finally {
237
+ // Every request that changes the unit takes parameters, and any of them
238
+ // may change what `get_control_info` answers, even one that failed: a
239
+ // request that timed out may still have reached the unit.
240
+ if (parameters) {
241
+ this.setStateCache.clear();
242
+ }
243
+ }
244
+ }
245
+
246
+ // What a unit without zones answers at `get_zone_setting` is not known, so
247
+ // it is not asked.
248
+ private async readZoneSetting(
249
+ capabilityFields: Record<string, string>,
250
+ ): Promise<Record<string, string>> {
251
+ return parseAirbaseZoneCount(capabilityFields) === 0
252
+ ? {}
253
+ : this.command(AIRBASE_ROUTES.getZoneSetting);
254
+ }
255
+
256
+ private async readControlInfo(): Promise<Record<string, string>> {
257
+ const fields = await this.command(AIRBASE_ROUTES.getControlInfo);
258
+ this.setStateCache.set(fields);
259
+ return fields;
260
+ }
261
+
262
+ private readCapabilityFields(): Promise<Record<string, string>> {
263
+ this.capabilityFields ??= (async () =>
264
+ mergeAirbaseCapabilityFields(
265
+ await this.command(AIRBASE_ROUTES.basicInfo),
266
+ await this.command(AIRBASE_ROUTES.getModelInfo),
267
+ ))();
268
+ // A failed read is not cached, so the next call tries again.
269
+ this.capabilityFields.catch(() => {
270
+ this.capabilityFields = undefined;
271
+ });
272
+ return this.capabilityFields;
273
+ }
274
+ }
@@ -31,7 +31,8 @@ export interface DaikinClient {
31
31
 
32
32
  /** Turn powerful, econo or streamer on or off, with a request of its own.
33
33
  * `DaikinCapabilities.specialModes` lists the ones the unit takes in each
34
- * mode, and the client sends any other as given. */
34
+ * mode, and the client sends any other as given. An `AirbaseDaikinClient`
35
+ * rejects every one with status 501. */
35
36
  setSpecialMode(mode: SpecialMode, enabled: boolean): Promise<void>;
36
37
 
37
38
  /** Read-only temperature / humidity readings. */
@@ -39,7 +40,7 @@ export interface DaikinClient {
39
40
 
40
41
  /** What `getState` and `getSensors` resolve with, together. A DSIOT adapter
41
42
  * answers both in one request, where calling the two sends the same request
42
- * twice. A classic adapter takes one request for each. */
43
+ * twice. A classic or an Airbase adapter takes one request for each. */
43
44
  getStateAndSensors(): Promise<DaikinStateAndSensors>;
44
45
 
45
46
  /** Close the connection to the adapter. */
@@ -0,0 +1,150 @@
1
+ import type {
2
+ DaikinCapabilities,
3
+ TemperatureRange,
4
+ } from "../../models/capabilities.js";
5
+ import {
6
+ type FanSpeed,
7
+ OPERATING_MODES,
8
+ type OperatingMode,
9
+ SWING_MODES,
10
+ } from "../../models/state.js";
11
+
12
+ const ALWAYS_OFFERED_MODES: readonly OperatingMode[] = ["cool", "heat", "fan"];
13
+ const THREE_FAN_LEVELS: FanSpeed[] = ["level1", "level3", "level5"];
14
+ const TWO_FAN_LEVELS: FanSpeed[] = ["level1", "level5"];
15
+
16
+ /** Merges the `basic_info` and `get_model_info` replies of an Airbase adapter
17
+ * into the one field map `parseAirbaseCapabilities`, `takesAirbaseFanAuto`,
18
+ * `takesAirbaseAirside` and `parseAirbaseZones` read. */
19
+ export function mergeAirbaseCapabilityFields(
20
+ basicInfo: Record<string, string>,
21
+ modelInfo: Record<string, string>,
22
+ ): Record<string, string> {
23
+ return { ...basicInfo, ...modelInfo };
24
+ }
25
+
26
+ /** Turns the field map from `mergeAirbaseCapabilityFields` into
27
+ * `DaikinCapabilities`. A unit with zones (`en_zone`) takes no `auto` fan
28
+ * speed and no direction. It lists no humidity setting, louver position or
29
+ * special mode, and reports `energyMonitoring` and `demandControl` as
30
+ * `false`: which field says a unit has either is not known. */
31
+ export function parseAirbaseCapabilities(
32
+ fields: Record<string, string>,
33
+ ): DaikinCapabilities {
34
+ const offeredModes = OPERATING_MODES.filter(
35
+ (mode) =>
36
+ ALWAYS_OFFERED_MODES.includes(mode) ||
37
+ (mode === "auto" && fields.en_auto === "1") ||
38
+ (mode === "dehumidify" && fields.en_dry === "1"),
39
+ );
40
+ const offered = (mode: OperatingMode, range: TemperatureRange) =>
41
+ offeredModes.includes(mode) ? range : null;
42
+ const none = { auto: [], dehumidify: [], cool: [], heat: [], fan: [] };
43
+
44
+ return {
45
+ modes: offeredModes,
46
+ fanSpeeds: fanSpeeds(fields),
47
+ swingModes:
48
+ !hasZones(fields) && fields.en_fdir === "1" ? [...SWING_MODES] : [],
49
+ verticalPositions: [],
50
+ horizontalPositions: [],
51
+ targetTemperaturesInC: {
52
+ // Auto runs from the lowest setpoint of cool to the highest of heat.
53
+ auto: offered("auto", range(fields.cool_l, 18, fields.heat_h, 30)),
54
+ cool: offered("cool", range(fields.cool_l, 18, fields.cool_h, 32)),
55
+ heat: offered("heat", range(fields.heat_l, 10, fields.heat_h, 30)),
56
+ dehumidify: null,
57
+ fan: null,
58
+ },
59
+ targetHumidities: none,
60
+ specialModes: none,
61
+ specialOutlet: false,
62
+ energyMonitoring: false,
63
+ demandControl: false,
64
+ scheduleTimer: ["1", "2"].includes(fields.en_scdltmr ?? ""),
65
+ model: fields.model,
66
+ };
67
+ }
68
+
69
+ /** Whether a unit takes fan auto, read from the field map of
70
+ * `mergeAirbaseCapabilityFields`: one with zones that counts its fan speeds
71
+ * (`frate_steps`), unless `en_frate_auto` is 0. */
72
+ export function takesAirbaseFanAuto(fields: Record<string, string>): boolean {
73
+ return (
74
+ isFanControllable(fields) &&
75
+ hasZones(fields) &&
76
+ fanLevels(fields).length > 0 &&
77
+ "frate_steps" in fields &&
78
+ (fields.en_frate_auto ?? "1") === "1"
79
+ );
80
+ }
81
+
82
+ /** Whether a unit takes airside, read from the field map of
83
+ * `mergeAirbaseCapabilityFields`: one with zones that reports
84
+ * `en_airside=1`. */
85
+ export function takesAirbaseAirside(fields: Record<string, string>): boolean {
86
+ return (
87
+ isFanControllable(fields) && hasZones(fields) && fields.en_airside === "1"
88
+ );
89
+ }
90
+
91
+ /** How many zones a unit has, read from the field map of
92
+ * `mergeAirbaseCapabilityFields`: `en_zone`, and none without it. */
93
+ export function parseAirbaseZoneCount(fields: Record<string, string>): number {
94
+ const count = Number.parseInt(fields.en_zone ?? "", 10);
95
+ return count > 0 ? count : 0;
96
+ }
97
+
98
+ function hasZones(fields: Record<string, string>): boolean {
99
+ return "en_zone" in fields && fields.en_zone !== "0";
100
+ }
101
+
102
+ // A unit that sets each zone's airflow itself (`en_linear_zone=1`) takes no
103
+ // fan speed.
104
+ function isFanControllable(fields: Record<string, string>): boolean {
105
+ return (
106
+ (fields.reg ?? "") !== "" &&
107
+ fields.reg !== "jp" &&
108
+ fields.en_frate === "1" &&
109
+ fields.en_linear_zone !== "1"
110
+ );
111
+ }
112
+
113
+ // Three levels unless `frate_steps` is 2, and none when it is not a number.
114
+ function fanLevels(fields: Record<string, string>): FanSpeed[] {
115
+ if (!("frate_steps" in fields)) {
116
+ return THREE_FAN_LEVELS;
117
+ }
118
+ const steps = Number.parseInt(fields.frate_steps ?? "", 10);
119
+ if (!Number.isFinite(steps)) {
120
+ return [];
121
+ }
122
+ return steps === 2 ? TWO_FAN_LEVELS : THREE_FAN_LEVELS;
123
+ }
124
+
125
+ function fanSpeeds(fields: Record<string, string>): FanSpeed[] {
126
+ if (!isFanControllable(fields)) {
127
+ return [];
128
+ }
129
+ const takesAuto = !hasZones(fields) && fields.en_frate_auto === "1";
130
+ return [...(takesAuto ? (["auto"] as const) : []), ...fanLevels(fields)];
131
+ }
132
+
133
+ // Setpoint limits are whole °C on the wire; any fraction is dropped.
134
+ function range(
135
+ low: string | undefined,
136
+ fallbackMin: number,
137
+ high: string | undefined,
138
+ fallbackMax: number,
139
+ ): TemperatureRange {
140
+ return {
141
+ min: wholeCelsius(low, fallbackMin),
142
+ max: wholeCelsius(high, fallbackMax),
143
+ step: 1,
144
+ };
145
+ }
146
+
147
+ function wholeCelsius(value: string | undefined, fallback: number): number {
148
+ const parsed = Number.parseFloat(value ?? "");
149
+ return Number.isFinite(parsed) ? Math.trunc(parsed) : fallback;
150
+ }