From 54ff7ecd0b87e59606de1305a2e550793f163fca Mon Sep 17 00:00:00 2001 From: DewGew Date: Fri, 5 May 2023 07:07:57 +0200 Subject: [PATCH 1/9] Fixes NoneType has no 'domain' --- smarthome.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/smarthome.py b/smarthome.py index 73bac92..7cdb8b5 100644 --- a/smarthome.py +++ b/smarthome.py @@ -652,6 +652,8 @@ def execute(self, command, params, challenge): def async_update(self): """Update the entity with latest info from Domoticz.""" + if not self.state: + return if self.state.domain == DOMAINS['group'] or self.state.domain == DOMAINS['scene']: getDevices('scene') From 11f92f4311e6fde41d3b5f111e07aedda56b72d2 Mon Sep 17 00:00:00 2001 From: DewGew Date: Fri, 5 May 2023 07:17:08 +0200 Subject: [PATCH 2/9] no aogDevs present while processing action.devices.QUERY --- smarthome.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/smarthome.py b/smarthome.py index 7cdb8b5..24ded11 100644 --- a/smarthome.py +++ b/smarthome.py @@ -5,6 +5,7 @@ import re import subprocess import sys +import time import yaml from collections.abc import Mapping from itertools import product @@ -389,6 +390,7 @@ def getAog(device): return aog +aogDevsReady = False aogDevs = {} deviceList = {} @@ -457,6 +459,7 @@ def deep_update(target, source): def getSettings(): """Get domoticz settings.""" global settings + global aogDevsReady url = DOMOTICZ_URL + DOMOTICZ_GET_SETTINGS_URL r = requests.get(url, auth=CREDITS) @@ -469,7 +472,8 @@ def getSettings(): settings['Language'] = devs['Language'] getVersion() - + aogDevsReady = True + logger.debug(json.dumps(settings, indent=2, sort_keys=False, ensure_ascii=False)) def getVersion(): @@ -1024,9 +1028,11 @@ def smarthome_sync(self, payload, token): https://developers.google.com/actions/smarthome/create-app#actiondevicessync """ devices = [] + aogDevsReady = False # lock smarthome_query while reloading devices aogDevs.clear() getDevices() # sync all devices getSettings() + agent_user_id = token.get('userAgentId', None) for state in aogDevs.values(): @@ -1049,7 +1055,12 @@ def smarthome_query(self, payload, token): """ response = {} devices = {} - + + loopCount = 5 + while (loopCount>0 and not aogDevsReady): # whait for 5 seconds if aogDevs array is refreshed + time.sleep(1) + loopCount -= 1 + for device in payload.get('devices', []): devid = device['id'] _GoogleEntity(aogDevs.get(devid, None)).async_update() @@ -1092,6 +1103,7 @@ def smarthome_exec(self, payload, token): if entity_id not in entities: if len(aogDevs) == 0: + aogDevsReady = False getDevices() getSettings() From cf064058cfb1d6fa120d6a6fee67f3272309f9aa Mon Sep 17 00:00:00 2001 From: DewGew Date: Fri, 5 May 2023 07:32:54 +0200 Subject: [PATCH 3/9] Fix that each device should have status field set --- smarthome.py | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/smarthome.py b/smarthome.py index 24ded11..6671557 100644 --- a/smarthome.py +++ b/smarthome.py @@ -592,7 +592,7 @@ def query_serialize(self): # if state.state == STATE_UNAVAILABLE: # return {'online': False} - attrs = {'online': True} + attrs = {'online': True, 'status': "SUCCESS"} for trt in self.traits(): deep_update(attrs, trt.query_attributes()) @@ -1067,7 +1067,7 @@ def smarthome_query(self, payload, token): state = aogDevs.get(devid, None) if not state: # If we can't find a state, the device is offline - devices[devid] = {'online': False} + devices[devid] = {'online': False, 'status': "ERROR"} continue e = _GoogleEntity(state) @@ -1075,7 +1075,7 @@ def smarthome_query(self, payload, token): devices[devid] = e.query_serialize() except Exception: logger.error("Unexpected error serializing query for %s", state) - devices[devid] = {"online": False} + devices[devid] = {"online": False, 'status': "ERROR"} response = {'devices': devices} logger.info(json.dumps(response, indent=2, sort_keys=True, ensure_ascii=False)) @@ -1160,7 +1160,7 @@ def say(self, s): #command "/say?text-to-say/lang@volume@device" SmartHomeReqHandler.send_resp("Error", s.url.query, scomm, stime, s) return itext = scomm.replace(" ","-") - itext=itext.split("/") + itext = itext.split("/") text = itext[0] if not text: return False @@ -1206,13 +1206,13 @@ def play(self, s): #command "/play?soundfile.mp3@volume else: rstatus="Error" rmessage = str(mp3_filename) + ", file not found!" - if rvol!="?": + if rvol != "?": answ, message = SmartHomeReqHandler.setvolume(str(round(rvol*100))) rmessage = rmessage + " restore volume " + str(round(rvol*100)) - if rcontent!="?": + if rcontent != "?": answ, message = SmartHomeReqHandler.playmedia(rcontent, rtype, 'PLAYING', 40) rmessage = rmessage + " restore stream : " + rcontent - if rdevice!="?": + if rdevice != "?": answ, message = SmartHomeReqHandler.switchdevice(rdevice) rmessage = rmessage + " restore device '" + rdevice+ "'" SmartHomeReqHandler.send_resp(rstatus, "play " + s.url.query, rmessage, stime, s) @@ -1237,31 +1237,31 @@ def send_resp(rstatus, rcommand, rmessage, stime, s): rtype = mc.status.content_type rpstate = mc.status.player_state if rpstate == "UNKNOWN": - rcontent="?" - rtype="?" - message='{"device":"'+ cast.device.friendly_name + '","status":"' + rstatus + '","command":"' + rcommand + '","volume":"' +rvolume +'","starttime":"' + stime + '","endtime":"' + etime + '","playstate":"' + rpstate + '","content":"' + rcontent + '","type":"' + rtype + '","message":"' + rmessage+ '"}' + rcontent = "?" + rtype = "?" + message = '{"device":"'+ cast.device.friendly_name + '","status":"' + rstatus + '","command":"' + rcommand + '","volume":"' +rvolume +'","starttime":"' + stime + '","endtime":"' + etime + '","playstate":"' + rpstate + '","content":"' + rcontent + '","type":"' + rtype + '","message":"' + rmessage+ '"}' s.send_json(200, message, False) logger.info(message) def read_input(ctext): global cast, mc, chromecasts stime = time.strftime("%d/%m/%y %H:%M:%S", time.localtime()) - answ="OK" - message="" + answ = "OK" + message = "" rdevice = "?" rvol = "?" rcontent = "?" rtype = "?" ctext = ctext.split("@") try: - svol=ctext[1] + svol = ctext[1] except: - svol="" + svol = "" try: - sdevice=ctext[2] + sdevice = ctext[2] except: - sdevice="" - if sdevice!="": + sdevice = "" + if sdevice != "": rdevice = cast.device.friendly_name answ, message = SmartHomeReqHandler.switchdevice(sdevice) if answ == "Error": @@ -1274,7 +1274,7 @@ def read_input(ctext): else: rcontent = "?" rtype = "?" - if svol!="": + if svol != "": cast.wait() rvol = cast.status.volume_level answ, message = SmartHomeReqHandler.setvolume(svol) @@ -1292,11 +1292,11 @@ def switchdevice(sdevice): return "OK","Switched to device " + str(cast.device.friendly_name) except Exception as e: logger.error('chromecasts init not succeeded, error : %s' % e) - return "Error","Not switched to device " + str(sdevice) + return "Error", "Not switched to device " + str(sdevice) def setvolume(svol): global cast, mc, chromecasts - svol=svol.replace("%","") + svol = svol.replace("%","") try: cast.wait() cast.set_volume(int(svol)/100) @@ -1305,7 +1305,7 @@ def setvolume(svol): return "OK","Volume level set to : " + svol +"%" except Exception as e: logger.error('Chromecast setvolume unsuccesfull, error : %s' % e) - return "Error","Volume level not set to : " + svol +"%" + return "Error", "Volume level not set to : " + svol +"%" def playmedia(pmedia,ptype, wstate, tmax): try: @@ -1313,17 +1313,17 @@ def playmedia(pmedia,ptype, wstate, tmax): mc.block_until_active() cast.wait() pstate = "?" - i=1 #max x seconds + i = 1 #max x seconds while (mc.status.player_state != wstate or pstate != wstate) and i Date: Fri, 5 May 2023 07:41:25 +0200 Subject: [PATCH 4/9] Update smarthome.py --- smarthome.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/smarthome.py b/smarthome.py index 6671557..28bbd75 100644 --- a/smarthome.py +++ b/smarthome.py @@ -440,6 +440,9 @@ def getDevices(devices="all", idx="0"): devlist = [(d.name, int(d.id), d.domain, d.state, d.room, d.nicknames, d.report_state, d.entity_id) for d in aogDevs.values()] devlist.sort(key=takeSecond) deviceList = json.dumps(devlist) + + if "all" == devices: + aogDevsReady = True def takeSecond(elem): return elem[1] @@ -1067,7 +1070,7 @@ def smarthome_query(self, payload, token): state = aogDevs.get(devid, None) if not state: # If we can't find a state, the device is offline - devices[devid] = {'online': False, 'status': "ERROR"} + devices[devid] = {'online': False, 'status': "OFFLINE"} continue e = _GoogleEntity(state) From b3d7903875de5e32b13e202fe84b091dbb50e478 Mon Sep 17 00:00:00 2001 From: DewGew Date: Fri, 5 May 2023 07:50:45 +0200 Subject: [PATCH 5/9] New version --- const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/const.py b/const.py index 4df763b..6f98dfa 100644 --- a/const.py +++ b/const.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Constants for Google Assistant.""" -VERSION = '1.23.3' +VERSION = '1.23.5' PUBLIC_URL = 'https://[your public url]' CONFIGFILE = 'config/config.yaml' LOGFILE = 'dzga.log' From 799c0b96c0a055195e26ec1d43b78af6ff4ff287 Mon Sep 17 00:00:00 2001 From: DewGew Date: Fri, 5 May 2023 17:48:05 +0200 Subject: [PATCH 6/9] Update trait.py --- trait.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/trait.py b/trait.py index d87307f..079dfa1 100644 --- a/trait.py +++ b/trait.py @@ -194,8 +194,6 @@ def execute(self, command, params): if domain not in [DOMAINS['sensor']]: if domain == DOMAINS['group']: - url = DOMOTICZ_URL + '/json.htm?type=command¶m=switchscene&idx=' + self.state.id + '&switchcmd=' + ( - 'On' if params['on'] else 'Off') url = DOMOTICZ_URL + '/json.htm?type=command¶m=switchscene&idx=' + self.state.id + '&switchcmd=' if params['on'] is True and state == 'Off': url += 'On' @@ -205,8 +203,6 @@ def execute(self, command, params): raise SmartHomeError(ERR_ALREADY_IN_STATE, 'Unable to execute {} for {}. Already in state '.format(command, self.state.entity_id)) else: - url = DOMOTICZ_URL + '/json.htm?type=command¶m=switchlight&idx=' + self.state.id + '&switchcmd=' + ( - 'On' if params['on'] else 'Off') url = DOMOTICZ_URL + '/json.htm?type=command¶m=switchlight&idx=' + self.state.id + '&switchcmd=' if params['on'] is True and state == 'Off': url += 'On' From bfb23766e73f6cb7f120a2edd8e557a7993a6ebd Mon Sep 17 00:00:00 2001 From: DewGew Date: Sun, 7 May 2023 18:04:43 +0200 Subject: [PATCH 7/9] Fix for #319 --- requirements/pip-requirements.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/requirements/pip-requirements.txt b/requirements/pip-requirements.txt index 8a6407e..79d76e8 100644 --- a/requirements/pip-requirements.txt +++ b/requirements/pip-requirements.txt @@ -4,8 +4,8 @@ future>=0.18.2 idna>=2.8 pid>=3.0.3 PyYAML>=5.1.2 -requests>=2.22.0 -urllib3>=1.25.7 +requests>=2.30.0 +urllib3>=1.26,<3 GitPython>=3.0.5 google-auth>=1.8.1 wheel>=0.34.2 @@ -13,6 +13,6 @@ Jinja2>=2.11.3 PyChromecast==9.1.2 gTTS>=2.2.1 unicode-slugify>=0.1.3 -protobuf==3.20.0 +protobuf==3.20.2 zeroconf>=0.25.1 casttube>=0.2.0 From 4df46d27011c1de0e1dab243f52532aec85455f2 Mon Sep 17 00:00:00 2001 From: DewGew Date: Sun, 7 May 2023 18:08:46 +0200 Subject: [PATCH 8/9] Update const.py --- const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/const.py b/const.py index 6f98dfa..9e418de 100644 --- a/const.py +++ b/const.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Constants for Google Assistant.""" -VERSION = '1.23.5' +VERSION = '1.23.6' PUBLIC_URL = 'https://[your public url]' CONFIGFILE = 'config/config.yaml' LOGFILE = 'dzga.log' From ecd58a465a9ad043d44b8c6c886f6fae01a52f31 Mon Sep 17 00:00:00 2001 From: DewGew Date: Mon, 8 May 2023 21:37:46 +0200 Subject: [PATCH 9/9] Update pip-requirements.txt --- requirements/pip-requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements/pip-requirements.txt b/requirements/pip-requirements.txt index 79d76e8..493bdf5 100644 --- a/requirements/pip-requirements.txt +++ b/requirements/pip-requirements.txt @@ -5,7 +5,7 @@ idna>=2.8 pid>=3.0.3 PyYAML>=5.1.2 requests>=2.30.0 -urllib3>=1.26,<3 +urllib3>=1.26,<2 GitPython>=3.0.5 google-auth>=1.8.1 wheel>=0.34.2