exports.id = 'mqttsubscribe'; exports.title = 'MQTT subscribe'; exports.group = 'MQTT'; exports.color = '#888600'; exports.version = '1.1.0'; exports.icon = 'sign-in'; exports.output = 1; exports.variables = true; exports.author = 'Martin Smola'; exports.options = {}; exports.html = `
@(Select a broker)
Topic
@(Supports variables, example: \`device/{device-id}\`)
@(QoS)
`; exports.readme = ` # MQTT subscribe The data recieved are passed to the output as follows: \`\`\`javascript { topic: '/lights/on', data: 'kitchen' } \`\`\` If the topic is wildcard then there's an array of matches in flowdata repository which can be used in Function component like so: \`\`\`javascript // wildcard -> /+/status // topic -> /devicename/status var match = flowdata.get('mqtt_wildcard'); // match === ['devicename'] \`\`\` More on wildcard topics [here](https://mosquitto.org/man/mqtt-7.html) `; exports.install = function(instance) { var old_topic; var ready = false; instance.custom.reconfigure = function(o, old_options) { ready = false; if (!MQTT.broker(instance.options.broker)) return instance.status('No broker', 'red'); if (instance.options.broker && instance.options.topic) { if (old_topic) MQTT.unsubscribe(instance.options.broker, instance.id, old_topic); old_topic = instance.arg(instance.options.topic); MQTT.subscribe(instance.options.broker, instance.id, old_topic); ready = true; return; } instance.status('Not configured', 'red'); }; instance.on('options', instance.custom.reconfigure); instance.on('close', function() { MQTT.unsubscribe(instance.options.broker, instance.id, instance.options.topic); OFF('mqtt.brokers.message', instance.custom.message); OFF('mqtt.brokers.status', instance.custom.brokerstatus); }); instance.custom.brokerstatus = function(status, brokerid, msg) { if (brokerid !== instance.options.broker) return; switch (status) { case 'connecting': instance.status('Connecting', '#a6c3ff'); break; case 'connected': instance.status('Connected', 'green'); break; case 'disconnected': instance.status('Disconnected', 'red'); break; case 'connectionfailed': instance.status('Connection failed', 'red'); break; case 'new': !ready && instance.custom.reconfigure(); break; case 'removed': instance.custom.reconfigure(); break; case 'error': instance.status(msg, 'red'); break; case 'reconfigured': instance.options.broker = msg; instance.reconfig(); instance.custom.reconfigure(); break; } } instance.custom.message = function(brokerid, topic, message) { if (brokerid !== instance.options.broker) return; var match = mqttWildcard(topic, old_topic); if (match) { var flowdata = instance.make({ topic: topic, data: message }) flowdata.set('mqtt_wildcard', match); instance.send2(flowdata); } } ON('mqtt.brokers.message', instance.custom.message); ON('mqtt.brokers.status', instance.custom.brokerstatus); instance.custom.reconfigure(); }; // https://github.com/hobbyquaker/mqtt-wildcard function mqttWildcard(topic, wildcard) { if (topic === wildcard) { return []; } else if (wildcard === '#') { return [topic]; } var res = []; var t = String(topic).split('/'); var w = String(wildcard).split('/'); var i = 0; for (var lt = t.length; i < lt; i++) { if (w[i] === '+') { res.push(t[i]); } else if (w[i] === '#') { res.push(t.slice(i).join('/')); return res; } else if (w[i] !== t[i]) { return null; } } if (w[i] === '#') { i += 1; } return (i === w.length) ? res : null; }