Nodered for Unifi AP via MQTT on Home Assistant

Inspired by @valvex and it’s great work here https://community.home-assistant.io/t/monitoring-your-unifi-ap/259703?u=sdomotica_automation and with some issue with Python Script, I decided to implement mine using Nodered and Mqtt dicover features of Home Assistant.

You can see all the infos of your AP and you can block and unblock all the devices connetecred
You can also turn-on / turn-off the AP led

Each component has attributes with info as IP address, statistics etc.

Here the Nodered Flow
I use this palette, that you have to install before import my flow

https://flows.nodered.org/node/node-red-contrib-unifi


[{"id":"3366c513d01846b6","type":"Unifi","z":"ca15b45a6a5a96ab","name":"","server":"0bbadfcf8bb33bc7","command":"30","debug":false,"x":330,"y":100,"wires":[["b7179904bebb3a88","05af66cd7cce372f","b2139d9142b197ad"]]},{"id":"9763d22b7dba8ff7","type":"inject","z":"ca15b45a6a5a96ab","name":"AllUsers","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"240","crontab":"","once":true,"onceDelay":"10","topic":"AllUsers","payload":"{\"command\": \"AllUsers\"}","payloadType":"json","x":100,"y":140,"wires":[["3366c513d01846b6"]]},{"id":"b7179904bebb3a88","type":"switch","z":"ca15b45a6a5a96ab","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"AllUsers","vt":"str"},{"t":"eq","v":"ClientDevices","vt":"str"},{"t":"eq","v":"Blocking","vt":"str"},{"t":"eq","v":"AccessDevices","vt":"str"},{"t":"eq","v":"Led","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":6,"x":530,"y":140,"wires":[["37ca55753a131511"],["b963e534079fc751"],["6386d006de2ba9fc"],["6e99d5d9567aa493"],["e081d7ad10a31626"],[]]},{"id":"37ca55753a131511","type":"function","z":"ca15b45a6a5a96ab","name":"AllUsers","func":"const a = msg.payload\nvar unifi_id = []\nvar unifi_id_blocked = []\n\na.forEach((element) => {\n    unifi_id.push(element._id)\n    if (typeof element.hostname != \"undefined\"){\n        var nome = \"Unifi: \" + element.hostname\n    } else {\n        if (element.oui != \"\") {\n            nome = \"Unifi: \" + element.oui\n        } else {\n            nome = \"Unifi: \" + element.mac\n        }\n    }\n\n\n    msg.topic = \"homeassistant/switch/\" +element._id + \"/config\"\n    msg.payload = {\n        \"name\": nome,\n        \"unique_id\": \"unifiswitch\" + element._id,\n        \"icon\": \"mdi:lan\",\n        \"availability_topic\": \"homeassistant/unifi/\" + element._id + \"/availability\",\n        \"json_attributes_topic\": \"homeassistant/unifi/\" + element._id  + \"/json\",\n        \"state_topic\": \"homeassistant/unifi/\" + element._id + \"/state\",\n        \"command_topic\": \"homeassistant/unificmd/\" + element._id + \"/\" + element.mac\n\n    }\n\n    //msg.payload = element\n    node.send(msg);\n\n});\nflow.set(\"unifiusers\", a)\nmsg.topic = \"endsetup\"\nmsg.payload = \"end\"\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":80,"wires":[["3e991dc8c13a492a"]]},{"id":"3e991dc8c13a492a","type":"switch","z":"ca15b45a6a5a96ab","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"endsetup","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":930,"y":80,"wires":[["23769bdba7c78250"],["fcb8c4111f3bddd0"]]},{"id":"fcb8c4111f3bddd0","type":"mqtt out","z":"ca15b45a6a5a96ab","name":"","topic":"","qos":"","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"dac17249.b02d3","x":1310,"y":240,"wires":[]},{"id":"23769bdba7c78250","type":"change","z":"ca15b45a6a5a96ab","name":"Ask Clients","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"ClientDevices\"}","tot":"json"},{"t":"set","p":"topic","pt":"msg","to":"ClientDevices","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1090,"y":80,"wires":[["ea9d4502fb30ca23"]]},{"id":"b963e534079fc751","type":"function","z":"ca15b45a6a5a96ab","name":"All clients status","func":"const a = msg.payload\nconst unifiusers = flow.get(\"unifiusers\")\nvar unificlient = []\n\n\na.forEach((element) => {\n    var attributi = {}\n    unificlient.push(element._id)\n    //send online status\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n    msg.payload = \"online\"\n    node.send(msg);    \n\n    //send client status\n    if (typeof element.blocked != \"undefined\"){\n        if (element.blocked == true) {\n            var stato = \"OFF\"\n        } else {\n            stato = \"ON\"\n        }\n    } else {\n        stato = \"ON\"\n    }\n\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/state\"\n    msg.payload = stato\n    node.send(msg);\n\n    //send client attributes\n    if (typeof element.mac != \"undefined\") { attributi[\"mac\"] = element.mac }\n    if (typeof element.last_seen != \"undefined\") { attributi[\"last_seen\"] = element.last_seen }\n    if (typeof element._uptime_by_uap != \"undefined\") { attributi[\"_uptime_by_uap\"] = element._uptime_by_uap }\n    if (typeof element.channel != \"undefined\") { attributi[\"channel\"] = element.channel }\n    if (typeof element.radio != \"undefined\") { attributi[\"radio\"] = element.radio }\n    if (typeof element.radio_name != \"undefined\") { attributi[\"radio_name\"] = element.radio_name }\n    if (typeof element.essid != \"undefined\") { attributi[\"essid\"] = element.essid }\n    if (typeof element.ip != \"undefined\") { attributi[\"ip\"] = element.ip }\n    if (typeof element.noise != \"undefined\") { attributi[\"noise\"] = element.noise }\n    if (typeof element.nss != \"undefined\") { attributi[\"nss\"] = element.nss }\n    if (typeof element.rx_rate != \"undefined\") { attributi[\"rx_rate\"] = element.rx_rate }\n    if (typeof element.rssi != \"undefined\") { attributi[\"rssi\"] = element.rssi }\n    if (typeof element.satisfaction != \"undefined\") { attributi[\"satisfaction\"] = element.satisfaction }\n    if (typeof element.satisfaction_now != \"undefined\") { attributi[\"satisfaction_now\"] = element.satisfaction_now }\n    if (typeof element.signal != \"undefined\") { attributi[\"signal\"] = element.signal }\n    if (typeof element.uptime != \"undefined\") { attributi[\"uptime\"] = element.uptime }\n    if (typeof element.tx_bytes != \"undefined\") { attributi[\"tx_bytes\"] = element.tx_bytes }\n    if (typeof element.rx_bytes != \"undefined\") { attributi[\"rx_bytes\"] = element.rx_bytes }\n    if (typeof element.tx_packets != \"undefined\") { attributi[\"tx_packets\"] = element.tx_packets }\n    if (typeof element.rx_packets != \"undefined\") { attributi[\"rx_packets\"] = element.rx_packets }\n    if (typeof element.blocked != \"undefined\") { attributi[\"blocked\"] = element.blocked }\n\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/json\"\n    msg.payload = attributi\n    node.send(msg);\n\n});\n\n//put offline other Users\nunifiusers.forEach((element) => {\n    if (unificlient.indexOf(element._id) !== -1) {\n        //client already managed as connected\n    } else {\n        //check if client has beed disabled\n        if (typeof element.blocked != \"undefined\" && element.blocked == true) { \n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n            msg.payload = \"online\"\n            node.send(msg);\n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/state\"\n            msg.payload = \"OFF\"\n            node.send(msg); \n        } else {\n        //not disable thus unvaiable\n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n            msg.payload = \"offline\"\n            node.send(msg); \n        }\n    }\n})\n\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":120,"wires":[["fcb8c4111f3bddd0"]]},{"id":"9facaba6ce550dd2","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unificmd/#","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":130,"y":460,"wires":[["e4a1cdee39b0d269"]]},{"id":"e4a1cdee39b0d269","type":"function","z":"ca15b45a6a5a96ab","d":true,"name":"Block or Unblock","func":"var Topic = msg.topic\nvar TOPIC = Topic.split('/')\nvar mac = TOPIC[3]\n\nif (msg.payload == \"ON\"){\n    msg.payload = {\n        \"command\": \"unblockClient\",\n        \"mac\": TOPIC[3]\n    }\n} else {\n    msg.payload = {\n        \"command\": \"blockClient\",\n        \"mac\": TOPIC[3]\n    }\n\n}\n\nmsg.topic = \"Blocking\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":460,"wires":[["3366c513d01846b6"]]},{"id":"6386d006de2ba9fc","type":"function","z":"ca15b45a6a5a96ab","name":"Block and Unblock Status","func":"const a = msg.payload[0][0]\nvar stato\nif (msg.payload[0][0].blocked == true  ){\n    stato = \"OFF\"\n} else {\n    stato = \"ON\"\n}\n\n\nmsg.topic = \"homeassistant/unifi/\" + msg.payload[0][0]._id + \"/state\"\nmsg.payload = stato\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":810,"y":160,"wires":[["fcb8c4111f3bddd0"]]},{"id":"c5d257fbdebb227f","type":"inject","z":"ca15b45a6a5a96ab","name":"AccessDevices","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"120","crontab":"","once":true,"onceDelay":"5","topic":"AccessDevices","payload":"{\"command\": \"AccessDevices\"}","payloadType":"json","x":130,"y":180,"wires":[["3366c513d01846b6"]]},{"id":"6e99d5d9567aa493","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices - Builder Dinamic","func":"const a = msg.payload\nmsg.accessdevices = a\n\na.forEach((element) => {\n    // send info about state of AP\n    if (typeof element.state != \"undefined\") {\n        if (typeof element.name != \"undefined\") {\n            var nome = element.name\n        } else {\n             nome = element.model\n        }\n\n        msg.topic = \"homeassistant/binary_sensor/ubiquiti\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": nome,\n            \"unique_id\": \"ubiquiti\" + element._id,\n            \"icon\": \"mdi:access-point\",\n            \"device_class\": \"connectivity\",\n            \"payload_on\": 1,\n            \"payload_off\": 0,\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/state/json\",\n            \"value_template\": \"{{ value_json.state }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/state/json\"\n        }\n        node.send(msg);\n    }\n\n\n    // send info connected clients\n    if (typeof element.num_sta != \"undefined\") {\n        msg.topic = \"homeassistant/sensor/ubiquitiusers\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"Users: \" + nome,\n            \"unique_id\": \"ubiquitiusers\" + element._id,\n            \"icon\": \"mdi:accpunt\",\n            \"unit_of_measurement\": \"n\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/users/json\",\n            \"value_template\": \"{{ value_json.num_sta }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/users/json\"\n        }\n        node.send(msg);\n    }\n\n\n    // AP led\n    if (typeof element.led_override != \"undefined\") {\n        msg.topic = \"homeassistant/light/ubiquitiled\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"Led: \" + nome,\n            \"unique_id\": \"ubiquitiled\" + element._id,\n            \"icon\": \"mdi:led-outline\",\n            \"payload_on\": \"on\",\n            \"payload_off\": \"off\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/led\",\n            \"command_topic\": \"homeassistant/unifiapcmd/led/\" + element._id\n        }\n        node.send(msg);\n    }\n\n\n    // send info about bytes\n    if (typeof element.bytes != \"undefined\") {\n        msg.topic = \"homeassistant/sensor/unifibytes\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"MB: \" + nome,\n            \"unique_id\": \"unifibytes\" + element._id,\n            \"icon\": \"mdi:speedometer\",\n            \"unit_of_measurement\": \"MB\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\",\n            \"value_template\": \"{{ value_json.bytes }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\"\n        }\n        node.send(msg);\n    }\n\n    // send info about radio\n    if (typeof element.vap_table != \"undefined\") {\n        var i = 1\n        element.vap_table.forEach((vap) => {\n            if (typeof vap[\"radio_name\"] != \"undefined\") {\n                var radionome = vap[\"radio_name\"]\n            } else {\n                radionome = \"\"\n            }\n            msg.topic = \"homeassistant/sensor/unifiradio_\" + i + element._id + \"/config\"\n            msg.payload = {\n                \"name\": \"Client Signal: \" + radionome,\n                \"unique_id\": \"unifiradio_\" + i + element._id,\n                \"icon\": \"mdi:wifi\",\n                \"unit_of_measurement\": \"db\",\n                \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[\"radio_name\"] + \"/info/json\",\n                \"value_template\": \"{{ value_json.avg_client_signal }}\",\n                \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[\"radio_name\"] + \"/info/json\"\n            }\n            node.send(msg);\n            i = i + 1\n\n        });\n    }\n\n\n\n\n    // send info about radio2\n    if (typeof element.radio_table_stats != \"undefined\") {\n        var i = 1\n        element.radio_table_stats.forEach((radio) => {\n            if (typeof radio[\"name\"] != \"undefined\") {\n                var radionome = radio[\"name\"]\n            } else {\n                radionome = \"\"\n            }\n\n            msg.topic = \"homeassistant/sensor/unifistatus_\" + i + element._id + \"/config\"\n            msg.payload = {\n                \"name\": \"Radio State: \" + radionome,\n                \"unique_id\": \"unifistatus_\" + i + element._id,\n                \"icon\": \"mdi:wifi\",\n                \"unit_of_measurement\": \"db\",\n                \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/info/json\",\n                \"value_template\": \"{{ value_json.avg_client_signal }}\",\n                \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state/json\"\n            }\n            node.send(msg);\n            i = i + 1\n        });\n    }\n\n\n});\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":200,"wires":[["52a518474c2ca6bf","fcb8c4111f3bddd0"]]},{"id":"52a518474c2ca6bf","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":"const a = msg.accessdevices\n\nvar array_ap = {}\nvar bytes_info = {}\n\nfunction secondsToString(seconds) {\n    var numyears = Math.floor(seconds / 31536000);\n    var numdays = Math.floor((seconds % 31536000) / 86400);\n    var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);\n    var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);\n    var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;\n    var human = \"\"\n    if (numyears>0){\n        human = human  + numyears + \"y \" \n    }\n    if (numdays > 0) {\n        human = human + numdays + \"d \"\n    }\n\n    if (numhours > 0) {\n        human = human + numhours + \"h \"\n    }\n\n    if (numminutes > 0) {\n        human = human + numminutes + \"m \"\n    }\n\n    if (numseconds > 0) {\n        human = human + numseconds + \"s \"\n    }\n\n    return human;\n\n}\n\na.forEach((element) => {\n    //msg.payload = element.vap_table\n    //msg.payload = element._id\n\n    //master topic for send info\n    var topic_radice = \"unifi/\" + element._id + \"/\"\n\n\n    //send info about some data of AP\n    const parametri = [\"disabled\",\"state\", \"_id\", \"model\", \"version\", \"type\", \"config_network.ip\", \"config_network.type\", \"uptime\", \"name\", \"satisfaction\", \"disabled\", \"num_sta\", \"user-num_sta\", \"user-wlan-num_sta\", \"guest-num_sta\", \"guest-wlan-num_sta\", \"system-stats\"]\n\n    var info_ap = {}\n    parametri.forEach((elementi) => {\n        if (typeof element[elementi] != \"undefined\") {\n            info_ap[elementi] = element[elementi]\n            if (elementi == \"system-stats\"){\n                info_ap[\"cpu\"] = element[\"system-stats\"].cpu\n                info_ap[\"mem\"] = element[\"system-stats\"].mem\n            }\n\n            if (elementi == \"uptime\") {\n                info_ap[\"uptimeU\"] = secondsToString(element[\"uptime\"])\n            }\n\n\n        }\n\n    });\n\n\n\n\n\n\n    // send info about state of AP\n    if (typeof element.state != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/state\"\n        msg.payload = element.state\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/state/json\"\n        msg.payload = info_ap\n        node.send(msg)\n    }\n\n\n    // AP led\n    if (typeof element.led_override != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/led\"\n        msg.payload = element.led_override\n        node.send(msg)\n    }\n    \n\n    // send info connected clients\n    if (typeof element.num_sta != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/users\"\n        msg.payload = element.num_sta\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/users/json\"\n        msg.payload = info_ap\n        node.send(msg)\n    }\n\n    // send info about bytes\n    if (typeof element.bytes != \"undefined\") {\n        bytes_info = {}\n        bytes_info[\"bytes\"] = element.bytes\n        if (typeof element.tx_bytes != \"undefined\") {\n            bytes_info[\"tx_bytes\"] = element.tx_bytes\n            bytes_info[\"MB_tx_bytes\"] = Math.round(element.tx_bytes / 10000) / 100\n        }\n\n        if (typeof element.tx_bytes != \"undefined\") {\n            bytes_info[\"rx_bytes\"] = element.tx_bytes\n            bytes_info[\"MB_rx_bytes\"] = Math.round(element.rx_bytes / 10000) / 100\n        }\n\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/bytes\"\n        msg.payload = Math.round(element.bytes / 10000) / 100\n        bytes_info[\"MB_bytes\"] = Math.round(element.bytes / 10000) / 100\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\"\n        msg.payload = bytes_info\n        node.send(msg)\n    }\n\n\n\n    // send info about radio\n    if (typeof element.vap_table != \"undefined\") {\n        const parametri2 = [\"avg_client_signal\", \"bw\", \"channel\", \"satisfaction\", \"radio\", \"radio_name\"];\n        element.vap_table.forEach((vap) => {\n            var info_radio = {}\n            parametri2.forEach((itemvap) => {\n                if (typeof vap[itemvap] != \"undefined\") {\n                    info_radio[itemvap] = vap[itemvap]\n                }\n                if (itemvap == \"radio_name\") {\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[itemvap] + \"/info\"\n                    msg.payload = vap[\"avg_client_signal\"]\n                    node.send(msg)\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[itemvap] + \"/info/json\"\n                    msg.payload = info_radio\n                    node.send(msg)\n                }\n            });\n        });\n    }\n\n\n\n\n    // send info about radio2\n    if (typeof element.radio_table_stats != \"undefined\") {\n        const parametri3 = [\"name\", \"channel\", \"satisfaction\", \"num_sta\", \"guest-num_sta\", \"user-num_sta\", \"radio\", \"state\"];\n        element.radio_table_stats.forEach((radio) => {\n            var info_radio2 = {}\n            parametri3.forEach((itemradio) => {\n                if (typeof radio[itemradio] != \"undefined\") {\n                    info_radio2[itemradio] = radio[itemradio]\n                }\n                if (itemradio == \"state\") {\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state\"\n                    msg.payload = radio[\"state\"]\n                    node.send(msg)\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state/json\"\n                    msg.payload = info_radio2\n                    node.send(msg)\n                }\n            });\n        });\n    }\n\n\n\n\n\n\n\n\n    //node.send(msg);\n    //console.log(element);\n});\n\n//return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1180,"y":160,"wires":[["fcb8c4111f3bddd0","1ffc7d6cbf08dafc"]]},{"id":"71ac4af553d3c733","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unifiapcmd/info","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":400,"wires":[["fbe063632d457edb"]]},{"id":"fbe063632d457edb","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":" msg.payload = {\n        \"command\": \"AccessDevices\"\n    }\nmsg.topic = \"AccessDevices\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":400,"wires":[["3366c513d01846b6"]]},{"id":"b2139d9142b197ad","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 13","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":20,"wires":[]},{"id":"4582b00e0058f4c0","type":"function","z":"ca15b45a6a5a96ab","name":"Led","func":"var Topic = msg.topic\nvar TOPIC = Topic.split('/')\nvar id = TOPIC[3]\n\nif (msg.payload == \"on\") {\n    msg.payload = {\n        \"command\": \"setapled\",\n        \"device_id\": TOPIC[3],\n        \"mode\": \"on\"\n    }\n} else {\n    msg.payload = {\n        \"command\": \"setapled\",\n        \"device_id\": TOPIC[3],\n        \"mode\": \"off\"\n    }\n\n}\n\nmsg.topic = \"Led\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":500,"wires":[["3366c513d01846b6","096e4907982047dc"]]},{"id":"096e4907982047dc","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":500,"wires":[]},{"id":"bb7cdedaf0576685","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unifiapcmd/led/#","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":150,"y":500,"wires":[["4582b00e0058f4c0"]]},{"id":"e081d7ad10a31626","type":"function","z":"ca15b45a6a5a96ab","name":"Send Led Status","func":"const a = msg.payload[0]\nmsg.topic = \"homeassistant/ubiquiti/\" + msg.payload[0]._id + \"/led\"\nmsg.payload = msg.payload[0].led_override\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":240,"wires":[["fcb8c4111f3bddd0"]]},{"id":"ea9d4502fb30ca23","type":"link out","z":"ca15b45a6a5a96ab","name":"to ask clients","mode":"link","links":["318241859f35d0e3"],"x":1225,"y":80,"wires":[]},{"id":"318241859f35d0e3","type":"link in","z":"ca15b45a6a5a96ab","name":"ask clients","links":["ea9d4502fb30ca23"],"x":65,"y":100,"wires":[["3366c513d01846b6"]]},{"id":"3b03ce0baf29792a","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/status","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":300,"wires":[["c2b6df73df87529a"]]},{"id":"c2b6df73df87529a","type":"switch","z":"ca15b45a6a5a96ab","name":"Online","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"online","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":350,"y":300,"wires":[["ff6306ab802ab554"]]},{"id":"ff6306ab802ab554","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":" msg.payload = {\n        \"command\": \"AccessDevices\"\n    }\nmsg.topic = \"AccessDevices\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":300,"wires":[["337d456b88dae300","3366c513d01846b6"]]},{"id":"337d456b88dae300","type":"delay","z":"ca15b45a6a5a96ab","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":720,"y":300,"wires":[["4566303d76ec6e23"]]},{"id":"4566303d76ec6e23","type":"function","z":"ca15b45a6a5a96ab","name":"AllUsers","func":"msg.payload = {\n    \"command\": \"AllUsers\"\n}\nmsg.topic = \"AllUsers\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":300,"wires":[["3366c513d01846b6"]]},{"id":"a7297fd85ea37b96","type":"comment","z":"ca15b45a6a5a96ab","name":"https://flows.nodered.org/node/node-red-contrib-unifi","info":"","x":230,"y":40,"wires":[]},{"id":"05af66cd7cce372f","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 24","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":420,"wires":[]},{"id":"32195e76ae96f3c3","type":"inject","z":"ca15b45a6a5a96ab","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":240,"wires":[["c2b6df73df87529a"]]},{"id":"1ffc7d6cbf08dafc","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 81","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1410,"y":180,"wires":[]},{"id":"0bbadfcf8bb33bc7","type":"unificonfig","name":"","ip":"192.168.1.123","port":"8443","site":"default","unifios":false,"ssl":false},{"id":"dac17249.b02d3","type":"mqtt-broker","name":"","broker":"192.168.1.57","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

And here the card

  - theme: Backend-selected
    title: Unifi
    path: unifi
    icon: phu:ubiquiti-ap
    badges: []
    cards:
      - type: entities
        entities:
          - entity: light.led_ac_lite_soggiorno
      - type: entities
        entities:
          - type: custom:multiple-entity-row
            entity: binary_sensor.ac_lite_soggiorno
            show_entity_picture: true
            icon: phu:ubiquiti-ap
            show_state: false
            secondary_info:
              attribute: uptimeU
            entities:
              - entity: binary_sensor.ac_lite_soggiorno
                attribute: cpu
                name: CPU
                unit: '%'
              - entity: binary_sensor.ac_lite_soggiorno
                attribute: mem
                name: Ram
                unit: '%'
              - icon: mdi:restart
                tap_action:
                  action: call-service
                  service: mqtt.publish
                  service_data:
                    topic: homeassistant/unifiapcmd/info
                    payload: refresh
          - type: custom:multiple-entity-row
            entity: binary_sensor.ac_lite_soggiorno
            icon: mdi:devices
            name: ' '
            show_state: false
            secondary_info:
              entity: binary_sensor.unifi_ac_lite_soggiorno
              attribute: num_sta
              name: ' '
              unit: Clients
            entities:
              - entity: sensor.radio_state_wifi0
                attribute: num_sta
                name: 2.4GhZ
                unit: ' '
              - entity: sensor.radio_state_wifi1
                name: 5GhZ
                attribute: num_sta
                unit: ' '
          - type: custom:mini-graph-card
            entities:
              - entity: sensor.users_ac_lite_soggiorno
            group: true
            hours_to_show: 4
            line_width: 3
            points_per_hour: 15
            show:
              icon: false
              name: false
              state: false
              labels: true
          - type: custom:multiple-entity-row
            entity: sensor.client_signal_wifi0
            icon: mdi:wifi
            name: 2.4 GhZ
            show_state: false
            secondary_info:
              entity: sensor.client_signal_wifi0
              name: ' '
              unit: dB
            entities:
              - entity: sensor.client_signal_wifi0
                attribute: satisfaction
                name: Satisfaction
                unit: '%'
              - entity: sensor.client_signal_wifi0
                attribute: channel
                name: Channel
                unit: ''
              - entity: sensor.radio_state_wifi0
                attribute: num_sta
                name: Clients
                unit: ''
          - type: custom:multiple-entity-row
            entity: sensor.client_signal_wifi0
            icon: mdi:wifi
            name: 5 GhZ
            show_state: false
            secondary_info:
              entity: sensor.client_signal_wifi1
              name: ' '
              unit: dB
            entities:
              - entity: sensor.client_signal_wifi1
                attribute: satisfaction
                name: Satisfaction
                unit: '%'
              - entity: sensor.client_signal_wifi1
                attribute: channel
                name: Channel
                unit: ''
              - entity: sensor.radio_state_wifi1
                attribute: num_sta
                name: Clients
                unit: ''
          - type: custom:mini-graph-card
            entities:
              - entity: sensor.client_signal_wifi1
            group: true
            font_size: 85
            hours_to_show: 24
            style: |
              ha-card {
                border-radius: 0px;
                box-shadow: none;
                } 
            show:
              icon: false
              graph: false
              name: false
              state: false
              extrema: true
              average: true
          - type: custom:mini-graph-card
            entities:
              - entity: sensor.client_signal_wifi1
            group: true
            hours_to_show: 4
            line_width: 3
            points_per_hour: 15
            show:
              icon: false
              name: false
              state: false
              labels: true
      - type: custom:auto-entities
        card:
          type: entities
        filter:
          include:
            - name: Unifi:*
          exclude: []

Bye
Sandro

2 Likes

Hi Sandro,

Still using this script?
I get the error message "TypeError: a.forEach is not a function" on all function nodes behind the switch node.

I tried to fix this but if I change the first line const a = msg.payload[0] to const a = msg.payload it looks like it is working, I see MQTT Topics but Node-Red then crashes continuously.

There was a Unifi API change. I updated the flow code in my post.

[{"id":"3366c513d01846b6","type":"Unifi","z":"ca15b45a6a5a96ab","name":"","server":"0bbadfcf8bb33bc7","command":"30","debug":false,"x":330,"y":100,"wires":[["b7179904bebb3a88","05af66cd7cce372f","b2139d9142b197ad"]]},{"id":"9763d22b7dba8ff7","type":"inject","z":"ca15b45a6a5a96ab","name":"AllUsers","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"240","crontab":"","once":true,"onceDelay":"10","topic":"AllUsers","payload":"{\"command\": \"AllUsers\"}","payloadType":"json","x":100,"y":140,"wires":[["3366c513d01846b6"]]},{"id":"b7179904bebb3a88","type":"switch","z":"ca15b45a6a5a96ab","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"AllUsers","vt":"str"},{"t":"eq","v":"ClientDevices","vt":"str"},{"t":"eq","v":"Blocking","vt":"str"},{"t":"eq","v":"AccessDevices","vt":"str"},{"t":"eq","v":"Led","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":6,"x":530,"y":140,"wires":[["37ca55753a131511"],["b963e534079fc751"],["6386d006de2ba9fc"],["6e99d5d9567aa493"],["e081d7ad10a31626"],[]]},{"id":"37ca55753a131511","type":"function","z":"ca15b45a6a5a96ab","name":"AllUsers","func":"const a = msg.payload\nvar unifi_id = []\nvar unifi_id_blocked = []\n\na.forEach((element) => {\n    unifi_id.push(element._id)\n    if (typeof element.hostname != \"undefined\"){\n        var nome = \"Unifi: \" + element.hostname\n    } else {\n        if (element.oui != \"\") {\n            nome = \"Unifi: \" + element.oui\n        } else {\n            nome = \"Unifi: \" + element.mac\n        }\n    }\n\n\n    msg.topic = \"homeassistant/switch/\" +element._id + \"/config\"\n    msg.payload = {\n        \"name\": nome,\n        \"unique_id\": \"unifiswitch\" + element._id,\n        \"icon\": \"mdi:lan\",\n        \"availability_topic\": \"homeassistant/unifi/\" + element._id + \"/availability\",\n        \"json_attributes_topic\": \"homeassistant/unifi/\" + element._id  + \"/json\",\n        \"state_topic\": \"homeassistant/unifi/\" + element._id + \"/state\",\n        \"command_topic\": \"homeassistant/unificmd/\" + element._id + \"/\" + element.mac\n\n    }\n\n    //msg.payload = element\n    node.send(msg);\n\n});\nflow.set(\"unifiusers\", a)\nmsg.topic = \"endsetup\"\nmsg.payload = \"end\"\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":760,"y":80,"wires":[["3e991dc8c13a492a"]]},{"id":"3e991dc8c13a492a","type":"switch","z":"ca15b45a6a5a96ab","name":"","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"endsetup","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":930,"y":80,"wires":[["23769bdba7c78250"],["fcb8c4111f3bddd0"]]},{"id":"fcb8c4111f3bddd0","type":"mqtt out","z":"ca15b45a6a5a96ab","name":"","topic":"","qos":"","retain":"true","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"dac17249.b02d3","x":1310,"y":240,"wires":[]},{"id":"23769bdba7c78250","type":"change","z":"ca15b45a6a5a96ab","name":"Ask Clients","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"command\":\"ClientDevices\"}","tot":"json"},{"t":"set","p":"topic","pt":"msg","to":"ClientDevices","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":1090,"y":80,"wires":[["ea9d4502fb30ca23"]]},{"id":"b963e534079fc751","type":"function","z":"ca15b45a6a5a96ab","name":"All clients status","func":"const a = msg.payload\nconst unifiusers = flow.get(\"unifiusers\")\nvar unificlient = []\n\n\na.forEach((element) => {\n    var attributi = {}\n    unificlient.push(element._id)\n    //send online status\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n    msg.payload = \"online\"\n    node.send(msg);    \n\n    //send client status\n    if (typeof element.blocked != \"undefined\"){\n        if (element.blocked == true) {\n            var stato = \"OFF\"\n        } else {\n            stato = \"ON\"\n        }\n    } else {\n        stato = \"ON\"\n    }\n\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/state\"\n    msg.payload = stato\n    node.send(msg);\n\n    //send client attributes\n    if (typeof element.mac != \"undefined\") { attributi[\"mac\"] = element.mac }\n    if (typeof element.last_seen != \"undefined\") { attributi[\"last_seen\"] = element.last_seen }\n    if (typeof element._uptime_by_uap != \"undefined\") { attributi[\"_uptime_by_uap\"] = element._uptime_by_uap }\n    if (typeof element.channel != \"undefined\") { attributi[\"channel\"] = element.channel }\n    if (typeof element.radio != \"undefined\") { attributi[\"radio\"] = element.radio }\n    if (typeof element.radio_name != \"undefined\") { attributi[\"radio_name\"] = element.radio_name }\n    if (typeof element.essid != \"undefined\") { attributi[\"essid\"] = element.essid }\n    if (typeof element.ip != \"undefined\") { attributi[\"ip\"] = element.ip }\n    if (typeof element.noise != \"undefined\") { attributi[\"noise\"] = element.noise }\n    if (typeof element.nss != \"undefined\") { attributi[\"nss\"] = element.nss }\n    if (typeof element.rx_rate != \"undefined\") { attributi[\"rx_rate\"] = element.rx_rate }\n    if (typeof element.rssi != \"undefined\") { attributi[\"rssi\"] = element.rssi }\n    if (typeof element.satisfaction != \"undefined\") { attributi[\"satisfaction\"] = element.satisfaction }\n    if (typeof element.satisfaction_now != \"undefined\") { attributi[\"satisfaction_now\"] = element.satisfaction_now }\n    if (typeof element.signal != \"undefined\") { attributi[\"signal\"] = element.signal }\n    if (typeof element.uptime != \"undefined\") { attributi[\"uptime\"] = element.uptime }\n    if (typeof element.tx_bytes != \"undefined\") { attributi[\"tx_bytes\"] = element.tx_bytes }\n    if (typeof element.rx_bytes != \"undefined\") { attributi[\"rx_bytes\"] = element.rx_bytes }\n    if (typeof element.tx_packets != \"undefined\") { attributi[\"tx_packets\"] = element.tx_packets }\n    if (typeof element.rx_packets != \"undefined\") { attributi[\"rx_packets\"] = element.rx_packets }\n    if (typeof element.blocked != \"undefined\") { attributi[\"blocked\"] = element.blocked }\n\n    msg.topic = \"homeassistant/unifi/\" + element._id + \"/json\"\n    msg.payload = attributi\n    node.send(msg);\n\n});\n\n//put offline other Users\nunifiusers.forEach((element) => {\n    if (unificlient.indexOf(element._id) !== -1) {\n        //client already managed as connected\n    } else {\n        //check if client has beed disabled\n        if (typeof element.blocked != \"undefined\" && element.blocked == true) { \n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n            msg.payload = \"online\"\n            node.send(msg);\n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/state\"\n            msg.payload = \"OFF\"\n            node.send(msg); \n        } else {\n        //not disable thus unvaiable\n            msg.topic = \"homeassistant/unifi/\" + element._id + \"/availability\"\n            msg.payload = \"offline\"\n            node.send(msg); \n        }\n    }\n})\n\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":120,"wires":[["fcb8c4111f3bddd0"]]},{"id":"9facaba6ce550dd2","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unificmd/#","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":130,"y":460,"wires":[["e4a1cdee39b0d269"]]},{"id":"e4a1cdee39b0d269","type":"function","z":"ca15b45a6a5a96ab","d":true,"name":"Block or Unblock","func":"var Topic = msg.topic\nvar TOPIC = Topic.split('/')\nvar mac = TOPIC[3]\n\nif (msg.payload == \"ON\"){\n    msg.payload = {\n        \"command\": \"unblockClient\",\n        \"mac\": TOPIC[3]\n    }\n} else {\n    msg.payload = {\n        \"command\": \"blockClient\",\n        \"mac\": TOPIC[3]\n    }\n\n}\n\nmsg.topic = \"Blocking\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":460,"wires":[["3366c513d01846b6"]]},{"id":"6386d006de2ba9fc","type":"function","z":"ca15b45a6a5a96ab","name":"Block and Unblock Status","func":"const a = msg.payload[0][0]\nvar stato\nif (msg.payload[0][0].blocked == true  ){\n    stato = \"OFF\"\n} else {\n    stato = \"ON\"\n}\n\n\nmsg.topic = \"homeassistant/unifi/\" + msg.payload[0][0]._id + \"/state\"\nmsg.payload = stato\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":810,"y":160,"wires":[["fcb8c4111f3bddd0"]]},{"id":"c5d257fbdebb227f","type":"inject","z":"ca15b45a6a5a96ab","name":"AccessDevices","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"120","crontab":"","once":true,"onceDelay":"5","topic":"AccessDevices","payload":"{\"command\": \"AccessDevices\"}","payloadType":"json","x":130,"y":180,"wires":[["3366c513d01846b6"]]},{"id":"6e99d5d9567aa493","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices - Builder Dinamic","func":"const a = msg.payload\nmsg.accessdevices = a\n\na.forEach((element) => {\n    // send info about state of AP\n    if (typeof element.state != \"undefined\") {\n        if (typeof element.name != \"undefined\") {\n            var nome = element.name\n        } else {\n             nome = element.model\n        }\n\n        msg.topic = \"homeassistant/binary_sensor/ubiquiti\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": nome,\n            \"unique_id\": \"ubiquiti\" + element._id,\n            \"icon\": \"mdi:access-point\",\n            \"device_class\": \"connectivity\",\n            \"payload_on\": 1,\n            \"payload_off\": 0,\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/state/json\",\n            \"value_template\": \"{{ value_json.state }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/state/json\"\n        }\n        node.send(msg);\n    }\n\n\n    // send info connected clients\n    if (typeof element.num_sta != \"undefined\") {\n        msg.topic = \"homeassistant/sensor/ubiquitiusers\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"Users: \" + nome,\n            \"unique_id\": \"ubiquitiusers\" + element._id,\n            \"icon\": \"mdi:accpunt\",\n            \"unit_of_measurement\": \"n\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/users/json\",\n            \"value_template\": \"{{ value_json.num_sta }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/users/json\"\n        }\n        node.send(msg);\n    }\n\n\n    // AP led\n    if (typeof element.led_override != \"undefined\") {\n        msg.topic = \"homeassistant/light/ubiquitiled\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"Led: \" + nome,\n            \"unique_id\": \"ubiquitiled\" + element._id,\n            \"icon\": \"mdi:led-outline\",\n            \"payload_on\": \"on\",\n            \"payload_off\": \"off\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/led\",\n            \"command_topic\": \"homeassistant/unifiapcmd/led/\" + element._id\n        }\n        node.send(msg);\n    }\n\n\n    // send info about bytes\n    if (typeof element.bytes != \"undefined\") {\n        msg.topic = \"homeassistant/sensor/unifibytes\" + element._id + \"/config\"\n        msg.payload = {\n            \"name\": \"MB: \" + nome,\n            \"unique_id\": \"unifibytes\" + element._id,\n            \"icon\": \"mdi:speedometer\",\n            \"unit_of_measurement\": \"MB\",\n            \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\",\n            \"value_template\": \"{{ value_json.bytes }}\",\n            \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\"\n        }\n        node.send(msg);\n    }\n\n    // send info about radio\n    if (typeof element.vap_table != \"undefined\") {\n        var i = 1\n        element.vap_table.forEach((vap) => {\n            if (typeof vap[\"radio_name\"] != \"undefined\") {\n                var radionome = vap[\"radio_name\"]\n            } else {\n                radionome = \"\"\n            }\n            msg.topic = \"homeassistant/sensor/unifiradio_\" + i + element._id + \"/config\"\n            msg.payload = {\n                \"name\": \"Client Signal: \" + radionome,\n                \"unique_id\": \"unifiradio_\" + i + element._id,\n                \"icon\": \"mdi:wifi\",\n                \"unit_of_measurement\": \"db\",\n                \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[\"radio_name\"] + \"/info/json\",\n                \"value_template\": \"{{ value_json.avg_client_signal }}\",\n                \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[\"radio_name\"] + \"/info/json\"\n            }\n            node.send(msg);\n            i = i + 1\n\n        });\n    }\n\n\n\n\n    // send info about radio2\n    if (typeof element.radio_table_stats != \"undefined\") {\n        var i = 1\n        element.radio_table_stats.forEach((radio) => {\n            if (typeof radio[\"name\"] != \"undefined\") {\n                var radionome = radio[\"name\"]\n            } else {\n                radionome = \"\"\n            }\n\n            msg.topic = \"homeassistant/sensor/unifistatus_\" + i + element._id + \"/config\"\n            msg.payload = {\n                \"name\": \"Radio State: \" + radionome,\n                \"unique_id\": \"unifistatus_\" + i + element._id,\n                \"icon\": \"mdi:wifi\",\n                \"unit_of_measurement\": \"db\",\n                \"state_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/info/json\",\n                \"value_template\": \"{{ value_json.avg_client_signal }}\",\n                \"json_attributes_topic\": \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state/json\"\n            }\n            node.send(msg);\n            i = i + 1\n        });\n    }\n\n\n});\n\n","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":840,"y":200,"wires":[["52a518474c2ca6bf","fcb8c4111f3bddd0"]]},{"id":"52a518474c2ca6bf","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":"const a = msg.accessdevices\n\nvar array_ap = {}\nvar bytes_info = {}\n\nfunction secondsToString(seconds) {\n    var numyears = Math.floor(seconds / 31536000);\n    var numdays = Math.floor((seconds % 31536000) / 86400);\n    var numhours = Math.floor(((seconds % 31536000) % 86400) / 3600);\n    var numminutes = Math.floor((((seconds % 31536000) % 86400) % 3600) / 60);\n    var numseconds = (((seconds % 31536000) % 86400) % 3600) % 60;\n    var human = \"\"\n    if (numyears>0){\n        human = human  + numyears + \"y \" \n    }\n    if (numdays > 0) {\n        human = human + numdays + \"d \"\n    }\n\n    if (numhours > 0) {\n        human = human + numhours + \"h \"\n    }\n\n    if (numminutes > 0) {\n        human = human + numminutes + \"m \"\n    }\n\n    if (numseconds > 0) {\n        human = human + numseconds + \"s \"\n    }\n\n    return human;\n\n}\n\na.forEach((element) => {\n    //msg.payload = element.vap_table\n    //msg.payload = element._id\n\n    //master topic for send info\n    var topic_radice = \"unifi/\" + element._id + \"/\"\n\n\n    //send info about some data of AP\n    const parametri = [\"disabled\",\"state\", \"_id\", \"model\", \"version\", \"type\", \"config_network.ip\", \"config_network.type\", \"uptime\", \"name\", \"satisfaction\", \"disabled\", \"num_sta\", \"user-num_sta\", \"user-wlan-num_sta\", \"guest-num_sta\", \"guest-wlan-num_sta\", \"system-stats\"]\n\n    var info_ap = {}\n    parametri.forEach((elementi) => {\n        if (typeof element[elementi] != \"undefined\") {\n            info_ap[elementi] = element[elementi]\n            if (elementi == \"system-stats\"){\n                info_ap[\"cpu\"] = element[\"system-stats\"].cpu\n                info_ap[\"mem\"] = element[\"system-stats\"].mem\n            }\n\n            if (elementi == \"uptime\") {\n                info_ap[\"uptimeU\"] = secondsToString(element[\"uptime\"])\n            }\n\n\n        }\n\n    });\n\n\n\n\n\n\n    // send info about state of AP\n    if (typeof element.state != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/state\"\n        msg.payload = element.state\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/state/json\"\n        msg.payload = info_ap\n        node.send(msg)\n    }\n\n\n    // AP led\n    if (typeof element.led_override != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/led\"\n        msg.payload = element.led_override\n        node.send(msg)\n    }\n    \n\n    // send info connected clients\n    if (typeof element.num_sta != \"undefined\") {\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/users\"\n        msg.payload = element.num_sta\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/users/json\"\n        msg.payload = info_ap\n        node.send(msg)\n    }\n\n    // send info about bytes\n    if (typeof element.bytes != \"undefined\") {\n        bytes_info = {}\n        bytes_info[\"bytes\"] = element.bytes\n        if (typeof element.tx_bytes != \"undefined\") {\n            bytes_info[\"tx_bytes\"] = element.tx_bytes\n            bytes_info[\"MB_tx_bytes\"] = Math.round(element.tx_bytes / 10000) / 100\n        }\n\n        if (typeof element.tx_bytes != \"undefined\") {\n            bytes_info[\"rx_bytes\"] = element.tx_bytes\n            bytes_info[\"MB_rx_bytes\"] = Math.round(element.rx_bytes / 10000) / 100\n        }\n\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/bytes\"\n        msg.payload = Math.round(element.bytes / 10000) / 100\n        bytes_info[\"MB_bytes\"] = Math.round(element.bytes / 10000) / 100\n        node.send(msg)\n        msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/bytes/json\"\n        msg.payload = bytes_info\n        node.send(msg)\n    }\n\n\n\n    // send info about radio\n    if (typeof element.vap_table != \"undefined\") {\n        const parametri2 = [\"avg_client_signal\", \"bw\", \"channel\", \"satisfaction\", \"radio\", \"radio_name\"];\n        element.vap_table.forEach((vap) => {\n            var info_radio = {}\n            parametri2.forEach((itemvap) => {\n                if (typeof vap[itemvap] != \"undefined\") {\n                    info_radio[itemvap] = vap[itemvap]\n                }\n                if (itemvap == \"radio_name\") {\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[itemvap] + \"/info\"\n                    msg.payload = vap[\"avg_client_signal\"]\n                    node.send(msg)\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + vap[itemvap] + \"/info/json\"\n                    msg.payload = info_radio\n                    node.send(msg)\n                }\n            });\n        });\n    }\n\n\n\n\n    // send info about radio2\n    if (typeof element.radio_table_stats != \"undefined\") {\n        const parametri3 = [\"name\", \"channel\", \"satisfaction\", \"num_sta\", \"guest-num_sta\", \"user-num_sta\", \"radio\", \"state\"];\n        element.radio_table_stats.forEach((radio) => {\n            var info_radio2 = {}\n            parametri3.forEach((itemradio) => {\n                if (typeof radio[itemradio] != \"undefined\") {\n                    info_radio2[itemradio] = radio[itemradio]\n                }\n                if (itemradio == \"state\") {\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state\"\n                    msg.payload = radio[\"state\"]\n                    node.send(msg)\n                    msg.topic = \"homeassistant/ubiquiti/\" + element._id + \"/\" + radio[\"name\"] + \"/state/json\"\n                    msg.payload = info_radio2\n                    node.send(msg)\n                }\n            });\n        });\n    }\n\n\n\n\n\n\n\n\n    //node.send(msg);\n    //console.log(element);\n});\n\n//return msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1180,"y":160,"wires":[["fcb8c4111f3bddd0","1ffc7d6cbf08dafc"]]},{"id":"71ac4af553d3c733","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unifiapcmd/info","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":140,"y":400,"wires":[["fbe063632d457edb"]]},{"id":"fbe063632d457edb","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":" msg.payload = {\n        \"command\": \"AccessDevices\"\n    }\nmsg.topic = \"AccessDevices\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":400,"wires":[["3366c513d01846b6"]]},{"id":"b2139d9142b197ad","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 13","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":740,"y":20,"wires":[]},{"id":"4582b00e0058f4c0","type":"function","z":"ca15b45a6a5a96ab","name":"Led","func":"var Topic = msg.topic\nvar TOPIC = Topic.split('/')\nvar id = TOPIC[3]\n\nif (msg.payload == \"on\") {\n    msg.payload = {\n        \"command\": \"setapled\",\n        \"device_id\": TOPIC[3],\n        \"mode\": \"on\"\n    }\n} else {\n    msg.payload = {\n        \"command\": \"setapled\",\n        \"device_id\": TOPIC[3],\n        \"mode\": \"off\"\n    }\n\n}\n\nmsg.topic = \"Led\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":390,"y":500,"wires":[["3366c513d01846b6","096e4907982047dc"]]},{"id":"096e4907982047dc","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 19","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":620,"y":500,"wires":[]},{"id":"bb7cdedaf0576685","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/unifiapcmd/led/#","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":150,"y":500,"wires":[["4582b00e0058f4c0"]]},{"id":"e081d7ad10a31626","type":"function","z":"ca15b45a6a5a96ab","name":"Send Led Status","func":"const a = msg.payload[0]\nmsg.topic = \"homeassistant/ubiquiti/\" + msg.payload[0]._id + \"/led\"\nmsg.payload = msg.payload[0].led_override\nreturn msg;","outputs":1,"timeout":"","noerr":0,"initialize":"","finalize":"","libs":[],"x":780,"y":240,"wires":[["fcb8c4111f3bddd0"]]},{"id":"ea9d4502fb30ca23","type":"link out","z":"ca15b45a6a5a96ab","name":"to ask clients","mode":"link","links":["318241859f35d0e3"],"x":1225,"y":80,"wires":[]},{"id":"318241859f35d0e3","type":"link in","z":"ca15b45a6a5a96ab","name":"ask clients","links":["ea9d4502fb30ca23"],"x":65,"y":100,"wires":[["3366c513d01846b6"]]},{"id":"3b03ce0baf29792a","type":"mqtt in","z":"ca15b45a6a5a96ab","name":"","topic":"homeassistant/status","qos":"2","datatype":"auto-detect","broker":"dac17249.b02d3","nl":false,"rap":true,"rh":0,"inputs":0,"x":120,"y":300,"wires":[["c2b6df73df87529a"]]},{"id":"c2b6df73df87529a","type":"switch","z":"ca15b45a6a5a96ab","name":"Online","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"online","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":350,"y":300,"wires":[["ff6306ab802ab554"]]},{"id":"ff6306ab802ab554","type":"function","z":"ca15b45a6a5a96ab","name":"AccessDevices","func":" msg.payload = {\n        \"command\": \"AccessDevices\"\n    }\nmsg.topic = \"AccessDevices\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":300,"wires":[["337d456b88dae300","3366c513d01846b6"]]},{"id":"337d456b88dae300","type":"delay","z":"ca15b45a6a5a96ab","name":"","pauseType":"delay","timeout":"15","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":720,"y":300,"wires":[["4566303d76ec6e23"]]},{"id":"4566303d76ec6e23","type":"function","z":"ca15b45a6a5a96ab","name":"AllUsers","func":"msg.payload = {\n    \"command\": \"AllUsers\"\n}\nmsg.topic = \"AllUsers\"\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":880,"y":300,"wires":[["3366c513d01846b6"]]},{"id":"a7297fd85ea37b96","type":"comment","z":"ca15b45a6a5a96ab","name":"https://flows.nodered.org/node/node-red-contrib-unifi","info":"","x":230,"y":40,"wires":[]},{"id":"05af66cd7cce372f","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 24","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":810,"y":420,"wires":[]},{"id":"32195e76ae96f3c3","type":"inject","z":"ca15b45a6a5a96ab","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":90,"y":240,"wires":[["c2b6df73df87529a"]]},{"id":"1ffc7d6cbf08dafc","type":"debug","z":"ca15b45a6a5a96ab","name":"debug 81","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1410,"y":180,"wires":[]},{"id":"0bbadfcf8bb33bc7","type":"unificonfig","name":"","ip":"192.168.1.123","port":"8443","site":"default","unifios":false,"ssl":false},{"id":"dac17249.b02d3","type":"mqtt-broker","name":"","broker":"192.168.1.57","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"15","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Hi Sandro,

Thanks for your response, the error message is indeed gone now, however, Node-Red keeps crashing even when I raise up the memory from 8GB to 12-16GB.

I see in in my MQTT Broker (EMQX) around 300 new topics, but in Home Assistant I don’t see any new things appearing in the MQTT Integration. Am I supposed to see a new device there (named unifiswitch or something)?

I’m going to check next week why the script causes Node-Red to crash, maybe I have too many devices and the number is running too high.
I have already tried using a rate-limit to circumvent the problem, but then the crashing only takes a little longer but doesn’t solve the problem in the end.

Edit: It looks like the node-red-contrib-unifi module is the issue, when I disable all the triggers (Inject nodes and MQTT nodes), Node-Red is still crashing if I disable the module it is not crashing anymore.

Which version of the node-red-contrib-unifi module have you running?

Hi all,
i also tried this node red flow and it seems to work correctly - I can see very much new entities in HA in the developer tools, but I also can not see any new ‘device’ in the mqtt device section of HA. Is this normal?

Thanks!

In my first post you can see what card you have to build.
The entity are created automatically and you can find in Mqtt integration here

immagine

thanks for the information. is it somehow possible to use the flow with the homeassistant websocket nodes instead via mqtt?

I don’t know how create dynamically entities with websocket in HA. Sorry. Free to change my flow

ok, i might have a look into it… the reason why i have asked is that if i copy this flow everything seems to work perfectly, but then quite often i have a big delay between pressing a lightswitch (which sends a mqtt message to the same mqtt broker as this flow is sending) and the light reaction (this command is also send via mqtt to zigbee2mqtt)… if i deactivate this flow this does not happen… i also checked with mqtt explorer and saw, that this flow send very much messages to the broker (every few seconds) and i believe that this slows down my mqtt server… i also do not get why it sends that many messages? because what I saw it should only send messages every 2 and 4 minutes and when a state of the HA entities changes (e.g.: the led switch state)… is i could fix the mqtt issue I would just use your flow… :slight_smile:

EDIT: i justz checked again and if seems that the intervall (2 and 4 minutes) is correct! But what I can see is that every inject sends the messages several times (e.g.: homeassistant/ubiquiti/64bcf2fc7ad76966c0e204e7/led get send 43 times every 2 minutes…) why?

Are you shure that don’t edit the inject node?
These are the two mines

I checked the inject nodes but they look the same.

I now logged the related mqtt-topics with the python script (GitHub - stevecope/mqtt-topic-logger: logs mqtt data for each topic in a separate file) where you can see that the mqtt messages are send several times (e.g.: homeassistant\ubiquiti\63d2b748043e751516584f16\led)

Here you find the zip file if you want to check: Download-Link

Maybe you can also try to check if the same occur in your system?

Try with mqttexplorer. Maybe that you have a wifi client that connect and disconnect and thus you have a lot of mqtt messages.
With mqttexplorer you can identify what device and it’s ip are generating the spam