diff --git a/appdaemon/plugins/hass/hassplugin.py b/appdaemon/plugins/hass/hassplugin.py index 9ad6209c3..1f8b6139f 100644 --- a/appdaemon/plugins/hass/hassplugin.py +++ b/appdaemon/plugins/hass/hassplugin.py @@ -96,7 +96,7 @@ def list_constraints(self): return [] # - # Persistent Session to HASS instance + # Persistent HTTP Session to HASS instance # @property def session(self): @@ -122,6 +122,47 @@ def session(self): ) return self._session + # + # Connect and return a new WebSocket to HASS instance + # + async def create_websocket(self): + # change to websocket protocol + url = self.ha_url + if url.startswith("https://"): + url = url.replace("https", "wss", 1) + elif url.startswith("http://"): + url = url.replace("http", "ws", 1) + + # ssl options + sslopt = {} + if self.cert_verify is False: + sslopt = {"cert_reqs": ssl.CERT_NONE} + if self.cert_path: + sslopt["ca_certs"] = self.cert_path + ws = websocket.create_connection("{}/api/websocket".format(url), sslopt=sslopt) + + # wait for successful connection + res = await utils.run_in_executor(self, ws.recv) + result = json.loads(res) + self.logger.info("Connected to Home Assistant %s", result["ha_version"]) + + # Check if auth required, if so send password + if result["type"] == "auth_required": + if self.token is not None: + auth = json.dumps({"type": "auth", "access_token": self.token}) + elif self.ha_key is not None: + auth = json.dumps({"type": "auth", "api_password": self.ha_key}) + else: + raise ValueError("HASS requires authentication and none provided in plugin config") + + await utils.run_in_executor(self, ws.send, auth) + result = json.loads(ws.recv()) + if result["type"] != "auth_ok": + self.logger.warning("Error in authentication") + raise ValueError("Error in authentication") + + return ws + # # Get initial state # @@ -282,37 +323,8 @@ async def get_updates(self): # noqa: C901 # # Connect to websocket interface # - url = self.ha_url - if url.startswith("https://"): - url = url.replace("https", "wss", 1) - elif url.startswith("http://"): - url = url.replace("http", "ws", 1) - - sslopt = {} - if self.cert_verify is False: - sslopt = {"cert_reqs": ssl.CERT_NONE} - if self.cert_path: - sslopt["ca_certs"] = self.cert_path - self.ws = websocket.create_connection("{}/api/websocket".format(url), sslopt=sslopt) - res = await utils.run_in_executor(self, self.ws.recv) - result = json.loads(res) - self.logger.info("Connected to Home Assistant %s", result["ha_version"]) - # - # Check if auth required, if so send password - # - if result["type"] == "auth_required": - if self.token is not None: - auth = json.dumps({"type": "auth", "access_token": self.token}) - elif self.ha_key is not None: - auth = json.dumps({"type": "auth", "api_password": self.ha_key}) - else: - raise ValueError("HASS requires authentication and none provided in plugin config") + self.ws = await self.create_websocket() - await utils.run_in_executor(self, self.ws.send, auth) - result = json.loads(self.ws.recv()) - if result["type"] != "auth_ok": - self.logger.warning("Error in authentication") - raise ValueError("Error in authentication") # # Subscribe to event stream #