///***************** HOME ASSISTANT ************************ // for uci mqtt discovery in HA const STATE_TOPIC = 'state' const STATE_CMD = 'state' const ENTITY = 'switch' const DISCOVERY = 'homeassistant' const NAMESPACE = 'uci' const COMMAND_TOPIC = 'set' // will use payload as the command function register(name,opts={}) { const topic = `${opts.discovery || DISCOVERY}/` + `${opts.entity || ENTITY}/` + `${opts.namespace || NAMESPACE ? `${opts.namespace || NAMESPACE }` :''}` console.log('subscription topic for HA',`${topic}/#`) this.getSocket(name).subscribe(`${topic}/#`) this.beforeProcessHook(async (packet) => { // console.log('incoming ha mqtt packet to modify') // console.dir(packet) // let modified = Object.assign({},packet) const topic = packet.cmd.split('/') const cmd = topic.pop() const id = topic.pop() // console.log(cmd, id) if (cmd=== (opts.state || STATE_TOPIC)) return null // ignore state commands (avoid infiite loop) else if (cmd===(opts.command||COMMAND_TOPIC)) packet.cmd = packet.data.toLowerCase() else packet.cmd = cmd delete packet.data Object.assign(packet,this.entities.find(ent => ent.id === id)) // console.log('translated to uci packet') // console.dir(packet) return packet }, {name:name}) this.afterProcessHook(async (packet) => { if (packet.error) { let npacket = {} npacket.cmd = 'error' npacket.payload = JSON.stringify(packet) return npacket } // console.log('after process', packet) return packet }, {name:name}) this.beforeSendHook(async (packet) => { if (packet.cmd === (opts.stateCmd || STATE_CMD)) { // console.log('preparing state topic/payload') if (packet.state && packet.gpio) { let mpacket = { cmd: `${topic}/${packet.id}/${opts.stateCmd || STATE_CMD}`, payload: ((packet.state || {})[packet.gpio.toString()] || '').toUpperCase() } // console.log('=============modified packet being pushed to broker================') // console.dir(mpacket) // console.log('================') return mpacket } // else console.log('bad state packet state/gpio',packet.state,packet.gpio) } // console.log('packet ignored, nothing sent to to HA') return null // only send/publish the required topic }, {name:name}) } export default register function init(mqtt,entities,opts={}) { console.log('initializing ha mqtt discovery') entities.forEach(ent => { const topic = `${opts.discovery || DISCOVERY}/` + `${opts.entity || ENTITY}/` + `${opts.namespace || NAMESPACE ? `${opts.namespace || NAMESPACE }/` :''}` + `${ent.id}` let payload = { name:`${opts.namespace || NAMESPACE ? `${opts.namespace || NAMESPACE }_` :''}${ent.id}`, command_topic:`${topic}/${opts.command || COMMAND_TOPIC}`, state_topic: `${topic}/${opts.state || STATE_TOPIC}`, json_attributes_topic:`${topic}/${opts.state || STATE_TOPIC}`, json_attributes_template:'{{ value_json.alias | tojson }}', } payload = JSON.stringify(payload) console.log('------ sending discovery payload to HA for ',ent.alias,':',ent.id,'-----') console.log('topic=>',`${topic}/config`) // console.log(payload) mqtt.publish(`${topic}/info`,null) // clear existing mqtt.publish(`${topic}/config`,payload,{retain:true}) }) } export { register,init }