Got a real weird one now. Thought I had sorted a good way to do mqtt connect + subscribe, but I have problem with it again.
I have this mqtt setup running on several raspberry pis. Normally this runs smooth with little to no hickup. Last week we started a new pi, so I copied the code over. And updated .env to get new connection credentials.
But on this new pi, connection toggles between connected / disconnected every 15 seconds! What a weird behavior? Was similar some times last year on another pi, but it sorted itself out before I spent more time on it.
I'm not sure where to look for details here as I don't find any info for why mqtt disconnects.
Thanks in advance to anyone who can share their thoughts!
Nodes:
[
{
"id": "a5184c5aab2f6cda",
"type": "subflow",
"name": "log",
"info": "# Writes log to file\r\nMust set env variable `logTopic` in parent flow to determine filename.\r\nThis can't be done as input variable because the parent may also be a subflow.\r\n\r\n### Inputs\r\n\r\n: logMessage (string) : the log message to write to file can be provided in the node configuration, or as a message property. By default it will use `msg.logMessage`.\r\n: logTopic (string) : determines parts of the file name. Typically enter flow name for this purpose.\r\n: logCompleteMsgObj (boolean): Add the entire msg object to the log message.\r\n: stdOut (boolean) : Also log to standard out (using debug node).\r\n\r\n### Details\r\n\r\nLogs are written to /data/logs/`msg.logTopic`_yyyy-MM-dd.txt. `msg.logTopic` is used as filename prefix. Typically use flow name for this purpose. Creates file and folder if they don't exist.\r\n\r\n`msg.logMessage` is used as the main content of the log to write. Datetime is automatically added as prefix. Each log is appended with newline.",
"category": "",
"in": [
{
"x": 100,
"y": 80,
"wires": [
{
"id": "0db769e63c22272e"
}
]
}
],
"out": [
{
"x": 1040,
"y": 80,
"wires": [
{
"id": "5f7d3b7030f7bb02",
"port": 0
},
{
"id": "0db769e63c22272e",
"port": 0
}
]
}
],
"env": [
{
"name": "logMessage",
"type": "str",
"value": "",
"ui": {
"label": {
"en-US": "Log message"
},
"type": "input",
"opts": {
"types": [
"str"
]
}
}
},
{
"name": "logCompleteMsgObj",
"type": "bool",
"value": "false",
"ui": {
"label": {
"en-US": "Log complete msg"
},
"type": "checkbox"
}
},
{
"name": "stdOut",
"type": "bool",
"value": "false",
"ui": {
"label": {
"en-US": "Debug (sidebar)"
},
"type": "checkbox"
}
},
{
"name": "logTopic",
"type": "env",
"value": "$parent.logTopic",
"ui": {
"type": "hide"
}
}
],
"meta": {},
"color": "#C7E9C0",
"icon": "font-awesome/fa-file-text"
},
{
"id": "b1add847796af765",
"type": "function",
"z": "a5184c5aab2f6cda",
"name": "prepare log",
"func": "msg._backup = RED.util.cloneMessage(msg);\n\nconst date = new Date().toISOString().replaceAll(\"-\", \"-\").replaceAll(\"T\", \"-\").replaceAll(\":\", \"-\").replaceAll(\".\", \"-\").replaceAll(\"Z\", \"-\");\nconst list = date.split(\"-\");\nconst year = list[0];\nconst month = list[1];\nconst day = list[2];\nconst hour = list[3];\nconst minute = list[4];\nconst second = list[5];\n\nlet logTopic;\ntry{\n logTopic = env.get(\"logTopic\").toLowerCase();\n if(!logTopic){\n node.error(\"ERROR: Log failed getting logTopic env from parent. Did you remember to set it?\");\n return;\n }\n} catch (error) {\n node.error(\"ERROR: Log failed getting logTopic env from parent. Did you remember to set it?\");\n return;\n}\n\nmsg.stdOut = env.get(\"stdOut\");\n\nlet logMessage = env.get(\"logMessage\") ? env.get(\"logMessage\") : msg.logMessage;\nlet logCompleteMsgObj = env.get(\"logCompleteMsgObj\");\nif(!logCompleteMsgObj){\n logCompleteMsgObj = msg?.logCompleteMsgObj ?? false;\n}\n\nif(logCompleteMsgObj){\n logMessage += \"\\n\";\n logMessage += JSON.stringify(msg._backup);\n}\n\nmsg.filename = `/data/logs/${logTopic}/${logTopic}_${year}-${month}-${day}.log`;\nmsg.payload = `${year}-${month}-${day} ${hour}:${minute}:${second} - ${logMessage}`;\n\nconst maxLineLength = 10000;\nif(msg.payload.length > maxLineLength){\n // Safeguard against excessively large logs\n msg.payload = msg.payload.slice(0, maxLineLength) + '... [TRUNCATED]';\n}\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 470,
"y": 140,
"wires": [
[
"3ea911242530d241",
"2c7e47352b7df809"
]
]
},
{
"id": "3ea911242530d241",
"type": "file",
"z": "a5184c5aab2f6cda",
"name": "write log file",
"filename": "filename",
"filenameType": "msg",
"appendNewline": true,
"createDir": true,
"overwriteFile": "false",
"encoding": "utf8",
"x": 670,
"y": 140,
"wires": [
[
"5f7d3b7030f7bb02"
]
]
},
{
"id": "e96bad283c240487",
"type": "catch",
"z": "a5184c5aab2f6cda",
"name": "",
"scope": null,
"uncaught": false,
"x": 660,
"y": 260,
"wires": [
[
"5ac9480a70f4d93a"
]
]
},
{
"id": "5ac9480a70f4d93a",
"type": "debug",
"z": "a5184c5aab2f6cda",
"name": "log failed error",
"active": true,
"tosidebar": true,
"console": true,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 850,
"y": 260,
"wires": []
},
{
"id": "fac2f56d19607dc3",
"type": "debug",
"z": "a5184c5aab2f6cda",
"name": "log std out",
"active": true,
"tosidebar": true,
"console": true,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 830,
"y": 200,
"wires": []
},
{
"id": "2c7e47352b7df809",
"type": "switch",
"z": "a5184c5aab2f6cda",
"name": "std out?",
"property": "stdOut",
"propertyType": "msg",
"rules": [
{
"t": "true"
},
{
"t": "else"
}
],
"checkall": "true",
"repair": false,
"outputs": 2,
"x": 660,
"y": 200,
"wires": [
[
"fac2f56d19607dc3"
],
[]
],
"inputLabels": [
"msg.stdOut"
],
"outputLabels": [
"true",
"false"
]
},
{
"id": "5f7d3b7030f7bb02",
"type": "function",
"z": "a5184c5aab2f6cda",
"name": "revert",
"func": "return msg._backup;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 810,
"y": 140,
"wires": [
[]
]
},
{
"id": "0db769e63c22272e",
"type": "function",
"z": "a5184c5aab2f6cda",
"name": "logMessage?",
"func": "const logMessage = env.get(\"logMessage\") ? env.get(\"logMessage\") : msg.logMessage;\n\nconst skip = logMessage ? null : msg;\nconst log = logMessage ? msg : null;\nreturn [skip, log];",
"outputs": 2,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 220,
"y": 80,
"wires": [
[],
[
"b1add847796af765"
]
],
"outputLabels": [
"Skip",
"Log"
]
},
{
"id": "71082c29770ea643",
"type": "inject",
"z": "a5184c5aab2f6cda",
"g": "6f8fb577b11364ed",
"name": "",
"props": [],
"repeat": "",
"crontab": "00 00 * * *",
"once": false,
"onceDelay": 0.1,
"topic": "",
"x": 210,
"y": 400,
"wires": [
[
"09a9a5f729dd65b4"
]
]
},
{
"id": "0c31a507622aeb8d",
"type": "file",
"z": "a5184c5aab2f6cda",
"g": "6f8fb577b11364ed",
"name": "write empty file",
"filename": "filename",
"filenameType": "msg",
"appendNewline": false,
"createDir": true,
"overwriteFile": "false",
"encoding": "utf8",
"x": 540,
"y": 400,
"wires": [
[]
]
},
{
"id": "09a9a5f729dd65b4",
"type": "function",
"z": "a5184c5aab2f6cda",
"g": "6f8fb577b11364ed",
"name": "empty log",
"func": "const date = new Date().toISOString().replaceAll(\"-\", \"-\").replaceAll(\"T\", \"-\").replaceAll(\":\", \"-\").replaceAll(\".\", \"-\").replaceAll(\"Z\", \"-\");\nconst list = date.split(\"-\");\nconst year = list[0]; // YYYY\nconst month = list[1]; // MM\nconst day = list[2]; // DD\n\nconst logTopic = env.get(\"$parent.logTopic\").toLowerCase();\nif(!logTopic){\n return; // silent quit\n}\n\nmsg.filename = `/data/logs/${logTopic}/${logTopic}_${year}-${month}-${day}.log`;\nmsg.payload = \"\";\n\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 370,
"y": 400,
"wires": [
[
"0c31a507622aeb8d"
]
]
},
{
"id": "6f8fb577b11364ed",
"type": "group",
"z": "a5184c5aab2f6cda",
"name": "Create new log file every day",
"style": {
"stroke": "#0070c0",
"fill": "#bfdbef",
"label": true,
"color": "#000000"
},
"nodes": [
"0c31a507622aeb8d",
"09a9a5f729dd65b4",
"71082c29770ea643"
],
"x": 114,
"y": 359,
"w": 532,
"h": 82
},
{
"id": "5b9dee777ab3c51a",
"type": "function",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "connect",
"func": "const output = {\n action: \"connect\", // \"connect\" / \"subscribe\"\n topic: \"v1/devices/me/rpc/request/+\",\n\n broker: {\n broker: \"mqtt.thingsboard.cloud\",\n port: 1883,\n \n force: false, \n cleansession: false,\n protocolVersion: 5,\n\n clientid: env.get(\"TB_MQTT_CLIENT_ID\"),\n username: env.get(\"TB_MQTT_ACCESS_TOKEN\"),\n //password: env.get(\"password\")\n }\n};\n\nconst connectMsg = RED.util.cloneMessage(output);\nconst subscribeMsg = RED.util.cloneMessage(output);\nsubscribeMsg.action = \"subscribe\";\n\nreturn [[connectMsg, subscribeMsg]];",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 840,
"y": 280,
"wires": [
[
"a976cec64a7db708"
]
]
},
{
"id": "6e4976dd19813128",
"type": "inject",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "connect & subscribe",
"props": [
{
"p": "timestamp",
"v": "",
"vt": "date"
}
],
"repeat": "",
"crontab": "",
"once": true,
"onceDelay": 0.1,
"topic": "",
"x": 240,
"y": 280,
"wires": [
[
"796b5dc9d1733fe9"
]
]
},
{
"id": "616ac68b4c37c932",
"type": "status",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "",
"scope": [
"a976cec64a7db708"
],
"x": 200,
"y": 340,
"wires": [
[
"b5bf24d17b3a6e18"
]
]
},
{
"id": "b5bf24d17b3a6e18",
"type": "switch",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "connected?",
"property": "status.text",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "node-red:common.status.connected",
"vt": "str"
},
{
"t": "eq",
"v": "node-red:common.status.disconnected",
"vt": "str"
}
],
"checkall": "false",
"repair": false,
"outputs": 2,
"x": 350,
"y": 340,
"wires": [
[
"3d133c46811031da"
],
[
"66d02ea984627117"
]
],
"outputLabels": [
"connected",
"disconnected"
]
},
{
"id": "66d02ea984627117",
"type": "subflow:a5184c5aab2f6cda",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "log",
"env": [
{
"name": "logMessage",
"value": "MQTT disconnected, attempting to re-connect.",
"type": "str"
},
{
"name": "logTopic",
"value": "$parent.logTopic",
"type": "env"
}
],
"x": 530,
"y": 360,
"wires": [
[
"8ad508cf707b872d"
]
]
},
{
"id": "3d133c46811031da",
"type": "subflow:a5184c5aab2f6cda",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "log",
"env": [
{
"name": "logMessage",
"value": "MQTT connected.",
"type": "str"
},
{
"name": "logTopic",
"value": "$parent.logTopic",
"type": "env"
}
],
"x": 530,
"y": 320,
"wires": [
[]
]
},
{
"id": "a976cec64a7db708",
"type": "mqtt in",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "mqtt subscribe",
"topic": "",
"qos": "0",
"datatype": "json",
"broker": "c032668b54c22629",
"nl": true,
"rap": true,
"rh": "2",
"inputs": 1,
"x": 1000,
"y": 280,
"wires": [
[
"1c21e709aefadba1"
]
]
},
{
"id": "c99afae0c869b98b",
"type": "catch",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "",
"scope": "group",
"uncaught": true,
"x": 210,
"y": 420,
"wires": [
[
"211330c1380ef9c3"
]
]
},
{
"id": "c279cb6c019b09d2",
"type": "subflow:a5184c5aab2f6cda",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "log",
"env": [
{
"name": "logMessage",
"value": "Unexpected error.",
"type": "str"
},
{
"name": "logCompleteMsgObj",
"value": "true",
"type": "bool"
},
{
"name": "logTopic",
"value": "$parent.logTopic",
"type": "env"
}
],
"x": 490,
"y": 420,
"wires": [
[]
]
},
{
"id": "8ad508cf707b872d",
"type": "delay",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"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": 660,
"y": 360,
"wires": [
[
"5b9dee777ab3c51a"
]
]
},
{
"id": "211330c1380ef9c3",
"type": "function",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "clean log",
"func": "// hide access token from logs\nif(msg?.broker?.username){\n msg.broker.username = \"MQTT Access Token\";\n}\nif(msg?._backup?.broker?.username){\n msg._backup.broker.username = \"MQTT Access Token\";\n}\nreturn msg;",
"outputs": 1,
"timeout": 0,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 360,
"y": 420,
"wires": [
[
"c279cb6c019b09d2"
]
]
},
{
"id": "796b5dc9d1733fe9",
"type": "delay",
"z": "97437e63b6ef93ef",
"g": "a756d21da814ee7f",
"name": "",
"pauseType": "delay",
"timeout": "5",
"timeoutUnits": "seconds",
"rate": "1",
"nbRateUnits": "1",
"rateUnits": "second",
"randomFirst": "1",
"randomLast": "5",
"randomUnits": "seconds",
"drop": false,
"allowrate": false,
"outputs": 1,
"x": 660,
"y": 280,
"wires": [
[
"5b9dee777ab3c51a"
]
]
},
{
"id": "c032668b54c22629",
"type": "mqtt-broker",
"name": "tb-nr-mqtt",
"broker": "thingsboard",
"port": "1883",
"clientid": "",
"autoConnect": false,
"usetls": false,
"protocolVersion": "5",
"keepalive": "60",
"cleansession": true,
"autoUnsubscribe": true,
"birthTopic": "",
"birthQos": "0",
"birthRetain": "false",
"birthPayload": "",
"birthMsg": {},
"closeTopic": "",
"closeQos": "0",
"closeRetain": "false",
"closePayload": "",
"closeMsg": {},
"willTopic": "",
"willQos": "0",
"willRetain": "false",
"willPayload": "",
"willMsg": {},
"userProps": "",
"sessionExpiry": ""
}
]