Open TEF2one opened 1 year ago
I also noticed the IR codes for RM4 do not work with ZS06 even when using the correct file format... Given I have both, I defined a flow in NodeRed which is able to read any Broadlink Base64 codes file and convert/re-learn commands with ZS06 to generate new MQTT Raw code files. I could share the flow on demand or provide some ZS06 commands files if there are some interest...
I also noticed the IR codes for RM4 do not work with ZS06 even when using the correct file format... Given I have both, I defined a flow in NodeRed which is able to read any Broadlink Base64 codes file and convert/re-learn commands with ZS06 to generate new MQTT Raw code files. I could share the flow on demand or provide some ZS06 commands files if there are some interest...
Could you share with me the flow for NodeRed? Thanks in advance
share with me the flow for NodeRed Here is what I have done so far, it's in 2 part the first extract all RM4 codes and replay them to teach the ZS06 and store the result in a CSV. Sometime some codes are missing so I have to run multple time on manually replay the missing codes. Then there is a quick converter that take the CSV and replace the learned code from an Broadlink doc converting it to a MQTT.
[{"id":"9c23481e17746023","type":"file in","z":"b7998df890ce76f5","name":"Dest","filename":"/data/ha/codes/climate/1124.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":860,"wires":[["3c74da852ee4d13e"]]},{"id":"a7fd69f6d8f938b7","type":"inject","z":"b7998df890ce76f5","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":75,"y":880,"wires":[["9c23481e17746023","32023e0b79768de7"]],"l":false},{"id":"32023e0b79768de7","type":"file in","z":"b7998df890ce76f5","name":"Src","filename":"/data/ha/ir_code_ac_up.csv","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":900,"wires":[["3c74da852ee4d13e"]]},{"id":"3c74da852ee4d13e","type":"join","z":"b7998df890ce76f5","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"filename","joiner":",","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":310,"y":880,"wires":[["aefe37416b3ce75b"]]},{"id":"aefe37416b3ce75b","type":"function","z":"b7998df890ce76f5","name":"parse","func":"const src = msg.payload;\nconst codes = parseCMD(src[isJson(src[0]) ? 1 : 0]);\nvar payload = JSON.parse(src[isJson(src[0])? 0 : 1]);\n\nudpateCMD(payload.commands, codes);\n\npayload.supportedController = \"MQTT\";\npayload.commandsEncoding = \"Raw\";\nmsg.payload = JSON.stringify(payload, null, 3);\nreturn msg;\n\n\nfunction udpateCMD(obj, cmd,prefix) {\n prefix = prefix === undefined ? \"\" : prefix + \".\";\n for (const k in obj) {\n let v = obj[k];\n if (typeof v === 'string' || v instanceof String) {\n if (cmd.hasOwnProperty(prefix + k)) {\n obj[k] = JSON.stringify({ ir_code_to_send: cmd[prefix + k] });\n }else{\n obj[k] = JSON.stringify({ ir_code_to_send: \"\" });\n }\n } else if(typeof v === 'object' && v !== null){\n udpateCMD(obj[k], cmd, prefix + k);\n }\n }\n};\n\nfunction parseCMD(data, delimiter = ',') {\n var map = new Object();\n data = data\n .slice(data.indexOf('\\n') + 1)\n .split('\\n').map(v => {\n const arr = v.split(delimiter);\n if (arr.hasOwnProperty(2)) {\n map[arr[1]] = arr[2];\n }\n });;\n return map;\n};\n\nfunction encode(code) {\n return JSON.stringify({ ir_code_to_send: code });\n}\nfunction isJson(str) {\n try {\n JSON.parse(str);\n } catch (e) {\n return false;\n }\n return true;\n}\nfunction csvToArray(str, delimiter = \",\") {\n let array = str.split(\"\\\\r\\\\n\").map(function (line) {\n return line.split(delimiter);\n });\n\n return array;\n}\nfunction CSVToJSON(data, delimiter = ','){\n const titles = data.slice(0, data.indexOf('\\n')).split(delimiter);\n return data\n .slice(data.indexOf('\\n') + 1)\n .split('\\n')\n .map(v => {\n const values = v.split(delimiter);\n return titles.reduce(\n (obj, title, index) => ((obj[title] = values[index]), obj),\n {}\n );\n });\n};\n/*\nfor (const property in object) {\n console.log(`${property}: ${object[property]}`);\n}\n*/\n//Object.values(animals).forEach(val => console.log(val));","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":880,"wires":[["f0008d2e6611cb68"]]},{"id":"f0008d2e6611cb68","type":"file","z":"b7998df890ce76f5","name":"Log","filename":"/data/ha/ir_codes.json","filenameType":"str","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":590,"y":880,"wires":[["91a7b887f11ea946"]]},{"id":"91a7b887f11ea946","type":"debug","z":"b7998df890ce76f5","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":880,"wires":[]},{"id":"7ed8ce32d57268ed","type":"inject","z":"b7998df890ce76f5","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":780,"wires":[["6a073749e4ebcb7f"]],"l":false},{"id":"c2c8045800223dd7","type":"group","z":"b7998df890ce76f5","name":"Covert SmartIr RM4 to ZS06","style":{"label":true},"nodes":["507a1ad555f8cf50","4fc5e2bbafd8efa0","43409397257f8e34","919071a27b8ec4d5","9198590c62f199cd","27b3cf4e0e4e340c","7ffb6262ef272467","77940daabc33296e","6687c91fb16fab29","afc7849272fc5590","deab06de0e53f081","c3074cf9a1021870","95d786911f0aaa53","eee196a1932ce952","41ef85dffa09612f","89f3de66fe8a1f19","0197f6a2ec029258","2b1b046b324202e0","cd0d3dcff7b1524e","15ec1eb773ebeac2","d05213882f8a597d","dcd9f2274b7ba955","685c00c55eb2b8a0","b31e93ef23ce44dd","b4561199d3f2db8c","ef7f66db1d630edb","ef9ccc686da68143","d5414260fedf7acd","e1bc3ab056cf684b","7cb92a52d69d1a1d","3fa36aaa406e9dd9","003f6678b4b7927a","6a073749e4ebcb7f"],"x":34,"y":459,"w":1352,"h":362},{"id":"507a1ad555f8cf50","type":"mqtt in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Listen","topic":"zigbee2mqtt/Guest Blaster","qos":"0","datatype":"auto-detect","broker":"7c05f96914c79996","nl":false,"rap":true,"rh":0,"inputs":0,"x":610,"y":720,"wires":[["919071a27b8ec4d5"]]},{"id":"4fc5e2bbafd8efa0","type":"file","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Log","filename":"/data/ha/ir_code.csv","filenameType":"str","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":1310,"y":740,"wires":[[]]},{"id":"43409397257f8e34","type":"csv","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","sep":",","hdrin":"","hdrout":"once","multi":"one","ret":"\\n","temp":"time,command,code","skip":"0","strings":true,"include_empty_strings":"","include_null_values":"","x":1170,"y":740,"wires":[["4fc5e2bbafd8efa0"]]},{"id":"919071a27b8ec4d5","type":"rbe","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"payload.learned_ir_code","topi":"topic","x":750,"y":720,"wires":[["89f3de66fe8a1f19"]]},{"id":"9198590c62f199cd","type":"api-call-service","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"RM4","server":"8093ca4.46eb138","version":5,"debugenabled":false,"domain":"remote","service":"send_command","areaId":[],"deviceId":[],"entityId":["remote.guest_rm4"],"data":"{\"command\":\"b64: \"& payload}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":890,"y":600,"wires":[[]]},{"id":"27b3cf4e0e4e340c","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"AC Down","filename":"/data/ha/codes/climate/1084.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":180,"y":500,"wires":[["6687c91fb16fab29"]]},{"id":"7ffb6262ef272467","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":540,"wires":[["77940daabc33296e"]],"l":false},{"id":"77940daabc33296e","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"AC Up","filename":"/data/ha/codes/climate/1124.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":540,"wires":[["6687c91fb16fab29"]]},{"id":"6687c91fb16fab29","type":"function","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"parse","func":"var obj = JSON.parse(msg.payload);\nvar table = flattenObject(obj.commands);\nvar date = new Date();\nmsg = [{ payload: table }, { reset: true, payload: { time: date.toISOString(), command: msg.filename } }];\nreturn msg;\n\n\n/*\nsetTimeout(function () {\n console.log(\"Executed after 1 second\");\n}, 1000);\n*/\n\nfunction payload(postion, payload) {\n const msg = new Array(node.outputCount);\n msg[postion] = { payload: payload };\n return msg;\n}\n\nfunction flattenObject(ob) {\n var toReturn = {};\n\n for (var i in ob) {\n if (!ob.hasOwnProperty(i)) continue;\n\n if ((typeof ob[i]) == 'object' && ob[i] !== null) {\n var flatObject = flattenObject(ob[i]);\n for (var x in flatObject) {\n if (!flatObject.hasOwnProperty(x)) continue;\n\n toReturn[i + '.' + x] = flatObject[x];\n }\n } else {\n toReturn[i] = ob[i];\n }\n }\n return toReturn;\n}","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":740,"wires":[["eee196a1932ce952"],["43409397257f8e34"]]},{"id":"afc7849272fc5590","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Fan","filename":"/data/ha/codes/fan/1240.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":580,"wires":[["6687c91fb16fab29"]]},{"id":"deab06de0e53f081","type":"mqtt out","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"ZS06","topic":"zigbee2mqtt/Guest Blaster/set","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"7c05f96914c79996","x":890,"y":560,"wires":[]},{"id":"c3074cf9a1021870","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learn","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"learn_ir_code\": \"ON\"}","payloadType":"json","x":750,"y":560,"wires":[["deab06de0e53f081"]]},{"id":"95d786911f0aaa53","type":"delay","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"limit","pauseType":"rate","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":610,"y":680,"wires":[["2b1b046b324202e0","3fa36aaa406e9dd9","003f6678b4b7927a"]]},{"id":"eee196a1932ce952","type":"split","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":470,"y":680,"wires":[["95d786911f0aaa53"]]},{"id":"41ef85dffa09612f","type":"join","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":",","joinerType":"str","accumulate":false,"timeout":"3","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":1030,"y":720,"wires":[["43409397257f8e34","0197f6a2ec029258"]]},{"id":"89f3de66fe8a1f19","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Code","rules":[{"t":"set","p":"topic","pt":"msg","to":"code","tot":"str"},{"t":"move","p":"payload.learned_ir_code","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"complete","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":720,"wires":[["41ef85dffa09612f"]]},{"id":"0197f6a2ec029258","type":"debug","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learned","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1180,"y":680,"wires":[]},{"id":"2b1b046b324202e0","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Time","rules":[{"t":"set","p":"topic","pt":"msg","to":"time","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"$now()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":640,"wires":[["41ef85dffa09612f"]]},{"id":"cd0d3dcff7b1524e","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Test","props":[{"p":"payload.ir_code_to_send","v":"C9kEvgHZBPgBhwHZBEAJ4AsDAPjgABsFhxzZBL4BQAMBvgFABYADAdkEQAkAh6ANQAvAAwCH4AwvwB0F2QS+AYcBQAWAAwL4AYcgLweHAdkEvgG+AUAF4AUDA9kEvgGAHUAJQAMAhyAvAb4BQAMBhwFABYADAPggB0ADA9kE+AHgAxcCvgGH4AAvBL4B2QSHIAPgAwcD2QS+AUATQAMBvgFAAwCH4AQvAb4B4AUDBdkEvgG+AUAFwAPgAS8BhwGAEwD44AIHAdkE4AEXAL4gFwL4AYegXwGHAUAPA4cB2QRAB8ADA9kEvgHgBRMAh6AvIAkAAUAF4AEDQA8B2QQgUQIB2QTgARcAh+AILwSHAdkEvqADAdkEgC8JhwHZBIcB2QSHAQ==","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":750,"y":520,"wires":[["deab06de0e53f081"]]},{"id":"15ec1eb773ebeac2","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Matrix","filename":"/data/ha/codes/media_player/1500.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":620,"wires":[["6687c91fb16fab29"]]},{"id":"d05213882f8a597d","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"TV","filename":"/data/ha/codes/media_player/1480.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":660,"wires":[["6687c91fb16fab29"]]},{"id":"dcd9f2274b7ba955","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Projector","filename":"/data/ha/codes/media_player/1361.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":180,"y":700,"wires":[["6687c91fb16fab29"]]},{"id":"685c00c55eb2b8a0","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Sound","filename":"/data/ha/codes/media_player/1044.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":740,"wires":[["6687c91fb16fab29"]]},{"id":"b31e93ef23ce44dd","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":500,"wires":[["27b3cf4e0e4e340c"]],"l":false},{"id":"b4561199d3f2db8c","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":580,"wires":[["afc7849272fc5590"]],"l":false},{"id":"ef7f66db1d630edb","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":620,"wires":[["15ec1eb773ebeac2"]],"l":false},{"id":"ef9ccc686da68143","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":660,"wires":[["d05213882f8a597d"]],"l":false},{"id":"d5414260fedf7acd","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":700,"wires":[["dcd9f2274b7ba955"]],"l":false},{"id":"e1bc3ab056cf684b","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":740,"wires":[["685c00c55eb2b8a0"]],"l":false},{"id":"7cb92a52d69d1a1d","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Reset","props":[{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":470,"y":640,"wires":[["95d786911f0aaa53"]]},{"id":"3fa36aaa406e9dd9","type":"trigger","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learn","op1":"{\"learn_ir_code\": \"ON\"}","op2":"","op1type":"json","op2type":"pay","duration":"300","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":750,"y":600,"wires":[["deab06de0e53f081"],["9198590c62f199cd"]]},{"id":"003f6678b4b7927a","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Cmd","rules":[{"t":"set","p":"topic","pt":"msg","to":"command","tot":"str"},{"t":"move","p":"parts.key","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":680,"wires":[["41ef85dffa09612f"]]},{"id":"6a073749e4ebcb7f","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Misc","filename":"/data/ha/ir_codes_todo.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":780,"wires":[["6687c91fb16fab29"]]},{"id":"7c05f96914c79996","type":"mqtt-broker","name":"MQTT","broker":"192.168.50.105","port":"1883","clientid":"NodeRed","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"8093ca4.46eb138","type":"server","name":"HA nodered","version":5,"addon":false,"rejectUnauthorizedCerts":false,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":true,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
share with me the flow for NodeRed Here is what I have done so far, it's in 2 part the first extract all RM4 codes and replay them to teach the ZS06 and store the result in a CSV. Sometime some codes are missing so I have to run multple time on manually replay the missing codes. Then there is a quick converter that take the CSV and replace the learned code from an Broadlink doc converting it to a MQTT.
[{"id":"9c23481e17746023","type":"file in","z":"b7998df890ce76f5","name":"Dest","filename":"/data/ha/codes/climate/1124.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":860,"wires":[["3c74da852ee4d13e"]]},{"id":"a7fd69f6d8f938b7","type":"inject","z":"b7998df890ce76f5","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":75,"y":880,"wires":[["9c23481e17746023","32023e0b79768de7"]],"l":false},{"id":"32023e0b79768de7","type":"file in","z":"b7998df890ce76f5","name":"Src","filename":"/data/ha/ir_code_ac_up.csv","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":900,"wires":[["3c74da852ee4d13e"]]},{"id":"3c74da852ee4d13e","type":"join","z":"b7998df890ce76f5","name":"","mode":"custom","build":"array","property":"payload","propertyType":"msg","key":"filename","joiner":",","joinerType":"str","accumulate":false,"timeout":"1","count":"2","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":310,"y":880,"wires":[["aefe37416b3ce75b"]]},{"id":"aefe37416b3ce75b","type":"function","z":"b7998df890ce76f5","name":"parse","func":"const src = msg.payload;\nconst codes = parseCMD(src[isJson(src[0]) ? 1 : 0]);\nvar payload = JSON.parse(src[isJson(src[0])? 0 : 1]);\n\nudpateCMD(payload.commands, codes);\n\npayload.supportedController = \"MQTT\";\npayload.commandsEncoding = \"Raw\";\nmsg.payload = JSON.stringify(payload, null, 3);\nreturn msg;\n\n\nfunction udpateCMD(obj, cmd,prefix) {\n prefix = prefix === undefined ? \"\" : prefix + \".\";\n for (const k in obj) {\n let v = obj[k];\n if (typeof v === 'string' || v instanceof String) {\n if (cmd.hasOwnProperty(prefix + k)) {\n obj[k] = JSON.stringify({ ir_code_to_send: cmd[prefix + k] });\n }else{\n obj[k] = JSON.stringify({ ir_code_to_send: \"\" });\n }\n } else if(typeof v === 'object' && v !== null){\n udpateCMD(obj[k], cmd, prefix + k);\n }\n }\n};\n\nfunction parseCMD(data, delimiter = ',') {\n var map = new Object();\n data = data\n .slice(data.indexOf('\\n') + 1)\n .split('\\n').map(v => {\n const arr = v.split(delimiter);\n if (arr.hasOwnProperty(2)) {\n map[arr[1]] = arr[2];\n }\n });;\n return map;\n};\n\nfunction encode(code) {\n return JSON.stringify({ ir_code_to_send: code });\n}\nfunction isJson(str) {\n try {\n JSON.parse(str);\n } catch (e) {\n return false;\n }\n return true;\n}\nfunction csvToArray(str, delimiter = \",\") {\n let array = str.split(\"\\\\r\\\\n\").map(function (line) {\n return line.split(delimiter);\n });\n\n return array;\n}\nfunction CSVToJSON(data, delimiter = ','){\n const titles = data.slice(0, data.indexOf('\\n')).split(delimiter);\n return data\n .slice(data.indexOf('\\n') + 1)\n .split('\\n')\n .map(v => {\n const values = v.split(delimiter);\n return titles.reduce(\n (obj, title, index) => ((obj[title] = values[index]), obj),\n {}\n );\n });\n};\n/*\nfor (const property in object) {\n console.log(`${property}: ${object[property]}`);\n}\n*/\n//Object.values(animals).forEach(val => console.log(val));","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":450,"y":880,"wires":[["f0008d2e6611cb68"]]},{"id":"f0008d2e6611cb68","type":"file","z":"b7998df890ce76f5","name":"Log","filename":"/data/ha/ir_codes.json","filenameType":"str","appendNewline":false,"createDir":false,"overwriteFile":"true","encoding":"none","x":590,"y":880,"wires":[["91a7b887f11ea946"]]},{"id":"91a7b887f11ea946","type":"debug","z":"b7998df890ce76f5","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":880,"wires":[]},{"id":"7ed8ce32d57268ed","type":"inject","z":"b7998df890ce76f5","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":780,"wires":[["6a073749e4ebcb7f"]],"l":false},{"id":"c2c8045800223dd7","type":"group","z":"b7998df890ce76f5","name":"Covert SmartIr RM4 to ZS06","style":{"label":true},"nodes":["507a1ad555f8cf50","4fc5e2bbafd8efa0","43409397257f8e34","919071a27b8ec4d5","9198590c62f199cd","27b3cf4e0e4e340c","7ffb6262ef272467","77940daabc33296e","6687c91fb16fab29","afc7849272fc5590","deab06de0e53f081","c3074cf9a1021870","95d786911f0aaa53","eee196a1932ce952","41ef85dffa09612f","89f3de66fe8a1f19","0197f6a2ec029258","2b1b046b324202e0","cd0d3dcff7b1524e","15ec1eb773ebeac2","d05213882f8a597d","dcd9f2274b7ba955","685c00c55eb2b8a0","b31e93ef23ce44dd","b4561199d3f2db8c","ef7f66db1d630edb","ef9ccc686da68143","d5414260fedf7acd","e1bc3ab056cf684b","7cb92a52d69d1a1d","3fa36aaa406e9dd9","003f6678b4b7927a","6a073749e4ebcb7f"],"x":34,"y":459,"w":1352,"h":362},{"id":"507a1ad555f8cf50","type":"mqtt in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Listen","topic":"zigbee2mqtt/Guest Blaster","qos":"0","datatype":"auto-detect","broker":"7c05f96914c79996","nl":false,"rap":true,"rh":0,"inputs":0,"x":610,"y":720,"wires":[["919071a27b8ec4d5"]]},{"id":"4fc5e2bbafd8efa0","type":"file","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Log","filename":"/data/ha/ir_code.csv","filenameType":"str","appendNewline":false,"createDir":false,"overwriteFile":"false","encoding":"none","x":1310,"y":740,"wires":[[]]},{"id":"43409397257f8e34","type":"csv","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","sep":",","hdrin":"","hdrout":"once","multi":"one","ret":"\\n","temp":"time,command,code","skip":"0","strings":true,"include_empty_strings":"","include_null_values":"","x":1170,"y":740,"wires":[["4fc5e2bbafd8efa0"]]},{"id":"919071a27b8ec4d5","type":"rbe","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"payload.learned_ir_code","topi":"topic","x":750,"y":720,"wires":[["89f3de66fe8a1f19"]]},{"id":"9198590c62f199cd","type":"api-call-service","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"RM4","server":"8093ca4.46eb138","version":5,"debugenabled":false,"domain":"remote","service":"send_command","areaId":[],"deviceId":[],"entityId":["remote.guest_rm4"],"data":"{\"command\":\"b64: \"& payload}","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":890,"y":600,"wires":[[]]},{"id":"27b3cf4e0e4e340c","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"AC Down","filename":"/data/ha/codes/climate/1084.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":180,"y":500,"wires":[["6687c91fb16fab29"]]},{"id":"7ffb6262ef272467","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":540,"wires":[["77940daabc33296e"]],"l":false},{"id":"77940daabc33296e","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"AC Up","filename":"/data/ha/codes/climate/1124.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":540,"wires":[["6687c91fb16fab29"]]},{"id":"6687c91fb16fab29","type":"function","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"parse","func":"var obj = JSON.parse(msg.payload);\nvar table = flattenObject(obj.commands);\nvar date = new Date();\nmsg = [{ payload: table }, { reset: true, payload: { time: date.toISOString(), command: msg.filename } }];\nreturn msg;\n\n\n/*\nsetTimeout(function () {\n console.log(\"Executed after 1 second\");\n}, 1000);\n*/\n\nfunction payload(postion, payload) {\n const msg = new Array(node.outputCount);\n msg[postion] = { payload: payload };\n return msg;\n}\n\nfunction flattenObject(ob) {\n var toReturn = {};\n\n for (var i in ob) {\n if (!ob.hasOwnProperty(i)) continue;\n\n if ((typeof ob[i]) == 'object' && ob[i] !== null) {\n var flatObject = flattenObject(ob[i]);\n for (var x in flatObject) {\n if (!flatObject.hasOwnProperty(x)) continue;\n\n toReturn[i + '.' + x] = flatObject[x];\n }\n } else {\n toReturn[i] = ob[i];\n }\n }\n return toReturn;\n}","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":740,"wires":[["eee196a1932ce952"],["43409397257f8e34"]]},{"id":"afc7849272fc5590","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Fan","filename":"/data/ha/codes/fan/1240.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":580,"wires":[["6687c91fb16fab29"]]},{"id":"deab06de0e53f081","type":"mqtt out","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"ZS06","topic":"zigbee2mqtt/Guest Blaster/set","qos":"0","retain":"false","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"7c05f96914c79996","x":890,"y":560,"wires":[]},{"id":"c3074cf9a1021870","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learn","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"learn_ir_code\": \"ON\"}","payloadType":"json","x":750,"y":560,"wires":[["deab06de0e53f081"]]},{"id":"95d786911f0aaa53","type":"delay","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"limit","pauseType":"rate","timeout":"2","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":610,"y":680,"wires":[["2b1b046b324202e0","3fa36aaa406e9dd9","003f6678b4b7927a"]]},{"id":"eee196a1932ce952","type":"split","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":470,"y":680,"wires":[["95d786911f0aaa53"]]},{"id":"41ef85dffa09612f","type":"join","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":",","joinerType":"str","accumulate":false,"timeout":"3","count":"3","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"num","reduceFixup":"","x":1030,"y":720,"wires":[["43409397257f8e34","0197f6a2ec029258"]]},{"id":"89f3de66fe8a1f19","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Code","rules":[{"t":"set","p":"topic","pt":"msg","to":"code","tot":"str"},{"t":"move","p":"payload.learned_ir_code","pt":"msg","to":"payload","tot":"msg"},{"t":"set","p":"complete","pt":"msg","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":720,"wires":[["41ef85dffa09612f"]]},{"id":"0197f6a2ec029258","type":"debug","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learned","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":1180,"y":680,"wires":[]},{"id":"2b1b046b324202e0","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Time","rules":[{"t":"set","p":"topic","pt":"msg","to":"time","tot":"str"},{"t":"set","p":"payload","pt":"msg","to":"$now()","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":640,"wires":[["41ef85dffa09612f"]]},{"id":"cd0d3dcff7b1524e","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Test","props":[{"p":"payload.ir_code_to_send","v":"C9kEvgHZBPgBhwHZBEAJ4AsDAPjgABsFhxzZBL4BQAMBvgFABYADAdkEQAkAh6ANQAvAAwCH4AwvwB0F2QS+AYcBQAWAAwL4AYcgLweHAdkEvgG+AUAF4AUDA9kEvgGAHUAJQAMAhyAvAb4BQAMBhwFABYADAPggB0ADA9kE+AHgAxcCvgGH4AAvBL4B2QSHIAPgAwcD2QS+AUATQAMBvgFAAwCH4AQvAb4B4AUDBdkEvgG+AUAFwAPgAS8BhwGAEwD44AIHAdkE4AEXAL4gFwL4AYegXwGHAUAPA4cB2QRAB8ADA9kEvgHgBRMAh6AvIAkAAUAF4AEDQA8B2QQgUQIB2QTgARcAh+AILwSHAdkEvqADAdkEgC8JhwHZBIcB2QSHAQ==","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":750,"y":520,"wires":[["deab06de0e53f081"]]},{"id":"15ec1eb773ebeac2","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Matrix","filename":"/data/ha/codes/media_player/1500.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":620,"wires":[["6687c91fb16fab29"]]},{"id":"d05213882f8a597d","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"TV","filename":"/data/ha/codes/media_player/1480.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":660,"wires":[["6687c91fb16fab29"]]},{"id":"dcd9f2274b7ba955","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Projector","filename":"/data/ha/codes/media_player/1361.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":180,"y":700,"wires":[["6687c91fb16fab29"]]},{"id":"685c00c55eb2b8a0","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Sound","filename":"/data/ha/codes/media_player/1044.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":740,"wires":[["6687c91fb16fab29"]]},{"id":"b31e93ef23ce44dd","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":500,"wires":[["27b3cf4e0e4e340c"]],"l":false},{"id":"b4561199d3f2db8c","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":580,"wires":[["afc7849272fc5590"]],"l":false},{"id":"ef7f66db1d630edb","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":620,"wires":[["15ec1eb773ebeac2"]],"l":false},{"id":"ef9ccc686da68143","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":660,"wires":[["d05213882f8a597d"]],"l":false},{"id":"d5414260fedf7acd","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":700,"wires":[["dcd9f2274b7ba955"]],"l":false},{"id":"e1bc3ab056cf684b","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":95,"y":740,"wires":[["685c00c55eb2b8a0"]],"l":false},{"id":"7cb92a52d69d1a1d","type":"inject","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Reset","props":[{"p":"reset","v":"true","vt":"bool"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":470,"y":640,"wires":[["95d786911f0aaa53"]]},{"id":"3fa36aaa406e9dd9","type":"trigger","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Learn","op1":"{\"learn_ir_code\": \"ON\"}","op2":"","op1type":"json","op2type":"pay","duration":"300","extend":false,"overrideDelay":false,"units":"ms","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":750,"y":600,"wires":[["deab06de0e53f081"],["9198590c62f199cd"]]},{"id":"003f6678b4b7927a","type":"change","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Cmd","rules":[{"t":"set","p":"topic","pt":"msg","to":"command","tot":"str"},{"t":"move","p":"parts.key","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":890,"y":680,"wires":[["41ef85dffa09612f"]]},{"id":"6a073749e4ebcb7f","type":"file in","z":"b7998df890ce76f5","g":"c2c8045800223dd7","name":"Misc","filename":"/data/ha/ir_codes_todo.json","filenameType":"str","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":170,"y":780,"wires":[["6687c91fb16fab29"]]},{"id":"7c05f96914c79996","type":"mqtt-broker","name":"MQTT","broker":"192.168.50.105","port":"1883","clientid":"NodeRed","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""},{"id":"8093ca4.46eb138","type":"server","name":"HA nodered","version":5,"addon":false,"rejectUnauthorizedCerts":false,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false,"cacheJson":true,"heartbeat":true,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
Thanks! I will try to learn NodeRed and use your flow! Best Regards
I will try to learn NodeRed
There isn't much to learn, mostly drag and drop functions. But JavaScript is quite helpful for more complex situation.
You may however, need to install missing nodes from the palette. it's another way to extend nodered capabilities For example the RM4 node is from a Home Asssitant ndoes collection simplifying the interaction with HA. (Confer node-red-contrib-home-assistant-websocket in the palette)
Note: you will need to update the references in the blue, purple & brown notes which respectively point to RM4, ZS06 and files.
I recommend processing only one config file at a time to avoid mixing the command between devices and reset the command file each time for the same reason.
I wonder whether it'd be possible to use this with ZHA instead of zigbee2mqtt? I'm using my Tuya Zigbee Blaster with ZHA and it works great.
I've come up with a slightly workable hackaround solution. Use an automation that listens for a MQTT topic and payload. Then trigger the IR signal with the ZHA cluster command. It means a new automation for every single payload which corresponds to the commands in the json file.
An improved version would be to use an MQTT sensor and store the payload in the sensor and then trigger the IR command with the sensor value. That way only one automation is needed. However, sensor states are limited to 255 characters and I couldn't figure out how to store an MQTT payload in a sensors attribute. All this effort makes me think I should just switch to zigbee2mqtt haha.
Following on #873, the Tuya Zigbee Blaster ZS06 is getting more and more popular, so could it get some official support? According to a previous post, it can actually work once the commands are encapsulated. I can now confirm it does work using the below example but could I request that smartIR accept json command so we wouln't have to escape all the double quotes:
}
Home Assistant version Home Assistant 2023.7.1 Supervisor 2023.07.1 Operating System 10.3 Frontend 20230705.1 - latest
SmartIR version 1.17.7
SmartIR configuration
Describe the bug
Tuya Zigbee Blaster ZS06 device unsupported through MQTT
Debug log