async def _update_subscriptions(self, characteristics, ev): """Subscribe or unsubscribe to characteristics.""" status = {} # We do one aid at a time to match what iOS does # even though its inefficient # https://github.com/home-assistant/core/issues/37996 # # Prebuild the payloads to avoid the set size changing # between await calls char_payloads = [ [{"aid": aid, "iid": iid, "ev": ev} for aid, iid in aid_iids] for _, aid_iids in groupby(characteristics, key=itemgetter(0)) ] for char_payload in char_payloads: response = await self.connection.put_json( "/characteristics", {"characteristics": char_payload}, ) if response: # An empty body is a success response for row in response.get("characteristics", []): status[(row["aid"], row["iid"])] = { "status": row["status"], "description": to_status_code(row["status"]).description, } return status
def format_characteristic_list(data): tmp = {} for c in data["characteristics"]: key = (c["aid"], c["iid"]) del c["aid"] del c["iid"] if "status" in c and c["status"] == 0: del c["status"] if "status" in c and c["status"] != 0: c["description"] = to_status_code(c["status"]).description tmp[key] = c return tmp
async def identify(self): await self._ensure_connected() response = await self.connection.post_json("/identify", {}) if not response: return True code = to_status_code(response["code"]) raise AlreadyPairedError( "Identify failed because: {reason} ({code}).".format( reason=code.description, code=code.value, )) return True
async def put_characteristics(self, characteristics): """ Update the values of writable characteristics. The characteristics have to be identified by accessory id (aid), instance id (iid). If do_conversion is False (the default), the value must be of proper format for the characteristic since no conversion is done. If do_conversion is True, the value is converted. :param characteristics: a list of 3-tupels of accessory id, instance id and the value :param do_conversion: select if conversion is done (False is default) :return: a dict from (aid, iid) onto {status, description} :raises FormatError: if the input value could not be converted to the target type and conversion was requested """ await self._ensure_connected() if "accessories" not in self.pairing_data: await self.list_accessories_and_characteristics() data = [] characteristics_set = set() for characteristic in characteristics: aid = characteristic[0] iid = characteristic[1] value = characteristic[2] characteristics_set.add(f"{aid}.{iid}") data.append({"aid": aid, "iid": iid, "value": value}) data = {"characteristics": data} response = await self.connection.put_json("/characteristics", data) if response: data = { (d["aid"], d["iid"]): { "status": d["status"], "description": to_status_code(d["status"]).description, } for d in response["characteristics"] } return data return {}
async def test_normalized_statuscodes(): """Verify we account for quirks in HAP implementations.""" assert to_status_code(70411) == HapStatusCode.INSUFFICIENT_AUTH assert to_status_code(-70411) == HapStatusCode.INSUFFICIENT_AUTH