diff --git a/README.md b/README.md
index 277963f3211fcc86c2f533b4ff27431895c22fe1..c92eea7d10179938eeac31d5ebd5b2026459c3b0 100644
--- a/README.md
+++ b/README.md
@@ -21,34 +21,39 @@ port = 4403
 [module_echo]
 name = Echo
 path = echo
-devices = 0
+device = 0
 channel = 0
 port = 1
 enabled = true
 debug = false
 reply = same
+hopLimit = 0
 
 [module_weather]
 name = Weather
 path = weather
-devices = 0
+device = 0
 channel = 0
 port = 1
 enabled = true
 debug = false
 reply = same
+hopLimit = 0
 ```
 
 Device section names must begin with `device_`, module section names must begin with `module_`, but the rest of the name is arbitrary.
 
+If you want to use the same module with multiple devices, you'll need to create a module configuration for each device.
+
 In module config:
 - `path` is either a magic word for one of the built-in modules, or the path to an external Synchronet JavaScript module (.js file).
-- `devices` can be a single number or a comma-separated list of device IDs (which must match the `id` field for a `[device_*]` above)
+- `device` must match the `id` of one of `device_*`
 - `port` is a Meshtastic [port number](https://buf.build/meshtastic/protobufs/docs/main:meshtastic#meshtastic.PortNum) for this module to listen on
 - `reply` is one of `same` (default), `direct`, or `broadcast`
   - `same` means that if the module receives a direct message, it will respond in a direct message, and if it receives the command in a broadcast message, it will respond with a broadcast message
   - `direct` means that regardless of how the original message was addressed, the response will be sent in a direct message
   - `broadcast` means that regardless of how the original message was addressed, the response will be sent in a broadcast message
+- `hopLimit` specifies the number of hops you want messages from this module to make on the mesh network ([see here for more info](https://meshtastic.org/docs/overview/mesh-algo/))
 
 ## Operation
 
diff --git a/build/synctastic.js b/build/synctastic.js
index 599c5ba213a4e93e228f5f17ed0b804325aba705..97a68984971ae2aaa4382b224a5ba18ff30ee462 100644
--- a/build/synctastic.js
+++ b/build/synctastic.js
@@ -3232,31 +3232,6 @@
     }
   });
 
-  // node_modules/core-js/internals/array-for-each.js
-  var require_array_for_each = __commonJS({
-    "node_modules/core-js/internals/array-for-each.js": function(exports, module) {
-      "use strict";
-      var $forEach = require_array_iteration().forEach;
-      var arrayMethodIsStrict = require_array_method_is_strict();
-      var STRICT_METHOD = arrayMethodIsStrict("forEach");
-      module.exports = !STRICT_METHOD ? function forEach(callbackfn) {
-        return $forEach(this, callbackfn, arguments.length > 1 ? arguments[1] : void 0);
-      } : [].forEach;
-    }
-  });
-
-  // node_modules/core-js/modules/es.array.for-each.js
-  var require_es_array_for_each = __commonJS({
-    "node_modules/core-js/modules/es.array.for-each.js": function() {
-      "use strict";
-      var $ = require_export();
-      var forEach = require_array_for_each();
-      $({ target: "Array", proto: true, forced: [].forEach !== forEach }, {
-        forEach: forEach
-      });
-    }
-  });
-
   // node_modules/core-js/modules/es.array.index-of.js
   var require_es_array_index_of = __commonJS({
     "node_modules/core-js/modules/es.array.index-of.js": function() {
@@ -5428,7 +5403,7 @@
       "use strict";
       var $ = require_export();
       $({ target: "Number", stat: true }, {
-        isNaN: function isNaN2(number) {
+        isNaN: function isNaN(number) {
           return number !== number;
         }
       });
@@ -9281,33 +9256,6 @@
     }
   });
 
-  // node_modules/core-js/modules/web.dom-collections.for-each.js
-  var require_web_dom_collections_for_each = __commonJS({
-    "node_modules/core-js/modules/web.dom-collections.for-each.js": function() {
-      "use strict";
-      var global2 = require_global();
-      var DOMIterables = require_dom_iterables();
-      var DOMTokenListPrototype = require_dom_token_list_prototype();
-      var forEach = require_array_for_each();
-      var createNonEnumerableProperty = require_create_non_enumerable_property();
-      var handlePrototype = function(CollectionPrototype) {
-        if (CollectionPrototype && CollectionPrototype.forEach !== forEach)
-          try {
-            createNonEnumerableProperty(CollectionPrototype, "forEach", forEach);
-          } catch (error) {
-            CollectionPrototype.forEach = forEach;
-          }
-      };
-      for (COLLECTION_NAME in DOMIterables) {
-        if (DOMIterables[COLLECTION_NAME]) {
-          handlePrototype(global2[COLLECTION_NAME] && global2[COLLECTION_NAME].prototype);
-        }
-      }
-      var COLLECTION_NAME;
-      handlePrototype(DOMTokenListPrototype);
-    }
-  });
-
   // node_modules/core-js/modules/web.dom-collections.iterator.js
   var require_web_dom_collections_iterator = __commonJS({
     "node_modules/core-js/modules/web.dom-collections.iterator.js": function() {
@@ -9407,7 +9355,6 @@
   require_es_array_filter();
   require_es_array_find();
   require_es_array_find_index();
-  require_es_array_for_each();
   require_es_array_index_of();
   require_es_array_is_array();
   require_es_array_iterator();
@@ -9506,7 +9453,6 @@
   require_esnext_typed_array_to_reversed();
   require_esnext_typed_array_to_sorted();
   require_esnext_typed_array_with();
-  require_web_dom_collections_for_each();
   require_web_dom_collections_iterator();
   require_web_self();
   function _callSuper(t, o, e) {
@@ -19976,23 +19922,12 @@
       } else if (typeof config.reply !== "string" || config.reply !== "same" && config.reply !== "direct" && config.reply !== "broadcast") {
         throw new Error("Invalid 'reply' setting for module ".concat(config.name));
       }
-      var devices = [];
-      if (typeof config.devices !== "number") {
-        if (typeof config.devices !== "string")
-          throw new Error("Invalid device list ".concat(config.devices, " for module ").concat(config.name));
-        config.devices.split(",").forEach(function(e) {
-          var n = parseInt(e, 10);
-          if (isNaN(n))
-            throw new Error("Invalid device id ".concat(e, " for module ").concat(config.name));
-          devices.push(n);
-        });
-      } else {
-        devices.push(config.devices);
-      }
+      if (typeof config.device !== "number")
+        throw new Error("Invalid device ".concat(config.device, " for module ").concat(config.name));
       var ret = __spreadProps(__spreadValues({}, config), {
         name: config.name,
         path: config.path,
-        devices: devices,
+        device: config.device,
         channel: config.channel,
         port: config.port,
         enabled: config.enabled,
@@ -20041,10 +19976,10 @@
       };
     }
     var Module = /* @__PURE__ */ function() {
-      function Module2(config, devices) {
+      function Module2(config, device) {
         _classCallCheck(this, Module2);
         this.config = config;
-        this.devices = devices;
+        this.device = device;
       }
       return _createClass(Module2, [{
         key: "log",
@@ -20059,14 +19994,14 @@
       }]);
     }();
     var Echo = /* @__PURE__ */ function(_Module) {
-      function Echo2(config, devices) {
+      function Echo2(config, device) {
         _classCallCheck(this, Echo2);
-        return _callSuper(this, Echo2, [config, devices]);
+        return _callSuper(this, Echo2, [config, device]);
       }
       _inherits(Echo2, _Module);
       return _createClass(Echo2, [{
         key: "handlePacket",
-        value: function handlePacket(packet, device, replyTo) {
+        value: function handlePacket(packet, replyTo) {
           var _a;
           if (packet.payloadVariant["case"] !== "decoded")
             return false;
@@ -20076,7 +20011,7 @@
             return false;
           var echo = "You sent: ".concat(msg.replace(/^.echo\s/, ""));
           var hopLimit = (_a = this.config.hopLimit) != null ? _a : void 0;
-          device.sendText({
+          this.device.sendText({
             text: echo,
             to: replyTo,
             channel: packet.channel,
@@ -20099,11 +20034,11 @@
       return "\uD83D\uDFE3";
     }
     var Weather = /* @__PURE__ */ function(_Module2) {
-      function Weather2(config, devices) {
+      function Weather2(config, device) {
         var _this4;
         _classCallCheck(this, Weather2);
         var _a;
-        _this4 = _callSuper(this, Weather2, [config, devices]);
+        _this4 = _callSuper(this, Weather2, [config, device]);
         var wc = config;
         _this4.units = "metric";
         if (typeof wc.units === "string") {
@@ -20115,21 +20050,8 @@
         }
         _this4.alertRebroadcast = (_a = wc.alertRebroadcast) != null ? _a : false;
         if (typeof wc.alertInterval === "number" && wc.alertInterval > 0) {
-          var alertBroadcastInterval2 = function alertBroadcastInterval22() {
-            for (var d2 = 0; d2 < this.devices.length; d2++) {
-              this.broadcastAlerts(this.devices[d2], this.config.channel, this.config.hopLimit);
-            }
-          };
-          var alertBroadcastInterval = alertBroadcastInterval2;
-          js.setInterval(alertBroadcastInterval2, wc.alertInterval, _this4);
-          var _loop3 = function _loop32(d2) {
-            _this4.devices[d2].on("ready", function() {
-              _this4.broadcastAlerts(_this4.devices[d2], _this4.config.channel, _this4.config.hopLimit);
-            });
-          };
-          for (var d = 0; d < _this4.devices.length; d++) {
-            _loop3(d);
-          }
+          js.setInterval(_this4.broadcastAlerts, wc.alertInterval, _this4);
+          _this4.device.on("ready", _this4.broadcastAlerts.bind(_this4));
         }
         return _this4;
       }
@@ -20193,10 +20115,10 @@
         }
       }, {
         key: "canBroadcastAlert",
-        value: function canBroadcastAlert(wa, devId) {
+        value: function canBroadcastAlert(wa) {
           var ret = true;
           var wah = js.global.md5_calc(wa);
-          var wal = "".concat(Date.now(), ",").concat(devId, ",").concat(wah);
+          var wal = "".concat(Date.now(), ",").concat(this.device.configId, ",").concat(wah);
           var fn = "".concat(js.global.system.temp_dir, "synctastic-weather-alerts.txt");
           var f = new js.global.File(fn);
           if (!f.exists) {
@@ -20209,7 +20131,7 @@
               throw new Error("Failed to open ".concat(fn, " for reading"));
             while (!f.eof) {
               var l = f.readln().split(",");
-              if (parseInt(l[1], 10) !== devId)
+              if (parseInt(l[1], 10) !== this.device.configId)
                 continue;
               if (l[2] !== wah)
                 continue;
@@ -20228,8 +20150,8 @@
         }
       }, {
         key: "broadcastAlerts",
-        value: function broadcastAlerts(device, channel, hopLimit) {
-          var nodeInfo = device.getNodeInfo(device.myNodeInfo.myNodeNum);
+        value: function broadcastAlerts() {
+          var nodeInfo = this.device.getNodeInfo(this.device.myNodeInfo.myNodeNum);
           if ((nodeInfo == null ? void 0 : nodeInfo.position) === void 0)
             return;
           var lat = nodeInfo.position.latitudeI * 1e-7;
@@ -20237,17 +20159,17 @@
           var wa = this.getCurrentAlerts(lat, lon);
           if (wa === void 0)
             return;
-          if (!this.alertRebroadcast && !this.canBroadcastAlert(wa, device.configId))
+          if (!this.alertRebroadcast && !this.canBroadcastAlert(wa))
             return;
-          device.sendText({
+          this.device.sendText({
             text: wa,
-            channel: channel,
-            hopLimit: hopLimit
+            channel: this.config.channel,
+            hopLimit: this.config.hopLimit
           });
         }
       }, {
         key: "handlePacket",
-        value: function handlePacket(packet, device, replyTo) {
+        value: function handlePacket(packet, replyTo) {
           if (packet.payloadVariant["case"] !== "decoded")
             return false;
           var dec = new TextDecoder();
@@ -20255,12 +20177,12 @@
           if (!msg.startsWith(".wx"))
             return false;
           try {
-            var nodeInfo = device.getNodeInfo(packet.from);
+            var nodeInfo = this.device.getNodeInfo(packet.from);
             if ((nodeInfo == null ? void 0 : nodeInfo.position) === void 0) {
               if (this.config.debug) {
                 this.log(sbbsdefs.LOG_DEBUG, "failed to find position for ".concat(packet.from, " in node DB. Falling back on self position"));
               }
-              nodeInfo = device.getNodeInfo(device.myNodeInfo.myNodeNum);
+              nodeInfo = this.device.getNodeInfo(this.device.myNodeInfo.myNodeNum);
             }
             if ((nodeInfo == null ? void 0 : nodeInfo.position) === void 0) {
               throw new Error("failed to find self position, cannot send lat/lon to weather API");
@@ -20282,7 +20204,7 @@
             }
             if (ws === void 0)
               return false;
-            device.sendText({
+            this.device.sendText({
               text: ws,
               to: replyTo,
               channel: packet.channel,
@@ -20301,7 +20223,7 @@
       var config = getConfig();
       var devices = {};
       var modules = [];
-      var _loop4 = function _loop42() {
+      var _loop3 = function _loop32() {
         var dev = void 0;
         if (config.devices[device].type === "serial") {
           var cfg = config.devices[device];
@@ -20328,7 +20250,7 @@
             var _module = _modules[_i17];
             if (_module.config.channel !== packet.channel)
               continue;
-            if (_module.config.devices.indexOf(dev.configId) < 0)
+            if (_module.config.device !== dev.configId)
               continue;
             if (packet.to !== defs_exports.BROADCAST && packet.to !== dev.myNodeInfo.myNodeNum)
               continue;
@@ -20340,32 +20262,30 @@
             if (_module.config.reply === "broadcast" || _module.config.reply === "same" && packet.to === defs_exports.BROADCAST) {
               to = defs_exports.BROADCAST;
             }
-            _module.handlePacket(packet, dev, to);
+            _module.handlePacket(packet, to);
           }
         });
         dev.connect();
         devices[config.devices[device].id] = dev;
       };
       for (var device in config.devices) {
-        if (_loop4())
+        if (_loop3())
           continue;
       }
       for (var module in config.modules) {
-        var devs = [];
-        for (var devId in config.modules[module].devices) {
-          if (devices[devId] !== void 0)
-            devs.push(devices[devId]);
+        if (devices[config.modules[module].device] === void 0) {
+          throw new Error("Invalid device specified for ".concat(config.modules[module].name));
         }
         switch (config.modules[module].path) {
           case "echo":
-            modules.push(new Echo(config.modules[module], devs));
+            modules.push(new Echo(config.modules[module], devices[config.modules[module].device]));
             break;
           case "weather":
-            modules.push(new Weather(config.modules[module], devs));
+            modules.push(new Weather(config.modules[module], devices[config.modules[module].device]));
             break;
           default:
             var m = js.global.load({}, config.modules[module].path);
-            modules.push(new m(config.modules[module]));
+            modules.push(new m(config.modules[module], devices[config.modules[module].device]));
             break;
         }
       }
diff --git a/src/lib/config.ts b/src/lib/config.ts
index 8569fad798927846ca00555ff683a38d7676b244..db89fa4eb1a57cdef908c60b235811c60f2f18d0 100644
--- a/src/lib/config.ts
+++ b/src/lib/config.ts
@@ -26,7 +26,7 @@ type ReplyType = 'same' | 'direct' | 'broadcast';
 export interface IModuleConfig {
 	name: string,
 	path: string,
-	devices: number[],
+	device: number,
 	channel: number,
 	port: number,
 	enabled: boolean,
@@ -105,24 +105,13 @@ function parseModuleConfig(config: IniSection): IModuleConfig {
 	} else if (typeof config.reply !== 'string' || (config.reply !== 'same' && config.reply !== 'direct' && config.reply !== 'broadcast')) {
 		throw new Error(`Invalid 'reply' setting for module ${config.name}`);
 	}
-
-	const devices = [];
-	if (typeof config.devices !== 'number') {
-		if (typeof config.devices !== 'string') throw new Error(`Invalid device list ${config.devices} for module ${config.name}`);
-		config.devices.split(',').forEach(e => {
-			const n = parseInt(e, 10);
-			if (isNaN(n)) throw new Error(`Invalid device id ${e} for module ${config.name}`);
-			devices.push(n);
-		});
-	} else {
-		devices.push(config.devices);
-	}
+	if (typeof config.device !== 'number') throw new Error(`Invalid device ${config.device} for module ${config.name}`);
 
 	const ret: IModuleConfig = {
 		...config,
 		name: config.name,
 		path: config.path,
-		devices,
+		device: config.device,
 		channel: config.channel,
 		port: config.port,
 		enabled: config.enabled,
diff --git a/src/lib/module.ts b/src/lib/module.ts
index 6e338c3bfea163c2343af67e957d83721b2cd193..d66dfeb16d54b4fc0310951a829fdcbb5c27d398 100644
--- a/src/lib/module.ts
+++ b/src/lib/module.ts
@@ -4,14 +4,14 @@ import { IModuleConfig } from './config';
 export default abstract class Module {
 
 	config: IModuleConfig;
-	devices: Device[];
+	device: Device;
 
-	constructor(config: IModuleConfig, devices: Device[]) {
+	constructor(config: IModuleConfig, device: Device) {
 		this.config = config;
-		this.devices = devices;
+		this.device = device;
 	}
 
-	abstract handlePacket(packet: protobuf.Mesh.MeshPacket, device: Device, replyTo: number): boolean; // 'true' if handled
+	abstract handlePacket(packet: protobuf.Mesh.MeshPacket, replyTo: number): boolean; // 'true' if handled
 
 	log(level: number, msg: string): void {
 		js.global.log(level, `${this.config.name}: ${msg}`);
diff --git a/src/modules/echo.ts b/src/modules/echo.ts
index a63b4372a7f918fb368f514c095ed1203d49bda9..ca3159142b6476266ddc5d12ba37503af247b672 100644
--- a/src/modules/echo.ts
+++ b/src/modules/echo.ts
@@ -4,11 +4,11 @@ import { IModuleConfig } from '../lib/config';
 
 export default class Echo extends Module {
 
-	constructor(config: IModuleConfig, devices: Device[]) {
-		super(config, devices);
+	constructor(config: IModuleConfig, device: Device) {
+		super(config, device);
 	}
 
-	handlePacket(packet: protobuf.Mesh.MeshPacket, device: Device, replyTo: number): boolean {
+	handlePacket(packet: protobuf.Mesh.MeshPacket, replyTo: number): boolean {
 		if (packet.payloadVariant.case !== 'decoded') return false;
 		// @ts-expect-error It's ambient
 		const dec = new TextDecoder();
@@ -16,7 +16,7 @@ export default class Echo extends Module {
 		if (!msg.startsWith('.echo ')) return false;
 		const echo = `You sent: ${msg.replace(/^.echo\s/, '')}`;
 		const hopLimit = this.config.hopLimit ?? undefined;
-		device.sendText({ text: echo, to: replyTo, channel: packet.channel, replyId: packet.id, hopLimit });
+		this.device.sendText({ text: echo, to: replyTo, channel: packet.channel, replyId: packet.id, hopLimit });
 		return true;
 	}
 
diff --git a/src/modules/weather.ts b/src/modules/weather.ts
index 198ab807d5a435d65d8a8df0153db45e338158c4..ebc5402a0e0fff018e0917f74ef8e2876946be24 100644
--- a/src/modules/weather.ts
+++ b/src/modules/weather.ts
@@ -24,8 +24,8 @@ export default class Weather extends Module {
 	private units: unit;
 	private alertRebroadcast: boolean;
 
-	constructor(config: IModuleConfig, devices: Device[]) {
-		super(config, devices);
+	constructor(config: IModuleConfig, device: Device) {
+		super(config, device);
 
 		const wc: IWeatherModuleConfig = config as IWeatherModuleConfig;
 		this.units = 'metric';
@@ -40,17 +40,8 @@ export default class Weather extends Module {
 		this.alertRebroadcast = wc.alertRebroadcast ?? false;
 
 		if (typeof wc.alertInterval === 'number' && wc.alertInterval > 0) {
-			function alertBroadcastInterval(this: Weather): void {
-				for (let d = 0; d < this.devices.length; d++) {
-					this.broadcastAlerts(this.devices[d], this.config.channel, this.config.hopLimit);
-				}
-			}
-			js.setInterval(alertBroadcastInterval, wc.alertInterval, this);
-			for (let d = 0; d < this.devices.length; d++) {
-				this.devices[d].on('ready', () => {
-					this.broadcastAlerts(this.devices[d], this.config.channel, this.config.hopLimit);
-				});
-			}
+			js.setInterval(this.broadcastAlerts, wc.alertInterval, this);
+			this.device.on('ready', this.broadcastAlerts.bind(this));
 		}
 	}
 
@@ -92,10 +83,10 @@ export default class Weather extends Module {
 		return ws === '' ? undefined : ws;
 	}
 
-	private canBroadcastAlert(wa: string, devId: number): boolean {
+	private canBroadcastAlert(wa: string): boolean {
 		let ret = true;
 		const wah = js.global.md5_calc(wa);
-		const wal = `${Date.now()},${devId},${wah}`;
+		const wal = `${Date.now()},${this.device.configId},${wah}`;
 		const fn = `${js.global.system.temp_dir}synctastic-weather-alerts.txt`;
 		const f = new js.global.File(fn);
 		if (!f.exists) {
@@ -106,7 +97,7 @@ export default class Weather extends Module {
 			if (!f.open('r')) throw new Error(`Failed to open ${fn} for reading`);
 			while (!f.eof) {
 				const l = f.readln().split(',');
-				if (parseInt(l[1], 10) !== devId) continue;
+				if (parseInt(l[1], 10) !== this.device.configId) continue;
 				if (l[2] !== wah) continue;
 				ret = false;
 				break;
@@ -121,18 +112,18 @@ export default class Weather extends Module {
 		return ret;
 	}
 
-	private broadcastAlerts(device: Device, channel: number, hopLimit: number | undefined): void {
-		const nodeInfo = device.getNodeInfo(device.myNodeInfo.myNodeNum);
+	private broadcastAlerts(): void {
+		const nodeInfo = this.device.getNodeInfo(this.device.myNodeInfo.myNodeNum);
 		if (nodeInfo?.position === undefined) return;
 		const lat = nodeInfo.position.latitudeI * .0000001;
 		const lon = nodeInfo.position.longitudeI * .0000001;
 		const wa = this.getCurrentAlerts(lat, lon);
 		if (wa === undefined) return;
-		if (!this.alertRebroadcast && !this.canBroadcastAlert(wa, device.configId)) return;
-		device.sendText({ text: wa, channel: channel, hopLimit });
+		if (!this.alertRebroadcast && !this.canBroadcastAlert(wa)) return;
+		this.device.sendText({ text: wa, channel: this.config.channel, hopLimit: this.config.hopLimit });
 	}
 
-	handlePacket(packet: protobuf.Mesh.MeshPacket, device: Device, replyTo: number): boolean {
+	handlePacket(packet: protobuf.Mesh.MeshPacket, replyTo: number): boolean {
 		if (packet.payloadVariant.case !== 'decoded') return false;
 		// @ts-expect-error It's ambient
 		const dec = new TextDecoder();
@@ -140,12 +131,12 @@ export default class Weather extends Module {
 		if (!msg.startsWith('.wx')) return false;
 
 		try {
-			let nodeInfo = device.getNodeInfo(packet.from);
+			let nodeInfo = this.device.getNodeInfo(packet.from);
 			if (nodeInfo?.position === undefined) {
 				if (this.config.debug) {
 					this.log(sbbsdefs.LOG_DEBUG, `failed to find position for ${packet.from} in node DB. Falling back on self position`);
 				}
-				nodeInfo = device.getNodeInfo(device.myNodeInfo.myNodeNum);
+				nodeInfo = this.device.getNodeInfo(this.device.myNodeInfo.myNodeNum);
 			}
 			if (nodeInfo?.position === undefined) {
 				throw new Error('failed to find self position, cannot send lat/lon to weather API');
@@ -167,7 +158,7 @@ export default class Weather extends Module {
 			}
 			if (ws === undefined) return false;
 			
-			device.sendText({ text: ws, to: replyTo, channel: packet.channel, replyId: packet.id, hopLimit: this.config.hopLimit });
+			this.device.sendText({ text: ws, to: replyTo, channel: packet.channel, replyId: packet.id, hopLimit: this.config.hopLimit });
 			return true;
 		} catch (err: any) {
 			this.error(err as string);
diff --git a/src/synctastic.ts b/src/synctastic.ts
index 05a9f340cbf9d8e15e907ec646c0655df0e345b7..4e90233dd0352395965656d7c39803023ab1638f 100644
--- a/src/synctastic.ts
+++ b/src/synctastic.ts
@@ -33,7 +33,7 @@ function init(): void {
 			if (dev === undefined) return;
 			for (const module of modules) {
 				if (module.config.channel !== packet.channel) continue;
-				if (module.config.devices.indexOf(dev.configId) < 0) continue;
+				if (module.config.device !== dev.configId) continue;
 				if (packet.to !== defs.BROADCAST && packet.to !== dev.myNodeInfo.myNodeNum) continue;
 				if (packet.payloadVariant.case !== 'decoded') continue;
 				if (module.config.port !== packet.payloadVariant.value.portnum) continue;
@@ -41,7 +41,7 @@ function init(): void {
 				if (module.config.reply === 'broadcast' || (module.config.reply === 'same' && packet.to === defs.BROADCAST)) {
 					to = defs.BROADCAST;
 				}
-				module.handlePacket(packet, dev, to);
+				module.handlePacket(packet, to);
 			}
 		});
 
@@ -53,21 +53,20 @@ function init(): void {
 
 	for (const module in config.modules) {
 
-		const devs: Device[] = [];
-		for (const devId in config.modules[module].devices) {
-			if (devices[devId] !== undefined) devs.push(devices[devId]);
+		if (devices[config.modules[module].device] === undefined) {
+			throw new Error(`Invalid device specified for ${config.modules[module].name}`);
 		}
 
 		switch (config.modules[module].path) {
 			case 'echo':
-				modules.push(new Echo(config.modules[module], devs));
+				modules.push(new Echo(config.modules[module], devices[config.modules[module].device]));
 				break;
 			case 'weather':
-				modules.push(new Weather(config.modules[module], devs));
+				modules.push(new Weather(config.modules[module], devices[config.modules[module].device]));
 				break;
 			default:
 				const m = js.global.load({}, config.modules[module].path);
-				modules.push(new m(config.modules[module]));
+				modules.push(new m(config.modules[module], devices[config.modules[module].device]));
 				break;
 		}