Skip to content

Commit 9c814fb

Browse files
samueltfbfacebook-github-bot
authored andcommitted
Adjust clock and battery polling based on results
Summary: When the VEET first connects, it sometimes won't return a valid battery result the first time it is polled, so we want to poll it more frequently until we get a valid result. Similarly, there is no reason to poll the clock frequently once we've determined we're in sync, so drop the poll rate after that. Simplest way to do this was to convert back to recursive setTimeout calls since we adjust based on the results of the function. I hate polling. Reviewed By: conordickinson Differential Revision: D71831256 fbshipit-source-id: ac1d0e144c8d605de252399bb508638880700888
1 parent 7972ffb commit 9c814fb

File tree

1 file changed

+64
-25
lines changed

1 file changed

+64
-25
lines changed

packages/main/src/MainWindow.ts

+64-25
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,15 @@ RegisterMainLogger();
3636

3737
const CONNECTION_RETRY_PERIOD = 3000;
3838
const DRIVE_RETRY_PERIOD = 1000;
39-
const BATTERY_POLL_PERIOD = 30 * 1000;
40-
const CLOCK_POLL_PERIOD = 5 * 1000;
4139
const SENSOR_POLL_WAIT_PERIOD = 10;
4240
const DEFAULT_RETRY_COUNT = 3;
4341
const DEFAULT_RETRY_DELAY = 500;
4442

43+
const BATTERY_FAST_POLL_PERIOD = 3 * 1000;
44+
const CLOCK_FAST_POLL_PERIOD = 3 * 1000;
45+
const BATTERY_SLOW_POLL_PERIOD = 30 * 1000;
46+
const CLOCK_SLOW_POLL_PERIOD = 60 * 1000;
47+
4548
const IMU_POLL_COMMAND = 'S0';
4649
const PHO_POLL_COMMAND = 'S1';
4750
const TOF_POLL_COMMAND = 'S2';
@@ -55,6 +58,28 @@ export const CALIBRATIONDB_PATH = () => path.join(FIRMWARE_PATH(), 'calibrationD
5558
export const DOCUMENTATION_PATH = () => path.join(ROOT_RESOURCE_PATH(), 'documentation');
5659
const VEET_MANUAL_PATH = () => path.join(DOCUMENTATION_PATH(), 'VEET 2.0 Device Manual.pdf');
5760

61+
62+
class PollingHelper {
63+
timeoutHandler_: NodeJS.Timeout | null = null;
64+
isPolling_ = true;
65+
constructor(readonly pollingCallback: () => Promise<number>) {
66+
this.runPolling();
67+
}
68+
public stop() {
69+
this.isPolling_ = false;
70+
this.timeoutHandler_ && clearTimeout(this.timeoutHandler_);
71+
this.timeoutHandler_ = null;
72+
}
73+
private runPolling() {
74+
void this.pollingCallback().then(nextDelay => {
75+
if (nextDelay > 0 && this.isPolling_) {
76+
this.timeoutHandler_ = setTimeout(() => this.runPolling(), nextDelay);
77+
}
78+
});
79+
}
80+
}
81+
82+
5883
export class MainWindow {
5984
private serialManager_: SerialManager;
6085
private browserWindow_: BrowserWindow | undefined = undefined;
@@ -64,8 +89,8 @@ export class MainWindow {
6489
private streamRecorder_: StreamRecorder | undefined = undefined;
6590

6691
// Intervals
67-
private batteryInterval_: NodeJS.Timeout | null = null;
68-
private clockInterval_: NodeJS.Timeout | null = null;
92+
private batteryPoller_: PollingHelper | null = null;
93+
private clockPoller_: PollingHelper | null = null;
6994
private connectionRetry_: NodeJS.Timeout | null = null;
7095
private driveRetry_: NodeJS.Timeout | null = null;
7196
private driveWatch_: FSWatcher | null = null;
@@ -206,29 +231,32 @@ export class MainWindow {
206231
return await this.serialManager_.runCommand(cmd);
207232
};
208233

234+
235+
209236
startPolls = async () => {
210-
if (this.batteryInterval_ == null) {
211-
await this.pollBattery();
212-
this.batteryInterval_ = setInterval(this.pollBattery, BATTERY_POLL_PERIOD);
237+
if (this.batteryPoller_) {
238+
this.batteryPoller_.stop();
213239
}
214-
if (this.clockInterval_ == null) {
215-
await this.pollClock();
216-
this.clockInterval_ = setInterval(this.pollClock, CLOCK_POLL_PERIOD);
240+
this.batteryPoller_ = new PollingHelper(this.pollBattery);
241+
242+
243+
if (this.clockPoller_) {
244+
this.clockPoller_.stop();
217245
}
246+
this.clockPoller_ = new PollingHelper(this.pollClock);
247+
248+
// Start polling
218249
void this.startPollSensorThread(); // note that this doesn't need to be stopped as it sleeps itself. also don't await this one
219250
};
220251

221252
stopPolls = () => {
222-
if (this.batteryInterval_ != null) {
223-
clearInterval(this.batteryInterval_);
224-
this.batteryInterval_ = null;
225-
setDatastoreValue('batteryPct', null);
226-
setDatastoreValue('batteryMV', null);
227-
}
228-
if (this.clockInterval_ != null) {
229-
clearInterval(this.clockInterval_);
230-
this.clockInterval_ = null;
231-
}
253+
this.batteryPoller_?.stop();
254+
this.batteryPoller_ = null;
255+
this.clockPoller_?.stop();
256+
this.clockPoller_ = null;
257+
258+
setDatastoreValue('batteryPct', null);
259+
setDatastoreValue('batteryMV', null);
232260
};
233261

234262
stopDriveWatch = () => {
@@ -307,11 +335,12 @@ export class MainWindow {
307335

308336
};
309337

310-
pollBattery = async () => {
338+
private pollBattery = async (): Promise<number> => {
311339
if (!this.isConnected_) {
312340
// We're disconnected. Shouldn't be called, so just return
313-
return;
341+
return BATTERY_FAST_POLL_PERIOD;
314342
}
343+
315344
const batteryString = await this.runCommand(null, 'GB');
316345
if (batteryString) {
317346

@@ -331,15 +360,19 @@ export class MainWindow {
331360
if (mv < 100 || mv > 6000) {
332361
// probably an invalid string
333362
logger.error(`Invalid battery response: "${batteryString}"`);
334-
return;
363+
return BATTERY_FAST_POLL_PERIOD;
335364
}
336365
// Map to a percentage. This is very rough, and things get wonky at the extremes, but we'll call anything over
337366
// 4.1V 100%, and anything less than 3.6V 1%, and linearly interpolate
338367
const frac = Math.max(invLerpClamped(3600, 4100, mv), 0.01);
339368
setDatastoreValue('batteryPct', frac);
340369
setDatastoreValue('batteryMV', mv);
341370
logger.info(`${batteryString} -> ${(frac * 100).toFixed(1)}%`);
371+
372+
// Valid battery value, so poll at the slower rate
373+
return BATTERY_SLOW_POLL_PERIOD;
342374
}
375+
return BATTERY_FAST_POLL_PERIOD;
343376
};
344377

345378
checkDriveSpace = async () => {
@@ -580,11 +613,12 @@ export class MainWindow {
580613
return await this.runCommand(null, `ST${curEpoch}`);
581614
};
582615

583-
pollClock = async () => {
616+
private pollClock = async (): Promise<number> => {
584617
if (!this.isConnected_) {
585618
// We're disconnected. Shouldn't be called, so just return
586-
return;
619+
return CLOCK_FAST_POLL_PERIOD;
587620
}
621+
588622
// Note that with the current serial connection, it will take an extra second or so
589623
// before we get the time back from the VEET, but we do not need precision timing
590624
const timeString = await this.runCommand(null, 'GT');
@@ -598,13 +632,18 @@ export class MainWindow {
598632
if (diff < -5) {
599633
logger.info(`VEET is ${-diff} seconds behind, syncing`);
600634
await this.syncClock();
635+
return CLOCK_FAST_POLL_PERIOD;
601636
} else if (diff > 5) {
602637
logger.info(`VEET is ${diff} seconds ahead, syncing`);
603638
await this.syncClock();
639+
return CLOCK_FAST_POLL_PERIOD;
604640
} else {
605641
logger.info('VEET is within 5 seconds of your PC');
642+
// Normal clock time, so poll at the slower rate
643+
return CLOCK_SLOW_POLL_PERIOD;
606644
}
607645
}
646+
return CLOCK_SLOW_POLL_PERIOD;
608647
};
609648

610649
startPollSensorThread = async () => {

0 commit comments

Comments
 (0)