def test_combining_dict_keys(): DATA_EMPTY_DICT = {"key_dict": {}} DATA_DICT_INT = {"key_dict": {"key_int": 0}} DATA_DICT_STRING = {"key_dict": {"key_string": "a"}} DATA_DICT_STRING2 = {"key_dict": {"key_string": "b"}} DATA_DICT_INTSTRING = {"key_dict": {"key_int": 0, "key_string": "a"}} command1 = Command("method", "path", DATA_EMPTY_DICT) command2 = Command("method", "path", DATA_DICT_INT) combined = command1 + command2 assert combined._data == DATA_DICT_INT command1 = Command("method", "path", DATA_DICT_INT) command2 = Command("method", "path", DATA_DICT_STRING) combined = command1 + command2 assert combined._data == DATA_DICT_INTSTRING command1 = Command("method", "path", DATA_DICT_STRING) command2 = Command("method", "path", DATA_DICT_STRING2) combined = command1 + command2 assert combined._data == DATA_DICT_STRING2 command1 = Command("method", "path", DATA_DICT_INT) command2 = Command("method", "path", DATA_DICT_STRING2) command3 = Command("method", "path", DATA_DICT_STRING) combined = command1 + command2 + command3 assert combined._data == DATA_DICT_INTSTRING
def test_combining_dict_keys(): DATA_EMPTY_DICT = {'key_dict': {}} DATA_DICT_INT = {'key_dict': {'key_int': 0}} DATA_DICT_STRING = {'key_dict': {'key_string': 'a'}} DATA_DICT_STRING2 = {'key_dict': {'key_string': 'b'}} DATA_DICT_INTSTRING = {'key_dict': {'key_int': 0, 'key_string': 'a'}} command1 = Command('method', 'path', DATA_EMPTY_DICT) command2 = Command('method', 'path', DATA_DICT_INT) combined = command1 + command2 assert combined._data == DATA_DICT_INT command1 = Command('method', 'path', DATA_DICT_INT) command2 = Command('method', 'path', DATA_DICT_STRING) combined = command1 + command2 assert combined._data == DATA_DICT_INTSTRING command1 = Command('method', 'path', DATA_DICT_STRING) command2 = Command('method', 'path', DATA_DICT_STRING2) combined = command1 + command2 assert combined._data == DATA_DICT_STRING2 command1 = Command('method', 'path', DATA_DICT_INT) command2 = Command('method', 'path', DATA_DICT_STRING2) command3 = Command('method', 'path', DATA_DICT_STRING) combined = command1 + command2 + command3 assert combined._data == DATA_DICT_INTSTRING
def test_combining_with_none(): DATA_INT = {'key_int': 0} command1 = Command('method', 'path', DATA_INT) combined = command1 + None assert combined._data == DATA_INT # Combining should mutate the original command command1.combine_data(None) assert command1._data == DATA_INT
def test_result(): def pr(value): return value + 1 command = Command('method', 'path', {}, process_result=pr) assert command.result is None assert command.raw_result is None command.result = 0 assert command.result == 1 assert command.raw_result == 0
def test_combining_with_none(): DATA_INT = {"key_int": 0} command1 = Command("method", "path", DATA_INT) combined = command1 + None assert combined._data == DATA_INT # Combining should mutate the original command command1.combine_data(None) assert command1._data == DATA_INT
def test_result(): """Test callback process_result.""" def process_result(value): return value + 1 command = Command("method", "path", {}, process_result=process_result) assert command.result is None assert command.raw_result is None command.process_result(0) assert command.result == 1 assert command.raw_result == 0
def test_combining_listed_dict_keys(): DATA_EMPTY_DICT = {'key_ldict': [{}]} DATA_DICT_INT = {'key_ldict': [{'key_int': 0}]} DATA_DICT_STRING = {'key_ldict': [{'key_string': 'a'}]} DATA_DICT_INTSTRING = {'key_ldict': [{'key_int': 0, 'key_string': 'a'}]} command1 = Command('method', 'path', DATA_EMPTY_DICT) command2 = Command('method', 'path', DATA_DICT_INT) combined = command1 + command2 assert combined._data == DATA_DICT_INT command1 = Command('method', 'path', DATA_DICT_INT) command2 = Command('method', 'path', DATA_DICT_STRING) combined = command1 + command2 assert combined._data == DATA_DICT_INTSTRING
def test_combining_list_keys(): DATA_EMPTY_LIST = {'key_list': []} DATA_INT_LIST1 = {'key_list': [0, 1, 2]} DATA_INT_LIST2 = {'key_list': [10, 11, 12]} command1 = Command('method', 'path', DATA_EMPTY_LIST) command2 = Command('method', 'path', DATA_INT_LIST1) combined = command1 + command2 assert combined._data == DATA_INT_LIST1 # Duplicated keys are replaced if not dicts command1 = Command('method', 'path', DATA_INT_LIST1) command2 = Command('method', 'path', DATA_INT_LIST2) combined = command1 + command2 assert combined._data == DATA_INT_LIST2
def test_combining_listed_dict_keys(): DATA_EMPTY_DICT = {"key_ldict": [{}]} DATA_DICT_INT = {"key_ldict": [{"key_int": 0}]} DATA_DICT_STRING = {"key_ldict": [{"key_string": "a"}]} DATA_DICT_INTSTRING = {"key_ldict": [{"key_int": 0, "key_string": "a"}]} command1 = Command("method", "path", DATA_EMPTY_DICT) command2 = Command("method", "path", DATA_DICT_INT) combined = command1 + command2 assert combined._data == DATA_DICT_INT command1 = Command("method", "path", DATA_DICT_INT) command2 = Command("method", "path", DATA_DICT_STRING) combined = command1 + command2 assert combined._data == DATA_DICT_INTSTRING
def test_combining_string_keys(): DATA_STRING = {'key_string': 'a'} DATA_STRING_SAME_KEY = {'key_string': 'same'} DATA_STRING2 = {'key_string_2': 'b'} COMBINED_STRING = {'key_string': 'a', 'key_string_2': 'b'} command1 = Command('method', 'path', DATA_STRING) command2 = Command('method', 'path', DATA_STRING2) combined = command1 + command2 assert combined._data == COMBINED_STRING command1 = Command('method', 'path', DATA_STRING) command2 = Command('method', 'path', DATA_STRING_SAME_KEY) # We should always take the last key if we can't merge combined = command1 + command2 assert combined._data == DATA_STRING_SAME_KEY
def test_combining_integer_keys(): DATA_INT = {'key_int': 0} DATA_INT_SAME_KEY = {'key_int': 1} DATA_INT2 = {'key_int_2': 1} COMBINED_INT = {'key_int': 0, 'key_int_2': 1} command1 = Command('method', 'path', DATA_INT) command2 = Command('method', 'path', DATA_INT2) combined = command1 + command2 assert combined._data == COMBINED_INT command1 = Command('method', 'path', DATA_INT) command2 = Command('method', 'path', DATA_INT_SAME_KEY) # We should always take the last key if we can't merge combined = command1 + command2 assert combined._data == DATA_INT_SAME_KEY
def test_property_access(): def pr(): pass def ec(): pass command = Command( method="method", path="path", data="data", parse_json=True, observe=False, observe_duration=0, process_result=pr, err_callback=ec, ) assert command.method == "method" assert command.path == "path" assert command.parse_json is True assert command.observe is False assert command.observe_duration == 0 assert command.process_result == pr assert command.err_callback == ec
def test_combining_string_keys(): DATA_STRING = {"key_string": "a"} DATA_STRING_SAME_KEY = {"key_string": "same"} DATA_STRING2 = {"key_string_2": "b"} COMBINED_STRING = {"key_string": "a", "key_string_2": "b"} command1 = Command("method", "path", DATA_STRING) command2 = Command("method", "path", DATA_STRING2) combined = command1 + command2 assert combined._data == COMBINED_STRING command1 = Command("method", "path", DATA_STRING) command2 = Command("method", "path", DATA_STRING_SAME_KEY) # We should always take the last key if we can't merge combined = command1 + command2 assert combined._data == DATA_STRING_SAME_KEY
def set_values(self, values, *, index=0): """ Set values on socket control. Returns a Command. """ assert len(self.raw) == 1, "Only devices with 1 socket supported" return Command("put", self._device.path, {ATTR_SWITCH_PLUG: [values]})
def set_values(self, values, *, index=0): """ Set values on light control. Returns a Command. """ assert len(self.raw) == 1, "Only devices with 1 light supported" return Command("put", self._device.path, {ATTR_LIGHT_CONTROL: [values]})
def test_combining_mutates(): DATA_INT = {'key_int': 0} DATA_INT2 = {'key_int_2': 1} COMBINED_INT = {'key_int': 0, 'key_int_2': 1} command1 = Command('method', 'path', DATA_INT) command2 = Command('method', 'path', DATA_INT2) combined = command1 + command2 # Adding shouldn't mutate the original commands assert command1._data == DATA_INT assert command2._data == DATA_INT2 assert combined._data == COMBINED_INT # Combining should mutate the original command command1.combine_data(command2) assert command1._data == COMBINED_INT assert command2._data == DATA_INT2
def test_combining_mutates(): DATA_INT = {"key_int": 0} DATA_INT2 = {"key_int_2": 1} COMBINED_INT = {"key_int": 0, "key_int_2": 1} command1 = Command("method", "path", DATA_INT) command2 = Command("method", "path", DATA_INT2) combined = command1 + command2 # Adding shouldn't mutate the original commands assert command1._data == DATA_INT assert command2._data == DATA_INT2 assert combined._data == COMBINED_INT # Combining should mutate the original command command1.combine_data(command2) assert command1._data == COMBINED_INT assert command2._data == DATA_INT2
def test_request_returns_single(monkeypatch): monkeypatch.setattr('aiocoap.Context.create_client_context', mock_create_context) api = APIFactory('127.0.0.1').request command = Command('', '') response = yield from api(command) assert type(response) != list
async def test_request_returns_list(monkeypatch): monkeypatch.setattr("aiocoap.Context.create_client_context", mock_create_context) api = (await APIFactory.init("127.0.0.1")).request command = Command("", "") response = await api([command, command, command]) assert type(response) == list
async def test_request_returns_list(monkeypatch): monkeypatch.setattr('aiocoap.Context.create_client_context', mock_create_context) api = APIFactory('127.0.0.1').request command = Command('', '') response = await api([command, command, command]) assert type(response) == list
def dump_all(): endpoints = api(gateway.get_endpoints()) for endpoint in endpoints: parts = endpoint[1:].split('/') if not all(part.isdigit() for part in parts): continue pprint(api(Command('get', parts))) print() print()
async def test_request_returns_single(monkeypatch): """Test return single object.""" monkeypatch.setattr("aiocoap.Context.create_client_context", mock_create_context) api = (await APIFactory.init("127.0.0.1")).request command = Command("", "") response = await api(command) assert not isinstance(response, list)
def set_value(self, value): """ Set values on blind control. Returns a Command. """ return Command('put', self._device.path, { ATTR_START_BLINDS: [ { ATTR_BLIND_CURRENT_POSITION: value } ] })
def test_url(): command = Command("method", ["path"], {}) url = command.url("host") assert url == "coaps://host:5684/path" command2 = Command("method", ["path1", "path2"], {}) url = command2.url("host") assert url == "coaps://host:5684/path1/path2"
def test_url(): command = Command('method', ['path'], {}) url = command.url('host') assert url == 'coaps://host:5684/path' command2 = Command('method', ['path1', 'path2'], {}) url = command2.url('host') assert url == 'coaps://host:5684/path1/path2'
def fetch(self): try: logger.info("Force fetch state for {}".format(self.device.name)) def process_result(result): return Device(result) self.device = self.api( Command('get', [ROOT_DEVICES, self.device.id], process_result=process_result)) time.sleep(0.1) except RequestTimeout as e: self.dirty = True logger.info("There was timeout for actions, retry in some time")
def test_property_access(): """Test property access in Command.""" def error_callback(): pass command = Command( method="method", path="path", data="data", parse_json=True, observe=False, observe_duration=0, err_callback=error_callback, ) assert command.method == "method" assert command.path == "path" assert command.parse_json is True assert command.observe is False assert command.observe_duration == 0 assert command.err_callback is error_callback
def test_property_access(): def pr(): pass def ec(): pass command = Command(method='method', path='path', data='data', parse_json=True, observe=False, observe_duration=0, process_result=pr, err_callback=ec) assert command.method == 'method' assert command.path == 'path' assert command.parse_json is True assert command.observe is False assert command.observe_duration == 0 assert command.process_result == pr assert command.err_callback == ec
async def run(shutdown): # Assign configuration variables. # The configuration check takes care they are present. conf = load_json(CONFIG_FILE) try: identity = conf[args.host].get('identity') psk = conf[args.host].get('key') api_factory = APIFactory(host=args.host, psk_id=identity, psk=psk) except KeyError: identity = uuid.uuid4().hex api_factory = APIFactory(host=args.host, psk_id=identity) try: psk = await api_factory.generate_psk(args.key) print('Generated PSK: ', psk) conf[args.host] = {'identity': identity, 'key': psk} save_json(CONFIG_FILE, conf) except AttributeError: raise PytradfriError("Please provide the 'Security Code' on the " "back of your Tradfri gateway using the " "-K flag.") api = api_factory.request gateway = Gateway() # end copy/pasted # # set and regularly renew the commissioning timeout, remove when done # async def keep_commissioning_alive(readiness): try: while True: await api(gateway.set_commissioning_timeout(60)) if readiness is not None: readiness() readiness = None await asyncio.sleep(45) finally: await api(gateway.set_commissioning_timeout(00)) commissioning_ready = asyncio.Future() commissioning = asyncio.Task( keep_commissioning_alive(lambda: commissioning_ready.set_result(None))) # # monitor the device list and give instructions # last_devices = None def devices_updated(result): nonlocal last_devices if last_devices is None: print("Originally, %s device(s) are known" % len(result)) else: for r in result: if r not in last_devices: asyncio.Task(new_device(r)) last_devices = result async def new_device(devno): nonlocal commissioning print("New device, fetching details...", end="", flush=True) device_command = gateway.get_device(devno) device = await api(device_command) print() print(" New device description: %s" % (device, )) if commissioning: if device.has_light_control: print("That was not in the expected sequence: This device was" " a light and not a controller. You can still pair" " another controller device.") else: print("Found a controller. You can now go ahead and add light" " bulbs by pairing them to the switch as you would do" " without a gateway. Press Ctrl-C when done.") commissioning.cancel() commissioning = None # if you wanted to implemente infinite-commissioning mode, you # should cancel or restart keep_commissioning_alive in a way # that resets the timeout, because the timeout will have gone # to 0 the moment the device was added. else: if not device.has_light_control: print("That was unexpected: A controller showed up even though" " the gateway was not in pairing mode any more.") else: print("You can still add more light bulbs; press Ctrl-C when" " done.") observe_devices = Command('get', [ROOT_DEVICES], observe=True, process_result=devices_updated) await api(observe_devices) await commissioning_ready print("Ready to start: Gateway is in commissioning mode.") print("Pressing the pairing button on a switch, dimmer or motion detector" " for 10s near the gateway until the gateway blinks fast. A few" " seconds later, it the new device shows up here. You may need to" " switch off light bulbs in the immediate vicinity (?).") # # run until the outer loop says not to any more # await api_factory.shutdown() await shutdown if commissioning is not None: print("Please allow for the commissioning mode to be disabled") commissioning.cancel()
def set_value(self, value): """ Set values on blind control. Returns a Command. """ return Command('put', self._device.path, {ATTR_START_BLINDS: [value]})