This is the way I like to do it:
I credit the idea to @robconnolly from his blog here:
https://webworxshop.com/2018/05/08/home-assistant-mqtt-discovery-sensors-in-node-red
This particular flow is to turn a camera that allows sending motion detection images to an FTP server into a HA motion sensor. JSON code for the flow below. It centers around a lot of Javascript function nodes that I’ll explain below.
The critical trick here is to send the autodiscovery config message before the state message. This ensures the config message always gets sent before the sensor state. Your MQTT server shouldn’t care too much about this but HA will love it. And you can always change how things work down the road without having to manually re-send the config message.
payload to MQTT node:
msg.topic = "homeassistant/binary_sensor/modetftp_" + msg.payload.sensor_name + "/state";
msg.payload.image = null;
return msg;
Send HASS AutoDiscovery MQTT Config node:
var sensor_config = {
payload: {
name: "MoDetFTP: "+msg.payload.sensor_name,
state_topic: "homeassistant/binary_sensor/modetftp_" + msg.payload.sensor_name + "/state",
device_class: "motion",
payload_on: 1,
payload_off: 0,
value_template: "{{ value_json.value }}",
json_attributes: [
"image_path",
"path",
"sensor_name"
]
},
topic: "homeassistant/binary_sensor/modetftp_" + msg.payload.sensor_name + "/config"
};
return sensor_config;
Full Flow (you’ll need to modify your MQTT server IP)
[
{
"id": "4507fdcc.9441d4",
"type": "tab",
"label": "MoDetFTP",
"disabled": false,
"info": "Motion Detection for IPCams over FTP"
},
{
"id": "6efa5ae8.cffb74",
"type": "ftp-server",
"z": "4507fdcc.9441d4",
"name": "MoDetFTP",
"port": "7077",
"x": 80,
"y": 40,
"wires": [
[
"79fa05a6.00b36c"
]
]
},
{
"id": "7cb07afd.600704",
"type": "mqtt out",
"z": "4507fdcc.9441d4",
"name": "MoDetMQTT",
"topic": "",
"qos": "2",
"retain": "true",
"broker": "1e4d139e.30fabc",
"x": 1030,
"y": 180,
"wires": []
},
{
"id": "79fa05a6.00b36c",
"type": "function",
"z": "4507fdcc.9441d4",
"name": "path and filename to payload",
"func": "parts = msg.topic.split('/');\nfiledata = msg.payload;\nmsg.payload = {};\nmsg.payload.path = msg.topic;\nmsg.payload.image = filedata;\nmsg.payload.sensor_name = null;\nif(parts.length > 1) {\n msg.payload.sensor_name = parts[1];\n msg.payload.image_path = parts;\n msg.payload.value = 1;\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 160,
"y": 100,
"wires": [
[
"5db8e9d4.19ba38"
]
]
},
{
"id": "4b7d1dd.fadabe4",
"type": "function",
"z": "4507fdcc.9441d4",
"name": "Send HASS AutoDiscovery MQTT Config",
"func": "var sensor_config = {\n payload: {\n name: \"MoDetFTP: \"+msg.payload.sensor_name,\n state_topic: \"homeassistant/binary_sensor/modetftp_\" + msg.payload.sensor_name + \"/state\",\n device_class: \"motion\",\n payload_on: 1,\n payload_off: 0,\n value_template: \"{{ value_json.value }}\",\n json_attributes: [\n \"image_path\",\n \"path\",\n \"sensor_name\"\n ]\n },\n topic: \"homeassistant/binary_sensor/modetftp_\" + msg.payload.sensor_name + \"/config\"\n};\nreturn sensor_config;",
"outputs": 1,
"noerr": 0,
"x": 540,
"y": 120,
"wires": [
[
"fc2c8e70.23fa8"
]
]
},
{
"id": "8e933788.a46688",
"type": "delay",
"z": "4507fdcc.9441d4",
"name": "Send Sensor Payload after 500ms",
"pauseType": "delay",
"timeout": "500",
"timeoutUnits": "milliseconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"x": 520,
"y": 180,
"wires": [
[
"fc2c8e70.23fa8"
]
]
},
{
"id": "5db8e9d4.19ba38",
"type": "function",
"z": "4507fdcc.9441d4",
"name": "payload to MQTT",
"func": "msg.topic = \"homeassistant/binary_sensor/modetftp_\" + msg.payload.sensor_name + \"/state\";\nmsg.payload.image = null;\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 190,
"y": 180,
"wires": [
[
"4b7d1dd.fadabe4",
"8e933788.a46688",
"6da07b80.652404"
]
]
},
{
"id": "ced9ebd1.240888",
"type": "change",
"z": "4507fdcc.9441d4",
"name": "detection level to 0",
"rules": [
{
"t": "set",
"p": "payload.value",
"pt": "msg",
"to": "0",
"tot": "num"
}
],
"action": "",
"property": "",
"from": "",
"to": "",
"reg": false,
"x": 570,
"y": 280,
"wires": [
[
"fc2c8e70.23fa8"
]
]
},
{
"id": "fc2c8e70.23fa8",
"type": "function",
"z": "4507fdcc.9441d4",
"name": "merge flows",
"func": "\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 850,
"y": 180,
"wires": [
[
"7cb07afd.600704"
]
]
},
{
"id": "6da07b80.652404",
"type": "trigger",
"z": "4507fdcc.9441d4",
"op1": "",
"op2": "",
"op1type": "nul",
"op2type": "payl",
"duration": "10",
"extend": true,
"units": "s",
"reset": "",
"bytopic": "topic",
"name": "Clear Sensor after 10s of no motion",
"x": 520,
"y": 240,
"wires": [
[
"ced9ebd1.240888"
]
]
},
{
"id": "1e4d139e.30fabc",
"type": "mqtt-broker",
"z": "",
"name": "twohunnid_mqtt",
"broker": "192.168.1.19",
"port": "1883",
"clientid": "",
"usetls": false,
"compatmode": true,
"keepalive": "60",
"cleansession": true,
"birthTopic": "",
"birthQos": "0",
"birthPayload": "",
"closeTopic": "",
"closeQos": "0",
"closePayload": "",
"willTopic": "",
"willQos": "0",
"willPayload": ""
}
]