# Connecting to Smart Home Devices

**URL:** <https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771>\
**Category:** Maker\
**Created:** [March 23, 2021, 3:31am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771 "2021-03-23T03:31:24Z")\
**Posts on this page:** 14\
**Page:** 2

<div class="post-metadata">

**Author:** ![matthew.ayre](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/matthew.ayre/32/19499_2.png) [@matthew.ayre](https://forum.inductiveautomation.com/u/matthew.ayre)\
**Post date:** [May 6, 2021, 7:08pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/21 "2021-05-06T19:08:16Z")

</div>

@dkhayes117, good to hear. If your feeling generous please share the code (either on another thread or on the Exchange (could have a chance at winning the [Exchange Challenge](https://inductiveautomation.com/blog/icc-2021-evolving-the-virtual-experience)))

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [May 6, 2021, 7:50pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/22 "2021-05-06T19:50:58Z")

</div>

I will post it when completed. What would be really cool for the winner of the exchange competition would be a special badge on the forum that would show beside your username 😀.

---

<div class="post-metadata">

**Author:** ![nminchin](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/nminchin/32/6911_2.png) [@nminchin](https://forum.inductiveautomation.com/u/nminchin)\
**Post date:** [May 7, 2021, 7:07am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/23 "2021-05-07T07:07:03Z")

</div>

As long as the next competition is made open internationally!!

---

<div class="post-metadata">

**Author:** ![Kallie\_Winners1](https://avatars.discourse-cdn.com/v4/letter/k/91b2a8/32.png) [@Kallie\_Winners1](https://forum.inductiveautomation.com/u/Kallie_Winners1)\
**Post date:** [December 2, 2022, 11:25pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/25 "2022-12-02T23:25:48Z")

</div>

did you ever get this working with the Ecobee? I'm working on a similar project.

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [December 3, 2022, 12:43am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/26 "2022-12-03T00:43:02Z")

</div>

Yes it works, but it has been a while since I've gotten to work on it. I'll post some code when I have time if you'd like.

Also, welcome to the community!

---

<div class="post-metadata">

**Author:** ![Kallie\_Winners1](https://avatars.discourse-cdn.com/v4/letter/k/91b2a8/32.png) [@Kallie\_Winners1](https://forum.inductiveautomation.com/u/Kallie_Winners1)\
**Post date:** [December 26, 2022, 4:00am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/27 "2022-12-26T04:00:42Z")

</div>

Thank you!

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [December 29, 2022, 8:31pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/28 "2022-12-29T20:31:21Z")

</div>

This is a ways off from being completed. My functions can be polished more, I basically wrote each one to work individually and was going to go back and combine some functionality, which I haven't done yet. When it is more polished, I will probably post the whole project on Ignition Exchange.

I have my api tokens and authorization stuff held in tags, which is not very secure. When I'm done with the functionality, I plan on storing those with encryption. Note it has been a while since these have been fully tested. Also note that you have to setup an ecobee dev account before you can use the APIs, [ecobee API](https://www.ecobee.com/home/developer/api/introduction/index.shtml)

```python
def getAuthorization():
	import system
	apiKey = system.tag.readBlocking('[default]Ecobee/APIKey').value
	params = {"response_type":"ecobeePin", "client_id":apiKey, "scope":"smartWrite"}
	#url = "https://api.ecobee.com/authorize?response_type=ecobeePin&client_id=%s&scope=smartWrite" % apiKey
	url = "https://api.ecobee.com/authorize"
	response = http.client.post(url=url, params = params)	
	json = response.getJson()
	tags = ['[default]Ecobee/AuthCode','[default]Ecobee/Pin']
	values = [json['code'],json['ecobeePin']]
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################

def getTokens():
	import system
	tags = ['[default]Ecobee/AuthCode','[default]Ecobee/APIKey']
	values = system.tag.readBlocking(tags)
	authCode = values[0].value
	apiKey = values[1].value	
	url = "https://api.ecobee.com/token"	
	postData = "grant_type=ecobeePin&code=%s&client_id=%s" % (authCode, apiKey)
	response = system.net.httpPost(url=url,postData=postData)
	json = system.util.jsonDecode(response)	
	tags = ['[default]Ecobee/Access Timeout','[default]Ecobee/Access Token', '[default]Ecobee/Refresh Token']
	values = [json['expires_in'],json['access_token'],json['refresh_token']]
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################

def refreshTokens():
	import system
	tags = ['[default]Ecobee/Refresh Token','[default]Ecobee/APIKey']
	values = system.tag.readBlocking(tags)
	refreshToken = values[0].value
	apiKey = values[1].value	
	params = {"grant_type":"refresh_token", "refresh_token":refreshToken, "client_id":apiKey, "ecobee_type":"jwt"}
	url = "https://api.ecobee.com/token"
	response = http.client.post(url=url,params=params)
	json = response.getJson()
	tags = ['[default]Ecobee/Access Timeout','[default]Ecobee/Access Token', '[default]Ecobee/Refresh Token']
	values = [json['expires_in'],json['access_token'],json['refresh_token']]
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################

def getRunTimeInfo():
	import system
	raw = system.tag.readBlocking('[default]Ecobee/Access Token')
	accessToken = raw[0].value
	headers = {'Content-Type': 'text/json','Authorization':'Bearer %s' % accessToken} 
	params = {"format":"json","body":{"selection":{"selectionType":"registered","selectionMatch":"","includeRuntime":"true"}}} #"includeAlerts":true
	
	url = 'https://api.ecobee.com/1/thermostat'
	response = http.client.get(url, params = params, headers=headers)
	json = response.getJson()	
	tags = []
	values = []
			
	for key in json['status']:
		tags.append('[default]Ecobee/API Return %s' % key)
		values.append(json['status'][key])
		
	for thermostat in json['thermostatList']:
		name = thermostat['name']
		baseTagPath = '[default]Ecobee/Thermostats/%s/Runtime/' % name
		
		for key in thermostat['runtime']:
			tags.append(baseTagPath + key)
			values.append(thermostat['runtime'][key])
			
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################

def getSettingsInfo():
	import system
	raw = system.tag.readBlocking('[default]Ecobee/Access Token')
	accessToken = raw[0].value
	headers = {"Content-Type": "text/json","Authorization":"Bearer %s" % accessToken} 
	params = {"format":"json", "body":{"selection":{"selectionType":"registered","selectionMatch":"","includeSettings":"true"}}} #"includeAlerts":true

	url = 'https://api.ecobee.com/1/thermostat'
	response = http.client.get(url, params=params, headers=headers)
	json = response.getJson()		
	tags = []
	values = []
		
	for key in json['status']:
		tags.append('[default]Ecobee/API Return %s' % key)
		values.append(json['status'][key])
		
	for thermostat in json['thermostatList']:
		name = thermostat['name']
		baseTagPath = '[default]Ecobee/Thermostats/%s/Settings/' % name
		
		for key in thermostat['settings']:
			tags.append(baseTagPath + key)
			values.append(thermostat['settings'][key])
			
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################
		
def getStatus():
	import system
	raw = system.tag.readBlocking('[default]Ecobee/Access Token')
	accessToken = raw[0].value
	headers = {'Content-Type': 'text/json','Authorization':'Bearer %s' % accessToken} 
	params = {"format":"json", "body":{"selection":{"selectionType":"registered","selectionMatch":"","includeEquipmentStatus":"true"}}} #"includeAlerts":true
	
	url = 'https://api.ecobee.com/1/thermostat' % body
	response = http.client.get(url, params=params, headers=headers)
	json = response.getJson()	
	tags = []
	values = []	
				
	for key in json['status']:
		tags.append('[default]Ecobee/API Return %s' % key)
		values.append(json['status'][key])
	
	for thermostat in json['thermostatList']:
		name = thermostat['name']
		baseTagPath = '[default]Ecobee/Thermostats/%s/' % name
		
		for key in thermostat:
			if key != 'name':
				tags.append(baseTagPath + key)
				values.append(thermostat[key])
			
	system.tag.writeBlocking(tags,values)
##########################################################################################################################################

def setTempHold(newHoldTemp, thermostatName, holdType, **kwargs):
	'''
		Args: newHoldTemp = temperature to hold at (must be between thermostat temp ranges)
			  thermostatName = Name of the thermostat to apply hold to
			  holdType = Type of hold ('dateTime', 'nextTranistion', 'indefinte', 'holdHours')
			  **kwargs = For optional arguments
			  			 optional args:
			  			 	startDate, startTime, endDate, endTime = required for 'dateTime' hold type, when to start and stop the temp hold
			  			 	fanSpeed = speed options (LOW, MEDIUM, HIGH, and OPTIMIZED
			  			 	holdHours = required for 'holdHours' hold type, how long to hold temp
			  kwargs is a dictionary. To use kwargs the arguments must be defined in the call 
			  example: ecobee.setTempHold(70, 'Main Floor', 'holdHours', holdHours = 2)			 	
	'''
	import system
		
	if holdType == 'dateTime':
		reqKeys = ('startDate','startTime','endDate', 'endTime')
		if not all(key in kwargs for key in reqKeys):
			# write to status tags 
			return
	elif holdType == 'holdHours':
		if 'holdHours' not in kwargs:
			# write to status tags 
			return	
	
	newHoldTemp *= 10	# Multiple temp by 10 because 700 = 70.0 deg
	keys = ['coolRangeHigh','coolRangeLow','heatRangeHigh','heatRangeLow', 'heatCoolMinDelta', 'hvacMode'] 
	tags = []
	for key in keys:
		tags.append('[default]Ecobee/Thermostats/%s/Settings/%s' % (thermostatName,key))
	tags.append('[default]Ecobee/Access Token')
	values = system.tag.readBlocking(tags)
	coolHigh = values[0].value
	coolLow = values[1].value
	heatHigh = values[2].value
	heatLow = values[3].value
	minDelta = values[4].value 
	hvacMode = values[5].value
	accessToken = values[6].value
	
	coolHold = heatHold = newHoldTemp	# Recommended that coolHold = heatHold
	
	if hvacMode == 'auto': # If hvacMode equals auto, cool hold should minDelta higher than heat hold
		coolHold += minDelta
		
	if coolLow <= coolHold <= coolHigh and heatLow <= heatHold <= heatHigh:	# Hold must be inside range
		reqDict = {'holdType':holdType, 'heatHoldTemp':heatHold, 'coolHoldTemp':coolHold}
		newDict = reqDict.copy()
		newDict.update(kwargs)
		dataParams = system.util.jsonEncode(newDict)

		data = {
			  "selection": {
				"selectionType":"registered",
				"selectionMatch":thermostatName
			  },
			  "functions": [
				{
				  "type":"setHold",
				  "params": dataParams
				}
			  ]
			} 
		
		headers = {"Content-Type": "application/json;charset=UTF-8","Authorization":"Bearer %s" % accessToken}
		params = {"format":"json"}
		url = 'https://api.ecobee.com/1/thermostat'
		response = http.client.post(url, headers=headers, data=data)	
		print response.getText()
	else:
		pass
		# Add script to write to status tag with error message
##########################################################################################################################################

def resumeProgram(thermostatName):
	import system
	raw = system.tag.readBlocking('[default]Ecobee/Access Token')
	accessToken = raw[0].value
	data = {
		  "selection": {
			"selectionType":"registered",
			"selectionMatch":thermostatName
		  },
		  "functions": [
			{
			  "type":"resumeProgram",
			  "params":{
				"resumeAll":"false"
			  }      
			}
		  ]
		}
	headers = {"Content-Type":"text/json","Authorization":"Bearer %s" % accessToken}
	params = {"format":"json"}
	url = 'https://api.ecobee.com/1/thermostat'
	response = http.client.post(url, params=params, headers=headers, data=data)	
	
##########################################################################################################################################

def getEvents():
	import system
	raw = system.tag.readBlocking('[default]Ecobee/Access Token')
	accessToken = raw[0].value
	headers = {'Content-Type': 'text/json','Authorization':'Bearer %s' % accessToken} 
	params = {"format":"json","body":{"selection":{"selectionType":"registered","selectionMatch":"","includeEvents":"true"}}} #"includeAlerts":true
	
	url = 'https://api.ecobee.com/1/thermostat'
	response = http.client.get(url=url, params=params, headers=headers)
	print response.getText()

```

---

<div class="post-metadata">

**Author:** ![WChester](https://avatars.discourse-cdn.com/v4/letter/w/df788c/32.png) [@WChester](https://forum.inductiveautomation.com/u/WChester)\
**Post date:** [January 1, 2023, 8:15pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/29 "2023-01-01T20:15:46Z")

</div>

I know this is an old thread but I've encountered some difficulties with this.

1. It is implied that the auth code remains the same. I have not found that to be the case and I find that I have to request access or I get IOError: Server returned HTTP response code: 400 for URL: [https://www.googleapis.com/oauth2/v4/token](https://www.googleapis.com/oauth2/v4/token) unless I go through the access request process again. Even when I am trying to refresh the token.

2. I kept getting an error in the getToken script as the response could not be parsed until I stripped all of the newline,tabs and whitespaces.  
I will continue to poke around at this but am curious if I am doing something wrong.  
I modified the getToken and refreshToken Script to use the system.net.getClient() and that works really good..

---

<div class="post-metadata">

**Author:** ![WChester](https://avatars.discourse-cdn.com/v4/letter/w/df788c/32.png) [@WChester](https://forum.inductiveautomation.com/u/WChester)\
**Post date:** [January 22, 2023, 12:23am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/30 "2023-01-22T00:23:23Z")

</div>

I did get this to work. The only problem is the refresh token expires every 7 days so I'm working on that now.

---

<div class="post-metadata">

**Author:** ![swolnisty](https://avatars.discourse-cdn.com/v4/letter/s/7bcc69/32.png) [@swolnisty](https://forum.inductiveautomation.com/u/swolnisty)\
**Post date:** [January 23, 2023, 6:54pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/31 "2023-01-23T18:54:47Z")

</div>

Interesting. I wonder if that refresh token expiration timeframe is a recent change? Admittedly, I haven't touched this code in probably a year and a half and I haven't been checking if it works either. I find that Home Assistant works well enough for the majority of my home automation needs that I haven't bothered doing much with Ignition other than using it to log aquarium water parameters into a database whenever I test my tank's water.

---

<div class="post-metadata">

**Author:** ![WChester](https://avatars.discourse-cdn.com/v4/letter/w/df788c/32.png) [@WChester](https://forum.inductiveautomation.com/u/WChester)\
**Post date:** [January 24, 2023, 12:57am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/32 "2023-01-24T00:57:37Z")

</div>

I've read it happening to other people. There is a way to publish the project that eliminates it, but I'm not worried about that now. I've actually have setup up data flow and am pretty happy right now. I also am going to attempt to pull live feeds on our camera's.

---

<div class="post-metadata">

**Author:** ![kyvislabs](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kyvislabs/32/26325_2.png) [@kyvislabs](https://forum.inductiveautomation.com/u/kyvislabs)\
**Post date:** [January 28, 2023, 1:16am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/33 "2023-01-28T01:16:07Z")

</div>

When are you implementing the Ecobee integration with the [Kyvis Labs API Client Module](https://forum.inductiveautomation.com/t/kyvis-labs-api-client-module/69120)?

---

<div class="post-metadata">

**Author:** ![dkhayes117](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/dkhayes117/32/68344_2.png) [@dkhayes117](https://forum.inductiveautomation.com/u/dkhayes117)\
**Post date:** [January 30, 2023, 1:08pm UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/34 "2023-01-30T13:08:11Z")

</div>

Wow, very interesting. I'll definitely have to check it out.

---

<div class="post-metadata">

**Author:** ![Wolfienary\_Alex](https://avatars.discourse-cdn.com/v4/letter/w/90db22/32.png) [@Wolfienary\_Alex](https://forum.inductiveautomation.com/u/Wolfienary_Alex)\
**Post date:** [November 13, 2024, 5:29am UTC](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771/35 "2024-11-13T05:29:35Z")

</div>

I totally get your struggle with Google’s OAuth2 process—it’s no joke! I ran into the same roadblocks while trying to connect my devices through Google Home, and honestly, it felt like they assumed everyone had a commercial-level setup.

[Previous page](https://forum.inductiveautomation.com/t/connecting-to-smart-home-devices/44771.md?page=1)
