diff --git a/build/synctastic.js b/build/synctastic.js
index 956c4d84570abbde4ece8fda54b3d9e5081bc4dd..b2058c91b6a3d4119f299f0bff91e4f7e9e3870a 100644
--- a/build/synctastic.js
+++ b/build/synctastic.js
@@ -15846,6 +15846,7 @@
         var _this;
         var debug = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : false;
         var configId = arguments.length > 1 ? arguments[1] : void 0;
+        var heartbeatInterval = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 30;
         _classCallCheck(this, Device2);
         _this = _callSuper(this, Device2);
         _this.timeoutMs = _RESPONSE_TIMEOUT * 1e3;
@@ -15860,6 +15861,9 @@
         _this.ackHandlers = {};
         _this.responseHandlers = {};
         _this.purgeEvent = js.setInterval(_this.purgeHandlers, _this.timeoutMs, _this);
+        _this.heartbeatInterval = heartbeatInterval * 1e3;
+        _this.heartbeatEvent = -1;
+        _this.lastWrite = Date.now();
         _this.initTime = Date.now();
         _this.initTimeout = _CONNECT_TIMEOUT * 1e3;
         return _this;
@@ -15907,7 +15911,6 @@
           if (!this.write(msg))
             this.error("failed to initialize");
           function onTimeout() {
-            js.global.writeln("timing out init");
             if (!this.ready)
               this.error("initialization timeout (configCompleteId not received from device)");
           }
@@ -15922,10 +15925,12 @@
       }, {
         key: "cycle",
         value: function cycle() {
-          if (!this.ready && Date.now() - this.initTime > this.initTimeout)
+          var now = Date.now();
+          if (!this.ready && now - this.initTime > this.initTimeout)
             this.error("initialization timeout (configCompleteId not received from device)");
           this.read();
           this.purgeHandlers();
+          this.sendHeartbeat();
           this._cycle();
         }
       }, {
@@ -15957,6 +15962,7 @@
           if (this.readyEvent > -1)
             js.clearTimeout(this.readyEvent);
           js.clearInterval(this.purgeEvent);
+          js.clearInterval(this.heartbeatInterval);
           this.purgeHandlers(true);
         }
       }, {
@@ -15995,6 +16001,9 @@
                 if (this.readyEvent > -1)
                   js.clearTimeout(this.readyEvent);
                 this.emit("ready");
+                this.heartbeatEvent = js.setInterval(function() {
+                  this.sendHeartbeat();
+                }, this.heartbeatInterval, this);
               }
               break;
             case "metadata":
@@ -16091,7 +16100,10 @@
             this.error("write: packet length ".concat(data.length, " exceeds maximum length ").concat(_MAXLEN));
           var header = [_START, _START2, data.length >> 8 & 255, data.length & 255];
           var buffer = new Uint8Array([].concat(header, _toConsumableArray(data)));
-          return this.sendToDevice(buffer);
+          var 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. */
       }, {
@@ -16414,10 +16426,12 @@
       }, {
         key: "sendHeartbeat",
         value: function sendHeartbeat() {
+          if (Date.now() - this.lastWrite < this.heartbeatInterval)
+            return;
           var toRadio = new mesh_pb_exports.ToRadio({
             payloadVariant: {
               "case": "heartbeat",
-              value: new mesh_pb_exports.Heartbeat({})
+              value: new mesh_pb_exports.Heartbeat()
             }
           });
           this.write(toRadio);
@@ -16522,10 +16536,12 @@
           }
           if (!this.socket.data_waiting)
             return;
+          this.log(sbbsdefs.LOG_DEBUG, "reading ".concat(this.socket.nread, " bytes from device"));
           var buf = [];
           while (this.socket.data_waiting) {
             buf.push(this.socket.recvBin(1));
           }
+          this.log(sbbsdefs.LOG_DEBUG, "read ".concat(buf.length, " bytes from device"));
           var data = new Uint8Array(buf);
           return data;
         }
@@ -16550,16 +16566,14 @@
       function SerialDevice2(port, baud) {
         var _this3;
         var pollInterval = arguments.length > 2 && arguments[2] !== void 0 ? arguments[2] : 10;
-        var heartbeatInterval = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : 30;
-        var debug = arguments.length > 4 && arguments[4] !== void 0 ? arguments[4] : false;
-        var configId = arguments.length > 5 ? arguments[5] : void 0;
+        var debug = arguments.length > 3 && arguments[3] !== void 0 ? arguments[3] : false;
+        var configId = arguments.length > 4 ? arguments[4] : void 0;
         _classCallCheck(this, SerialDevice2);
         _this3 = _callSuper(this, SerialDevice2, [debug, configId]);
         _this3.deviceTag = "serial ".concat(port);
         _this3.handle = new js.global.COM(port);
         _this3.handle.baud_rate = baud;
         _this3.pollInterval = pollInterval;
-        _this3.heartbeatInterval = heartbeatInterval;
         return _this3;
       }
       _inherits(SerialDevice2, _Device2);
@@ -16570,7 +16584,6 @@
           if (!this.handle.open())
             return false;
           this.pollEvent = js.setInterval(this.read, this.pollInterval * 1e3, this);
-          this.heartbeatEvent = js.setInterval(this.sendHeartbeat, this.heartbeatInterval * 1e3, this);
           this.init(timeout);
           return true;
         }
@@ -16583,8 +16596,6 @@
           this.handle.close();
           if (this.pollEvent !== void 0)
             js.clearInterval(this.pollEvent);
-          if (this.heartbeatEvent !== void 0)
-            js.clearInterval(this.heartbeatEvent);
           this.destroy();
           return true;
         }
@@ -16616,11 +16627,6 @@
       }, {
         key: "_cycle",
         value: function _cycle() {
-          var now = Date.now();
-          if (this.lastHeartbeat === void 0 || now - this.lastHeartbeat >= this.heartbeatInterval) {
-            this.lastHeartbeat = now;
-            this.sendHeartbeat();
-          }
         }
       }]);
     }(Device);
@@ -16885,7 +16891,7 @@
         var dev = void 0;
         if (config.devices[device].type === "serial") {
           var cfg = config.devices[device];
-          dev = new SerialDevice(cfg.port, cfg.baud, void 0, void 0, cfg.debug, cfg.id);
+          dev = new SerialDevice(cfg.port, cfg.baud, void 0, cfg.debug, cfg.id);
           dev.on("ready", function() {
             return js.global.log(sbbsdefs.LOG_INFO, "".concat(cfg.type, " device ").concat(cfg.port, " is ready"));
           });
@@ -16910,7 +16916,7 @@
               continue;
             if (_module.config.devices.indexOf(dev.configId) < 0)
               continue;
-            if (packet.to !== 4294967295 && packet.to !== dev.myNodeInfo.myNodeNum)
+            if (packet.to !== defs_exports.BROADCAST && packet.to !== dev.myNodeInfo.myNodeNum)
               continue;
             if (packet.payloadVariant["case"] !== "decoded")
               continue;