@cecnic1989/homebridge-roborock-mower 0.2.1 → 0.2.2

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/README.md CHANGED
@@ -30,8 +30,10 @@ Each state is a contact sensor so the Home app can trigger on it ("A Sensor Dete
30
30
  | **Mowing** | it starts cutting or driving to a zone | cutting stops |
31
31
  | **Returning** | it heads back to the dock | it reaches the dock |
32
32
 
33
- Example for a dock inside a garage: *Leaving opens → open garage*, *Mowing opens → close garage*, *Returning opens → open garage*, *Docked closes → close garage*.
34
- Note: the mower starts driving ~1.5 s after "Leaving" opens, so for the outbound trip pair it with a time-based automation on the mowing schedule if the door needs longer.
33
+ Example for a dock inside a garage: *Docked opens → open garage*, *Mowing opens → close garage*, *Returning opens → open garage*, *Docked closes → close garage*.
34
+ Prefer **Docked opens** over *Leaving opens* for the departure trigger: both fire on the same push, but Docked can only open once per trip. The mower starts driving ~1.5 s after that push, so if the door needs longer, add a time-based automation on the mowing schedule as well.
35
+
36
+ Accessories take the name you gave the mower in the Roborock app (renames follow on the next sync); names you set in the Home app are kept.
35
37
 
36
38
  Sensors flip only after a state holds for `sensorDebounceSeconds` (default 3 s); faults and battery update immediately. While the cloud connection is down, sensors show as inactive rather than stale.
37
39
 
@@ -25,10 +25,15 @@ export declare class MowerAccessory {
25
25
  private readonly applied;
26
26
  private readonly pending;
27
27
  private last;
28
+ private baseName;
29
+ private readonly debounceMs;
28
30
  constructor(hap: Hap, accessory: PlatformAccessory, log: Logging, options: SensorOptions);
29
31
  setInformation(info: DeviceInformation): void;
32
+ rename(displayName: string): void;
30
33
  update(state: DerivedState): void;
31
34
  setOnline(online: boolean): void;
35
+ dispose(): void;
36
+ private sensorName;
32
37
  private schedule;
33
38
  private apply;
34
39
  private pushFault;
@@ -1,7 +1,7 @@
1
1
  const SENSOR_LABELS = { docked: 'Docked', leaving: 'Leaving', mowing: 'Mowing', returning: 'Returning' };
2
2
  const SENSOR_KEYS = Object.keys(SENSOR_LABELS);
3
3
  // Home-app automations trigger on "opens"/"closes". Docked closes when the mower is home;
4
- // the activity sensors open when their activity starts, so "Leaving opens → open the garage" reads naturally.
4
+ // the activity sensors open when their activity starts, so "Docked opens → open the garage" reads naturally.
5
5
  function contactValue(key, active, c) {
6
6
  const detected = c.ContactSensorState.CONTACT_DETECTED;
7
7
  const notDetected = c.ContactSensorState.CONTACT_NOT_DETECTED;
@@ -20,12 +20,16 @@ export class MowerAccessory {
20
20
  applied = new Map();
21
21
  pending = new Map();
22
22
  last = {};
23
+ baseName;
24
+ debounceMs;
23
25
  constructor(hap, accessory, log, options) {
24
26
  this.hap = hap;
25
27
  this.accessory = accessory;
26
28
  this.log = log;
27
29
  this.options = options;
28
30
  const { Service, Characteristic } = hap;
31
+ this.baseName = accessory.displayName;
32
+ this.debounceMs = Number.isFinite(options.debounceSeconds) && options.debounceSeconds > 0 ? options.debounceSeconds * 1000 : 0;
29
33
  if (!accessory.getService(Service.AccessoryInformation)) {
30
34
  accessory.addService(Service.AccessoryInformation);
31
35
  }
@@ -37,15 +41,20 @@ export class MowerAccessory {
37
41
  }
38
42
  continue;
39
43
  }
40
- const name = `${accessory.displayName} ${SENSOR_LABELS[key]}`;
41
- const service = existing ?? accessory.addService(Service.ContactSensor, name, key);
44
+ if (existing) {
45
+ // Restored from cache: leave Name/ConfiguredName alone so renames made in the Home app survive restarts.
46
+ this.sensors.set(key, existing);
47
+ continue;
48
+ }
49
+ const name = this.sensorName(key);
50
+ const service = accessory.addService(Service.ContactSensor, name, key);
42
51
  service.setCharacteristic(Characteristic.Name, name);
43
52
  service.setCharacteristic(Characteristic.ConfiguredName, name);
44
53
  this.sensors.set(key, service);
45
54
  }
46
55
  const existingBattery = accessory.getService(Service.Battery);
47
56
  if (options.battery) {
48
- this.battery = existingBattery ?? accessory.addService(Service.Battery, `${accessory.displayName} Battery`);
57
+ this.battery = existingBattery ?? accessory.addService(Service.Battery, `${this.baseName} Battery`);
49
58
  }
50
59
  else if (existingBattery) {
51
60
  accessory.removeService(existingBattery);
@@ -59,6 +68,21 @@ export class MowerAccessory {
59
68
  .setCharacteristic(Characteristic.SerialNumber, info.serial ?? this.accessory.UUID)
60
69
  .setCharacteristic(Characteristic.FirmwareRevision, info.firmware ?? '0');
61
70
  }
71
+ // Follows a rename made in the Roborock app. ConfiguredName is only touched if the user never changed it in Home.
72
+ rename(displayName) {
73
+ const c = this.hap.Characteristic;
74
+ const previousBase = this.baseName;
75
+ this.baseName = displayName;
76
+ for (const [key, service] of this.sensors) {
77
+ const previous = `${previousBase} ${SENSOR_LABELS[key]}`;
78
+ const next = this.sensorName(key);
79
+ service.updateCharacteristic(c.Name, next);
80
+ if (service.getCharacteristic(c.ConfiguredName).value === previous) {
81
+ service.updateCharacteristic(c.ConfiguredName, next);
82
+ }
83
+ }
84
+ this.battery?.updateCharacteristic(c.Name, `${displayName} Battery`);
85
+ }
62
86
  update(state) {
63
87
  for (const key of this.sensors.keys()) {
64
88
  this.schedule(key, state[key]);
@@ -71,7 +95,16 @@ export class MowerAccessory {
71
95
  service.updateCharacteristic(this.hap.Characteristic.StatusActive, online);
72
96
  }
73
97
  }
74
- // Activity flags must hold for debounceSeconds before HomeKit sees them; the first value is applied immediately.
98
+ dispose() {
99
+ for (const pending of this.pending.values()) {
100
+ clearTimeout(pending.timer);
101
+ }
102
+ this.pending.clear();
103
+ }
104
+ sensorName(key) {
105
+ return `${this.baseName} ${SENSOR_LABELS[key]}`;
106
+ }
107
+ // Activity flags must hold for the debounce period before HomeKit sees them; the first value is applied immediately.
75
108
  schedule(key, value) {
76
109
  const pending = this.pending.get(key);
77
110
  if (this.applied.get(key) === value) {
@@ -87,20 +120,20 @@ export class MowerAccessory {
87
120
  if (pending) {
88
121
  clearTimeout(pending.timer);
89
122
  }
90
- if (!this.applied.has(key) || this.options.debounceSeconds <= 0) {
123
+ if (!this.applied.has(key) || this.debounceMs === 0) {
91
124
  this.apply(key, value);
92
125
  return;
93
126
  }
94
127
  const timer = setTimeout(() => {
95
128
  this.pending.delete(key);
96
129
  this.apply(key, value);
97
- }, this.options.debounceSeconds * 1000);
130
+ }, this.debounceMs);
98
131
  this.pending.set(key, { value, timer });
99
132
  }
100
133
  apply(key, value) {
101
134
  this.applied.set(key, value);
102
135
  this.sensors.get(key)?.updateCharacteristic(this.hap.Characteristic.ContactSensorState, contactValue(key, value, this.hap.Characteristic));
103
- this.log.debug(`${this.accessory.displayName}: ${SENSOR_LABELS[key]} ${value ? 'on' : 'off'}`);
136
+ this.log.debug(`${this.baseName}: ${SENSOR_LABELS[key]} ${value ? 'on' : 'off'}`);
104
137
  }
105
138
  pushFault(fault) {
106
139
  if (!this.options.faultIndicator || this.last.fault === fault) {
@@ -1 +1 @@
1
- {"version":3,"file":"accessory.js","sourceRoot":"","sources":["../../src/mower/accessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"accessory.js","sourceRoot":"","sources":["../../src/mower/accessory.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { API, Characteristic, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig, Service } from 'homebridge';
2
2
  import type mqtt from 'mqtt';
3
- import type { StoredSession } from './roborock/types.js';
3
+ import { type StoredSession } from './roborock/types.js';
4
4
  export interface RoborockMowerConfig extends PlatformConfig {
5
5
  pollInterval?: number;
6
6
  exposeDocked?: boolean;
@@ -31,16 +31,27 @@ export declare class RoborockMowerPlatform implements DynamicPlatformPlugin {
31
31
  private homeId?;
32
32
  private session?;
33
33
  private reconcileTimer?;
34
+ private retryTimer?;
35
+ private startPromise?;
36
+ private stopped;
37
+ private sessionExpiredLogged;
34
38
  private readonly mowers;
35
39
  constructor(log: Logging, config: PlatformConfig, api: API, deps?: PlatformDeps);
36
40
  configureAccessory(accessory: PlatformAccessory): void;
41
+ whenStarted(): Promise<void>;
42
+ pollSeconds(): number;
43
+ reconcile(): Promise<void>;
37
44
  private sensorOptions;
45
+ private now;
38
46
  private start;
39
47
  private stop;
48
+ private startMqtt;
49
+ private restoreFromCache;
50
+ private track;
51
+ private subscribeMqtt;
52
+ private syncFromCloud;
40
53
  private syncMowers;
54
+ private remove;
41
55
  private applyDps;
42
- private startMqtt;
43
- private pollSeconds;
44
- private scheduleReconcile;
45
- private reconcile;
56
+ private saveStatus;
46
57
  }
package/dist/platform.js CHANGED
@@ -1,15 +1,35 @@
1
1
  import { MowerAccessory } from './mower/accessory.js';
2
- import { deriveMowerState, describeMowState, DPS } from './mower/state.js';
2
+ import { deriveMowerState, describeMowState } from './mower/state.js';
3
3
  import { findMowers } from './roborock/mower.js';
4
4
  import { RoborockMqtt } from './roborock/mqtt-client.js';
5
- import { readSession } from './roborock/session-store.js';
5
+ import { readSession, writeStatus } from './roborock/session-store.js';
6
+ import { RoborockApiError } from './roborock/types.js';
6
7
  import { RoborockWebApi } from './roborock/web-api.js';
7
8
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
8
9
  const MIN_POLL_SECONDS = 900; // Roborock rate-limits home data; python-roborock budgets 5/hour.
10
+ const MAX_POLL_SECONDS = 86_400;
9
11
  const DEFAULT_POLL_SECONDS = 3600;
12
+ const STARTUP_RETRY_MS = 5 * 60_000;
13
+ const MISSES_BEFORE_REMOVAL = 3;
14
+ const SESSION_EXPIRED = 'session-expired';
10
15
  function message(error) {
11
16
  return error instanceof Error ? error.message : String(error);
12
17
  }
18
+ // Config edited by hand bypasses the schema; never let a bad value become NaN timers.
19
+ function numberOption(value, fallback, min, max) {
20
+ const n = typeof value === 'number' ? value : Number(value);
21
+ if (value === undefined || value === null || value === '' || !Number.isFinite(n)) {
22
+ return fallback;
23
+ }
24
+ return Math.min(max, Math.max(min, n));
25
+ }
26
+ function toCached(device) {
27
+ const { duid, name, model, productName, localKey, sn, fv, pv } = device;
28
+ return { duid, name, model, productName, localKey, sn, fv, pv };
29
+ }
30
+ function isSessionExpired(error) {
31
+ return error instanceof RoborockApiError && (error.code === 2010 || error.code === 401);
32
+ }
13
33
  export class RoborockMowerPlatform {
14
34
  log;
15
35
  config;
@@ -24,6 +44,10 @@ export class RoborockMowerPlatform {
24
44
  homeId;
25
45
  session;
26
46
  reconcileTimer;
47
+ retryTimer;
48
+ startPromise;
49
+ stopped = false;
50
+ sessionExpiredLogged = false;
27
51
  mowers = new Map();
28
52
  constructor(log, config, api, deps = {}) {
29
53
  this.log = log;
@@ -33,7 +57,9 @@ export class RoborockMowerPlatform {
33
57
  this.Service = api.hap.Service;
34
58
  this.Characteristic = api.hap.Characteristic;
35
59
  this.pluginConfig = config;
36
- this.api.on('didFinishLaunching', () => void this.start());
60
+ this.api.on('didFinishLaunching', () => {
61
+ this.startPromise = this.start();
62
+ });
37
63
  this.api.on('shutdown', () => this.stop());
38
64
  }
39
65
  // Called by Homebridge for each accessory restored from cache, before didFinishLaunching.
@@ -41,6 +67,16 @@ export class RoborockMowerPlatform {
41
67
  this.log.info(`Loading accessory from cache: ${accessory.displayName}`);
42
68
  this.accessories.set(accessory.UUID, accessory);
43
69
  }
70
+ whenStarted() {
71
+ return this.startPromise ?? Promise.resolve();
72
+ }
73
+ pollSeconds() {
74
+ return numberOption(this.pluginConfig.pollInterval, DEFAULT_POLL_SECONDS, MIN_POLL_SECONDS, MAX_POLL_SECONDS);
75
+ }
76
+ // Safety net only: re-reads home data so a missed push, a rename, or a new device is picked up eventually.
77
+ async reconcile() {
78
+ await this.syncFromCloud('re-sync');
79
+ }
44
80
  sensorOptions() {
45
81
  const c = this.pluginConfig;
46
82
  return {
@@ -50,130 +86,235 @@ export class RoborockMowerPlatform {
50
86
  returning: c.exposeReturning ?? true,
51
87
  battery: c.exposeBattery ?? true,
52
88
  faultIndicator: c.faultIndicator ?? true,
53
- debounceSeconds: c.sensorDebounceSeconds ?? 3,
89
+ debounceSeconds: numberOption(c.sensorDebounceSeconds, 3, 0, 60),
54
90
  };
55
91
  }
92
+ now() {
93
+ return this.deps.now?.() ?? Date.now();
94
+ }
56
95
  async start() {
57
96
  const session = await (this.deps.readSession ?? readSession)(this.api.user.storagePath());
58
97
  if (!session) {
59
98
  this.log.warn(`${PLATFORM_NAME}: not signed in. Open the plugin settings in the Homebridge UI to sign in.`);
60
99
  return;
61
100
  }
101
+ if (this.stopped) {
102
+ return;
103
+ }
62
104
  this.session = session;
63
105
  this.webApi = new RoborockWebApi({
64
106
  email: session.email, clientId: session.clientId, region: session.region, fetch: this.deps.fetch, now: this.deps.now,
65
107
  });
66
- let home;
108
+ // MQTT first: it only needs the session, so cached mowers get live updates even if the cloud is unreachable right now.
109
+ this.startMqtt(session);
110
+ const synced = await this.syncFromCloud('startup');
111
+ if (this.stopped) {
112
+ return;
113
+ }
114
+ if (!synced) {
115
+ this.log.warn(`Roborock cloud sync will be retried in ${STARTUP_RETRY_MS / 60_000} minutes.`);
116
+ this.retryTimer = setTimeout(() => void this.reconcile(), STARTUP_RETRY_MS);
117
+ this.retryTimer.unref?.();
118
+ }
119
+ this.reconcileTimer = setInterval(() => void this.reconcile(), this.pollSeconds() * 1000);
120
+ this.reconcileTimer.unref?.();
121
+ }
122
+ stop() {
123
+ this.stopped = true;
124
+ this.mqtt?.stop();
125
+ clearInterval(this.reconcileTimer);
126
+ clearTimeout(this.retryTimer);
127
+ for (const tracked of this.mowers.values()) {
128
+ tracked.accessory.dispose();
129
+ }
130
+ }
131
+ startMqtt(session) {
67
132
  try {
68
- this.homeId = await this.webApi.getHomeId(session.userData);
69
- home = await this.webApi.getHomeData(session.userData, this.homeId);
133
+ this.mqtt = new RoborockMqtt(session.userData.rriot, this.log, this.deps.connectMqtt);
134
+ this.mqtt.onConnectionChange((connected) => {
135
+ for (const tracked of this.mowers.values()) {
136
+ tracked.accessory.setOnline(connected && tracked.online);
137
+ }
138
+ if (!connected) {
139
+ this.log.warn('Roborock MQTT disconnected; sensors marked inactive until it reconnects.');
140
+ }
141
+ });
142
+ this.restoreFromCache();
143
+ this.mqtt.start();
70
144
  }
71
145
  catch (error) {
72
- this.log.error(`Roborock cloud: ${message(error)}`);
73
- this.scheduleReconcile();
146
+ this.log.error(`Roborock MQTT could not start: ${message(error)}. State will only refresh every ${this.pollSeconds()}s.`);
147
+ this.restoreFromCache();
148
+ }
149
+ }
150
+ // Accessories Homebridge restored carry the device identity in their context, so they can be tracked before any cloud call.
151
+ restoreFromCache() {
152
+ for (const platformAccessory of this.accessories.values()) {
153
+ const device = platformAccessory.context.device;
154
+ if (device?.duid && !this.mowers.has(device.duid)) {
155
+ this.track(platformAccessory, device);
156
+ }
157
+ }
158
+ }
159
+ track(platformAccessory, device) {
160
+ const accessory = new MowerAccessory(this.api.hap, platformAccessory, this.log, this.sensorOptions());
161
+ accessory.setInformation({ model: device.model, serial: device.sn, firmware: device.fv });
162
+ const tracked = { device, online: true, platformAccessory, accessory, dps: {} };
163
+ this.mowers.set(device.duid, tracked);
164
+ accessory.setOnline(this.mqtt?.connected ?? false);
165
+ this.subscribeMqtt(tracked);
166
+ return tracked;
167
+ }
168
+ subscribeMqtt(tracked) {
169
+ if (!this.mqtt) {
74
170
  return;
75
171
  }
76
- this.syncMowers(home);
77
- this.startMqtt(session);
78
- this.scheduleReconcile();
172
+ if (!tracked.device.localKey) {
173
+ this.log.error(`${tracked.device.name}: no localKey in home data; live updates unavailable.`);
174
+ return;
175
+ }
176
+ this.mqtt.subscribe(tracked.device.duid, tracked.device.localKey, (dps) => this.applyDps(tracked, dps, 'push'));
79
177
  }
80
- stop() {
81
- this.mqtt?.stop();
82
- if (this.reconcileTimer) {
83
- clearInterval(this.reconcileTimer);
178
+ async syncFromCloud(reason) {
179
+ if (!this.webApi || !this.session) {
180
+ return false;
84
181
  }
182
+ let home;
183
+ try {
184
+ this.homeId ??= await this.webApi.getHomeId(this.session.userData);
185
+ home = await this.webApi.getHomeData(this.session.userData, this.homeId);
186
+ }
187
+ catch (error) {
188
+ if (isSessionExpired(error)) {
189
+ if (!this.sessionExpiredLogged) {
190
+ this.sessionExpiredLogged = true;
191
+ this.log.error('Roborock session is no longer valid. Sign in again in the plugin settings.');
192
+ }
193
+ await this.saveStatus(SESSION_EXPIRED);
194
+ }
195
+ else {
196
+ this.log.warn(`Roborock cloud ${reason} failed: ${message(error)}`);
197
+ }
198
+ return false;
199
+ }
200
+ if (this.stopped) {
201
+ return true;
202
+ }
203
+ this.sessionExpiredLogged = false;
204
+ this.syncMowers(home);
205
+ await this.saveStatus();
206
+ return true;
85
207
  }
86
- // Creates/updates one accessory per mower on the account and drops cached ones that are gone.
208
+ // Creates/updates one accessory per mower on the account; removal needs several consecutive confirmed absences.
87
209
  syncMowers(home) {
88
210
  const devices = findMowers(home);
211
+ const listed = (home.devices?.length ?? 0) + (home.receivedDevices?.length ?? 0);
89
212
  if (devices.length === 0) {
90
- const total = (home.devices?.length ?? 0) + (home.receivedDevices?.length ?? 0);
91
- this.log.warn(`No mower found on this Roborock account (${total} other device(s)).`);
213
+ this.log.warn(listed === 0
214
+ ? 'Roborock returned an empty device list; keeping the cached mower(s).'
215
+ : `No mower found on this Roborock account (${listed} other device(s)).`);
92
216
  }
93
217
  const seen = new Set();
94
218
  for (const device of devices) {
95
- const uuid = this.api.hap.uuid.generate(device.duid);
96
- seen.add(uuid);
219
+ seen.add(device.duid);
220
+ const cached = toCached(device);
97
221
  let tracked = this.mowers.get(device.duid);
98
222
  if (!tracked) {
223
+ const uuid = this.api.hap.uuid.generate(device.duid);
99
224
  let platformAccessory = this.accessories.get(uuid);
100
225
  if (!platformAccessory) {
101
226
  platformAccessory = new this.api.platformAccessory(device.name, uuid);
102
227
  this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [platformAccessory]);
103
228
  this.accessories.set(uuid, platformAccessory);
104
229
  }
105
- const accessory = new MowerAccessory(this.api.hap, platformAccessory, this.log, this.sensorOptions());
106
- accessory.setInformation({ model: device.model, serial: device.sn, firmware: device.fv });
107
- tracked = { device, accessory, dps: {} };
108
- this.mowers.set(device.duid, tracked);
230
+ tracked = this.track(platformAccessory, cached);
109
231
  this.log.info(`Found mower "${device.name}" (model=${device.model}, pv=${device.pv}, online=${device.online})`);
110
232
  }
111
- tracked.device = device;
112
- this.applyDps(tracked, device.deviceStatus ?? {});
113
- tracked.accessory.setOnline(device.online !== false && (this.mqtt?.connected ?? true));
114
- }
115
- for (const [uuid, platformAccessory] of this.accessories) {
116
- if (!seen.has(uuid)) {
117
- this.log.info(`Removing accessory no longer on the account: ${platformAccessory.displayName}`);
118
- this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [platformAccessory]);
119
- this.accessories.delete(uuid);
233
+ else if (!tracked.device.localKey && cached.localKey) {
234
+ tracked.device = cached;
235
+ this.subscribeMqtt(tracked);
236
+ }
237
+ tracked.device = cached;
238
+ const context = tracked.platformAccessory.context;
239
+ context.device = cached;
240
+ context.missedSyncs = 0;
241
+ context.lastSeenAt = this.now();
242
+ if (tracked.platformAccessory.displayName !== device.name) {
243
+ this.log.info(`Renaming "${tracked.platformAccessory.displayName}" to "${device.name}" (changed in the Roborock app)`);
244
+ tracked.platformAccessory.displayName = device.name;
245
+ tracked.accessory.rename(device.name);
246
+ }
247
+ this.api.updatePlatformAccessories([tracked.platformAccessory]);
248
+ // The cloud snapshot can lag the live pushes; only use it when we have nothing fresher.
249
+ const connected = this.mqtt?.connected ?? false;
250
+ if (tracked.lastPushAt === undefined || !connected) {
251
+ this.applyDps(tracked, device.deviceStatus ?? {}, 'cloud');
252
+ }
253
+ else {
254
+ this.log.debug(`${device.name}: cloud snapshot ignored in favour of live state: ${JSON.stringify(device.deviceStatus)}`);
255
+ }
256
+ tracked.online = device.online !== false;
257
+ tracked.accessory.setOnline(tracked.online && connected);
258
+ }
259
+ if (listed === 0) {
260
+ return;
261
+ }
262
+ for (const [duid, tracked] of [...this.mowers]) {
263
+ if (seen.has(duid)) {
264
+ continue;
265
+ }
266
+ const context = tracked.platformAccessory.context;
267
+ const missed = (context.missedSyncs ?? 0) + 1;
268
+ context.missedSyncs = missed;
269
+ if (missed >= MISSES_BEFORE_REMOVAL) {
270
+ this.remove(tracked);
271
+ }
272
+ else {
273
+ this.log.warn(`${tracked.device.name} missing from the account (${missed}/${MISSES_BEFORE_REMOVAL} syncs); removed after ${MISSES_BEFORE_REMOVAL}.`);
274
+ this.api.updatePlatformAccessories([tracked.platformAccessory]);
120
275
  }
121
276
  }
122
277
  }
123
- applyDps(tracked, update) {
124
- const previous = tracked.dps[DPS.MOW_STATE];
278
+ remove(tracked) {
279
+ this.log.info(`Removing accessory no longer on the account: ${tracked.platformAccessory.displayName}`);
280
+ tracked.accessory.dispose();
281
+ this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [tracked.platformAccessory]);
282
+ this.accessories.delete(tracked.platformAccessory.UUID);
283
+ this.mowers.delete(tracked.device.duid);
284
+ }
285
+ applyDps(tracked, update, source) {
125
286
  for (const [key, value] of Object.entries(update)) {
126
287
  tracked.dps[Number(key)] = value;
127
288
  }
289
+ if (source === 'push') {
290
+ tracked.lastPushAt = this.now();
291
+ }
128
292
  const state = deriveMowerState(tracked.dps);
129
- if (state.mowState !== previous) {
293
+ if (state.mowState !== tracked.last?.mowState) {
130
294
  this.log.info(`${tracked.device.name}: ${describeMowState(state.mowState)} (battery ${state.battery ?? '?'}%)`);
131
295
  }
132
- this.log.debug(`${tracked.device.name} dps: ${JSON.stringify(update)}`);
296
+ this.log.debug(`${tracked.device.name} ${source} dps: ${JSON.stringify(update)}`);
297
+ tracked.last = state;
133
298
  tracked.accessory.update(state);
134
299
  }
135
- startMqtt(session) {
300
+ async saveStatus(lastError) {
301
+ const devices = [...this.mowers.values()].map((tracked) => ({
302
+ duid: tracked.device.duid,
303
+ name: tracked.device.name,
304
+ model: tracked.device.model,
305
+ productName: tracked.device.productName,
306
+ online: tracked.online,
307
+ fv: tracked.device.fv,
308
+ mowState: tracked.last?.mowState,
309
+ mowStateName: tracked.last ? describeMowState(tracked.last.mowState) : undefined,
310
+ battery: tracked.last?.battery,
311
+ }));
312
+ const status = { updatedAt: this.now(), devices, ...(lastError ? { lastError } : {}) };
136
313
  try {
137
- this.mqtt = new RoborockMqtt(session.userData.rriot, this.log, this.deps.connectMqtt);
138
- this.mqtt.onConnectionChange((connected) => {
139
- for (const tracked of this.mowers.values()) {
140
- tracked.accessory.setOnline(connected && tracked.device.online !== false);
141
- }
142
- if (!connected) {
143
- this.log.warn('Roborock MQTT disconnected; sensors marked inactive until it reconnects.');
144
- }
145
- });
146
- for (const tracked of this.mowers.values()) {
147
- if (!tracked.device.localKey) {
148
- this.log.error(`${tracked.device.name}: no localKey in home data; live updates unavailable.`);
149
- continue;
150
- }
151
- this.mqtt.subscribe(tracked.device.duid, tracked.device.localKey, (dps) => this.applyDps(tracked, dps));
152
- }
153
- this.mqtt.start();
154
- }
155
- catch (error) {
156
- this.log.error(`Roborock MQTT could not start: ${message(error)}. State will only refresh every ${this.pollSeconds()}s.`);
157
- }
158
- }
159
- pollSeconds() {
160
- return Math.max(MIN_POLL_SECONDS, this.pluginConfig.pollInterval ?? DEFAULT_POLL_SECONDS);
161
- }
162
- // Safety net only: re-reads home data so a missed push or a new device is picked up eventually.
163
- scheduleReconcile() {
164
- this.reconcileTimer = setInterval(() => void this.reconcile(), this.pollSeconds() * 1000);
165
- this.reconcileTimer.unref?.();
166
- }
167
- async reconcile() {
168
- if (!this.webApi || !this.session) {
169
- return;
170
- }
171
- try {
172
- this.homeId ??= await this.webApi.getHomeId(this.session.userData);
173
- this.syncMowers(await this.webApi.getHomeData(this.session.userData, this.homeId));
314
+ await writeStatus(this.api.user.storagePath(), status);
174
315
  }
175
316
  catch (error) {
176
- this.log.warn(`Roborock cloud re-sync skipped: ${message(error)}`);
317
+ this.log.debug(`Could not write status file: ${message(error)}`);
177
318
  }
178
319
  }
179
320
  }
@@ -1 +1 @@
1
- {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
@@ -21,6 +21,7 @@ export declare class RoborockMqtt {
21
21
  private client?;
22
22
  private readonly subscriptions;
23
23
  private readonly connectionListeners;
24
+ private lastConnected;
24
25
  constructor(rriot: RRiot, log: MqttLogger, connect?: typeof mqtt.connect);
25
26
  start(): void;
26
27
  get connected(): boolean;
@@ -19,6 +19,7 @@ export class RoborockMqtt {
19
19
  client;
20
20
  subscriptions = new Map();
21
21
  connectionListeners = [];
22
+ lastConnected = false;
22
23
  constructor(rriot, log, connect = mqtt.connect) {
23
24
  this.rriot = rriot;
24
25
  this.log = log;
@@ -44,6 +45,7 @@ export class RoborockMqtt {
44
45
  this.emitConnection(true);
45
46
  });
46
47
  this.client.on('close', () => this.emitConnection(false));
48
+ this.client.on('offline', () => this.emitConnection(false));
47
49
  this.client.on('reconnect', () => this.log.debug('Roborock MQTT reconnecting'));
48
50
  this.client.on('error', (error) => this.log.warn(`Roborock MQTT error: ${error.message}`));
49
51
  this.client.on('message', (topic, payload) => this.onMessage(topic, payload));
@@ -54,6 +56,7 @@ export class RoborockMqtt {
54
56
  stop() {
55
57
  const client = this.client;
56
58
  this.client = undefined;
59
+ this.lastConnected = false;
57
60
  client?.removeAllListeners();
58
61
  client?.end(true);
59
62
  }
@@ -93,7 +96,12 @@ export class RoborockMqtt {
93
96
  }
94
97
  }
95
98
  }
99
+ // mqtt.js emits close after every failed reconnect attempt; listeners only want the transitions.
96
100
  emitConnection(connected) {
101
+ if (connected === this.lastConnected) {
102
+ return;
103
+ }
104
+ this.lastConnected = connected;
97
105
  for (const listener of this.connectionListeners) {
98
106
  listener(connected);
99
107
  }
@@ -1 +1 @@
1
- {"version":3,"file":"mqtt-client.js","sourceRoot":"","sources":["../../src/roborock/mqtt-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"mqtt-client.js","sourceRoot":"","sources":["../../src/roborock/mqtt-client.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,24 @@
1
1
  import type { StoredSession } from './types.js';
2
2
  export declare function sessionPath(storagePath: string): string;
3
+ export declare function statusPath(storagePath: string): string;
4
+ export interface StatusDevice {
5
+ duid: string;
6
+ name: string;
7
+ model: string;
8
+ productName?: string;
9
+ online: boolean;
10
+ fv?: string;
11
+ mowState?: number;
12
+ mowStateName?: string;
13
+ battery?: number;
14
+ }
15
+ export interface PlatformStatus {
16
+ updatedAt: number;
17
+ devices: StatusDevice[];
18
+ lastError?: string;
19
+ }
3
20
  export declare function readSession(storagePath: string): Promise<StoredSession | undefined>;
4
21
  export declare function writeSession(storagePath: string, session: StoredSession): Promise<void>;
5
22
  export declare function clearSession(storagePath: string): Promise<void>;
23
+ export declare function readStatus(storagePath: string): Promise<PlatformStatus | undefined>;
24
+ export declare function writeStatus(storagePath: string, status: PlatformStatus): Promise<void>;
@@ -1,9 +1,12 @@
1
- import { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
1
+ import { chmod, mkdir, readFile, rename, rm, writeFile } from 'node:fs/promises';
2
2
  import { dirname, join } from 'node:path';
3
3
  // Lives outside config.json so the Homebridge UI's schema form can never overwrite it.
4
4
  export function sessionPath(storagePath) {
5
5
  return join(storagePath, 'roborock-mower', 'session.json');
6
6
  }
7
+ export function statusPath(storagePath) {
8
+ return join(storagePath, 'roborock-mower', 'status.json');
9
+ }
7
10
  function isSession(value) {
8
11
  const candidate = value;
9
12
  return typeof candidate?.email === 'string'
@@ -12,29 +15,50 @@ function isSession(value) {
12
15
  && typeof candidate.userData?.token === 'string'
13
16
  && typeof candidate.userData.rriot === 'object';
14
17
  }
15
- export async function readSession(storagePath) {
18
+ async function readJson(path) {
16
19
  let raw;
17
20
  try {
18
- raw = await readFile(sessionPath(storagePath), 'utf8');
21
+ raw = await readFile(path, 'utf8');
19
22
  }
20
23
  catch {
21
24
  return undefined;
22
25
  }
23
26
  try {
24
- const parsed = JSON.parse(raw);
25
- return isSession(parsed) ? parsed : undefined;
27
+ return JSON.parse(raw);
26
28
  }
27
29
  catch {
28
30
  return undefined;
29
31
  }
30
32
  }
31
- export async function writeSession(storagePath, session) {
32
- const path = sessionPath(storagePath);
33
+ // Write to a sibling temp file and rename so a crash mid-write never leaves a truncated file behind.
34
+ async function writeFileAtomic(path, data, mode) {
33
35
  await mkdir(dirname(path), { recursive: true });
34
- await writeFile(path, JSON.stringify(session, null, 2), { mode: 0o600 });
35
- await chmod(path, 0o600);
36
+ const tmp = `${path}.${process.pid}.tmp`;
37
+ try {
38
+ await writeFile(tmp, data, { mode });
39
+ await chmod(tmp, mode);
40
+ await rename(tmp, path);
41
+ }
42
+ catch (error) {
43
+ await rm(tmp, { force: true }).catch(() => undefined);
44
+ throw error;
45
+ }
46
+ }
47
+ export async function readSession(storagePath) {
48
+ const parsed = await readJson(sessionPath(storagePath));
49
+ return isSession(parsed) ? parsed : undefined;
50
+ }
51
+ export async function writeSession(storagePath, session) {
52
+ await writeFileAtomic(sessionPath(storagePath), JSON.stringify(session, null, 2), 0o600);
36
53
  }
37
54
  export async function clearSession(storagePath) {
38
55
  await rm(sessionPath(storagePath), { force: true });
39
56
  }
57
+ export async function readStatus(storagePath) {
58
+ const parsed = await readJson(statusPath(storagePath));
59
+ return typeof parsed?.updatedAt === 'number' && Array.isArray(parsed.devices) ? parsed : undefined;
60
+ }
61
+ export async function writeStatus(storagePath, status) {
62
+ await writeFileAtomic(statusPath(storagePath), JSON.stringify(status, null, 2), 0o600);
63
+ }
40
64
  //# sourceMappingURL=session-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/roborock/session-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAI1C,uFAAuF;AACvF,MAAM,UAAU,WAAW,CAAC,WAAmB;IAC7C,OAAO,IAAI,CAAC,WAAW,EAAE,gBAAgB,EAAE,cAAc,CAAC,CAAC;AAC7D,CAAC;AAED,SAAS,SAAS,CAAC,KAAc;IAC/B,MAAM,SAAS,GAAG,KAAsC,CAAC;IACzD,OAAO,OAAO,SAAS,EAAE,KAAK,KAAK,QAAQ;WACtC,OAAO,SAAS,CAAC,QAAQ,KAAK,QAAQ;WACtC,OAAO,SAAS,CAAC,MAAM,EAAE,OAAO,KAAK,QAAQ;WAC7C,OAAO,SAAS,CAAC,QAAQ,EAAE,KAAK,KAAK,QAAQ;WAC7C,OAAO,SAAS,CAAC,QAAQ,CAAC,KAAK,KAAK,QAAQ,CAAC;AACpD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB,EAAE,OAAsB;IAC5E,MAAM,IAAI,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACzE,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAAmB;IACpD,MAAM,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AACtD,CAAC"}
1
+ {"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/roborock/session-store.ts"],"names":[],"mappings":"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"}
@@ -80,6 +80,7 @@ export class RoborockWebApi {
80
80
  }
81
81
  // Asks each regional host whether it knows the account; the answer also carries the country values the login needs.
82
82
  async resolveRegion() {
83
+ let unreachable = 0;
83
84
  for (const baseUrl of this.candidates) {
84
85
  const url = new URL('/api/v1/getUrlByEmail', baseUrl);
85
86
  url.searchParams.set('email', this.email);
@@ -89,6 +90,7 @@ export class RoborockWebApi {
89
90
  envelope = await this.call(url, { method: 'POST', headers: this.loginHeaders() });
90
91
  }
91
92
  catch {
93
+ unreachable++;
92
94
  continue;
93
95
  }
94
96
  if (envelope.code === 2003 || envelope.code === 1001) {
@@ -100,6 +102,9 @@ export class RoborockWebApi {
100
102
  return this.region;
101
103
  }
102
104
  }
105
+ if (unreachable === this.candidates.length) {
106
+ throw new RoborockApiError('Could not reach the Roborock servers (network or DNS). Check connectivity and try again.');
107
+ }
103
108
  throw new RoborockApiError('Could not find a Roborock region for this account. Check the email address.');
104
109
  }
105
110
  requestEmailCode() {
@@ -1 +1 @@
1
- {"version":3,"file":"web-api.js","sourceRoot":"","sources":["../../src/roborock/web-api.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web-api.js","sourceRoot":"","sources":["../../src/roborock/web-api.ts"],"names":[],"mappings":"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"}
package/dist/ui/server.js CHANGED
@@ -1,9 +1,13 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils';
3
+ import { describeMowState, deriveMowerState } from '../mower/state.js';
3
4
  import { findMowers } from '../roborock/mower.js';
4
- import { clearSession, readSession, writeSession } from '../roborock/session-store.js';
5
+ import { clearSession, readSession, readStatus, writeSession, writeStatus } from '../roborock/session-store.js';
5
6
  import { RoborockWebApi } from '../roborock/web-api.js';
7
+ const STALE_AFTER_MS = 2 * 60 * 60_000;
6
8
  class RoborockMowerUiServer extends HomebridgePluginUiServer {
9
+ // One cloud client per account for the life of this UI process, so the send/verify pair shares its rate limiter.
10
+ current;
7
11
  constructor() {
8
12
  super();
9
13
  this.onRequest('/session', () => this.guard(() => this.session()));
@@ -19,36 +23,64 @@ class RoborockMowerUiServer extends HomebridgePluginUiServer {
19
23
  }
20
24
  return this.homebridgeStoragePath;
21
25
  }
26
+ apiFor(email, clientId, region) {
27
+ if (this.current?.email !== email || this.current.clientId !== clientId) {
28
+ this.current = { email, clientId, api: new RoborockWebApi({ email, clientId, region }) };
29
+ }
30
+ return this.current.api;
31
+ }
22
32
  async session() {
23
33
  const session = await readSession(this.storagePath);
24
- return { email: session?.email ?? null };
34
+ const status = await readStatus(this.storagePath);
35
+ return { email: session?.email ?? null, lastError: status?.lastError };
25
36
  }
26
37
  async sendCode({ email }) {
27
38
  const clientId = randomUUID();
28
- const api = new RoborockWebApi({ email, clientId });
29
- const region = await api.requestEmailCode();
39
+ const region = await this.apiFor(email, clientId).requestEmailCode();
30
40
  return { clientId, region };
31
41
  }
32
42
  async verifyCode({ email, clientId, region, code }) {
33
- const api = new RoborockWebApi({ email, clientId, region });
34
- const userData = await api.loginWithCode(code.trim());
43
+ const userData = await this.apiFor(email, clientId, region).loginWithCode(code.trim());
35
44
  await writeSession(this.storagePath, { email, clientId, region, userData });
45
+ await writeStatus(this.storagePath, { updatedAt: 0, devices: [] }); // clears any session-expired flag
36
46
  return { email };
37
47
  }
38
48
  async signOut() {
39
49
  await clearSession(this.storagePath);
40
50
  }
51
+ // Serves the platform's status file; only a freshly signed-in account (no status yet) costs a cloud call.
41
52
  async devices() {
53
+ const status = await readStatus(this.storagePath);
54
+ if (status && status.updatedAt > 0) {
55
+ return { ...status, stale: Date.now() - status.updatedAt > STALE_AFTER_MS };
56
+ }
42
57
  const session = await readSession(this.storagePath);
43
58
  if (!session) {
44
59
  throw new Error('Not signed in.');
45
60
  }
46
- const api = new RoborockWebApi({ email: session.email, clientId: session.clientId, region: session.region });
61
+ const fresh = await this.fetchStatus(session);
62
+ await writeStatus(this.storagePath, fresh);
63
+ return { ...fresh, stale: false };
64
+ }
65
+ async fetchStatus(session) {
66
+ const api = this.apiFor(session.email, session.clientId, session.region);
47
67
  const homeId = await api.getHomeId(session.userData);
48
68
  const home = await api.getHomeData(session.userData, homeId);
49
- const mowers = findMowers(home);
50
- const total = (home.devices?.length ?? 0) + (home.receivedDevices?.length ?? 0);
51
- return { mowers, otherDeviceCount: total - mowers.length };
69
+ const devices = findMowers(home).map((mower) => {
70
+ const state = deriveMowerState(Object.fromEntries(Object.entries(mower.deviceStatus ?? {}).map(([k, v]) => [Number(k), v])));
71
+ return {
72
+ duid: mower.duid,
73
+ name: mower.name,
74
+ model: mower.model,
75
+ productName: mower.productName,
76
+ online: mower.online !== false,
77
+ fv: mower.fv,
78
+ mowState: state.mowState,
79
+ mowStateName: describeMowState(state.mowState),
80
+ battery: state.battery,
81
+ };
82
+ });
83
+ return { updatedAt: Date.now(), devices };
52
84
  }
53
85
  async guard(run) {
54
86
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/ui/server.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,8 @@
19
19
  </div>
20
20
  </div>
21
21
 
22
+ <div id="session-expired" class="alert alert-warning d-none">Roborock session expired — sign out and sign in again.</div>
23
+
22
24
  <div id="signed-in" class="d-none">
23
25
  <p>Signed in as <strong id="signed-in-email"></strong></p>
24
26
  <button id="sign-out" type="button" class="btn btn-outline-danger btn-sm">Sign out</button>
@@ -20,26 +20,39 @@
20
20
  }
21
21
  }
22
22
 
23
- function renderDevices({ mowers, otherDeviceCount }) {
23
+ function renderDevices({ devices, updatedAt, stale }) {
24
24
  const container = $('devices');
25
25
  container.replaceChildren();
26
- if (mowers.length === 0) {
26
+ if (devices.length === 0) {
27
27
  const p = document.createElement('p');
28
28
  p.className = 'text-warning';
29
- p.textContent = `No mower found on this account (${otherDeviceCount} other Roborock device(s)).`;
29
+ p.textContent = 'No mower found on this account. Restart Homebridge after adding one in the Roborock app.';
30
30
  container.appendChild(p);
31
31
  return;
32
32
  }
33
- for (const mower of mowers) {
34
- const details = document.createElement('details');
35
- const summary = document.createElement('summary');
36
- summary.textContent = `${mower.name} — ${mower.model}${mower.online === false ? ' (offline)' : ''}`;
37
- const pre = document.createElement('pre');
38
- pre.className = 'small mt-2';
39
- pre.textContent = JSON.stringify(mower, null, 2);
40
- details.append(summary, pre);
41
- container.appendChild(details);
33
+ for (const device of devices) {
34
+ const row = document.createElement('div');
35
+ row.className = 'mb-2';
36
+ const title = document.createElement('strong');
37
+ title.textContent = device.name;
38
+ const detail = document.createElement('div');
39
+ detail.className = 'small';
40
+ const bits = [device.model, device.online ? (device.mowStateName ?? 'state unknown') : 'offline'];
41
+ if (device.battery !== undefined) {
42
+ bits.push(`battery ${device.battery}%`);
43
+ }
44
+ if (device.fv) {
45
+ bits.push(`firmware ${device.fv}`);
46
+ }
47
+ detail.textContent = bits.join(' · ');
48
+ row.append(title, detail);
49
+ container.appendChild(row);
42
50
  }
51
+ const when = document.createElement('p');
52
+ when.className = 'small mt-2';
53
+ const minutes = Math.max(0, Math.round((Date.now() - updatedAt) / 60_000));
54
+ when.textContent = `Last synced ${minutes} min ago${stale ? ' — is Homebridge running?' : ''}.`;
55
+ container.appendChild(when);
43
56
  }
44
57
 
45
58
  // A freshly installed plugin has no platform block yet; without one Homebridge never starts the platform.
@@ -64,13 +77,15 @@
64
77
 
65
78
  async function render() {
66
79
  let email = null;
80
+ let lastError;
67
81
  try {
68
- ({ email } = await request('/session'));
82
+ ({ email, lastError } = await request('/session'));
69
83
  } catch (error) {
70
84
  homebridge.toast.error(error.message, 'Could not read sign-in state');
71
85
  }
72
86
  show($('signed-out'), !email);
73
87
  show($('signed-in'), Boolean(email));
88
+ show($('session-expired'), lastError === 'session-expired');
74
89
  if (!email) {
75
90
  return;
76
91
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@cecnic1989/homebridge-roborock-mower",
3
3
  "displayName": "Homebridge Roborock Mower",
4
4
  "type": "module",
5
- "version": "0.2.1",
5
+ "version": "0.2.2",
6
6
  "description": "Homebridge plugin for Roborock RockMow robot lawn mowers",
7
7
  "author": "cecnic1989",
8
8
  "license": "Apache-2.0",