Closed ogiewon closed 6 years ago
Dan,
You are the man, I have been looking for this type of information.
So if I am not mistaken, one would need to shut down the ST Homekit/Homebridge integration. But what would the steps (ie the config.json file) look like to do an install because I would LOVE to test this!!!
I believe you are correct. I originally tried having both “platforms” in the config.json file. To get it to work at all, I had to remove the real SmartThings platform. Afterwards, I had to use the Hubitat cloud endpoint. I was then able to see a few devices in HomeKit on my phone that were in the “switch” group, but nothing from the “sensor” group.
So, it is a promising start.
So to remove the ST platform would be to simply eliminate it from the config.json, but what are you placing into the config.json instead?
Justin Bennett, Esq.
Personal E-Mail Account. Although this was sent from my personal e-mail this communication may contain privileged or other confidential information. If you are not the intended recipient, or believe that you have received this communication in error, please do not print, copy, retransmit, disseminate, or otherwise use the information contained herein. Also, please notify sender that you have received this communication in error, and delete the copy thereof you have received. Thank you.
On Feb 12, 2018, 10:52 AM -0500, ogiewon notifications@github.com, wrote:
I believe you are correct. I originally tried having both “platforms” in the config.json file. To get it to work at all, I had to remove the real SmartThings platform. Afterwards, I had to use the Hubitat cloud endpoint. I was then able to see a few devices in HomeKit on my phone that were in the “switch” group, but nothing from the “sensor” group. So, it is a promising start. — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
In your Hubitat JSON Complete API app, you can select the devices you want exposed (same as ST) and then display the Config data. Basically the exact same data that you’d get from the SmartThings App on your phone. But instead, you get it from the Hubitat hub’s web page instead.
In the code posted above, it will present the LOCAL OAUTH endpoint data needed for config.json. This endpoint is http only, not https. Thus, the reason I posted this issue.
This looks like exactly the device I wanted ages ago and closely resembles where Home Automation started. I'll need to get one ordered. The current Smartthings connection uses https and it is a simple matter (I think) to swap it out to http if that's the only issue. I'm fairly sure you can just remove the s in the first line of lib/smartthingsapi.js https://github.com/pdlove/homebridge-smartthings/blob/0b20eae7448a928fa97ad5df2f5566994aec600f/lib/smartthingsapi.js#L1 Bt No guarantees that won't break something else, but give it a try. I'll get one ordered and be able to test more when it comes in.
This would be excellent!
Here is my most up to date version of the "JASON Complete API" groovy code for Hubitat. This version uses recently added API calls for generating the Endpoint information. This version is configured to generate the LOCAL endpoint when displaying the information needed for config.json.
To use the cloud endpoint, just comment/uncomment the following section appropriately.
def renderConfig() {
def configJson = new groovy.json.JsonOutput().toJson([
description: "JSON API",
platforms: [
[
platform: "SmartThings",
name: "SmartThings",
//
//Original SmartThings cloud endpoint
//app_url: apiServerUrl("/api/smartapps/installations/"),
//
//Hubitat cloud endpoint
//app_url: "${getApiServerUrl()}/${hubUID}/apps/",
//
//Hubitat local endpoint
app_url: getLocalApiServerUrl() + "/",
app_id: app.id,
access_token: state.accessToken
]
],
])
def configString = new groovy.json.JsonOutput().prettyPrint(configJson)
render contentType: "text/plain", data: configString
}
Here is the full version of the Hubitat App. I have not tested it yet using @pdlove 's recommended changes to the lib/smartthingsapi.js file.
/**
* JSON Complete API
*
* Copyright 2017 Paul Lovelace
*
* Modifications for Hubitat (in progress) - Dan Ogorchock 2/14/2018
*/
definition(
name: "JSON Complete API",
namespace: "pdlove",
author: "Paul Lovelace",
description: "API for JSON with complete set of devices",
category: "SmartThings Labs",
iconUrl: "https://raw.githubusercontent.com/pdlove/homebridge-smartthings/master/smartapps/JSON%401.png",
iconX2Url: "https://raw.githubusercontent.com/pdlove/homebridge-smartthings/master/smartapps/JSON%402.png",
iconX3Url: "https://raw.githubusercontent.com/pdlove/homebridge-smartthings/master/smartapps/JSON%403.png",
oauth: true)
preferences {
page(name: "copyConfig")
}
//When adding device groups, need to add here
def copyConfig() {
if (!state.accessToken) {
createAccessToken()
}
dynamicPage(name: "copyConfig", title: "Configure Devices", install:true, uninstall:true) {
section("Select devices to include in the /devices API call") {
paragraph "Version 0.5.5"
input "deviceList", "capability.refresh", title: "Most Devices", multiple: true, required: false
input "sensorList", "capability.sensor", title: "Sensor Devices", multiple: true, required: false
input "switchList", "capability.switch", title: "All Switches", multiple: true, required: false
//paragraph "Devices Selected: ${deviceList ? deviceList?.size() : 0}\nSensors Selected: ${sensorList ? sensorList?.size() : 0}\nSwitches Selected: ${switchList ? switchList?.size() : 0}"
}
section("Configure Pubnub") {
input "pubnubSubscribeKey", "text", title: "PubNub Subscription Key", multiple: false, required: false
input "pubnubPublishKey", "text", title: "PubNub Publish Key", multiple: false, required: false
input "subChannel", "text", title: "Channel (Can be anything)", multiple: false, required: false
}
section() {
paragraph "View this SmartApp's configuration to use it in other places."
//Original SmartThings cloud endpoint
//href url:"${apiServerUrl("/api/smartapps/installations/${app.id}/config?access_token=${state.accessToken}")}", style:"embedded", required:false, title:"Config", description:"Tap, select, copy, then click \"Done\""
//Hubitat cloud endpoint
//href url:"${getApiServerUrl()}/${hubUID}/apps/${app.id}/config?access_token=${state.accessToken}", style:"embedded", required:false, title:"Config", description:"Tap, select, copy, then click \"Done\""
//Hubitat local endpoint
href url:fullLocalApiServerUrl("config") + "?access_token=${state.accessToken}", style:"embedded", required:false, title:"Config", description:"Tap, select, copy, then click \"Done\""
}
section() {
paragraph "View the JSON generated from the installed devices."
//Original SmartThings cloud endpoint
//href url:"${apiServerUrl("/api/smartapps/installations/${app.id}/devices?access_token=${state.accessToken}")}", style:"embedded", required:false, title:"Device Results", description:"View accessories JSON"
//Hubitat cloud endpoint
//href url:"${getApiServerUrl()}/${hubUID}/apps/${app.id}/devices?access_token=${state.accessToken}", style:"embedded", required:false, title:"Device Results", description:"View accessories JSON"
//Hubitat local endpoint
href url:fullLocalApiServerUrl("devices") + "?access_token=${state.accessToken}", style:"embedded", required:false, title:"Device Results", description:"View accessories JSON"
}
section() {
paragraph "Enter the name you would like shown in the smart app list"
label title:"SmartApp Label (optional)", required: false
}
}
}
def renderDevices() {
def deviceData = []
deviceList.each {
try {
deviceData << [name: it.displayName,
basename: it.name,
deviceid: it.id,
status: it.status,
manufacturerName: it.getManufacturerName(),
modelName: it.getModelName(),
lastTime: it.getLastActivity(),
capabilities: deviceCapabilityList(it),
commands: deviceCommandList(it),
attributes: deviceAttributeList(it)
]
} catch (e) {
log.error("Error Occurred Parsing Device "+it.displayName+", Error " + e)
}
}
sensorList.each {
try {
deviceData << [name: it.displayName,
basename: it.name,
deviceid: it.id,
status: it.status,
manufacturerName: it.getManufacturerName(),
modelName: it.getModelName(),
lastTime: it.getLastActivity(),
capabilities: deviceCapabilityList(it),
commands: deviceCommandList(it),
attributes: deviceAttributeList(it)
]
} catch (e) {
log.error("Error Occurred Parsing Device "+it.displayName+", Error " + e)
}
}
switchList.each {
try {
deviceData << [name: it.displayName,
basename: it.name,
deviceid: it.id,
status: it.status,
manufacturerName: it.getManufacturerName(),
modelName: it.getModelName(),
lastTime: it.getLastActivity(),
capabilities: deviceCapabilityList(it),
commands: deviceCommandList(it),
attributes: deviceAttributeList(it)
]
} catch (e) {
log.error("Error Occurred Parsing Device "+it.displayName+", Error " + e)
}
}
return deviceData
}
def findDevice(paramid) {
def device = deviceList.find { it.id == paramid }
if (device) return device
device = sensorList.find { it.id == paramid }
if (device) return device
device = switchList.find { it.id == paramid }
return device
}
//No more individual device group definitions after here.
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
if(!state.accessToken) {
createAccessToken()
}
registerAll()
state.subscriptionRenewed = 0
subscribe(location, null, HubResponseEvent, [filterEvents:false])
log.debug "0.5.5"
}
def authError() {
[error: "Permission denied"]
}
def renderConfig() {
def configJson = new groovy.json.JsonOutput().toJson([
description: "JSON API",
platforms: [
[
platform: "SmartThings",
name: "SmartThings",
//
//Original SmartThings cloud endpoint
//app_url: apiServerUrl("/api/smartapps/installations/"),
//
//Hubitat cloud endpoint
//app_url: "${getApiServerUrl()}/${hubUID}/apps/",
//
//Hubitat local endpoint
app_url: getLocalApiServerUrl() + "/",
app_id: app.id,
access_token: state.accessToken
]
],
])
def configString = new groovy.json.JsonOutput().prettyPrint(configJson)
render contentType: "text/plain", data: configString
}
def renderLocation() {
[
latitude: location.latitude,
longitude: location.longitude,
mode: location.mode,
name: location.name,
temperature_scale: location.temperatureScale,
zip_code: location.zipCode,
hubIP: location.hubs[0].getDataValue("localIP"),
//hubIP: location.hubs[0].localIP,
smartapp_version: '0.5.5'
]
}
def CommandReply(statusOut, messageOut) {
def replyData =
[
status: statusOut,
message: messageOut
]
def replyJson = new groovy.json.JsonOutput().toJson(replyData)
render contentType: "application/json", data: replyJson
}
def deviceCommand() {
log.info("Command Request")
def device = findDevice(params.id)
def command = params.command
if (!device) {
log.error("Device Not Found")
CommandReply("Failure", "Device Not Found")
} else if (!device.hasCommand(command)) {
log.error("Device "+device.displayName+" does not have the command "+command)
CommandReply("Failure", "Device "+device.displayName+" does not have the command "+command)
} else {
def value1 = request.JSON?.value1
def value2 = request.JSON?.value2
try {
if (value2) {
device."$command"(value1,value2)
} else if (value1) {
device."$command"(value1)
} else {
device."$command"()
}
log.info("Command Successful for Device "+device.displayName+", Command "+command)
CommandReply("Success", "Device "+device.displayName+", Command "+command)
} catch (e) {
log.error("Error Occurred For Device "+device.displayName+", Command "+command)
CommandReply("Failure", "Error Occurred For Device "+device.displayName+", Command "+command)
}
}
}
def deviceAttribute() {
def device = findDevice(params.id)
def attribute = params.attribute
if (!device) {
httpError(404, "Device not found")
} else {
def currentValue = device.currentValue(attribute)
[currentValue: currentValue]
}
}
def deviceQuery() {
def device = findDevice(params.id)
if (!device) {
device = null
httpError(404, "Device not found")
}
if (result) {
def jsonData =
[
name: device.displayName,
deviceid: device.id,
capabilities: deviceCapabilityList(device),
commands: deviceCommandList(device),
attributes: deviceAttributeList(device)
]
def resultJson = new groovy.json.JsonOutput().toJson(jsonData)
render contentType: "application/json", data: resultJson
}
}
def deviceCapabilityList(device) {
def i=0
device.capabilities.collectEntries { capability->
[
(capability.name):1
]
}
}
def deviceCommandList(device) {
def i=0
device.supportedCommands.collectEntries { command->
[
(command.name): (command.arguments)
]
}
}
def deviceAttributeList(device) {
device.supportedAttributes.collectEntries { attribute->
try {
[
(attribute.name): device.currentValue(attribute.name)
]
} catch(e) {
[
(attribute.name): null
]
}
}
}
def getAllData() {
//Since we're about to send all of the data, we'll count this as a subscription renewal and clear out pending changes.
state.subscriptionRenewed = now()
state.devchanges = []
def deviceData =
[ location: renderLocation(),
deviceList: renderDevices() ]
def deviceJson = new groovy.json.JsonOutput().toJson(deviceData)
render contentType: "application/json", data: deviceJson
}
def startSubscription() {
//This simply registers the subscription.
state.subscriptionRenewed = now()
def deviceJson = new groovy.json.JsonOutput().toJson([status: "Success"])
render contentType: "application/json", data: deviceJson
}
def endSubscription() {
//Because it takes too long to register for an api command, we don't actually unregister.
//We simply blank the devchanges and change the subscription renewal to two hours ago.
state.devchanges = []
state.subscriptionRenewed = 0
def deviceJson = new groovy.json.JsonOutput().toJson([status: "Success"])
render contentType: "application/json", data: deviceJson
}
def registerAll() {
//This has to be done at startup because it takes too long for a normal command.
log.debug "Registering All Events"
state.devchanges = []
registerChangeHandler(deviceList)
registerChangeHandler(sensorList)
registerChangeHandler(switchList)
}
def registerChangeHandler(myList) {
myList.each { myDevice ->
def theAtts = myDevice.supportedAttributes
theAtts.each {att ->
subscribe(myDevice, att.name, changeHandler)
log.debug "Registering ${myDevice.displayName}.${att.name}"
}
}
}
def changeHandler(evt) {
//Send to Pubnub if we need to.
if (pubnubPublishKey!=null) {
def deviceData = [device: evt.deviceId, attribute: evt.name, value: evt.value, date: evt.date]
def changeJson = new groovy.json.JsonOutput().toJson(deviceData)
def changeData = URLEncoder.encode(changeJson)
def uri = "http://pubsub.pubnub.com/publish/${pubnubPublishKey}/${pubnubSubscribeKey}/0/${subChannel}/0/${changeData}"
log.debug "${uri}"
httpGet(uri)
}
if (state.directIP!="") {
//Send Using the Direct Mechanism
def deviceData = [device: evt.deviceId, attribute: evt.name, value: evt.value, date: evt.date]
//How do I control the port?!?
log.debug "Sending Update to ${state.directIP}:${state.directPort}"
def result = new hubitat.device.HubAction(
method: "GET",
path: "/update",
headers: [
HOST: "${state.directIP}:${state.directPort}",
change_device: evt.deviceId,
change_attribute: evt.name,
change_value: evt.value,
change_date: evt.date
]
)
//log.debug "changeHandler: sending result = ${result}"
sendHubCommand(result)
}
//Only add to the state's devchanges if the endpoint has renewed in the last 10 minutes.
if (state.subscriptionRenewed>(now()-(1000*60*10))) {
// if (evt.isStateChange()) {
log.debug "evt.getIsStateChange() = ${evt.getIsStateChange()}"
if (evt.getIsStateChange()) {
state.devchanges << [device: evt.deviceId, attribute: evt.name, value: evt.value, date: evt.date]
} else if (state.subscriptionRenewed>0) { //Otherwise, clear it
log.debug "Endpoint Subscription Expired. No longer storing changes for devices."
state.devchanges=[]
state.subscriptionRenewed=0
}
}
}
def getChangeEvents() {
//Store the changes so we can swap it out very quickly and eliminate the possibility of losing any.
//This is mainly to make this thread safe because I'm willing to bet that a change event can fire
//while generating/sending the JSON.
def oldchanges = state.devchanges
state.devchanges=[]
state.subscriptionRenewed = now()
if (oldchanges.size()==0) {
def deviceJson = new groovy.json.JsonOutput().toJson([status: "None"])
render contentType: "application/json", data: deviceJson
} else {
def changeJson = new groovy.json.JsonOutput().toJson([status: "Success", attributes:oldchanges])
render contentType: "application/json", data: changeJson
}
}
def enableDirectUpdates() {
log.debug("Command Request")
state.directIP = params.ip
state.directPort = params.port
log.debug("Trying ${state.directIP}:${state.directPort}")
def result = new hubitat.device.HubAction(
method: "GET",
path: "/initial",
headers: [
HOST: "${state.directIP}:${state.directPort}"
],
query: deviceData
)
sendHubCommand(result)
}
def HubResponseEvent(evt) {
log.debug(evt.description)
}
def locationHandler(evt) {
def description = evt.description
def hub = evt?.hubId
log.debug "cp desc: " + description
if (description.count(",") > 4)
{
def bodyString = new String(description.split(',')[5].split(":")[1].decodeBase64())
log.debug(bodyString)
}
}
def getSubscriptionService() {
def replyData =
[
pubnub_publishkey: pubnubPublishKey,
pubnub_subscribekey: pubnubSubscribeKey,
pubnub_channel: subChannel
]
def replyJson = new groovy.json.JsonOutput().toJson(replyData)
render contentType: "application/json", data: replyJson
}
mappings {
/* if (!params.access_token || (params.access_token && params.access_token != state.accessToken)) {
path("/devices") { action: [GET: "authError"] }
path("/config") { action: [GET: "authError"] }
path("/location") { action: [GET: "authError"] }
path("/:id/command/:command") { action: [POST: "authError"] }
path("/:id/query") { action: [GET: "authError"] }
path("/:id/attribute/:attribute") { action: [GET: "authError"] }
path("/subscribe") { action: [GET: "authError"] }
path("/getUpdates") { action: [GET: "authError"] }
path("/unsubscribe") { action: [GET: "authError"] }
path("/startDirect/:ip/:port") { action: [GET: "authError"] }
path("/getSubcriptionService") { action: [GET: "authError"] }
} else {
*/
path("/devices") { action: [GET: "getAllData"] }
path("/config") { action: [GET: "renderConfig"] }
path("/location") { action: [GET: "renderLocation"] }
path("/:id/command/:command") { action: [POST: "deviceCommand"] }
path("/:id/query") { action: [GET: "deviceQuery"] }
path("/:id/attribute/:attribute") { action: [GET: "deviceAttribute"] }
path("/subscribe") { action: [GET: "startSubscription"] }
path("/getUpdates") { action: [GET: "getChangeEvents"] }
path("/unsubscribe") { action: [GET: "endSubscription"] }
path("/startDirect/:ip/:port") { action: [GET: "enableDirectUpdates"] }
path("/getSubcriptionService") { action: [GET: "getSubscriptionService"] }
// }
}
Ok, another quick update. I was able to get the homebridge-smartthings plugin to communicate to Hubitat via the LAN using http (instead of https) by making two changes:
I added the change recommended by @pdlove
homebridge-smartthings/lib/smartthingsapi.js
Line 1 -> var http = require('https');
and had to change 443 to 80 in
Line 88 -> app_port = appURL.port || "80";
Here is the console output on my Raspberry Pi. Note that only devices in the 'all switches' group are properly recognized. Those in the 'sensor devices' or 'most devices' are never properly recognized by the plug-in.
pi@raspberrypi2:~/.homebridge $ homebridge WARNING The program 'node' uses the Apple Bonjour compatibility layer of Avahi. WARNING Please fix your application to use the native API of Avahi! WARNING For more information see http://0pointer.de/avahi-compat?s=libdns_sd&e=node WARNING The program 'node' called 'DNSServiceRegister()' which is not supported (or only supported partially) in the Apple Bonjour compatibility layer of Avahi. WARNING Please fix your application to use the native API of Avahi! WARNING For more information see http://0pointer.de/avahi-compat?s=libdns_sd&e=node&f=DNSServiceRegister [2018-2-14 20:39:51] Loaded plugin: homebridge-smartthings [2018-2-14 20:39:51] Registering platform 'homebridge-smartthings.SmartThings' [2018-2-14 20:39:51] --- [2018-2-14 20:39:51] Loaded config.json with 0 accessories and 1 platforms. [2018-2-14 20:39:51] --- [2018-2-14 20:39:51] Loading 1 platforms... [2018-2-14 20:39:51] [SmartThings] Initializing SmartThings platform... [2018-2-14 20:39:51] [SmartThings] Fetching Smart Things devices. [2018-2-14 20:39:51] [SmartThings] Device Skipped - Group unknown, Name Office Zigbee Contact Sensor, ID 33, JSON: {"name":"Office Zigbee Contact Sensor","basename":"Generic Zigbee Contact Sensor","deviceid":"33","status":"ACTIVE","manufacturerName":null,"modelName":null,"lastTime":null,"capabilities":{"TemperatureMeasurement":1,"Battery":1,"ContactSensor":1,"Configuration":1,"Refresh":1,"Sensor":1},"commands":{"configure":null,"enrollResponse":null,"refresh":null},"attributes":{"battery":88,"contact":"closed","temperature":72.67}} [2018-2-14 20:39:51] [SmartThings] Device Skipped - Group unknown, Name Office Zigbee Motion Sensor, ID 65, JSON: {"name":"Office Zigbee Motion Sensor","basename":"Generic Zigbee Motion Sensor","deviceid":"65","status":"ACTIVE","manufacturerName":null,"modelName":null,"lastTime":null,"capabilities":{"TemperatureMeasurement":1,"Battery":1,"MotionSensor":1,"Configuration":1,"Refresh":1,"Sensor":1},"commands":{"configure":null,"enrollResponse":null,"refresh":null},"attributes":{"battery":77,"motion":"inactive","temperature":72.87}} [2018-2-14 20:39:51] [SmartThings] Device Added - Group switch, Name Garage Overhead, ID 388 [2018-2-14 20:39:51] [SmartThings] Device Added - Group switch, Name Outside Backyard Floodlights, ID 453 [2018-2-14 20:39:51] [SmartThings] Device Added - Group switch, Name Outside Front Door Lights, ID 452 [2018-2-14 20:39:51] [SmartThings] Device Added - Group switch, Name Outside Frontyard Floodlights, ID 454 [2018-2-14 20:39:51] [SmartThings] Device Added - Group switch, Name Outside Garage Door Light, ID 364 [2018-2-14 20:39:51] [SmartThings] Unknown Capabilities: ["TemperatureMeasurement","ContactSensor","MotionSensor"] [2018-2-14 20:39:51] [SmartThings] Initializing platform accessory 'Garage Overhead'... [2018-2-14 20:39:51] [SmartThings] Initializing platform accessory 'Outside Backyard Floodlights'... [2018-2-14 20:39:51] [SmartThings] Initializing platform accessory 'Outside Front Door Lights'... [2018-2-14 20:39:51] [SmartThings] Initializing platform accessory 'Outside Frontyard Floodlights'... [2018-2-14 20:39:51] [SmartThings] Initializing platform accessory 'Outside Garage Door Light'... Setup Payload: X-HM://0023ISYWYCGDJ Scan this code with your HomeKit app on your iOS device to pair with Homebridge: . . . .
Or enter this code with your HomeKit app on your iOS device to pair with Homebridge: . . .
[2018-2-14 20:39:52] Homebridge is running on port 51826. [2018-2-14 20:39:52] [SmartThings] Direct Connect Is Listening On 192.168.1.145:8000 [2018-2-14 20:39:52] [SmartThings] SmartThings Hub Communication Established
Looks like Hubitat is stripping out spaces in the JSON devices data, causing any Capability that normally has a space in the name (e.g. "Temperature Measurement") to never match what /accessories/smartthings.js is looking for.
Not sure if it is best to try to fix this on the Hubitat "Complete JSON Api" side of things, or the /accessories/smartthings.js module. Thoughts?
I assume all the "Smartthings" logging on your RPI console is NOT smart things itself but rather hubitat?
Correct. I am trying to make as few changes to @pdlove 's homebridge-smartthings plug in as possible. Eventually a fork of this code may need to exist, where all of the hard-coded "SmartThings" references are replaced with "Hubitat". Hopefully, it will even be possible to run both the homebridge-smartthings and homebridge-hubitat plug-ins side by side on the same system.
The SmartThings plugin will require massive work as they get their own REST API to a point that we can use it. That said, I've also ordered a hubitat so I may have a more efficient integration coming up with that product.
I am all in on this concept. ST has proven too unreliable for me and from the device installs I have done with Hubitat the system works as advertised. Even disconnected my internet connection and still watched it all hum along beautifully.
I hope this can be done... from when I used your ST Homebridge integration I marveled at the speed in which Homekit handled commands through both the home app and Siri (much faster than Alexa/ST) and rightfully or wrongly attributed it to the fact that the apple tv was executing things locally.
If you can help get home kit integration into hubitat. Off the charts insane automation will be forthcoming.
I have the homebridge-smartthings plug-in working on Hubitat, EXCEPT for the Direct Update feature. It appears that the routine in index.js is having trouble parsing the “headers” portion of the GET request that is sent. I have asked the Hubitat developers for advice, since the data received from Hubitat must be different than what ST is sending for the exact same command in the JSON Complete API groovy app.
@JDogg016 the speed was due to having worked with the developers to optimize the speed as best as possible. I have low tolerance for delays between a motion detector picking up motion and an action occurring. With Smartthings, your IOS device communicates with the Homebridge Hub, which communicates with the cloud, which communicates with the Smartthings Hub which sends the update directly to Homebridge and back to IOS. Alexa simply replaces Homebridge with a cloud but there's still considerable delay (in my opinion) when using Alexa locally with the Hue Hub emulator that floating around on the web.
@ogiewon My hub will be in Monday. I'll get some devices on it and take a look. I'm also working on a proper project plan for the work I need to still do one homebridge-smartthings and homebridge in general. It's too big of a project for me to keep track of in my head anymore. I'll post a link when I have it.
I think you will be quite pleased with Hubitat. Also, I thought your ST-Homebridge integration was brilliant and I applaud the speed of that app and can't imagine the responsiveness if ported over to Hubitat. I'm sure if you can help there will be a bunch of us looking to "reimburse" you for your hubitat.
Interesting project. Can CoRE/webcore be run on hubitat too? I'd love to have a 100% local solution as ST outages seem to be on the rise.
Technically, sure you could get CoRE to run...maybe even webCoRE...but it will require a very good ST/Hubitat groovy programmer...
I've half-way started a hubitat-dedicated project. I'm having trouble with my ZWave devices on it so I haven't gotten very far. I do have a few Zigbee lights on it and, while it has a long way to go, it's a great concept. I'll reference the other project here when I get it uploaded this weekend. Basically it will, in it's current state, use a modified smartapp to get the device information but updates will be streamed straight from the hub via web sockets. I'm working on extracting the device information straight from the hub and the only issue I'm having is that the capabilities aren't exposed on any of the web pages so I can't just scrape it from the html.
This looks very useful and far more sophisticated than the kludge I wrote for my use on SmartThings. What is the status of this project. (I tried to install it on SmartThings but ran into problems -- will get back to it when I have time to delve more).
I'm interested as well, and would be game to help.
@tooluser - This has already been completed for Hubitat by @tonesto7
Take a look here
https://community.hubitat.com/t/homebridge-plug-in/1155?u=ogiewon
Hubitat port of this is available at https://github.com/tonesto7/homebridge-hubitat-tonesto7. Therefore, I am closing this issue for now.
@ogiewon Thanks for taking the time to reply, it's hard to follow the maze of existing work - that helped immensely!
This appears to be tied to home bridge -- is there documentation on the message format and how to automatically report on any new devices that are added to the system?
Paul,
I would love to see a version of homebridge-smartthings revised to work on the new Hubitat Elevation Hub. This new hub was designed by a team of very capable SmartThings users, so the new system is very backwards compatible with existing SmartThings groovy code. One of the major advantage of this new system is that everything runs locally on the hub, resulting is excellent performance. It exposes both local and cloud OAUTH endpoints, so Homebridge should be able to communicate on the local LAN. This would result in excellent performance.
I have attempted to modify the JSON Complete API SmartApp to run on the Hubitat Hub. It successfully compiles and does run. I have modified a few sections to add the Hubitat endpoints (showing both the cloud and local endpoints). Unfortunately, the hub does not appear to support HTTPS encrypted traffic on the local network (i.e. connection refused error using https). The cloud endpoint does, of course, support https. I am not sure how to modify the homebridge-smartthings plugin to allow for unencrypted local traffic. I was able to get the homebridge-smartthings plugin to work somewhat, using the Hubitat cloud endpoint, just for testing. However, only devices in the "switch" group showed up in Homekit on my iPhone. The other devices all were listed as not belonging to a group. The two "switch" devices did show up in Homekit on my phone, and I could control them!
So, it seems like it is very close to working. Since Hubitat currently does not really have a native user interface (i.e. no smartphone app exists), having Homebridge running with a fast local LAN connection would be a very welcome option to iOS users.
Thoughts? Want to take on a challenge that right up your alley? ;)
Dan
Here is my modified version of your SmartApp that I have been testing with on Hubitat. [Update 2/11/2018: I figured out how to determine the Hubitat hub's local IP address on the fly without user input. Version below has been updated accordingly.