async def test_observe_device(self): device = Device.init_from_file(di='1', class_name='EchoDevice', path=self.config_path) device_task = await wait_run_device(device) device2 = Device.init_from_file(di='2', class_name='EchoDevice', path=self.config_path) device2_task = await wait_run_device(device2) result = await device2.discovery_resource() di = device.get_device_id() await device2.observe(result[di].links['/oic/mnt'], device2.on_action) await asyncio.sleep(1) listening = device.get_param('/oic/con', 'listening') self.assertEqual(len(listening), 1, 'add observe') self.assertEqual(listening[0]['href'], '/oic/mnt') await device2.observe(result[di].links['/oic/mnt']) await asyncio.sleep(1) listening = device.get_param('/oic/con', 'listening') self.assertEqual(len(listening), 0, 'remove observe') device_task.cancel() device2_task.cancel() await device_task await device2_task
async def test_device_self_get_request(self): defines.EXCHANGE_LIFETIME = 2 device0 = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) await wait_run_device(device0) address = list(device0.transport_layer.eps_coap_ipv4.keys())[0] request = Request() # request.token = _token # request.query = {'owned': ['TRUE']} request.type = NON request.code = Code.GET request.uri_path = '/oic/res' request.content_type = 10000 request.source = ( address, list(device0.transport_layer.eps_coap_ipv4[address].keys())[0]) # request.multicast = True # request.family = _msg.family request.scheme = 'coap' request.destination = ( address, list(device0.transport_layer.eps_coap_ipv4[address].keys())[0]) # request.destination = (address, 5683) res2 = await device0.transport_layer.coap.send_message(request) links = res2.decode_payload() await asyncio.sleep(15) await device0.stop() self.assertGreater(len(links), 7) link = links[0] self.assertIn('href', link) self.assertIn('eps', link) pass
async def action_run_device(self, link): di = link.get('di') try: class_name = link['dmno'] except KeyError: raise KeyNotFound(detail='dmno', action='action_run_device') from None if di and di in self._running_devices: raise Exception('device is already running') if class_name == 'VirtualServer': process = multiprocessing.Process(target=self.device_process, args=(class_name, di, self.queue, dict(path=self.path)), daemon=True) process.start() self._running_devices[link['di']] = process return None else: device = Device.init_from_file(class_name=class_name, di=link.get('di'), path=self.path, loop=self.loop, log=self.log) link['di'] = device.get_device_id() task = self.loop.create_task(device.main()) device.task = task self._running_devices[link['di']] = device return device
async def find_by_id(self, _id, **kwargs): driver = Device.init_from_config(class_name=_id) return { "id": _id, "links": driver.data, "_actions": driver.get_install_actions() }
async def api_find_devices(self, view, **kwargs): async def notify(message): message['percent'] = percent await view.notify(message) handler, data = await self.prepare_json_request(view) items = data['items'] if items is None: # ищем все устройства items = await handler.query(data['filter']) count = len(items) devices = [] for i, item in enumerate(items): if count > 2: percent = (i + 1) * 100 / count else: percent = None device = Device.init_from_config(class_name=item['id']) devices += await device.find_devices(notify=notify) # for elem in devices: # new_device = Device.init_from_config(elem) # new_device.save_config() # di = new_device.get_device_id() # await view.device.action_add_device({'di': di, 'dmno': device.__class__.__name__}) # raise Exception('bbbad') return self.response.json_response(devices)
async def test_init(self): device = Device.init_from_file(di='1', class_name='EchoDevice', path=self.config_path) self.assertTrue(isinstance(device, EchoDevice), 'instance') self.assertEqual(device.get_param('/oic/p', 'mnpv'), Device.version, 'platform version ') self.assertEqual(device.get_param('/oic/d', 'sv'), device.version, 'device version') self.assertEqual(device.get_param('/oic/d', 'dmno'), EchoDevice.__name__, 'device class') self.assertEqual(device.get_param('/oic/d', 'di'), '1', 'di') self.assertEqual(device.get_param('/oic/con', 'udpCoapPort'), 11111, 'coap port from file') device = EchoDevice.init_from_file(di='1', path='{}/config/'.format( path.dirname(__file__))) self.assertTrue(isinstance(device, EchoDevice), 'instance') self.assertEqual(device.get_param('/oic/p', 'mnpv'), Device.version, 'platform version ') self.assertEqual(device.get_param('/oic/d', 'sv'), device.version, 'device version') self.assertEqual(device.get_param('/oic/d', 'dmno'), EchoDevice.__name__, 'device class') self.assertEqual(device.get_param('/oic/d', 'di'), '1', 'di') self.assertEqual(device.get_param('/oic/con', 'udpCoapPort'), 11111, 'coap port from file') pass
def device_process(class_name, di, queue, kwargs): h = logging.handlers.QueueHandler(queue) # Just the one handler needed kwargs['loop'] = asyncio.new_event_loop() root = logging.getLogger() root.handlers = [] root.addHandler(h) device = Device.init_from_file(class_name=class_name, di=di, **kwargs) device.run()
async def test_save_config(self): device = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) new_id = '3' device.set_device_id(new_id) data = device.save_config() self.assertEqual(data[1]['/oic/d']['di'], new_id) self.assertEqual(data[1]['/oic/d']['di'], new_id) self.assertEqual(data[1]['/oic/sec/doxm']['deviceuuid'], new_id) pass
async def test_run_stop_device(self): device = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) await wait_run_device(device) eps = device.transport_layer.eps_coap_ipv6 ip_eps = eps[list(eps.keys())[0]] ep = ip_eps[list(ip_eps.keys())[0]] transport = ep.transport self.assertFalse(transport.is_closing(), 'closing coap') await device.stop() self.assertTrue(transport.is_closing(), 'closing coap') pass
async def test_run_coap_with_a_known_port_number(self): device = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) port = device.get_param('/oic/con', 'udpCoapPort') await device.transport_layer.start() unicast_endpoints = device.transport_layer.coap.endpoint_layer.unicast_endpoints # self.assertIn('::', unicast_endpoints) # self.assertIn(port, unicast_endpoints['::']) # self.assertIn('', unicast_endpoints) # self.assertIn(port, unicast_endpoints['']) await device.transport_layer.stop() self.assertFalse(unicast_endpoints) pass
async def test_save_config(self): data = b'X\x01\xb4\x85\xa0\x02\xacA\x8d\x04N*\xb3oic\x03sec\x04doxmKowned=FALSE"\'\x10\xe2\x06\xe3\x08\x00' ('192.168.1.15', 61689) device = Device.init_from_file(di='1', class_name='EchoDevice', path=self.config_path) device.set_device_id('3') data = device.save_config() self.assertDictEqual(data[1], { '/oic/d': { 'di': '3' }, '/oic/con': { 'udpCoapPort': 11111 } }) pass
async def find_devices(self, **kwargs): notify = kwargs.get('notify') if notify: await notify({'message': f'Ищем {self.__class__.__name__}...'}) result = [] for i in range(2): await asyncio.sleep(1) if notify: await notify({'message': f'Найдено {self.__class__.__name__}: {i + 1}'}) tmp_device = EchoDevice.init_from_config({}) result.append(dict( id=tmp_device.get_device_id(), name=tmp_device.get_device_name(), links=tmp_device.get_discover_res(), _actions=Device.get_install_actions() )) return result
async def test_discovery_device2(self): device0 = Device.init_from_file( di='20000000-0000-0000-0000-000000000002', class_name='EchoDevice', path=self.config_path) device_task = await wait_run_device(device0) # device = Device.init_from_config() # device_task = await wait_run_device(device) # a = device0.transport_layer.eps await asyncio.sleep(10000) # result = await device0.transport_layer.discovery_resource() # di = device0.get_device_id() # self.assertIn(di, result, 'device found') # await device0.stop() # self.assertTrue(device0.coap.endpoint['IPv6']['transport'].is_closing(), 'clossing coap') # self.assertTrue(device0.coap.endpoint['multicast'][0]['transport'].is_closing(), 'run IPv6 transport') pass
async def test_discover_unowned_devices(self): target_address = ('192.168.1.15', 50497) device = Device.init_from_file( di='00000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) device_task = await wait_run_device(device) # to = ResourceLink.init_from_uri('coap://192.168.1.18:50408/oic/sec/doxm') # result = await device.request('retrieve', to, {}, query={'owned': ['FALSE']}) await asyncio.sleep(10000) pass # di = device.get_device_id() # self.assertIn(di, result, 'device found') # device_task.cancel() # await device_task # self.assertTrue(device.coap.endpoint['IPv6']['transport'].is_closing(), 'clossing coap') # self.assertTrue(device.coap.endpoint['multicast'][0]['transport'].is_closing(), 'run IPv6 transport') pass
async def api_find_devices(self, view, **kwargs): async def notify(_data): await asyncio.sleep(0.2) current = datetime.now() if (current - status['time_last_notify']).total_seconds() > 0.5: if progress: _data = { 'progress': progress + _data.get('progress', 1), 'message': f'found {found + _data.get("found", 0)} {_data.get("message", "")}' } else: _data = { 'progress': _data.get('progress', 1), 'message': f'found {_data.get("found", 0)} {_data.get("message", "")}' } await view.notify(_data) status['time_last_notify'] = current action = kwargs['_action'] handler, data = await self.prepare_json_request(view) items = data['items'] if items is None: # ищем все устройства items = await handler.query(data['filter']) count = len(items) devices = [] found = 0 status = {'time_last_notify': datetime.now()} progress = None await view.notify({'message': f'Ищем...'}) for i, item in enumerate(items): if count > 2: progress = (i + 1) * 100 * 100 / (count * 100) device = Device.init_from_config(item['links']) device.coap = view.device.coap devices += action.add_stat(await device.find_devices(notify=notify)) found += len(devices) await view.notify({'message': f'Founded {found}'}) return self.response.json_response(devices)
async def test_run_coap_without_port_number(self): device = Device.init_from_config() self.assertEqual(device.get_param('/oic/con', 'udpCoapPort'), 0) await device.transport_layer.start() self.assertTrue(device.get_param('/oic/con', 'udpCoapPort') > 0) eps_ipv4 = device.transport_layer.eps_coap_ipv4 self.assertTrue(device.transport_layer.eps_coap_ipv4, 'dont run IPv4 transport') first_ip = list(eps_ipv4)[0] eps_ipv4_first_ip = eps_ipv4[first_ip] first_port = list(eps_ipv4_first_ip)[0] ep = eps_ipv4_first_ip[first_port] self.assertTrue(device.transport_layer.eps_coap_ipv4, 'dont run IPv4 transport') self.assertFalse(ep.transport.is_closing(), 'run IPv4 transport') await device.transport_layer.stop() self.assertTrue(ep.transport.is_closing(), 'IPv4 transport dont close') pass
async def test_device_self_handshake(self): defines.EXCHANGE_LIFETIME = 2 device0 = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) await wait_run_device(device0) ep = device0.transport_layer.coap.endpoint_layer.find_endpoint( scheme='coaps') to = { 'net_interface': ep.address[0], 'coaps': ep.address, 'family': ep.family } res = await device0.transport_layer.send_raw_data( to, b'\x16\xfe\xfd\x00\x00\x00\x00\x00\x00\x00\x02\x00b\x01\x00\x00V\x00\x00\x00\x00\x00\x00\x00V\xfe\xfd`\xc6_,\xdc\x0b&\xcf1L\x98\x15%\xcc\xd6\xf5\xba\xb4\xb5\x93\xd39\rk\xfb\x16l\xf0\xdd\xd9,a\x00\x00\x00\x04\xff\x00\x00\xff\x01\x00\x00(\x00\r\x00\x12\x00\x10\x06\x03\x06\x01\x05\x03\x05\x01\x04\x03\x04\x01\x03\x03\x03\x01\x00\n\x00\x04\x00\x02\x00\x17\x00\x0b\x00\x02\x01\x00\x00\x17\x00\x00', secure=True) await asyncio.sleep(10000) pass
def find_drivers(**kwargs): result = {} log = kwargs.get('log') for path1 in syspath: device_dir = os.path.normpath('{}/BubotObj/OcfDevice/subtype'.format(path1)) if os.path.isdir(device_dir): device_list = os.listdir(device_dir) for device_name in device_list: device_path = os.path.normpath('{0}/{1}/{1}.py'.format(device_dir, device_name)) if not os.path.isfile(device_path): continue try: driver = Device.init_from_config(class_name=device_name, save_config=False) except Exception as err: if log: log.error(f'Init from config {device_name}: {err}') continue if driver.template: continue add_driver = True filter_rt = kwargs.get('rt') if filter_rt: try: find = False for href in driver.data: rt = driver.data[href].get('rt') if filter_rt in rt: find = True break if not find: add_driver = False except Exception as e: add_driver = False if add_driver: result[device_name] = dict( path=os.path.normpath('{0}/{1}'.format(device_dir, device_name)), # driver=driver ) return result
async def test_init(self): device = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) res, response = await device.res['/oic/res'].render_GET_advanced( Request(), Response()) request = Request() request.query = {'rt': ['oic.r.doxm']} res, response = await device.res['/oic/res'].render_GET_advanced( request, Response()) self.assertTrue(isinstance(device, EchoDevice), 'instance') self.assertEqual(device.get_param('/oic/p', 'mnpv'), Device.version, 'platform version ') self.assertEqual(device.get_param('/oic/d', 'sv'), device.version, 'device version') self.assertEqual(device.get_param('/oic/d', 'dmno'), EchoDevice.__name__, 'device class') self.assertEqual(device.get_param('/oic/d', 'di'), '10000000-0000-0000-0000-000000000001', 'di') self.assertEqual(device.get_param('/oic/con', 'udpCoapPort'), 11111, 'coap port from file') device = EchoDevice.init_from_file( di='10000000-0000-0000-0000-000000000001', path='{}/config/'.format(path.dirname(__file__))) self.assertTrue(isinstance(device, EchoDevice), 'instance') self.assertEqual(device.get_param('/oic/p', 'mnpv'), Device.version, 'platform version ') self.assertEqual(device.get_param('/oic/d', 'sv'), device.version, 'device version') self.assertEqual(device.get_param('/oic/d', 'dmno'), EchoDevice.__name__, 'device class') self.assertEqual(device.get_param('/oic/d', 'di'), '10000000-0000-0000-0000-000000000001', 'di') self.assertEqual(device.get_param('/oic/con', 'udpCoapPort'), 11111, 'coap port from file') pass
async def query(self, **kwargs): drivers = find_drivers() result = [] filter = kwargs.get('filter', {}) for name in drivers: try: search = filter.get('searchString') if search and name.upper().find(search.upper()) < 0: continue # if self.drivers[name].get('data') is None: driver = Device.init_from_config(class_name=name) # self.drivers[name]['handler'] = _device driver.set_device_id('') result.append( dict(_id=name, name=driver.get_device_name(), links=driver.get_discover_res(), _actions=driver.get_install_actions())) except Exception as e: pass result.sort(key=lambda x: x.get('name')) return result
async def test_discover_proxy(self): device = Device.init_from_file( di='00000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) _remote = ('192.168.1.18', 57040) device_task = await wait_run_device(device) to = ResourceLink.init_from_uri( f'coap://{_remote[0]}:{_remote[1]}/oic/sec/doxm') result1 = await device.request('retrieve', to, {}, query={'owned': ['FALSE']}) to = ResourceLink.init_from_uri( f'coap://{_remote[0]}:{_remote[1]}/oic/res') # result2 = await device.request('retrieve', to, {}, query={'rt': ['oic.r.doxm']}) result2 = await device.request('retrieve', to, {}) # _result2 = [{ # 'anchor': 'ocf://9c048f2a-cd37-4591-53f9-e700d3b04682', # 'href': '/oic/sec/doxm', # 'rt': ['oic.r.doxm'], # 'if': ['oic.if.rw', 'oic.if.baseline'], # 'p': {'bm': 1}, # 'eps': [{'ep': 'coap://192.168.1.18:58742', 'lat': 240}, {'ep': 'coaps://192.168.1.18:58743', 'lat': 240}, # {'ep': 'coap+tcp://192.168.1.18:50941', 'lat': 240}, # {'ep': 'coaps+tcp://192.168.1.18:50942', 'lat': 240}]}] print(result2) pass # await asyncio.sleep(10000) pass # di = device.get_device_id() # self.assertIn(di, result, 'device found') # device_task.cancel() # await device_task # self.assertTrue(device.coap.endpoint['IPv6']['transport'].is_closing(), 'clossing coap') # self.assertTrue(device.coap.endpoint['multicast'][0]['transport'].is_closing(), 'run IPv6 transport') pass
async def api_add_devices(self, view, **kwargs): handler, data = await self.prepare_json_request(view) items = data['items'] if items is None: # ищем все устройства items = await handler.query(data['filter']) for i, item in enumerate(items): device = Device.init_from_config(item['links']) device.save_config() di = device.get_device_id() await view.device.action_add_device({ 'di': di, 'n': device.get_device_name(), 'dmno': device.__class__.__name__ }) # add device ti db device_data = DeviceLink.init_from_device(device).to_object_data() ocf_device = OcfDevice(view.storage, account_id=view.session.get('account')) await ocf_device.update(device_data) return self.response.json_response(data['items'])
def __init__(self, **kwargs): self._running_devices = {} self.loop = None self.task = None self.queue = None Device.__init__(self, **kwargs)
async def test_just_works_otm(self): self.device = Device.init_from_file( di='10000000-0000-0000-0000-000000000001', class_name='EchoDevice', path=self.config_path) self.device_task = await wait_run_device(self.device) self.devices = await self.device.transport_layer.discovery_resource( filter={'oic/d': [{ 'n': 'Lamp' }]}, timeout=3) self.target = None for device in self.devices: if device['n'] == 'Lamp': self.target = device break if self.target is None: raise Exception('iotivity not found. please run SimpleServer') a = 1 logger = logging.getLogger('aio_dtls.protocol_dtls') logger.setLevel(logging.DEBUG) to = self.target server_uuid = self.device.get_device_id() obt_uuid = self.target['di'] endpoint = self.device.transport_layer.get_endpoint(to, secure=True) to['href'] = '/oic/sec/doxm' oic_res = await self.device.transport_layer.send_message('post', to, {'oxmsel': 0}, timeout=10000) # res = self.send_with_dtlslib(to['coaps']) data = oic_res.decode_payload() to['href'] = '/oic/sec/pstat' response = await self.device.transport_layer.send_message( 'post', to, {'om': 4}, secure=True, timeout=10000, ) # to['href'] = '/oic/sec/doxm' response = await self.device.transport_layer.send_message( 'post', to, {'deviceuuid': obt_uuid}, secure=True, timeout=10000) # to['href'] = '/oic/sec/doxm' response = await self.device.transport_layer.send_message( 'post', to, {'rowneruuid': server_uuid}, secure=True, timeout=10000) # to['href'] = '/oic/sec/acl2' response = await self.device.transport_layer.send_message( 'post', to, {'rowneruuid': server_uuid}, secure=True, timeout=10000) to['href'] = '/oic/sec/pstat' response = await self.device.transport_layer.send_message( 'post', to, {'rowneruuid': server_uuid}, secure=True, timeout=10000) to['href'] = '/oic/sec/cred' response = await self.device.transport_layer.send_message( 'post', to, { 'creds': [{ 'credtype': 1, 'subjectuuid': server_uuid, 'privatedata': { 'encoding': 'oic.sec.encoding.raw', 'data': b'' } }], 'rowneruuid': server_uuid }, secure=True, timeout=10000) to['href'] = '/oic/sec/sdi' response = await self.device.transport_layer.send_message( 'post', to, { 'uuid': '00000000-0000-0000-0000-000000000000', 'name': '', 'priv': False }, secure=True, timeout=10000) to['href'] = '/oic/sec/doxm' response = await self.device.transport_layer.send_message( 'post', to, {'owned': True}, secure=True, timeout=10000, ) from aio_dtls.tls.helper import Helper from uuid import UUID connection = endpoint.sock.connection_manager.get_connection( to['coaps']) identity_hint = UUID(obt_uuid).bytes psk = Helper.generate_owner_psk(connection, 'oic.sec.doxm.jw'.encode(), UUID(server_uuid).bytes, identity_hint) print('device uuid', UUID(obt_uuid).bytes.hex(" ")) print('psk', psk.hex(" ")) # await endpoint.send_alert() response = await self.device.transport_layer.send_message( 'post', to, {'owned': True}, secure=True, timeout=10000, identity_hint=UUID(obt_uuid).bytes, new_connection=dict( ciphers=['TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256'], psk=psk, identity_hint=identity_hint)) # import json # a = json.dumps(oic_res) await asyncio.sleep(10000) pass