Hi Brad,
Ok, Here goes! Let me know if you have any issues with the below.
The Pulse 2 Hub has a Telnet Interface where you can send commands and receive updates on the states of the blinds.
You can use any telnet client and connect to the IP address of the Pulse 2 hub but you need to use port 1487.
The commands to send require a ! to start then the Blind address as found in the Pulse 2 app, then the command and then a position (if needed) ending with a ;
There’s a few commands but the only two that I’m interested in are the ones that control the blind movement. m to move and s to stop
So with the Blind Address being PR6 and I want to open it 50% then I would send !PR6m050;
If i wanted it fully open !PR6m000; or fully closed !PR6m100; or to stop it in its tracks !PR6s;
The Hub also sends back updates. You get Position and Battery voltage and there’s extra data that I’m not sure of and don’t seem to need.
You can investigate the other commands/data if you want but the main one I’m interested in is the position of the blind. If you wanted you could read out the battery voltage and send that to OpenHab but i haven’t done that yet.
For example the position of the above blind is reported as !PR6rXXX???,??? (XXX = position and the rest doesn’t matter!)
OK, So OpenHab needs to open a telnet connection to the Hub and process Blind Controls to and from these commands.
If OpenHAB had a Telnet Binding we wouldn’t need Node-Red but it doesn’t so it needs to be installed.
Google Node-Red and follow install instructions. I’m using Windows so it was quite easy. If you’re using Linux then I cant help.
If you’re not familiar with Node-Red this can get tricky.
Once Node-Red (NR) is installed you need to add 2 extra nodes. node-red-contrib-openhab3 and node-red-contrib-telnet-client.
You can google these or just go to Manage Palette in NR and search for them there
Once the extra Nodes are in then import my Flow below.
[
{
"id": "dc2e333.7536d5",
"type": "tab",
"label": "Blind Control",
"disabled": false,
"info": ""
},
{
"id": "77dd9941.1f0c3",
"type": "telnet-read",
"z": "dc2e333.7536d5",
"name": "",
"connection": "e5d38a88.f6d0a8",
"x": 310,
"y": 120,
"wires": [
[
"fae7385.1ed8248",
"116b5f23.34c551"
]
]
},
{
"id": "c894d31e.d9b5",
"type": "telnet-send",
"z": "dc2e333.7536d5",
"name": "",
"connection": "e5d38a88.f6d0a8",
"x": 310,
"y": 200,
"wires": []
},
{
"id": "fae7385.1ed8248",
"type": "function",
"z": "dc2e333.7536d5",
"name": "Decode",
"func": "\nvar rxs = msg.payload;\n// rxs = Recieved string should be !BBBcXXX????,???\n// BBB = Blind Address\n// c = command (m = move, r read)\n// XXX = value\n// ??? = unknown and not needed\n\nvar blindaddress = rxs.substring(1,4); // Get Blind address,\nif (blindaddress == \"EUC\") return null; //error!!! need to do something\n \nif (rxs.substring(4,5) != \"r\") return null; //only interested in r (read) for now\n\n/* if we need to deal with more commands\nvar cmdv =\"\";\nvar cmd = rxs.substring(4,5); \n switch(cmd)\n {\n case \"p\": // Battery Voltage \n cmdv = rxs.substring(7,12);\n break;\n case \"r\": \n cmdv = rxs.substring(5,8);\n break;\n //default: return // unknown \n }\n*/\n \n\n msg.topic = blindaddress;\n msg.payload = rxs.substring(5,8); // Blind Position.\n if (msg.payload==\"?,R\") return null; //error? \nreturn msg;",
"outputs": 1,
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 460,
"y": 160,
"wires": [
[
"fd46da46.d346a"
]
]
},
{
"id": "fd46da46.d346a",
"type": "switch",
"z": "dc2e333.7536d5",
"name": "",
"property": "topic",
"propertyType": "msg",
"rules": [
{
"t": "eq",
"v": "R6D",
"vt": "str"
},
{
"t": "eq",
"v": "PR6",
"vt": "str"
},
{
"t": "eq",
"v": "DC3",
"vt": "str"
}
],
"checkall": "true",
"repair": false,
"outputs": 3,
"x": 590,
"y": 160,
"wires": [
[
"2209fbabf3e4b418"
],
[
"b5d85b199d146345"
],
[
"c51d02c9fea7d38c"
]
]
},
{
"id": "d5034494.8f0368",
"type": "debug",
"z": "dc2e333.7536d5",
"name": "Debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 90,
"y": 240,
"wires": []
},
{
"id": "116b5f23.34c551",
"type": "debug",
"z": "dc2e333.7536d5",
"name": "Debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"targetType": "msg",
"statusVal": "",
"statusType": "auto",
"x": 330,
"y": 60,
"wires": []
},
{
"id": "b028e6169f8eef89",
"type": "openhab2-in2",
"z": "dc2e333.7536d5",
"name": "",
"controller": "dca5b83085a6363d",
"itemname": "nrBlinds_Command",
"topic": "",
"initialstate": false,
"whenupdated": false,
"whencommand": true,
"whenchanged": false,
"changedfrom": "",
"changedto": "",
"x": 110,
"y": 160,
"wires": [
[
"d5034494.8f0368",
"c894d31e.d9b5"
]
]
},
{
"id": "c51d02c9fea7d38c",
"type": "openhab2-out2",
"z": "dc2e333.7536d5",
"name": "",
"controller": "dca5b83085a6363d",
"itemname": "nrBlindDining",
"topic": "ItemUpdate",
"payload": "",
"onlywhenchanged": false,
"x": 760,
"y": 220,
"wires": []
},
{
"id": "b5d85b199d146345",
"type": "openhab2-out2",
"z": "dc2e333.7536d5",
"name": "",
"controller": "dca5b83085a6363d",
"itemname": "nrBlindLounge",
"topic": "ItemUpdate",
"payload": "",
"onlywhenchanged": false,
"x": 760,
"y": 160,
"wires": []
},
{
"id": "2209fbabf3e4b418",
"type": "openhab2-out2",
"z": "dc2e333.7536d5",
"name": "",
"controller": "dca5b83085a6363d",
"itemname": "nrBlindKitchen",
"topic": "ItemUpdate",
"payload": "",
"onlywhenchanged": false,
"x": 760,
"y": 100,
"wires": []
},
{
"id": "e5d38a88.f6d0a8",
"type": "telnet-connection",
"name": "Acmeda Pulse2 Hub",
"address": "192.168.0.100",
"port": "1487",
"inDelimiter": ";",
"outDelimiter": "\\n",
"timeOut": "100000",
"clearOut": "",
"openTries": "1"
},
{
"id": "dca5b83085a6363d",
"type": "openhab2-controller2",
"name": "OH3",
"protocol": "http",
"host": "localhost",
"port": "8080",
"path": "",
"username": "oh.nodered.EWSUUeALWX3PbFgqZBFVaJI5SVuRumyEwACCZBDqUXRHZlopzlePeYNyXueNhQcZdb2KBNFyNpWayuEA",
"password": "",
"ohversion": "v3",
"token": ""
}
]
You will need to modify it to work.
Configure the connections:
- For OpenHAB you will need to generate an API Key. (check community as to how or ask me!)
- For The Pulse Hub you just need the IP and Port
Edit the Switch Node which sorts the Blind addresses so you need to match yours.
The Green Nodes are OpenHAB Items (You should use mine until you’re good with it all).
The Rest should be OK
OK Node-Red Done, On to OpenHAB. (assuming you’re using OH3)
Create a String item, Call it nrBlinds_Commands
Create a RollerShutter Item for each of your blinds.(use nrBlindLounge for example)
Add the Blind address as a Tag (Make sure its the 1st tag)
Create an ECMAScript and Give it a name.
Copy the below script into it. (This should work for any Blind as long as the Blind address is in the Tags)
var logger = Java.type("org.slf4j.LoggerFactory").getLogger("org.openhab.Script: Blind Automation");
var Thread = Java.type("java.lang.Thread");
var finalcmd; // Command that will be sent to Blind. "!BBBcXXX;" BBB = Blind address, c = command, xxx = number
var cmd = command.toString(); // Get Command that triggered rule (UP,DOWN,STOP or Number)
var bl = ir.getItem(event.itemName); // Get Item that triggered Rule
var ba = bl.getTags().toString().substr(1,3); // Get Blind address from Tag, works but ugly and relies on the blind address being the 1st tag.
// Will eventually use custom Metadata when it can be seen in UI
switch(cmd) // Convert RollerBlind Command to Pulse 2 Hub Command
{
case "UP": finalcmd = 'm000;'
break;
case "DOWN": finalcmd = 'm100;'
break;
case "STOP": finalcmd = 's;'
break;
default: finalcmd = 'm'+"000".substring(0,3-cmd.length)+cmd+';' // must be a number so pad it to 3 digits and add 'm'.
}
finalcmd = "!" + ba + finalcmd;
logger.info("ItemName: "+event.itemName+", Recieved Command: "+cmd+", Sent to Blind: "+finalcmd);
events.sendCommand('nrBlinds_Command',finalcmd);
Thread.sleep(100); // Delay to stop multiple script instances running at same time (OH bug?)
Last thing is create a rule that will run the script any time one of your RollerShutter Items get Updated.
That should be It!.
You should now be able to control your Blinds with the RollerShutter Items.
You can Add Metadata so google can control them through openhab instead of the Cloud.
Hope this Helps… Let me know if anything is unclear.