mysa-client 0.1.0__py3-none-any.whl
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.
- mysa_client/__init__.py +4 -0
- mysa_client/cloud/README.md +460 -0
- mysa_client/cloud/__init__.py +90 -0
- mysa_client/cloud/auth.py +243 -0
- mysa_client/cloud/client.py +1026 -0
- mysa_client/cloud/commands.py +169 -0
- mysa_client/cloud/const.py +279 -0
- mysa_client/cloud/exceptions.py +50 -0
- mysa_client/cloud/models.py +683 -0
- mysa_client/cloud/observations.py +160 -0
- mysa_client/cloud/schedules.py +84 -0
- mysa_client/cloud/srp.py +162 -0
- mysa_client/cloud/trace.py +37 -0
- mysa_client/cloud/validation.py +97 -0
- mysa_client/homekit/README.md +161 -0
- mysa_client/homekit/__init__.py +62 -0
- mysa_client/homekit/advertisement.py +106 -0
- mysa_client/homekit/controller.py +420 -0
- mysa_client/homekit/device.py +718 -0
- mysa_client/homekit/exceptions.py +59 -0
- mysa_client/homekit/models.py +144 -0
- mysa_client/py.typed +0 -0
- mysa_client-0.1.0.dist-info/METADATA +188 -0
- mysa_client-0.1.0.dist-info/RECORD +26 -0
- mysa_client-0.1.0.dist-info/WHEEL +4 -0
- mysa_client-0.1.0.dist-info/licenses/LICENSE +21 -0
mysa_client/__init__.py
ADDED
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
# Mysa cloud protocol
|
|
2
|
+
|
|
3
|
+
- [API varieties](#the-three-api-varieties)
|
|
4
|
+
- [Operations](#operations-and-relevance-to-home-assistant)
|
|
5
|
+
- [Read/write mappings](#readwrite-comparisons)
|
|
6
|
+
- [Recommended reads](#recommended-reconciliation-of-cloud-reads)
|
|
7
|
+
- [Recommended writes](#recommended-reconciliation-of-cloud-writes)
|
|
8
|
+
- [Integration status and validation](#integration-status-and-validation)
|
|
9
|
+
|
|
10
|
+
Supporting references: [authentication](../../../docs/cloud-auth.md),
|
|
11
|
+
[state and model fields](../../../docs/cloud-state.md),
|
|
12
|
+
[workflows](../../../docs/cloud-workflows.md), and
|
|
13
|
+
[firmware/connectivity](https://github.com/SokolskyNikita/mysa-homeassistant/blob/main/docs/firmware-and-connectivity.md).
|
|
14
|
+
|
|
15
|
+
## Context and conventions
|
|
16
|
+
|
|
17
|
+
Mysa exposes overlapping cloud services: structured device state, older
|
|
18
|
+
telemetry, and stored account/device settings. A successful request does not
|
|
19
|
+
necessarily mean fresh data or an applied thermostat command. This guide
|
|
20
|
+
covers the useful operations, their API mappings, and **recommended cloud-only
|
|
21
|
+
selection rules** for an integrating application. Endpoint support and Mysa Local policy are tracked separately; see the [Home Assistant integration tracker](https://github.com/SokolskyNikita/mysa-homeassistant/blob/main/docs/implementation/cloud.md).
|
|
22
|
+
|
|
23
|
+
Applications should own automations, scenes, presence, notifications, and dashboards.
|
|
24
|
+
Mysa's cloud remains useful for device control, hardware settings, runtime,
|
|
25
|
+
firmware, and inspecting existing Mysa schedules that could affect commands.
|
|
26
|
+
HomeKit/cloud reconciliation is outside this document.
|
|
27
|
+
|
|
28
|
+
The three access paths used below are:
|
|
29
|
+
|
|
30
|
+
| Shorthand | API variety | HTTPS base URL |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| **S** | Structured/current services | `https://mysa-backend.mysa.cloud` |
|
|
33
|
+
| **R** | Legacy REST through the modern host | `https://mysa-backend.mysa.cloud` |
|
|
34
|
+
| **L** | Legacy REST through the older host | `https://app-prod.mysa.cloud` |
|
|
35
|
+
|
|
36
|
+
**R and L are two entry points to overlapping services, not independent
|
|
37
|
+
thermostat measurements.** The distinction matters for route availability;
|
|
38
|
+
S and R share a hostname but have different response formats.
|
|
39
|
+
|
|
40
|
+
Notation: `{dev}` is the account's device ID, `{home}` its home ID, and `{id}`
|
|
41
|
+
the resource ID returned by creation/discovery. **ST** means S's `reported`
|
|
42
|
+
state sections, **TEL** its `latestTelemetry.reading`, **LT** the legacy
|
|
43
|
+
`DeviceStatesObj[dev]` telemetry, and **REC** the device's settings record.
|
|
44
|
+
Temperatures and setpoints are Celsius regardless of screen units. Decode
|
|
45
|
+
mode, lock, and fan enums by API/model before comparing them.
|
|
46
|
+
|
|
47
|
+
The live findings apply to two Baseboard Lites (`BB-V2-0-L`, firmware
|
|
48
|
+
`3.17.5.13`), checked October 10–12, 2026. Other-model mappings are identified
|
|
49
|
+
as such. This is a reverse-engineered protocol, not a vendor API contract.
|
|
50
|
+
|
|
51
|
+
### Shared authentication
|
|
52
|
+
|
|
53
|
+
All three paths use the **same Cognito ID token**, sent raw in
|
|
54
|
+
`authorization` with **no `Bearer` prefix**. Send `accept: application/json`,
|
|
55
|
+
a descriptive `user-agent`, and `content-type: application/json` for JSON
|
|
56
|
+
bodies. No separate login or AWS request signing is needed for R or L.
|
|
57
|
+
|
|
58
|
+
Use `MysaAuth.sign_in(email, password)` for the Cognito SRP exchange, or
|
|
59
|
+
initialize it with a saved refresh token. `async_get_id_token()` handles
|
|
60
|
+
refresh; retain a replacement refresh token through `on_refresh_token` when
|
|
61
|
+
one is returned. The public Cognito identifiers are in [`const.py`](const.py),
|
|
62
|
+
and the exchange is described in the [authentication reference](../../../docs/cloud-auth.md#cognito-sign-in).
|
|
63
|
+
Credentials and token persistence belong to the caller.
|
|
64
|
+
|
|
65
|
+
<a id="requests-and-state"></a>
|
|
66
|
+
|
|
67
|
+
## The three API varieties
|
|
68
|
+
|
|
69
|
+
### S — structured/current services
|
|
70
|
+
|
|
71
|
+
Use the modern base URL and shared authentication above. Discover the account
|
|
72
|
+
with `GET /mobile/bootstrap?versionNumber={APP_VERSION}`, using `APP_VERSION`
|
|
73
|
+
from `const.py`, then request state for the discovered IDs:
|
|
74
|
+
|
|
75
|
+
[Batch-state exchange with existing response fixture](../../../examples/cloud/state-batch.success.json)
|
|
76
|
+
|
|
77
|
+
A batch returns `{device_id: {"data": state}}`; inspect individual entries for
|
|
78
|
+
failure. `GET /state/{dev}` returns one state object directly. ST contains
|
|
79
|
+
configuration/control sections such as `targetHeat`, `modes`, and
|
|
80
|
+
`physicalInterface`; TEL contains measurements. Where a section has
|
|
81
|
+
`desired` and `reported`, only `reported` is evidence of applied state.
|
|
82
|
+
|
|
83
|
+
Commands use section changes with `source: 3`:
|
|
84
|
+
|
|
85
|
+
[Setpoint request and accepted reply](../../../examples/cloud/state-update.setpoint.json)
|
|
86
|
+
|
|
87
|
+
This requests a setpoint change; it does not select heat mode. Source 3 appears
|
|
88
|
+
as `app` in change history. Current capability, usage, schedule, hold, and
|
|
89
|
+
live-mode routes are listed in the comparison tables. S's state routes return
|
|
90
|
+
403 on L; changing the hostname does not provide a second structured API.
|
|
91
|
+
|
|
92
|
+
### R — legacy REST on the modern host
|
|
93
|
+
|
|
94
|
+
Use the same modern base URL, ID token, and headers. Two distinct reads matter:
|
|
95
|
+
|
|
96
|
+
- `GET /devices/state` returns LT: `DeviceStatesObj[dev]`, generally with
|
|
97
|
+
independent `{v, t}` pairs for each field.
|
|
98
|
+
- `GET /devices` returns `DevicesObj[dev]` settings records; `GET /devices/{dev}`
|
|
99
|
+
reads one record. REC describes stored configuration, not live measurements.
|
|
100
|
+
|
|
101
|
+
Settings writes use `POST /devices/{dev}/` with the fields to change; preserve
|
|
102
|
+
the trailing slash. For example, `{"Format":"fahrenheit"}` changes the
|
|
103
|
+
thermostat's screen setting. The response can echo stored values without
|
|
104
|
+
proving application. Legacy history and schedule endpoints also use R.
|
|
105
|
+
|
|
106
|
+
### L — legacy REST on the older host
|
|
107
|
+
|
|
108
|
+
Use `https://app-prod.mysa.cloud` with the **same authentication and request
|
|
109
|
+
formats as R**. For example, `GET /devices/state` and
|
|
110
|
+
`POST /devices/{dev}/` work on both. Treat L as a compatibility route for
|
|
111
|
+
specific operations, not an additional source to poll continuously.
|
|
112
|
+
|
|
113
|
+
Availability is operation-specific: saved-schedule event editing works on L
|
|
114
|
+
but returns 404 on R; some R discovery routes and current services return 403
|
|
115
|
+
on L. The client's existing `replace_device()` uses L's `/devices/purgeadd`.
|
|
116
|
+
Do not replace the entire client's base URL to obtain legacy telemetry.
|
|
117
|
+
|
|
118
|
+
## Operations and relevance to Home Assistant
|
|
119
|
+
|
|
120
|
+
This is the consolidated operation inventory, independent of API flavor.
|
|
121
|
+
**Include** means a normal client capability; **Consider** means optional or
|
|
122
|
+
model-specific; **Skip** means no dedicated new client method or routine HA
|
|
123
|
+
polling. Existing maintenance helpers can remain even when a full app feature
|
|
124
|
+
is not recommended. Read/write labels describe the operation, not a host.
|
|
125
|
+
|
|
126
|
+
| Operation | What it does | HA recommendation |
|
|
127
|
+
| --- | --- | --- |
|
|
128
|
+
| Account/device discovery · read | Finds homes, device IDs, models, names, and membership | **Include** the discovery needed for setup; do not build account administration |
|
|
129
|
+
| Capabilities · read | Describes supported modes, controls, ranges, and model features | **Include**; combine with observed valid readings, rather than trusting every flag |
|
|
130
|
+
| Room temperature / humidity · read | Reports ambient conditions | **Include**; climate and humidity entities |
|
|
131
|
+
| Setpoint / operating mode · read/write | Selects the requested temperature and heating/cooling/off mode | **Include**; core climate controls |
|
|
132
|
+
| AC fan / swing · read/write | Selects fan speed and vent direction | **Include when supported**; honor the AC remote's available commands |
|
|
133
|
+
| Heating activity / runtime · read | Reports recent duty and accumulated heating time | **Include**; distinguish interval activity from an instantaneous relay state |
|
|
134
|
+
| Measured electrical data · read | Reports power/current/energy on hardware that measures it | **Consider by model**; skip Lite's zero/unmeasured fields; label calculated energy as an estimate |
|
|
135
|
+
| Setpoint limits · read/write | Restricts temperatures accepted at the thermostat | **Include**; hardware constraints remain useful with HA automations |
|
|
136
|
+
| Temperature offset · read/write | Calibrates the thermostat's ambient reading/control | **Include**; do not substitute an HA display-only correction |
|
|
137
|
+
| Button lock · read/write | Locks the physical controls | **Include** as device configuration |
|
|
138
|
+
| Wake / idle brightness · read/write | Sets the physical display's two brightness levels | **Include** as device configuration |
|
|
139
|
+
| Display units · read/write | Chooses Celsius/Fahrenheit on the thermostat screen | **Include**; independent of HA's display units |
|
|
140
|
+
| Heater profile · read/write | Selects the installed heater's switching profile | **Include** as installation configuration, not a routine automation target |
|
|
141
|
+
| Floor limits/probe, adaptive display, remote tracking, HVAC configuration · read/write | Configures model-specific sensors and control behavior | **Consider only on matching hardware**; Lite cannot validate these controls |
|
|
142
|
+
| Identity / installed firmware · read | Identifies hardware and current firmware | **Include** as device metadata |
|
|
143
|
+
| Device name / time zone · read/write | Stores Mysa's label and schedule time zone | **Read** for discovery/schedule interpretation; **skip cloud rename**, consider time-zone writes only for explicit Mysa schedule setup |
|
|
144
|
+
| Firmware availability / update · read/write | Checks for an offered version and requests installation | **Include**; user-initiated update, not an automatic consequence of polling |
|
|
145
|
+
| Cloud connection / data age · read | Describes API reachability and thermostat reporting freshness | **Include** separate health/freshness diagnostics |
|
|
146
|
+
| RSSI / internal temperatures / free heap · read | Helps diagnose radio, sensor, or firmware behavior | **Consider** diagnostics, disabled by default; not extra climate readings |
|
|
147
|
+
| Live reporting · write | Temporarily asks devices to upload more frequently | **Consider** for cloud responsiveness and troubleshooting; not a permanent background stream by default |
|
|
148
|
+
| Usage / reading history · read | Supplies runtime totals and past measurements | **Include runtime**; **consider** history for gaps/troubleshooting, not a duplicate HA recorder |
|
|
149
|
+
| State-change history · read | Explains what changed a target or mode | **Consider** on demand when Mysa and HA behavior disagree |
|
|
150
|
+
| Device schedules · read/write | Stores timed thermostat actions | **Include inspection/removal** of conflicting existing schedules; **exclude** in-place schedule editing as a client feature. Prefer HA scheduling |
|
|
151
|
+
| Hold / resume · read/write | Overrides a Mysa schedule temporarily or permanently, then resumes it | **Include when a Mysa schedule exists**; HA-only scheduling does not need a cloud hold for every command |
|
|
152
|
+
| Home/Away/Vacation shortcuts · read/write | Applies a stored bundle of device actions | **Consider inspection/cleanup** for coexistence; **skip new shortcut creation/apply UI**, use HA scenes |
|
|
153
|
+
| Demand-response state · read | Indicates a utility event that may affect behavior | **Consider** a read-only explanation/status; skip enrollment management |
|
|
154
|
+
| Device claim / replacement / removal · write | Changes the device's association with a Mysa account | **Consider** explicit setup/recovery tools only; not normal thermostat control |
|
|
155
|
+
| Saved schedule templates · read/write | Stores reusable schedules and applies copies to devices | **Skip** template management; recognize applied device schedules through the schedule operation above |
|
|
156
|
+
| Mysa zones / aggregate energy · read/write | Groups devices and summarizes a Mysa home/zone | **Skip**; use HA areas/groups and validated energy sources |
|
|
157
|
+
| Geofences / crossings · read/write | Runs Mysa actions when a phone enters or leaves | **Skip**; use HA presence and automations |
|
|
158
|
+
| Alerts / reminders / notifications · read/write | Stores thresholds, reminders, push tokens, and notification preferences; sends notifications | **Skip**; use HA automations and notification services |
|
|
159
|
+
| Mysa account/home/access management · read/write | Edits profiles/homes, transfers access, manages invitations, or deletes accounts | **Skip** beyond discovery required for setup |
|
|
160
|
+
| App/third-party services · read/write | Handles app flags, phone diagnostics, analytics, localization, Alexa authorization, and property-manager features | **Skip**; they do not improve thermostat control in HA |
|
|
161
|
+
| Obsolete provisioning helpers · read/write | Supplies legacy NFC or anonymous AC-setup credentials | **Skip**; separate from an authenticated HA thermostat client |
|
|
162
|
+
| Mysa eco / Early On / animation settings · read/write | Supplies app-specific energy/schedule behavior and display animation | **Skip new methods**; prioritize HA scheduling and the explicit hardware controls above. Early On is unavailable on Lite; eco/animation effects were not established |
|
|
163
|
+
|
|
164
|
+
## Read/write comparisons
|
|
165
|
+
|
|
166
|
+
`—` means no applicable mapping in our evidence, not proof that no future
|
|
167
|
+
endpoint could expose it. **Reported** means the changed value appeared in ST;
|
|
168
|
+
**applied** means thermostat behavior independently confirmed it. **Stored**
|
|
169
|
+
means only a record round trip was established. Model-specific entries below
|
|
170
|
+
come from app/code mappings, not Lite hardware validation.
|
|
171
|
+
|
|
172
|
+
### Read matrix
|
|
173
|
+
|
|
174
|
+
R and L cells name the data source, not just a similarly named field. `= R`
|
|
175
|
+
means the same route/format is available; it is not another vote for a value.
|
|
176
|
+
|
|
177
|
+
| Value | S | R | L |
|
|
178
|
+
| --- | --- | --- | --- |
|
|
179
|
+
| Room temperature / humidity | TEL `roomTemperature` / `humidity` | LT `CorrectedTemp.v` / `Humidity.v` | = R |
|
|
180
|
+
| Internal temperatures | TEL `rawTemperature`, `coreTemperature` | LT `SensorTemp.v`, `HeatSink.v` | = R |
|
|
181
|
+
| Heating target | ST `targetHeat.setpoint`; TEL `heatSetpoint` | LT `SetPoint.v` | = R |
|
|
182
|
+
| Operating mode | ST `modes.mode`; TEL `mode` uses a different enum | LT `Mode.v`, `TstatMode.v`, each with its own enum | = R |
|
|
183
|
+
| Cooling / AC controls | ST `targetCool.setpoint`, `modes.fan_mode`, `verticalSwingState`, `horizontalSwingState` | REC `SupportedModes` / `SupportedCaps` describes available commands, not current state | = R formats; other-model support not live-verified |
|
|
184
|
+
| Minimum / maximum target | ST `targetHeat.lockoutMin` / `lockoutMax` | REC `MinSetpoint` / `MaxSetpoint` | = R |
|
|
185
|
+
| Button lock | ST `physicalInterface.lockout` | LT `Lock.v`; REC `ButtonState` | = R |
|
|
186
|
+
| Wake / idle brightness | ST `physicalInterface.activeIntensity` / `idleIntensity` | REC `MaxBrightness` / `MinBrightness`; LT `Brightness.v` is only one value | = R |
|
|
187
|
+
| Screen units | ST `physicalInterface.format` | REC `Format` | = R |
|
|
188
|
+
| Temperature offset | ST `tracking.ambientOffset` | — | — |
|
|
189
|
+
| Heater profile | ST `bbConfig.controlType` | REC `DutyCycleOpt` | = R |
|
|
190
|
+
| Heating activity / interval runtime | TEL `dutyCycle`, `onTime` | LT `Duty.v`, `OnTime.v`, `OffTime.v` | = R |
|
|
191
|
+
| Electrical data | TEL `voltage`, `maxCurrent`, `powerConsumed`, `instantLoad`; ST `power` | LT `Voltage.v`, `Current.v`; REC `Voltage` is configuration | = R |
|
|
192
|
+
| RSSI / free heap | TEL `rssi`, `freeHeap` | LT `Rssi.v`, `FreeHeap.v` | = R |
|
|
193
|
+
| Connection / timestamps | `latestTelemetry.isConnected`, `lastConnected`; TEL `timestamp`; ST section timestamps | LT `Connected.v/t`, individual field `t`, top-level `Timestamp` | = R |
|
|
194
|
+
| Identity / names / time zone | ST `identity.model`, `fw`; bootstrap account data | REC `Id`, `Model`, `Name`, `Home`, `TimeZone` | = R |
|
|
195
|
+
| Capabilities | `GET /capabilities/{dev}` | `GET /devices/capabilities`; REC for model-specific command metadata | Capability-list route returns 403; REC still works |
|
|
196
|
+
| Firmware availability | — | `GET /devices/update_available/{dev}`; `/devices/firmware` lists versions | = R |
|
|
197
|
+
| Usage / raw history | `POST /telemetry/usage/{dev}` | `POST /batchReadings/v2/{dev}` | Same route, but bucket keys can differ |
|
|
198
|
+
| Change history | `GET /state/history/{dev}` | `POST /energy/setpoints/device/{dev}` for target changes | = R |
|
|
199
|
+
| Active schedules / holds | `GET /schedule?homeId={home}`; `/schedule/hold/{dev}` | `GET /schedules` (v1), `/schedules/v2/{dev}` (v2); LT `ScheduleMode` / `HoldTime` are hints | = R |
|
|
200
|
+
| Shortcuts / demand response | ST `drState` where present | `GET /homes/{home}/scenes`; `/devices/{dev}/drstate` | = R |
|
|
201
|
+
|
|
202
|
+
### Write matrix
|
|
203
|
+
|
|
204
|
+
S field paths below are sent in `POST /state/{dev}/update`; R/L settings
|
|
205
|
+
fields are sent in `POST /devices/{dev}/`. These are available routes, not a
|
|
206
|
+
recommendation to use them all.
|
|
207
|
+
|
|
208
|
+
| Operation | S | R | L |
|
|
209
|
+
| --- | --- | --- | --- |
|
|
210
|
+
| Heating target | `targetHeat.setpoint`: applied on one Lite, unconfirmed on the other | — | — |
|
|
211
|
+
| Heat / off | `modes.mode` = 4 / 0: same mixed application | REC `Mode` object: stored only, **not a working mode command** | = R |
|
|
212
|
+
| AC target / fan / swing | `targetCool.setpoint`, `modes.fan_mode`, directional swing fields; model-specific | No verified direct control mapping | = R |
|
|
213
|
+
| Button lock | `physicalInterface.lockout` = 3 / 0: reported | `ButtonState` = `Locked` / `Unlocked`: reported | = R |
|
|
214
|
+
| Wake / idle brightness | `physicalInterface.activeIntensity` / `idleIntensity`: reported | `MaxBrightness` / `MinBrightness`: reported | = R |
|
|
215
|
+
| Temperature offset | `tracking.ambientOffset`: reported | — | — |
|
|
216
|
+
| Setpoint limits | `targetHeat.lockoutMin` / `lockoutMax`: reported | `MinSetpoint` / `MaxSetpoint`: reported | = R |
|
|
217
|
+
| Screen units | `physicalInterface.format` = `C` / `F`: applied | `Format` = `celsius` / `fahrenheit`: applied | = R |
|
|
218
|
+
| Heater profile | `bbConfig.controlType` = 8 / 9: reported | `DutyCycleOpt` = 8 / 9: reported | = R |
|
|
219
|
+
| Device name / time zone | — | `Name` / `TimeZone`: stored | = R |
|
|
220
|
+
| Schedules | `POST /schedule`; full-body `PUT /schedule/{id}`; `DELETE /schedule/{id}/attach/{dev}` | v1 `POST /schedules/device/update/{dev}`; v2 `POST /schedules/v2/`, `DELETE /schedules/v2/{id}` | = R, with v1 body difference noted below |
|
|
221
|
+
| Hold / resume | `POST /schedule/hold`; `DELETE /schedule/hold/{dev}`: stored/removed | — | — |
|
|
222
|
+
| Firmware trigger | `POST /devices/{dev}/firmware-update` with JSON `{}`: accepted | — | Same trigger returns 403 |
|
|
223
|
+
| Live reporting | `POST /mysa-legacy/stream/home/{home}` with `{"timeout":seconds}`: accepted | — | Same route returns 403 |
|
|
224
|
+
| Claim / remove / replace | — | `POST /devices`, `DELETE /devices/{dev}` | Claim/delete work; existing replacement uses `POST /devices/purgeadd` |
|
|
225
|
+
|
|
226
|
+
The remaining app-oriented operations are intentionally compact here: shortcut
|
|
227
|
+
edit/apply, alert, zone, geofence, and reminder record operations worked on R
|
|
228
|
+
and L; shortcut application was inconsistent. Saved-template create/rename/
|
|
229
|
+
apply/delete worked on both, but event editing worked only on L (R: 404).
|
|
230
|
+
`ecoMode` and `Animation` settings persisted on both without verified physical
|
|
231
|
+
effects. These results do not justify expanding the HA client with those app
|
|
232
|
+
features. Other account/app administration is known from app sources, not
|
|
233
|
+
validated as thermostat functionality.
|
|
234
|
+
|
|
235
|
+
## Recommended reconciliation of cloud reads
|
|
236
|
+
|
|
237
|
+
The following is a conservative cloud-only selection policy for an integrating application. Home Assistant maintains its own acquisition and selection implementation in the [cloud tracker](https://github.com/SokolskyNikita/mysa-homeassistant/blob/main/docs/implementation/cloud.md).
|
|
238
|
+
Use **S + R** for normal cloud state acquisition: one S batch and one R legacy
|
|
239
|
+
state request at the configured cloud interval. Cache REC separately. Use L
|
|
240
|
+
as a replacement for a failing R route with backoff, not a third permanent
|
|
241
|
+
poll. Do not average values or count matching R/L responses as corroboration.
|
|
242
|
+
|
|
243
|
+
### One selection rule, applied per field
|
|
244
|
+
|
|
245
|
+
1. **Normalize.** Decode each source into the same units/enums and preserve
|
|
246
|
+
`source`, `observed_at`, and `fetched_at`. Parse ISO timestamps and Unix
|
|
247
|
+
seconds/milliseconds. Use the individual LT field's `t`, TEL's reading
|
|
248
|
+
timestamp, or the relevant ST section timestamp; never borrow a sibling
|
|
249
|
+
field's timestamp. Keep target temperature separate from an effective
|
|
250
|
+
target altered by a hold or other control behavior.
|
|
251
|
+
2. **Validate.** Reject missing, malformed, non-finite, or semantically invalid
|
|
252
|
+
values. Zero and `false` are valid where the field allows them. A timestamp
|
|
253
|
+
more than one minute in the future is invalid (the existing HA guard); do not let it win a
|
|
254
|
+
newest-value comparison. A valid clock on one section does not validate
|
|
255
|
+
another section.
|
|
256
|
+
3. **Choose by the field policy below.** For **Latest** fields, choose the
|
|
257
|
+
newest valid, fresh observation; ties prefer S, then R, then L. Include the
|
|
258
|
+
cached observation so a delayed response cannot roll a newer value back. An
|
|
259
|
+
un-timestamped measurement is not fresh merely because its HTTP response
|
|
260
|
+
just arrived. For **Config** fields, use the named authority/fallback;
|
|
261
|
+
their change timestamps may legitimately be old. REC is stored intent,
|
|
262
|
+
never another device measurement.
|
|
263
|
+
4. **Keep provenance.** Retain last-known values with their original age when
|
|
264
|
+
no fresh candidate exists; expose stale/unavailable state rather than
|
|
265
|
+
refreshing their timestamps. A missing field or failed device in a batch
|
|
266
|
+
must not erase good data for other fields/devices. Keep pending writes
|
|
267
|
+
separate from confirmed readings.
|
|
268
|
+
|
|
269
|
+
For measurement freshness, a suggested starting limit is **35 minutes outside
|
|
270
|
+
live reporting**, because ordinary Lite uploads can be 12–30 minutes apart.
|
|
271
|
+
During an established live-reporting session, use **max(90 seconds, three poll
|
|
272
|
+
intervals)**. These are configurable policy defaults, not vendor guarantees
|
|
273
|
+
or a claim that a 30-minute-old temperature is real-time. A future-dated
|
|
274
|
+
measurement is rejected rather than having its clock silently corrected.
|
|
275
|
+
For a configuration field with an invalid timestamp, do not use that timestamp
|
|
276
|
+
to outrank another source; retain its unconfirmed/last-known status.
|
|
277
|
+
|
|
278
|
+
| Field / operation | Selection and HA behavior |
|
|
279
|
+
| --- | --- |
|
|
280
|
+
| Room temperature / humidity | **Latest** S TEL vs R/L LT. Use `CorrectedTemp`, never internal sensor temperatures. Accept valid humidity even when the Lite capability flag says false |
|
|
281
|
+
| Heating target / mode | Use the newest plausibly timestamped device report from ST or LT; use TEL only after matching target semantics and decoding its different mode enum. Unlike measurements, an unchanged target need not expire after 35 minutes. Without comparable timestamps prefer ST, then LT, and mark freshness unknown. Never use REC `Mode` or S `desired` as confirmation |
|
|
282
|
+
| Cooling target / fan / swing | **Config:** ST; REC only describes allowed choices. No verified legacy-state fallback in this guide |
|
|
283
|
+
| Minimum / maximum target | **Config:** ST pair, then REC pair if absent; validate minimum ≤ maximum. Never turn an uncertain/fallback value into permission to exceed known device limits |
|
|
284
|
+
| Button lock | Prefer the newest valid device report from ST or LT when timestamps are comparable; otherwise ST, then LT. REC is a stored-setting fallback only |
|
|
285
|
+
| Wake / idle brightness | **Config:** ST pair, then REC pair. LT's single brightness value cannot reconstruct both settings |
|
|
286
|
+
| Screen units | **Config:** REC `Format`, ST as fallback. ST has lagged the screen setting. This selects the configured screen units, not proof of physical application or HA's preferred display unit |
|
|
287
|
+
| Temperature offset | **Config:** ST only; absent means unknown, not zero |
|
|
288
|
+
| Heater profile | **Config:** ST, then REC `DutyCycleOpt` as stored configuration; validate against the device family |
|
|
289
|
+
| Heating activity | **Latest** normalized duty/interval observation. Keep each source's interval meaning; do not add R/L duty or runtime together or infer heater-off from Lite's zero power fields |
|
|
290
|
+
| Runtime / history | Prefer S usage `oH1` for runtime; R batch history only as an explicit fallback after bucket/unit normalization. Fetch bounded periods and do not sum overlapping sources. Historical samples do not become current readings |
|
|
291
|
+
| Identity / name / time zone / firmware | REC for identity/name/time zone; firmware information endpoint for offered/installed version, with ST identity as installed-version fallback. Cache metadata rather than treating old unchanged values as stale telemetry |
|
|
292
|
+
| Capabilities / model controls | S capabilities plus REC model/remote metadata. Preserve hardware limits; do not invent unsupported controls. Model-specific configuration has no general Lite fallback |
|
|
293
|
+
| Schedules / holds | Read S schedules and holds, plus legacy schedule sources when inspecting existing Mysa automation. An empty S list does not establish that no legacy schedule exists. Do not use REC `Schedule` or LT hold hints as the complete resource |
|
|
294
|
+
| Shortcuts / demand response | On-demand shortcut inspection through R/L. For demand response use ST when present, otherwise the dedicated R route; no merging of unrelated account mode fields |
|
|
295
|
+
| Connection / health | Keep request success and data freshness separate for S and legacy reads. A 200 or connected flag cannot make stale measurements fresh; track selected source and age per field. Do not let one failing API mark both paths failed |
|
|
296
|
+
| RSSI / internal temperatures / heap | Apply **Latest** only when diagnostics are requested/enabled. Discard from normal entity publication otherwise |
|
|
297
|
+
| Lite electrical values, unreliable energy summaries, and **Skip** operations | Do not request extra endpoints or create entities for them. Ignore incidental fields returned in shared responses |
|
|
298
|
+
|
|
299
|
+
Cache records at a slower interval (the integration currently uses 10 minutes),
|
|
300
|
+
usage at 15 minutes, firmware at six hours, and capabilities at 24 hours.
|
|
301
|
+
Refresh affected configuration after a command and after rediscovery. Read
|
|
302
|
+
optional schedules/history/diagnostics on demand or when that feature is
|
|
303
|
+
actually enabled. These are cloud fetch rules, not local/cloud routing rules.
|
|
304
|
+
|
|
305
|
+
## Recommended reconciliation of cloud writes
|
|
306
|
+
|
|
307
|
+
**Choose one route per semantic command. Do not broadcast every write to S,
|
|
308
|
+
R, and L, and do not copy discrepant readings back into the other APIs.**
|
|
309
|
+
Most differences reflect lag or representation, not three stores to repair.
|
|
310
|
+
|
|
311
|
+
| Command | Preferred route | Alternative / verification |
|
|
312
|
+
| --- | --- | --- |
|
|
313
|
+
| Setpoint / mode; supported AC controls | S | No verified R/L replacement. Confirm device-reported values with the read policy; REC `Mode` is not a fallback |
|
|
314
|
+
| Offset | S | No verified alternative; confirm ST |
|
|
315
|
+
| Lock / brightness / setpoint limits | S | R settings are a validated alternative; L is the same legacy path on another host. Select an alternative for a known route/device limitation, not as routine fan-out. Confirm ST or equivalent LT; a REC echo alone is insufficient |
|
|
316
|
+
| Screen units | R settings | L if that route is unavailable; S is also supported. Read REC for configured units and ST for reported confirmation when it catches up |
|
|
317
|
+
| Heater profile | R settings | L as host fallback; S is also supported. Read REC and ST, preserving a pending/mismatched state if application is unconfirmed |
|
|
318
|
+
| Existing device schedule creation | S, only when explicitly using Mysa scheduling | Keep an existing legacy schedule in its native format unless deliberately migrating it. Avoid creating parallel S/v1/v2 schedules for the same intent. Full-body in-place editing is outside client scope |
|
|
319
|
+
| Schedule removal / hold / resume | Remove through the resource's native route; S for holds | Re-read that schedule/hold source. Removing a template is not removing its applied schedules; a hold record alone does not confirm an immediate target change |
|
|
320
|
+
| Firmware update / temporary live reporting | S dedicated endpoint | Confirm firmware availability/version or advancing telemetry, respectively; no R/L duplicate trigger |
|
|
321
|
+
| Claim / remove / replace | Existing explicit setup/recovery method | Use the documented operation and host; never run these as automatic write-repair strategies |
|
|
322
|
+
| Time zone | R, only for an explicit Mysa schedule configuration request | Verify REC; changing HA's time zone must not silently rewrite the thermostat |
|
|
323
|
+
| **Skip** operations, cloud renaming, app-only settings | No new write path | Use HA's corresponding features; no background synchronization into the Mysa app |
|
|
324
|
+
|
|
325
|
+
Validate capabilities and ranges, serialize changes per device, and send the
|
|
326
|
+
smallest semantic change. Send both brightness values together; preserve a
|
|
327
|
+
valid minimum/maximum pair. A setpoint change and a mode change are distinct
|
|
328
|
+
commands unless deliberately combined in one S body. Use the mode-specific
|
|
329
|
+
AC fan conversion in `commands.py`; raw enum values are not interchangeable.
|
|
330
|
+
|
|
331
|
+
Record an accepted command as **pending**, then re-read its confirmation
|
|
332
|
+
source. Matching `desired` or echoed REC is not physical confirmation. If the
|
|
333
|
+
requested value already matched the previous confirmed state, treat it as an
|
|
334
|
+
idempotent no-op, not a liveness test. A changed device report can confirm
|
|
335
|
+
application; where only REC is available, report stored configuration without
|
|
336
|
+
claiming device confirmation.
|
|
337
|
+
|
|
338
|
+
An explicit unsupported-route response can justify a validated alternative.
|
|
339
|
+
After a timeout or 200 without confirmation, re-read first: the command may
|
|
340
|
+
still apply. Do not immediately resend through another API, oscillate settings
|
|
341
|
+
to force synchronization, or apply a late retry after a newer user command.
|
|
342
|
+
Use bounded retries/backoff. Resource creation, firmware triggers, and other
|
|
343
|
+
non-idempotent actions require checking their outcome before any retry.
|
|
344
|
+
|
|
345
|
+
## Other protocol and implementation details
|
|
346
|
+
|
|
347
|
+
### Important wire rules
|
|
348
|
+
|
|
349
|
+
| Area | Rule |
|
|
350
|
+
| --- | --- |
|
|
351
|
+
| Time / mode | Legacy field timestamps can mix seconds and milliseconds in one response. S `modes.mode`, TEL `mode`, and LT mode fields have different enums; Lite heat is S mode 4 but TEL mode 3 |
|
|
352
|
+
| Telemetry quality | One Lite returned implausible future TEL timestamps while LT returned current readings. Freshness must be per field/source, not inferred from HTTP success |
|
|
353
|
+
| Electrical data | Lite current/power fields were zero and voltage was configured; legacy device energy summaries also produced implausible averages. Neither establishes measured consumption |
|
|
354
|
+
| Usage | `/telemetry/usage/{dev}` uses `timezone`, Unix-second `start`/`end`, `summary`, and `aggregatedReadings`; raw readings need the expanded request described in the [usage reference](../../../docs/cloud-state.md#usage) |
|
|
355
|
+
| Legacy batch history | `/batchReadings/v2/{dev}` takes `attributes`, `start`, `end`, `attributesProcesses`; relevant fields include `h`, `c`, `s`, `a.oC`, `a.oH`, `ms`, `fs`, `tm`, `t`. Use `sum` for runtime counters, `none` for raw values; normalize timestamp-keyed buckets before use |
|
|
356
|
+
| Modern schedules | Events use Sunday = `"0"`, local `HH:MM:00`, `clientKey`, and semantic `state`. Use the device's `TimeZone`. In-place PUT needs `name`, `events`, `deviceType`, `homeId`, `deviceIds`, `reusable`; a name/events-only body fails |
|
|
357
|
+
| Legacy v1 schedules | POST body uses `ScheduledActions`, mapping weekday names to `{Minute,SetPoint}` entries. R additionally requires `Device` and `Model`. Seven empty weekday arrays clear events |
|
|
358
|
+
| Legacy v2 schedules | POST body: `Schedule` with `Version`, `Owner`, `Events` (plus `Id` for update), `Devices`, and `Model`. GET uses the **device ID**; DELETE uses the **schedule ID** with `Devices` and `Model` in its body |
|
|
359
|
+
| Schedule discovery | Modern lists can omit legacy schedules; REC `Schedule` can retain a deleted ID. Inspect the actual legacy resources. Saved-template apply creates separate `V2Schedules` resources |
|
|
360
|
+
| Holds | `startTime` must be in the future; the client adds ten seconds. Temporary holds add `endTime`. Both are UTC ISO timestamps. Do not infer an immediate setpoint change merely from hold creation |
|
|
361
|
+
| Firmware | POST the trigger with JSON `{}`; a bodyless request returned 415. Trigger acceptance is not completed installation. No newer release was available during validation |
|
|
362
|
+
| Newer-model features | Lite rejected Smart Early On eligibility and had no newer OTA fleet. Remote tracking was not reported after a direct write. Gate these features by model; accepting `desired` is not support |
|
|
363
|
+
|
|
364
|
+
For legacy v2 schedules, `Events` maps weekday number → minute number → device
|
|
365
|
+
command. A Lite example is `{"0":{"1437":{"BB2L":"3|22|%|%|%|%|%"}}}`.
|
|
366
|
+
The pipe-separated command has its own legacy enum/field ordering; do not
|
|
367
|
+
insert S's mode number. Detailed other-model and provisioning notes remain in
|
|
368
|
+
the [state and model reference](../../../docs/cloud-state.md) and
|
|
369
|
+
[account/schedule workflows](../../../docs/cloud-workflows.md). This guide
|
|
370
|
+
owns the reconciled protocol conclusions and selection recommendations.
|
|
371
|
+
|
|
372
|
+
### Integration status and validation
|
|
373
|
+
|
|
374
|
+
The client exposes the documented endpoints and semantic encoders, with
|
|
375
|
+
model-specific mappings that remain app/code-derived unless hardware evidence is
|
|
376
|
+
identified. Automated protocol tests use simulated responses and do not establish
|
|
377
|
+
device compatibility. Live validation currently covers two Baseboard Lite
|
|
378
|
+
`BB-V2-0-L` devices on firmware `3.17.5.13`; their cloud setpoint and mode
|
|
379
|
+
application differed. Other model profiles, full schedule execution, notification
|
|
380
|
+
delivery, and installation of a new firmware release remain unverified. The
|
|
381
|
+
[Home Assistant cloud tracker](https://github.com/SokolskyNikita/mysa-homeassistant/blob/main/docs/implementation/cloud.md)
|
|
382
|
+
separately records integration policy, gaps, and validation work.
|
|
383
|
+
|
|
384
|
+
### Using the client
|
|
385
|
+
|
|
386
|
+
`MysaAuth` and `MysaClient` are exported by [`__init__.py`](__init__.py).
|
|
387
|
+
The caller supplies and closes the `aiohttp` session. See the complete
|
|
388
|
+
[cloud example](../../../examples/cloud_basic.py) for login, token persistence,
|
|
389
|
+
account discovery, reading, and an explicitly enabled setpoint write.
|
|
390
|
+
|
|
391
|
+
### How it is organized
|
|
392
|
+
|
|
393
|
+
| File | Responsibility |
|
|
394
|
+
| --- | --- |
|
|
395
|
+
| [`auth.py`](auth.py), [`srp.py`](srp.py) | Cognito authentication, serialized token refresh, SRP calculations |
|
|
396
|
+
| [`client.py`](client.py) | HTTP requests, endpoint methods, response handling |
|
|
397
|
+
| [`commands.py`](commands.py) | Semantic controls, enum conversion, schedule encoding |
|
|
398
|
+
| [`models.py`](models.py) | Typed response parsing, preserving original JSON in `raw` |
|
|
399
|
+
| [`const.py`](const.py), [`exceptions.py`](exceptions.py) | Hosts, protocol constants/enums, errors |
|
|
400
|
+
|
|
401
|
+
The standalone package has no Home Assistant dependency. The integration owns
|
|
402
|
+
polling, per-field freshness, command confirmation, and local/cloud
|
|
403
|
+
reconciliation; see its
|
|
404
|
+
[architecture guide](https://github.com/SokolskyNikita/mysa-homeassistant/blob/main/docs/architecture.md).
|
|
405
|
+
The project metadata says `0.1.0`, but no release has been published yet.
|
|
406
|
+
|
|
407
|
+
### Public API and integration helpers
|
|
408
|
+
|
|
409
|
+
The supported top-level API is exported by [`__init__.py`](__init__.py):
|
|
410
|
+
`MysaAuth`, `Tokens`, `MysaClient`, `Bootstrap`, `Capabilities`,
|
|
411
|
+
`DeviceRecord`, `DeviceState`, `FirmwareInfo`, `StateChange`, `UsageBucket`,
|
|
412
|
+
`UsageDay`, `Mode`, `AcFan`, `ButtonLock`, `HeaterType`, `DutyCycleOpt`,
|
|
413
|
+
`Swing`, `ModelFamily`, `MysaError` and its typed subclasses, plus
|
|
414
|
+
`ScheduleEventSpec`, `encode_schedule_events`, `make_state`, `model_family`,
|
|
415
|
+
`value_range`, `iso_utc`, and `jwt_claims`.
|
|
416
|
+
|
|
417
|
+
These additional submodule helpers are also supported because the Home
|
|
418
|
+
Assistant consumer imports them directly:
|
|
419
|
+
|
|
420
|
+
| Module | Supported names |
|
|
421
|
+
| --- | --- |
|
|
422
|
+
| [`commands.py`](commands.py) | `auto_temperature_changes`, `button_lock_changes`, `display_brightness_changes`, `display_unit_settings`, `fan_speed_changes`, `heater_type_settings`, `hvac_fan_changes`, `mode_changes`, `setpoint_limit_changes`, `swing_changes`, `temperature_changes`, `temperature_offset_changes` |
|
|
423
|
+
| [`const.py`](const.py) | `API_BASE`, `EXPERIMENTAL_CLOUD_FAMILIES`, `SWING_VERTICAL`, `model_family`; public models and enums are also re-exported at the package level |
|
|
424
|
+
| [`models.py`](models.py) | The response models exported by the package root, retained at this submodule path for direct imports |
|
|
425
|
+
| [`exceptions.py`](exceptions.py) | The public `MysaError` exception hierarchy, retained at this submodule path for direct imports |
|
|
426
|
+
| [`observations.py`](observations.py) | `MEASUREMENT_MAX_AGE`, `MEASUREMENTS`, `STATE_FIELDS`, `TELEMETRY_FIELDS`, `Observation`, `number`, `observe`, `valid_value` |
|
|
427
|
+
| [`trace.py`](trace.py) | `route_template` for redacted request-route reporting |
|
|
428
|
+
| [`validation.py`](validation.py) | `validate_basic_command` for conservative validation of experimental models |
|
|
429
|
+
|
|
430
|
+
Other names prefixed with an underscore are private implementation details.
|
|
431
|
+
|
|
432
|
+
### Errors, timeouts, retries, and caller responsibilities
|
|
433
|
+
|
|
434
|
+
The current transport uses a 20-second timeout. A 401 causes one forced token
|
|
435
|
+
refresh and retry; a remaining 401 or 403 raises `MysaApiError`, not automatic
|
|
436
|
+
reauthentication. Route absence or permissions can explain 403. A 404 raises
|
|
437
|
+
`MysaNotFoundError`; only resource-specific helpers such as schedule/hold reads
|
|
438
|
+
normalize an absent resource to an empty result. A 429 raises
|
|
439
|
+
`MysaRateLimitError` with numeric `Retry-After` when supplied; timeout,
|
|
440
|
+
transport failure, or 5xx raises `MysaConnectionError`. There is no general
|
|
441
|
+
transport retry loop. A 401 retry only follows a forced token refresh; ambiguous
|
|
442
|
+
commands are never replayed after cancellation, timeout, or connection loss. The
|
|
443
|
+
legacy host fallback is limited to known operations and eligible failures; it is
|
|
444
|
+
not a general retry or a second measurement source. The caller owns polling,
|
|
445
|
+
backoff, freshness, and deciding how to reconcile an uncertain command.
|
|
446
|
+
|
|
447
|
+
Cognito failures use the `MysaAuthError` hierarchy. The implementation handles
|
|
448
|
+
the password-verifier SRP challenge; unsupported challenges raise
|
|
449
|
+
`MysaUnsupportedChallengeError`.
|
|
450
|
+
|
|
451
|
+
### Validation references
|
|
452
|
+
|
|
453
|
+
HTTP/parser behavior is covered by [`tests/cloud/test_client.py`](../../../tests/cloud/test_client.py)
|
|
454
|
+
and SRP by [`tests/cloud/test_srp.py`](../../../tests/cloud/test_srp.py), using
|
|
455
|
+
fixtures rather than live devices. Live checks established the distinctions
|
|
456
|
+
between accepted writes, stored records, and reported/applied values above;
|
|
457
|
+
full scheduled execution, notification delivery, and installation of a new
|
|
458
|
+
firmware release were not established. The two Lites also differed in cloud
|
|
459
|
+
setpoint/mode application, so confirmation remains necessary even for a
|
|
460
|
+
supported route.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Standalone async client for Mysa's cloud API.
|
|
2
|
+
|
|
3
|
+
Nothing in this package imports Home Assistant, so it can move to its own PyPI
|
|
4
|
+
package later.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .auth import MysaAuth, Tokens, jwt_claims
|
|
8
|
+
from .client import MysaClient, iso_utc
|
|
9
|
+
from .commands import ScheduleEventSpec, encode_schedule_events, make_state
|
|
10
|
+
from .const import (
|
|
11
|
+
MODEL_FAMILIES,
|
|
12
|
+
MODEL_NAMES,
|
|
13
|
+
SWING_HORIZONTAL,
|
|
14
|
+
SWING_VERTICAL,
|
|
15
|
+
TESTED_MODELS,
|
|
16
|
+
WIFI_ONLY_FAMILIES,
|
|
17
|
+
AcFan,
|
|
18
|
+
ButtonLock,
|
|
19
|
+
ChangeSource,
|
|
20
|
+
DutyCycleOpt,
|
|
21
|
+
HeaterType,
|
|
22
|
+
Mode,
|
|
23
|
+
ModelFamily,
|
|
24
|
+
Swing,
|
|
25
|
+
model_family,
|
|
26
|
+
)
|
|
27
|
+
from .exceptions import (
|
|
28
|
+
MysaApiError,
|
|
29
|
+
MysaAuthError,
|
|
30
|
+
MysaConnectionError,
|
|
31
|
+
MysaError,
|
|
32
|
+
MysaInvalidCredentialsError,
|
|
33
|
+
MysaNotFoundError,
|
|
34
|
+
MysaRateLimitError,
|
|
35
|
+
MysaUnsupportedChallengeError,
|
|
36
|
+
)
|
|
37
|
+
from .models import (
|
|
38
|
+
Bootstrap,
|
|
39
|
+
Capabilities,
|
|
40
|
+
DeviceRecord,
|
|
41
|
+
DeviceState,
|
|
42
|
+
FirmwareInfo,
|
|
43
|
+
StateChange,
|
|
44
|
+
UsageBucket,
|
|
45
|
+
UsageDay,
|
|
46
|
+
value_range,
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
__all__ = [
|
|
50
|
+
"MODEL_FAMILIES",
|
|
51
|
+
"MODEL_NAMES",
|
|
52
|
+
"SWING_HORIZONTAL",
|
|
53
|
+
"SWING_VERTICAL",
|
|
54
|
+
"TESTED_MODELS",
|
|
55
|
+
"WIFI_ONLY_FAMILIES",
|
|
56
|
+
"AcFan",
|
|
57
|
+
"Bootstrap",
|
|
58
|
+
"ButtonLock",
|
|
59
|
+
"Capabilities",
|
|
60
|
+
"ChangeSource",
|
|
61
|
+
"DeviceRecord",
|
|
62
|
+
"DeviceState",
|
|
63
|
+
"DutyCycleOpt",
|
|
64
|
+
"FirmwareInfo",
|
|
65
|
+
"HeaterType",
|
|
66
|
+
"Mode",
|
|
67
|
+
"ModelFamily",
|
|
68
|
+
"MysaApiError",
|
|
69
|
+
"MysaAuth",
|
|
70
|
+
"MysaAuthError",
|
|
71
|
+
"MysaClient",
|
|
72
|
+
"MysaConnectionError",
|
|
73
|
+
"MysaError",
|
|
74
|
+
"MysaInvalidCredentialsError",
|
|
75
|
+
"MysaNotFoundError",
|
|
76
|
+
"MysaRateLimitError",
|
|
77
|
+
"MysaUnsupportedChallengeError",
|
|
78
|
+
"ScheduleEventSpec",
|
|
79
|
+
"StateChange",
|
|
80
|
+
"Swing",
|
|
81
|
+
"Tokens",
|
|
82
|
+
"UsageBucket",
|
|
83
|
+
"UsageDay",
|
|
84
|
+
"encode_schedule_events",
|
|
85
|
+
"iso_utc",
|
|
86
|
+
"jwt_claims",
|
|
87
|
+
"make_state",
|
|
88
|
+
"model_family",
|
|
89
|
+
"value_range",
|
|
90
|
+
]
|