HomeKit integration

So, this is very much a work in progress, and only vaguely approaching functional at the moment…but…

Using https://github.com/KhaosT/HAP-NodeJS I’ve got my phone capable of opening a virtualized garadget.

If anyone else wants to give it a try, the steps are (from memory)

  • git clone https://github.com/KhaosT/HAP-NodeJS.git
  • cd HAP-NodeJS
  • npm install
  • npm install node-libcurl (If you are on a Mac: npm install node-libcurl --build-from-source instead!)
  • swap out the LightAccessory.js file under accessories for the one in-line below
  • don’t forget to edit in your device’s ID and your API key!
  • node BridgedCore.js

At this point you need something on your iDevice to talk to homekit stuff, and the best option I’ve found is https://itunes.apple.com/us/app/home-smart-home-automation/id995994352?mt=8

It’s spendy, but is really well put together and will let you talk to any kind of device and do some nice organization and scenario setups.

At this point you MUST be on the same network as the computer running HAP-NodeJS.

  • Open Home
  • Click the Plus to add a “home”, you should see a bunch of options including Demo Light
  • Select Demo Light
  • On = open, Off = closed

Off also currently equals “Crashed” since my JS knowledge is almost non-existent. This is just copy/paste from the lib-nodejs examples folder with a couple minor modifications. Both on and off leave the session open, and that makes things really unhappy.

Worth mentioning: you cannot talk to HomeKit devices from outside your home network without an AppleTV. Apple loves to sell you more things so any HomeKit system consists of a HomeKit Bridge (HAP-NodeJS in our case), A device to be controlled, and if you want in from the outside world…a HomeKit Extender (AppleTV).

There is an example GarageDoor device in the HAP-NodeJS accessories folder, and I intend to get it running so you can do more than just open and close (also you can talk to Siri about the “garage door” and “open” instead of “turn on the light” being secret code for “open the garage”).

Lastly, here’s the LightAccessory.js file you’ll want to copy in:

var Accessory = require('../').Accessory;
var Service = require('../').Service;
var Characteristic = require('../').Characteristic;
var uuid = require('../').uuid;


// Curl Setup
var Curl = require( 'node-libcurl' ).Curl,
  querystring = require( 'querystring' );

//https://api.particle.io/v1/devices/$device_id/setState -d access_token=$api_key -d arg="closed"
var endpoint = 'setState';
var device = 'YOUR_DEVICE_ID_GOES_HERE';
var api_key = 'YOUR_API_KEY_GOES_HERE';
var action = 'open';

var curl = new Curl(),
    url  = 'https://api.particle.io/v1/devices/' + device + '/' + endpoint,
    data = 'access_token=' + api_key + '&arg=' + action ;


// here's a fake hardware device that we'll expose to HomeKit
var FAKE_LIGHT = {
  powerOn: false,
  brightness: 100, // percentage

  setPowerOn: function(on) {
    console.log("Turning the light %s!", on ? "on" : "off");
    FAKE_LIGHT.powerOn = on;
    if (on) {
	var action = 'closed'
	curl.setOpt( Curl.option.URL, url );
	curl.setOpt( Curl.option.FOLLOWLOCATION, true );
	curl.setOpt( Curl.option.POSTFIELDS, data );
	curl.setOpt( Curl.option.HTTPHEADER, ['User-Agent: node-libcurl/1.0'] );
	curl.setOpt( Curl.option.VERBOSE, true );

	console.log( querystring.stringify( data ) );

	curl.perform();

	curl.on( 'end', function( statusCode, body ) {

	    console.log( body );

	    this.close();
	});

	curl.on( 'error', curl.close.bind( curl ) );
    } else {
	curl.setOpt( Curl.option.URL, url );
	curl.setOpt( Curl.option.FOLLOWLOCATION, true );
	curl.setOpt( Curl.option.POSTFIELDS, data );
	curl.setOpt( Curl.option.HTTPHEADER, ['User-Agent: node-libcurl/1.0'] );
	curl.setOpt( Curl.option.VERBOSE, true );

	console.log( querystring.stringify( data ) );

	curl.perform();

	curl.on( 'end', function( statusCode, body ) {

	    console.log( body );

	    this.close();
	});

	curl.on( 'error', curl.close.bind( curl ) );
    };
  },
  setBrightness: function(brightness) {
    console.log("Setting light brightness to %s", brightness);
    FAKE_LIGHT.brightness = brightness;
  },
  identify: function() {
    console.log("Identify the light!");
  }
}
1 Like

FYI : There is an Openhab to HomeKit bridge (HomeBridge) that will make most anything ( as long as there exists some way to map it) from OpenHab to HomeKit. That’s how I was planning on bridging my Garadgets to HomeKit.

UPDATE 6:

I got doorStatus and setState done. Now to wrap homebridge/homekit around it.

require(“request”) // request
require(“just-get-json”) //helps get json

//set vars
var setState = require(“request”)
var gJson = require(“just-get-json”)
var cloudURL = ‘https://api.particle.io/v1/devices/
var access_token = process.env.access_token
var deviceID = process.env.deviceid
var gdoorStatusURL = cloudURL + deviceID + ‘/doorStatus?access_token=’ + access_token
var gsetStateURL = cloudURL + deviceID + ‘/setState’

//get json
getStatus = gJson(gdoorStatusURL)

//parse function
parseStatus = function(a_status) {
var split1 = a_status.result.split(“|”) //array split by |
var split2 = split1[0].split(“=”) //array split by =
var a_result = split2[1] //set gStatus
return a_result
}

//doorStatus
var gStatus = parseStatus(getStatus);
//setState
switch(gStatus) {
case ‘closed’:
setState.post(
gsetStateURL, {
form: {
access_token: access_token,
args: ‘open’
}
}
)
console.log(‘garage is opening’) //debug - echo opening
break
case ‘open’:
setState.post(
gsetStateURL, {
form: {
access_token: access_token,
args: ‘closed’
}
}
);
console.log(‘garage is closing’) //debug - echo closing
break
case ‘stopped’:
break
case ‘offline’:
break
case ‘timeout’:
break
case ‘closing’:
/* setState.post(
gsetStateURL, {
form: {
access_token: access_token,
args: ‘stop’
}
}
);
/
break
case ‘opening’:
/
setState.post(
gsetStateURL, {
form: {
access_token: access_token,
args: ‘stop’
}
}
);
*/
break
}

UPDATE 5:
I need to find out how to grab the json from the url. I tried some ways but it didnt work so I paused on that and chose to work on the parse of the data. I was able to write my version of getting the status of the garage.
running this under runkit.com

So next step is to figure out json file from url then figure how homekit will poll updates from this module.

I am divided between telling homekit that this is a garage or a light bulb. Recently any door/lock/garage type requires you to choose to run the scene removing the automation.

var aJson = {
“cmd”: “VarReturn”,
“name”: “doorStatus”,
“result”: “status=open|time=47m|sensor=95|signal=-47”
};
var split1 = aJson.result.split(“|”) //array split by |
console.log(split1[0]) //debug - echo value for status
var split2 = split1[0].split(“=”); //array split by =
var gStatus = split2[1] //set gStatus
console.log(gStatus); //debug - echo value for gStatus
switch(gStatus) {
case ‘closed’:
console.log(‘garage is closed’); //debug - echo closed
break;
case ‘open’:
console.log(‘garage is open’); //debug - echo open
break;
case ‘stopped’:
case ‘offline’:
case ‘timeout’:
case ‘closing’:
case ‘opening’:
}

UPDATE 4:
I got Homebridge-particle to work.
Now time to rewrite it for just garadget.
I still need to program in doorStatus

Looks like all I had to do was look for line 141 in index.js

var argument = this.args.replace(“{STATE}”, (state ? “1” : “0”));

Change to

var argument = this.args.replace(“{STATE}”, (state ? “open” : “close”));

**NOTE: for some reason when i cloned the repository it came out to be {STATE
Make sure to add the } or else the request will be “open%7D” and it won’t work.

I also added this assessory in my config.json

{
    	"accessory": "Garadget",
    	"name": "Garage-Name",
        "deviceid": "42XXXXXXXXXXXXXXXXX",
    	"type": "LIGHT",
    	"function_name": "setState",
    	"args": "{STATE}"
}

Of course add your access key
and change
"cloudurl": "https://api.particle.io/v1/devices/",

.
OLD
Any more information? I am going to try to get this to work with homekit. I’ll check out openhab and this
UPDATE:
MacOS + Xcode + nodeJS + homebridge

I am planning on moving development from my Mac into a permanent solution for the homebridge server(Raspberry pi 3).

So I am using this plugin GitHub - krvarma/homebridge-particle: Homebridge plugin for Particle Devices
very limited types (LIGHT, SENSOR).

Had to change to
"cloudurl": "https://api.particle.io/v1/devices/",

I got it to at least do something with

{
“accessory”: “Garadget”,
“name”: “Garage”,
“deviceid”: “XXXXXXXXXXXXXX”,
“type”: “LIGHT”,
“function_name”: “setState”,
“args”: “open”
}

But the issue is that the particle doesnt report back open or closed so I can’t simply just put if open then arg = close

I’ll have to figure this out some more later but maybe someone has gotten further.

Or if anyone has a suggestion to not use this plugin.
In the end I might have to write a new plugin just for garadget.

UPDATE 2:
I’ll have a look at garadget’s firmware to find events and args.
Looks like doorStatus will be the var i need.

https://www.garadget.com/my/js/door.js
the results i get

{
“cmd”: “VarReturn”,
“name”: “doorStatus”,
“result”: “status=closed|time=47m|sensor=95|signal=-47”,
“coreInfo”: {
“last_app”: “”,
“last_heard”: “”,
“connected”: true,
“last_handshake_at”: “”,
“deviceID”: “XXXXXXXXXXX”,
“product_id”:
}
}

need to parse to just get the status.
UPDATE 3:
Looks like I have to plan to rewrite a bunch of stuff in the index.js to get this to work
//initial
set vars
Get status = doorStatus

//if toggled
If “close” then
setState = “open”
else
setState = “close”
end if
Return arg

1 Like

I have appletv and many iOS devices. Let me know how I can help.