diff --git a/web/bindings/mqtt.json b/web/bindings/mqtt.json index dbf5f103..a9a593ee 100644 --- a/web/bindings/mqtt.json +++ b/web/bindings/mqtt.json @@ -411,11 +411,13 @@ { "topic": "state/pumps/@bind=data.id;/@bind=data.name;", "message": "{\"id\":@bind=data.id;,\"isOn\":@bind=data.flow > 0 || data.rpm > 0?'\"on\"':'\"off\"';}", - "description": "Bind 'on'/'off' as a message to the state topic." + "description": "Bind 'on'/'off' as a message to the state topic.", + "enabled": true }, { "topic": "state/pumps/@bind=data.id;/@bind=data.name;/rpm", - "message": "{\"rpm\":@bind=data.rpm;}" + "message": "{\"rpm\":@bind=data.rpm;}", + "enabled": true }, { "topic": "state/pumps/@bind=data.id;/@bind=data.name;/flow", diff --git a/web/interfaces/mqttInterface.ts b/web/interfaces/mqttInterface.ts index 3b08417a..2349b6b2 100644 --- a/web/interfaces/mqttInterface.ts +++ b/web/interfaces/mqttInterface.ts @@ -134,8 +134,8 @@ export class MqttInterfaceBindings extends BaseInterfaceBindings { let root = this.rootTopic(); if (typeof this.subscriptions !== 'undefined') { for (let i = 0; i < this.subscriptions.length; i++) { - let sub = this.subscriptions[i]; - if(sub.enabled !== false) this.topics.push(new MqttTopicSubscription(root, sub)); + let sub = this.subscriptions[i]; + if(sub.enabled !== false) this.topics.push(new MqttTopicSubscription(root, sub)); } } else if (typeof root !== 'undefined') { @@ -155,6 +155,7 @@ export class MqttInterfaceBindings extends BaseInterfaceBindings { `state/temps`, `config/tempSensors`, `config/chemController`, + `config/pump`, `state/chemController`, `config/chlorinator`, `state/chlorinator`]; @@ -403,8 +404,8 @@ export class MqttInterfaceBindings extends BaseInterfaceBindings { // RKS: Not sure why there is no processing of state vs config here. Right now the topics are unique // between them so it doesn't matter but it will become an issue. switch (topics[topics.length - 1].toLowerCase()) { - case 'setstate': { - let id = parseInt(msg.id, 10); + case 'setstate': { + let id = parseInt(msg.id, 10); if (typeof id !== 'undefined' && isNaN(id)) { logger.error(`Inbound MQTT ${topics} has an invalid id (${id}) in the message (${msg}).`) }; @@ -456,7 +457,7 @@ export class MqttInterfaceBindings extends BaseInterfaceBindings { switch (topics[topics.length - 2].toLowerCase()) { case 'circuits': case 'circuit': - try { + try { await sys.board.circuits.toggleCircuitStateAsync(id); } catch (err) { logger.error(`Error processing MQTT topic ${topics[topics.length - 2]}: ${err.message}`); } @@ -472,6 +473,54 @@ export class MqttInterfaceBindings extends BaseInterfaceBindings { logger.warn(`MQTT: Inbound topic ${topics[topics.length - 1]} not matched to event ${topics[topics.length - 2].toLowerCase()}. Message ${msg} `) } break; + } + case 'pump': + { + let id = parseInt(msg.id, 10); + if (typeof id !== 'undefined' && isNaN(id)) { + logger.error(`Inbound MQTT ${topics} has an invalid id (${id}) in the message (${Utils.stringifyJSON(msg)}).`) + }; + switch (topics[topics.length - 2].toLowerCase()) { + case 'config': + let circuits = msg.circuits; + if(typeof circuits !== 'undefined') circuits.forEach(async ckt => { + if(typeof ckt !== 'undefined') { + let circuits_id = parseInt(ckt.id,10); + let circuit = parseInt(ckt.circuit,10); + let speed = parseInt(ckt.speed,10); + if ((typeof circuits_id !== 'undefined' && isNaN(circuits_id)) || (typeof circuit !== 'undefined' && isNaN(circuit)) || (typeof speed !== 'undefined' && isNaN(speed))) { + logger.error(`Inbound pump config MQTT ${topics} contains invalid circuit parameters in the message (${Utils.stringifyJSON(msg)}).`); + return; + } else { + let units = ckt.units; + if(typeof units !== 'undefined') { + let val = parseInt(ckt.units.val,10); + if(typeof val !== 'undefined' && isNaN(val)) { + logger.error(`Inbound pump config MQTT ${topics} invalid circuits.units.val (${circuits.units.val}) in the message (${Utils.stringifyJSON(msg)}).`); + return; + } else { + //validated a circuit is well formed + try { await sys.board.pumps.setPumpAsync(msg); } + catch (err) { logger.error(`Error processing MQTT topic ${topics[topics.length - 2]}: ${err.message}`); } + } + } else { + logger.error(`Inbound pump config MQTT ${topics} must include circuits.units list in the message (${Utils.stringifyJSON(msg)}).`); + return; + } + } + } else { + logger.error(`Inbound pump config MQTT ${topics} has an invalid circuit: (${Utils.stringifyJSON(circuits)}) in the message (${Utils.stringifyJSON(msg)}).`); + return; + } + }); else { + logger.error(`Inbound pump config MQTT ${topics} has a invalid circuits: (${Utils.stringifyJSON(circuits)}) in the message (${Utils.stringifyJSON(msg)}).`); + return; + } + break; + default: + logger.warn(`MQTT: Inbound pump topic ${topics[topics.length - 1]} not matched to event ${topics[topics.length - 2].toLowerCase()}. Message ${Utils.stringifyJSON(msg)} `) + } + break; } case 'heatsetpoint': try {