Here is what I have been using for the past few months to integrate with my MyQ garage door opener. This script is not optimized, but it works well for me, and I am lazy…
Put this script in a package called myq. Enclosed is a reference tag implementation. You will have to make an instance of the tag, and set the device parameter equal to your devices serial number.
tags.json (6.0 KB)
Script
class MyQ():
#This appid can be anything.... i believe
appId = 'Vj8pQggXLhLy0WHahglCD4N1nAkkXQtGYpq2HrHD7H1nvmbT55KqtN6RSF4ILB/i'
agent = 'myQ/19569 CFNetwork/1107.1 Darwin/19.0.0'
username = "yourmyqusername"
password = "yourmyqpassword"
apiVersion = 5
endpoint = 'https://api.myqdevice.com/api/v{}'.format(apiVersion)
client = system.net.httpClient()
security_token = None
accountId = None
LOG = system.util.getLogger("com.thundranos.myq")
last_update = system.date.fromMillis(0)
status_code = None
headers = {
"Content-Type": "application/json",
"User-Agent": agent,
"ApiVersion": 5,
"BrandId": "2",
"Culture": "en",
"MyQApplicationId": appId,
"SecurityToken": ""
};
def login(self,username=None,password=None,force = False):
if username:
self.username = username
if password:
self.password = password
if not self.security_token or force:
if self.username and self.password:
url = self.endpoint + "/Login"
response = self.client.post(url = url, data = {"UserName":self.username,"Password":self.password},headers=self.headers)
self.status_code = response.statusCode
if response.statusCode == 200:
self.security_token = response.getJson()["SecurityToken"]
self.headers['SecurityToken'] = response.getJson()["SecurityToken"]
self.getAccountId()
def getAccountId(self):
if not self.accountId:
url = self.endpoint + "/My?expand=account"
response = self.client.get(url = url,headers=self.headers)
self.status_code = response.statusCode
if response.statusCode == 200:
self.accountId = response.json["Account"]["Id"]
def getSecurityToken(self):
return self.security_token
def updateState(self):
if self.status_code != 200:
self.login()
if self.security_token and self.accountId:
url = self.endpoint + '.1/Accounts/{}/Devices'.format(self.accountId)
response = self.client.get(url = url,headers=self.headers)
self.status_code = response.statusCode
state = {}
for item in response.json["items"]:
state[str(item["serial_number"])] = item
self.state = state
self.last_update = system.date.now()
def getState(self,device=None,state=None,force = False):
if force or system.date.secondsBetween(self.last_update,system.date.now())>60:
self.updateState()
if device:
if state:
return self.state[device]["state"][state]
return self.state[device]
return self.state
def setDoorState(self,device,state):
data = {"action_type":"open" if state else "close"}
self.LOG.info('device:{} state:{}'.format(device,state))
if self.status_code != 200:
self.login()
if self.security_token and self.accountId:
self.LOG.info("here")
url = self.endpoint + '.1/Accounts/{}/Devices/{}/actions'.format(self.accountId,device)
response = self.client.put(url=url, data=data, headers=self.headers)
myq = MyQ()
So, to get started, you will want to find the serial number of your myq device, in the resulting JSON from the following. You will see numerous devices listed including the gateway and the door opener. You will need to note the serial number.
myq.myq.login()
myq.myq.getState()
For the tag bindings, I do the following. This will give me the door value. For the scan rate, we check every second. Internally, the script will update every 60 seconds, unless force is set to true, then it will update every time the function is called. At home, I have the scan tag true for 30s after any action, for higher speed querying.
runScript("myq.myq.getState",1000,"yourserialnumber","door_state",{[.]../../metadata/scan})
To open or close the door, invoke the following script.
myq.myq.setDoorState("yourdeviceserialnumber",desiredstate)
Where desiredstate
False = close
True = open