Harmony Hub Integration

I do have issues with the ST port that persist on hubitat and I was hoping the api solution would alleviate it.

I realistically just need to understand where the docker install would mount (ie. docker/jonmaxxon/harmony-api

When installing a docker by command line, docker automatically installs the files into the correct directory.

In synology, unfortunately, you have to tell docker where to put the files.

Can you tell me (on your RPI) the name of the directory containing the docker for the harmony-api?

I have never used docker. I installed harmony-api as a Linux service. First on a Raspberry Pi, and later on Ubuntu.

Are the hubs on the same account? The app is pulling a list of hubs from Harmony servers so it shouldn't be any local issue finding the hubs. If the hubs are on multiple accounts, you can try changing line 54 singleInstance to false and installing another instance of the app on a different account.

Yes, the hubs are on the same account. It may be a harmony issue as well and not ST, but the hubitat app will not find all my hubs.

Harmony however does.

@mattw , @ogiewon do either of you see status updates on your Harmony devices in Hubitat when you turn on/off via the remote control (or anything other than Hubitat)? If I turn off via Alexa (direct integration) or my remote, it does not automatically sync to my Hubitat devices. Not a big deal but I was just curious if you both were seeing this as well and also if you found a workaround. I was considering making a rule that refreshes the hub device every minute or so.

I see the exact same thing. However, if you wait long enough, it should synchronize. In fact, I see the exact same behavior within SmartThings.

The biggest downside I can see for this is that you cannot use the status of the Harmony Activity switch devices to trigger other actions within Hubitat as there is too much of a delay (up to 5 minutes).

Here is the section of code which appears to be called every 5 minutes (there is a runIn(5, ...) command in the second routine below. I guess you could just reduce this time to every 1 minute, but you will be hitting the Logitech server 5 times more frequently.

def poll() {
	// GET THE LIST OF ACTIVITIES
    if (state.HarmonyAccessToken) {
        def tokenParam = [auth: state.HarmonyAccessToken]
        def params = [
            uri: "https://home.myharmony.com/cloudapi/state?${toQueryString(tokenParam)}",
            headers: ["Accept": "application/json"],
            contentType: 'application/json'
        ]
        //asynchttp_v1.get('pollResponse', params)
        httpGet(params) { response -> pollResponse(response) }
        
      } else {
        log.warn "Harmony - Access token has expired"
      }
}

def pollResponse(response) {
	if (response.status != 200) {
	    log.error "Harmony - response has error: $response.errorMessage"
	    if (response.status == 401) { // token is expired
			state.remove("HarmonyAccessToken")
			log.warn "Harmony - Access token has expired"
	    }
	} else {
		def ResponseValues
		try {
			// json response already parsed into JSONElement object
			ResponseValues = response.data
		} catch (e) {
			log.error "Harmony - error parsing json from response: $e"
		}
		if (ResponseValues) {
	        def map = [:]
	        ResponseValues.hubs.each {
		        // Device-Watch relies on the Logitech Harmony Cloud to get the Device state.
		        def isAlive = it.value.status
		        def d = getChildDevice("harmony-${it.key}")
		        d?.sendEvent(name: "DeviceWatch-DeviceStatus", value: isAlive!=504? "online":"offline", displayed: false, isStateChange: true)
		        if (it.value.message == "OK") {
					map["${it.key}"] = "${it.value.response.data.currentAvActivity},${it.value.response.data.activityStatus}"
					def hub = getChildDevice("harmony-${it.key}")
					if (hub) {
						if (it.value.response.data.currentAvActivity == "-1") {
							hub.sendEvent(name: "currentActivity", value: "--", descriptionText: "There isn't any activity running", displayed: false)
						} else {
							def currentActivity
							def activityDTH = getChildDevice("harmony-${it.key}-${it.value.response.data.currentAvActivity}")
							if (activityDTH)
								currentActivity = activityDTH.device.displayName
							else
								currentActivity = getActivityName(it.value.response.data.currentAvActivity,it.key)
							hub.sendEvent(name: "currentActivity", value: currentActivity, descriptionText: "Current activity is ${currentActivity}", displayed: false)
						}
					}
	          	} else {
	            	log.trace "Harmony - error response: $it.value.message"
	          	}
        	}
	        def activities = getChildDevices()
	        def activitynotrunning = true
	        activities.each { activity ->
	            def act = activity.deviceNetworkId.split('-')
	            if (act.size() > 2) {
	                def aux = map.find { it.key == act[1] }
	                if (aux) {
	                    def aux2 = aux.value.split(',')
	                    def childDevice = getChildDevice(activity.deviceNetworkId)
	                    if ((act[2] == aux2[0]) && (aux2[1] == "1" || aux2[1] == "2")) {
                            if(childDevice?.currentSwitch != "on")
	                        	childDevice?.sendEvent(name: "switch", value: "on")
	                        if (aux2[1] == "1")
	                            runIn(5, "poll", [overwrite: true])
	                    } else {
                            if(childDevice?.currentSwitch != "off")
	                        	childDevice?.sendEvent(name: "switch", value: "off")
	                        if (aux2[1] == "3")
	                            runIn(5, "poll", [overwrite: true])
	                    }
	                }
	            }
	        }
		} else {
			log.debug "Harmony - did not get json results from response body: $response.data"
		}
	}
}
2 Likes

Yeah, unfortunately the API is polling based. When I first started looking at it I checked the API documentation to see if there was anything SmartThings didn’t implement. There wasn’t anything available that’s event based.

I was going to double check the documentation again, but it looks like Logitech has abandoned it, most likely in their transition to a new site layout. It wasn’t even “official” anyways since it was just a link to a Google doc.

You can change the polling interval in the runIn command that @ogiewon mentioned. I didn’t try any other value than 5 minutes from the original SmartThings code. Not sure if there’s any rate limit on the Harmony API but worth a shot.

If you do want something that’s more event based, a possible solution is to use a smart outlet with power reporting. Then have a condition if wattage > threshold call poll() This won’t catch everything though if you switch activities which don’t have a large wattage change. I don’t think the poll() command is exposed right now but should be easy to change.

2 Likes

I notice harmony events in my log and I dont have any apps installed at all. Under hub events

ssdbTemp urn:myharmony-com:device:harmony:1

I see many other ssdpTemp devices I’m assuming these are all just the other network devices such as sonos, smart TV, etc.

Has anyone actually tried changing this polling interval to see if it causes issues? I'd love to decrease the delay somewhat in my setup.

I thought of another workaround, but it requires SmartThings (since it’s one of the supported integrations). Create virtual switches in ST, then on your Harmony settings, head to Devices, add Home Control > SmartThings > authorize these virtual switches. In each activity add control for your virtual activity switch (turn on at start, off at end). Use the Hubitat™ SmartThings Integration to access these switches on Hubitat. You can use one switch if you just need to know when any activity is on, or individual switches per activity.

These will be “read only” switches, but at least you can respond to events quicker.

Exactly what I was doing already. Was just hoping to finally do away with ST completely.

I'll stick with my current configuration if playing the polling rate could cause issues unless someone else has had success with it.

I still have the issue of Harmony recognizing my hubs. This has gone one since ST.

Are you referring to the ST Harmony integration not finding your Logitech Harmony Hub?

If so, do you think it could also be related to your Alexa discovery issues?

If so, it sure seems like you have some sort of a LAN issue… :wink:

Just a heads up...

If your Harmony Hub is slow to respond to commands from your remote control, please know that the issue has been identified as a Logitech problem. Cycling the power on your Harmony Hub appears to fix the issue, at least temporarily.

https://community.logitech.com/s/question/0D55A00007Vv0XESAZ/harmony-hub-based-remotes-lag-latency-when-controlling-devices

Yup...had this issue last night. A reboot fixed it for me. Didn't realize it was a widespread issue

Same here. Power cycled the remote and hub last night and everything went back to normal.

Had to recycle a few times too. But it seems to fix it. I feel sorry for their support teams today.

Just came here wondering what was up with my Harmony Integration. Good to know. Thanks for sharing.

Thanks I thought I was losing my mind fighting with Alexa to turn my xbox or tv on last night .. I did power cycle out of ... well ... desperation and it did the trick for a while...

Today seems much better

I had the same thing happen, but only on one of my three harmony hubs. power cycle fixed it for me. my harmony hub is still connected to smartthings, but the devices in smartthings are gone, so I thought it might be an issue with that. glad it wasn't!