From 9a36e63d177ddb027f5e3bd76af825b87cdaf366 Mon Sep 17 00:00:00 2001
From: echicken <echicken@bbs.electronicchicken.com>
Date: Sat, 27 Apr 2024 05:05:40 +0000
Subject: [PATCH] Don't send heartbeat if we've written something within the
 heartbeat interval. (This didn't solve my problem anyway so might be best to
 just move heartbeat back to SerialDevice exclusively.)

---
 src/lib/device.ts | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/lib/device.ts b/src/lib/device.ts
index b5ac975..dcb1283 100644
--- a/src/lib/device.ts
+++ b/src/lib/device.ts
@@ -35,7 +35,7 @@ export default abstract class Device extends js.global.EventEmitter {
 	private readyEvent: number;
 	private heartbeatInterval: number;
 	private heartbeatEvent: number;
-	private lastHeartbeat?: number;
+	private lastWrite: number;
 	private initTime: number;
 	private initTimeout: number;
 	private readonly timeoutMs: number = RESPONSE_TIMEOUT * 1000;
@@ -58,8 +58,9 @@ export default abstract class Device extends js.global.EventEmitter {
 		this.ackHandlers = {};
 		this.responseHandlers = {};
 		this.purgeEvent = js.setInterval(this.purgeHandlers, this.timeoutMs, this);
-		this.heartbeatInterval = heartbeatInterval;
+		this.heartbeatInterval = heartbeatInterval * 1000;
 		this.heartbeatEvent = -1;
+		this.lastWrite = Date.now();
 		this.initTime = Date.now();
 		this.initTimeout = CONNECT_TIMEOUT * 1000;
 	}
@@ -126,10 +127,7 @@ export default abstract class Device extends js.global.EventEmitter {
 		if (!this.ready && now - this.initTime > this.initTimeout) this.error(`initialization timeout (configCompleteId not received from device)`);
 		this.read();
 		this.purgeHandlers();
-		if (this.lastHeartbeat === undefined || now - this.lastHeartbeat >= this.heartbeatInterval) {
-			this.lastHeartbeat = now;
-			this.sendHeartbeat();
-		}
+		this.sendHeartbeat();
 		this._cycle();
 	}
 
@@ -187,7 +185,7 @@ export default abstract class Device extends js.global.EventEmitter {
 					if (this.readyEvent > -1) js.clearTimeout(this.readyEvent);
 					this.emit('ready');
 					// @ts-expect-error shut up
-					this.heartbeatEvent = js.setInterval(function () { this.sendHeartbeat(); }, 30000, this)
+					this.heartbeatEvent = js.setInterval(function () { this.sendHeartbeat(); }, this.heartbeatInterval, this)
 				}
 				break;
 			case 'metadata':
@@ -278,7 +276,9 @@ export default abstract class Device extends js.global.EventEmitter {
 		if (data.length > MAXLEN) this.error(`write: packet length ${data.length} exceeds maximum length ${MAXLEN}`);
 		const header = [START1, START2, (data.length>>8)&0xFF, data.length&0xFF];
 		const buffer = new Uint8Array([...header, ...data]);
-		return this.sendToDevice(buffer);
+		const res = this.sendToDevice(buffer);
+		if (res) this.lastWrite = Date.now();
+		return res;
 	}
 
 	/** Assembles a [MeshPacket](https://buf.build/meshtastic/protobufs/docs/main:meshtastic#meshtastic.MeshPacket) based on your parameters and writes it to the device. */
@@ -584,6 +584,7 @@ export default abstract class Device extends js.global.EventEmitter {
 
 	/** You probably don't need to call this directly. It's only really needed for SerialDevice, and is handled there for you even in synchronous scripts. */
 	sendHeartbeat(): void {
+		if (Date.now() - this.lastWrite < this.heartbeatInterval) return;
 		const toRadio: protobuf.Mesh.ToRadio = new protobuf.Mesh.ToRadio({
 			payloadVariant: {
 				case: 'heartbeat',
-- 
GitLab