Using openHASP with Node-Red

@yogy You don't need to use the pages.jsonl if you don't want to, you can send everything from NR when the screen boots up.

For the example above this is how I set up the switches and the navbar at the bottom.

[{"id":"a09f9c2122f70c6f","type":"mqtt out","z":"c8c7826a005c7f46","name":"","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"","x":1600,"y":720,"wires":[]},{"id":"0b6d91a713cf41d0","type":"function","z":"c8c7826a005c7f46","name":"Page 0/1/Nav","func":"msg.topic = \"hasp/plate/command\"\n\n// Define common values \n\nconst text_color = \"#bfbfbf\"\nconst menuValues = {\n    \"page\": 0,\n    \"obj\": \"btn\",\n    \"radius\": 35,\n    \"bg_color\": \"#393939\",\n    \"text_font\": 24,\n    \"align\": \"center\",\n    \"border_opa30\": 0,\n    \"text_color\": text_color,\n    \"y\": 405,\n    \"w\": 108,\n    \"h\": 75,\n};\n\nconst btnValues = {\n    \"page\": 1,\n    \"obj\": \"btn\",\n    \"w\": 160,\n    \"h\": 110,\n    \"x\": 320,\n    \"outline_width\": 1,\n    \"outline_color\": \"#aaaaaa\",\n    \"outline_opa\": 50,\n    \"bg_color\": \"#515151\",\n    \"bg_opa\": 255,\n    \"border_opa\": 255,\n    \"border_side\": 1,\n    \"border_width\": 11,\n    \"border_color\": \"#393939\",\n    \"radius\": 8,\n    \"text_font\": 58,\n    \"text_color\": text_color,\n    \"text_line_space\": -20,\n    \"value_font\": 30,\n    \"value_ofs_y\": 26,\n    \"value_color\": text_color\n\n};\n\n\nmsg.payload = [\n    {\n        \"page\": 0,\n        \"id\": 10,\n        \"obj\": \"obj\",\n        \"x\": 0,\n        \"y\": 405,\n        \"w\": 480,\n        \"h\": 75,\n        \"radius\": 35,\n        \"border_opa30\": 0,\n        \"bg_color\": \"#393939\",\n    },\n\n    {\n        \"page\": 0,\n        \"id\": 11,\n        \"obj\": \"label\",\n        \"x\": 10,\n        \"y\": 0,\n        \"w\": 50,\n        \"h\": 50,\n        \"text\": \"\\uE5A9\",\n        \"text_color\": \"red\",\n        \"text_font\": 30,\n    }\n]\n\nnode.send(msg);\nmsg.payload = [\n    {\n        \"id\": 1,\n        \"x\": 10,\n        \"text\": \"\\uE60C\\nMore\",\n        ...menuValues,\n    },\n    {\n        \"id\": 2,\n        \"x\": 128,\n        \"text\": \"\\uE425\\nSwitch\",\n        ...menuValues,\n    },\n    {\n        \"id\": 3,\n        \"x\": 246,\n        \"text\": \"\\uE425\\nDevice\",\n        ...menuValues,\n    },\n    {\n        \"id\": 4,\n        \"x\": 364,\n        \"text\": \"\\uE493\\nSettings\",\n        ...menuValues,\n    }\n];\n\nnode.send(msg);\n\nmsg.payload = [\n    {\n        \"id\": 1,\n        \"y\": 0,\n        \"text\": \"\\n\",\n        \"value_str\": \"Wall\",\n        ...btnValues\n    },\n    {\n        \"id\": 2,\n        \"y\": 136,\n        \"text\": \"\\n\",\n        \"value_str\": \"Main\",\n        ...btnValues\n    },\n    {\n        \"id\": 3,\n        \"y\": 272,\n        \"obj\": \"btn\",\n        \"text\": \"\\n\",\n        \"value_str\": \"Lamp\",\n        ...btnValues\n    },\n    { \"page\": 1, \"id\": 0, \"bg_color\": \"#000000\" } //set background to black\n]\n\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1285,"y":645,"wires":[["ade4a70b5089b9d2","a09f9c2122f70c6f"]]},{"id":"367d1c7288a6d800","type":"inject","z":"c8c7826a005c7f46","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":915,"y":645,"wires":[["0b6d91a713cf41d0"]]}]

To change the appearance of the buttons I update a number of properties to show as on or off -

[{"id":"d2a3b5143f7983db","type":"function","z":"c8c7826a005c7f46","name":"Update Hasp Buttons","func":"let onOff = msg.payload\n\n// Build json to send to hasp\nconst on = {\n    \"page\": msg.page,\n    \"id\": msg.id,\n    \"text_color\": \"#dea031\",\n    \"bg_color\": \"#404040\",\n    \"text_line_space\": -40,\n    \"border_side\": 2,\n    \"border_color\": \"#5d5d5d\",\n    \"value_ofs_y\": 36,\n    \"value_color\": \"#a4a4a4\",\n\n}\nconst off = {\n    \"page\": msg.page,\n    \"id\": msg.id,\n    \"text_color\": \"#bfbfbf\",\n    \"bg_color\": \"#515151\",\n    \"text_line_space\": -20,\n    \"border_side\": 1,\n    \"border_color\": \"#393939\",\n    \"value_ofs_y\": 26,\n    \"value_color\": \"#bfbfbf\",\n}\nmsg.payload = onOff === \"ON\" ? on : off\n\nreturn msg\n","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1660,"y":1695,"wires":[["82e9a3cd930455f8"]],"info":"const mapping = flow.get(\"mapping\")\r\nlet foundButton = null;\r\nlet page = 0\r\nlet id = 0\r\n\r\n// Modify incomming Tasmota topic to match outgoing topic,\r\n// so we can lookup the Hasp button that called it\r\nlet topic = msg.topic.split(\"/\")\r\nlet index = \"cmnd/\" + topic[1] + \"/\" + topic[2]\r\n\r\n// Reverse lookup plate topic\r\nfor (const button in mapping) {\r\n    if (mapping[button] === index) {\r\n        foundButton = button;\r\n        break;\r\n    }\r\n}\r\nif (foundButton === null) {\r\n    node.warn(\"no matching button \" + msg.topic);\r\n    return\r\n}\r\n\r\nlet parts = foundButton.split(\"/\")\r\n\r\ntopic = `hasp/${parts[1]}/command/${parts[3]}` //hasp topic\r\nnode.status({ text: `${parts[3]} ${msg.payload}` });\r\n\r\n// Build json to send to hasp\r\n\r\nconst on = {\r\n    \"bg_color\": \"#616161\",\r\n    \"text_color\": \"#dea031\",\r\n    \r\n}\r\nconst off = {\r\n    \"bg_color\": \"#393939\",\r\n    \"text_color\": \"#bfbfbf\",\r\n   \r\n}\r\n\r\nlet update = (msg.payload === \"ON\" ? on : off)\r\n\r\nObject.keys(update).forEach(key => {\r\n    msg = { \"topic\": `${topic}.${key}`, \"payload\": update[key] }\r\n    node.send(msg)\r\n}\r\n)\r\n\r\nreturn \r\n"},{"id":"82e9a3cd930455f8","type":"mqtt out","z":"c8c7826a005c7f46","name":"","topic":"","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"","x":1865,"y":1695,"wires":[]},{"id":"aacb3ccb7948749f","type":"inject","z":"c8c7826a005c7f46","name":"Button 1 ON","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"page","v":"1","vt":"num"},{"p":"id","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"has/pplate/command/jsonl","payload":"ON","payloadType":"str","x":1460,"y":1680,"wires":[["d2a3b5143f7983db"]]},{"id":"8d037f082de31a12","type":"inject","z":"c8c7826a005c7f46","name":"Button 1 OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"},{"p":"page","v":"1","vt":"num"},{"p":"id","v":"1","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"has/pplate/command/jsonl","payload":"OFF","payloadType":"str","x":1460,"y":1725,"wires":[["d2a3b5143f7983db"]]}]
2 Likes