def test_put_characteristic(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m1:
            with mock.patch('homekit.controller.ble_impl.DeviceManager') as m2:
                m1.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                c.pairings['test-pairing'].list_accessories_and_characteristics()

                result = c.pairings['test-pairing'].put_characteristics([
                    (1, 10, True),
                ])
                self.assertEqual(result, {})
                self.assertTrue(a.services[1].characteristics[0].get_value())

                result = c.pairings['test-pairing'].put_characteristics([
                    (1, 10, False),
                ])
                self.assertEqual(result, {})
                self.assertFalse(a.services[1].characteristics[0].get_value())
    def test_pair_unpair(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        device = manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.DeviceManager') as m1:
            with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m2:
                m1.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                c.pairings['test-pairing'].list_accessories_and_characteristics()
                self.assertEqual(len(device.peers), 1)

                c.remove_pairing('test-pairing')

                self.assertEqual(len(device.peers), 0)
                self.assertNotIn('test-pairing', c.pairings)
    def test_discovery(self):
        model_mixin.id_counter = 0

        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.controller.DiscoveryDeviceManager') as m:
            m.return_value = manager

            self.assertEqual(c.discover_ble(0), [{
                'acid': 9,
                'category': 'Thermostat',
                'cn': 2,
                'cv': 2,
                'device_id': '99:99:99:99:99:99',
                'flags': 'unpaired',
                'gsn': 3985,
                'mac': '00:00:00:00:00',
                'name': 'Test',
                'sf': 1,
            }])
Example #4
0
def setup_accessories_from_file(path):
    """Load an collection of accessory defs from JSON data."""
    with open(path, 'r') as accessories_data:
        accessories_json = json.load(accessories_data)

    accessories = []

    for accessory_data in accessories_json:
        accessory = Accessory('Name', 'Mfr', 'Model', '0001', '0.1')
        accessory.services = []
        accessory.aid = accessory_data['aid']
        for service_data in accessory_data['services']:
            service = FakeService('public.hap.service.accessory-information')
            service.type = service_data['type']
            service.iid = service_data['iid']

            for char_data in service_data['characteristics']:
                char = FakeCharacteristic(1, '23', None)
                char.type = char_data['type']
                char.iid = char_data['iid']
                char.perms = char_data['perms']
                char.format = char_data['format']
                if 'description' in char_data:
                    char.description = char_data['description']
                if 'value' in char_data:
                    char.value = char_data['value']
                service.characteristics.append(char)

            accessory.services.append(service)

        accessories.append(accessory)

    return accessories
Example #5
0
async def setup_test_component(hass, services):
    """Load a fake homekit accessory based on a homekit accessory model."""
    domain = None
    for service in services:
        service_name = ServicesTypes.get_short(service.type)
        if service_name in HOMEKIT_ACCESSORY_DISPATCH:
            domain = HOMEKIT_ACCESSORY_DISPATCH[service_name]
            break

    assert domain, 'Cannot map test homekit services to homeassistant domain'

    config = {'discovery': {}}

    with mock.patch('homekit.Controller') as controller:
        fake_controller = controller.return_value = FakeController()
        await async_setup_component(hass, DOMAIN, config)

    accessory = Accessory('TestDevice', 'example.com', 'Test', '0001', '0.1')
    accessory.services.extend(services)
    pairing = fake_controller.add(accessory)

    discovery_info = {
        'host': '127.0.0.1',
        'port': 8080,
        'properties': {
            'md': 'TestDevice',
            'id': '00:00:00:00:00:00',
            'c#': 1,
        }
    }

    fire_service_discovered(hass, SERVICE_HOMEKIT, discovery_info)
    await hass.async_block_till_done()

    return Helper(hass, '.'.join((domain, 'testdevice')), pairing, accessory)
    def test_get_characteristic_disconnected_read(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        d = manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m1:
            with mock.patch('homekit.controller.ble_impl.DeviceManager') as m2:
                m1.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                c.pairings['test-pairing'].list_accessories_and_characteristics()

                # Establishes a secure session
                c.pairings['test-pairing'].get_characteristics([(1, 4)])

                # Disconnect from virtual bluetooth device - BleSession doesn't know yet
                d.disconnect()

                # Further reads should throw an error
                self.assertRaises(
                    exceptions.AccessoryDisconnectedError,
                    c.pairings['test-pairing'].get_characteristics,
                    [(1, 4)],
                )
    def test_identify(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m1:
            with mock.patch('homekit.controller.ble_impl.DeviceManager') as m2:
                m1.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                c.pairings['test-pairing'].list_accessories_and_characteristics()

                self.assertIsNone(a.services[0].characteristics[0].value)
                c.pairings['test-pairing'].identify()
                self.assertTrue(a.services[0].characteristics[0].value)
Example #8
0
    def setUpClass(cls):
        # prepare config file for unpaired accessory server
        cls.config_file = tempfile.NamedTemporaryFile()
        cls.config_file.write("""{
              "accessory_ltpk": "7986cf939de8986f428744e36ed72d86189bea46b4dcdc8d9d79a3e4fceb92b9",
              "accessory_ltsk": "3d99f3e959a1f93af4056966f858074b2a1fdec1c5fd84a51ea96f9fa004156a",
              "accessory_pairing_id": "12:34:56:00:01:0B",
              "accessory_pin": "010-22-020",
              "c#": 0,
              "category": "Lightbulb",
              "host_ip": "127.0.0.1",
              "host_port": 54321,
              "name": "unittestLight",
              "peers": {
              },
              "unsuccessful_tries": 0
            }""".encode())
        cls.config_file.flush()

        # Make sure get_id() numbers are stable between tests
        model_mixin.id_counter = 0

        cls.httpd = AccessoryServer(cls.config_file.name, None)
        cls.httpd.set_identify_callback(identify_callback)
        accessory = Accessory('Testlicht', 'lusiardi.de', 'Demoserver', '0001',
                              '0.1')
        accessory.set_identify_callback(identify_callback)
        lightBulbService = LightBulbService()
        lightBulbService.set_on_set_callback(set_value)
        accessory.services.append(lightBulbService)
        cls.httpd.add_accessory(accessory)
        t = T(cls.httpd)
        t.start()
        time.sleep(10)
        cls.controller_file = tempfile.NamedTemporaryFile()
    def test_get_characteristic_invalid_iid(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m1:
            with mock.patch('homekit.controller.ble_impl.DeviceManager') as m2:
                m1.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                c.pairings['test-pairing'].list_accessories_and_characteristics()
                result = c.pairings['test-pairing'].get_characteristics([
                    (2, 1),
                ])

        self.assertEqual(result, {
            (2, 1): {
                "status": 6,
                "description": "Accessory was not able to perform the requested operation",
            }
        })
Example #10
0
    def setUpClass(cls):
        # prepare config file for paired accessory server, delete false for Windows, so we can close the file and open
        # it for reading after that
        cls.config_file = tempfile.NamedTemporaryFile(delete=False)
        cls.config_file.write("""{
            "accessory_ltpk": "7986cf939de8986f428744e36ed72d86189bea46b4dcdc8d9d79a3e4fceb92b9",
            "accessory_ltsk": "3d99f3e959a1f93af4056966f858074b2a1fdec1c5fd84a51ea96f9fa004156a",
            "accessory_pairing_id": "12:34:56:00:01:0A",
            "accessory_pin": "031-45-154",
            "c#": 1,
            "category": "Lightbulb",
            "host_ip": "127.0.0.1",
            "host_port": 51842,
            "name": "unittestLight",
            "peers": {
                "decc6fa3-de3e-41c9-adba-ef7409821bfc": {
                    "admin": true,
                    "key": "d708df2fbf4a8779669f0ccd43f4962d6d49e4274f88b1292f822edc3bcf8ed8"
                },
                "ABCDEFfa3-de3e-41c9-adba-ef7409821bfc": {
                    "admin": false,
                    "key": "d708df2fbf4a8779669f0ccd43f4962d6d49e4274f88b1292f822edc3bcf8ed8"
                }
            },
            "unsuccessful_tries": 0
        }""".encode())
        cls.config_file.close()

        # Make sure get_id() numbers are stable between tests
        model_mixin.id_counter = 0

        cls.logger = list()
        cls.httpd = AccessoryServer(cls.config_file.name, logger=cls.logger)
        cls.httpd.set_identify_callback(identify_callback)
        accessory = Accessory('Testlicht', 'lusiardi.de', 'Demoserver', '0001',
                              '0.1')
        accessory.set_identify_callback(identify_callback)
        lightBulbService = LightBulbService()
        lightBulbService.set_on_set_callback(set_value)
        accessory.services.append(lightBulbService)
        cls.httpd.add_accessory(accessory)
        t = T(cls.httpd)
        t.start()
        time.sleep(5)
        cls.controller_file = tempfile.NamedTemporaryFile(delete=False)
        cls.controller_file.write("""{
            "alias": {
                "Connection": "IP",
                "iOSDeviceLTPK": "d708df2fbf4a8779669f0ccd43f4962d6d49e4274f88b1292f822edc3bcf8ed8",
                "iOSPairingId": "decc6fa3-de3e-41c9-adba-ef7409821bfc",
                "AccessoryLTPK": "7986cf939de8986f428744e36ed72d86189bea46b4dcdc8d9d79a3e4fceb92b9",
                "AccessoryPairingID": "12:34:56:00:01:0A",
                "AccessoryPort": 51842,
                "AccessoryIP": "127.0.0.1",
                "iOSDeviceLTSK": "fa45f082ef87efc6c8c8d043d74084a3ea923a2253e323a7eb9917b4090c2fcc"
            }
        }""".encode())
        cls.controller_file.close()
Example #11
0
    def setUpClass(cls):
        cls.config_file = tempfile.NamedTemporaryFile()
        cls.config_file.write("""{
            "accessory_ltpk": "7986cf939de8986f428744e36ed72d86189bea46b4dcdc8d9d79a3e4fceb92b9",
            "accessory_ltsk": "3d99f3e959a1f93af4056966f858074b2a1fdec1c5fd84a51ea96f9fa004156a",
            "accessory_pairing_id": "12:34:56:00:01:0A",
            "accessory_pin": "031-45-154",
            "c#": 1,
            "category": "Lightbulb",
            "host_ip": "127.0.0.1",
            "host_port": 51842,
            "name": "unittestLight",
            "peers": {
                "decc6fa3-de3e-41c9-adba-ef7409821bfc": {
                    "admin": true,
                    "key": "d708df2fbf4a8779669f0ccd43f4962d6d49e4274f88b1292f822edc3bcf8ed8"
                }
            },
            "unsuccessful_tries": 0
        }""".encode())
        cls.config_file.flush()

        cls.httpd = AccessoryServer(cls.config_file.name, None)
        cls.httpd.set_identify_callback(identify_callback)
        accessory = Accessory('Testlicht', 'lusiardi.de', 'Demoserver', '0001',
                              '0.1')
        accessory.set_identify_callback(identify_callback)
        lightBulbService = LightBulbService()
        lightBulbService.set_on_set_callback(set_value)
        accessory.services.append(lightBulbService)
        cls.httpd.add_accessory(accessory)
        t = T(cls.httpd)
        t.start()
        time.sleep(5)
        cls.controller_file = tempfile.NamedTemporaryFile()
        cls.controller_file.write("""{
            "alias": {
                "iOSDeviceLTPK": "d708df2fbf4a8779669f0ccd43f4962d6d49e4274f88b1292f822edc3bcf8ed8",
                "iOSPairingId": "decc6fa3-de3e-41c9-adba-ef7409821bfc",
                "AccessoryLTPK": "7986cf939de8986f428744e36ed72d86189bea46b4dcdc8d9d79a3e4fceb92b9",
                "AccessoryPairingID": "12:34:56:00:01:0A",
                "AccessoryPort": 51842,
                "AccessoryIP": "127.0.0.1",
                "iOSDeviceLTSK": "fa45f082ef87efc6c8c8d043d74084a3ea923a2253e323a7eb9917b4090c2fcc"
            }
        }""".encode())
        cls.controller_file.flush()
Example #12
0
    def test_unpaired_identify(self):
        model_mixin.id_counter = 0

        c = Controller()

        a = Accessory('test-dev-123', 'TestCo', 'Test Dev Pro', '00000', 1)
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch(
                'homekit.controller.ble_impl.device.DeviceManager') as m:
            m.return_value = manager
            self.assertIsNone(a.services[0].characteristics[0].value)
            self.assertTrue(c.identify_ble('00:00:00:00:00'))
            self.assertTrue(a.services[0].characteristics[0].value)
Example #13
0
    def test_pair_malformed_pin(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory('test-dev-123', 'TestCo', 'Test Dev Pro', '00000', 1)
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch(
                'homekit.controller.ble_impl.device.DeviceManager') as m:
            m.return_value = manager
            c.perform_pairing_ble('test-pairing', '00:00:00:00:00',
                                  '111-11-111')
            self.assertRaises(exceptions.MalformedPinError,
                              c.perform_pairing_ble, 'alias2',
                              '12:34:56:00:01:0B', '01022021')
Example #14
0
    def test_pair_success(self):
        model_mixin.id_counter = 0
        c = Controller()

        a = Accessory('test-dev-123', 'TestCo', 'Test Dev Pro', '00000', 1)
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch(
                'homekit.controller.ble_impl.device.DeviceManager') as m:
            m.return_value = manager
            c.perform_pairing_ble('test-pairing', '00:00:00:00:00',
                                  '111-11-111')

        self.assertEqual(c.pairings['test-pairing'].pairing_data['Connection'],
                         'BLE')
Example #15
0
    def test_unpaired_identify_already_paired(self):
        model_mixin.id_counter = 0

        c = Controller()

        a = Accessory('test-dev-123', 'TestCo', 'Test Dev Pro', '00000', 1)
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch(
                'homekit.controller.ble_impl.device.DeviceManager') as m:
            m.return_value = manager
            c.perform_pairing_ble('test-pairing', '00:00:00:00:00',
                                  '111-11-111')
            self.assertIsNone(a.services[0].characteristics[0].value)
            self.assertRaises(exceptions.AlreadyPairedError, c.identify_ble,
                              '00:00:00:00:00')
Example #16
0
async def setup_accessories_from_file(hass, path):
    """Load an collection of accessory defs from JSON data."""
    accessories_fixture = await hass.async_add_executor_job(
        load_fixture,
        os.path.join('homekit_controller', path),
    )
    accessories_json = json.loads(accessories_fixture)

    accessories = []

    for accessory_data in accessories_json:
        accessory = Accessory('Name', 'Mfr', 'Model', '0001', '0.1')
        accessory.services = []
        accessory.aid = accessory_data['aid']
        for service_data in accessory_data['services']:
            service = FakeService('public.hap.service.accessory-information')
            service.type = service_data['type']
            service.iid = service_data['iid']

            for char_data in service_data['characteristics']:
                char = FakeCharacteristic(1, '23', None)
                char.type = char_data['type']
                char.iid = char_data['iid']
                char.perms = char_data['perms']
                char.format = char_data['format']
                if 'description' in char_data:
                    char.description = char_data['description']
                if 'value' in char_data:
                    char.value = char_data['value']
                if 'minValue' in char_data:
                    char.minValue = char_data['minValue']
                if 'maxValue' in char_data:
                    char.maxValue = char_data['maxValue']
                if 'valid-values' in char_data:
                    char.valid_values = char_data['valid-values']
                service.characteristics.append(char)

            accessory.services.append(service)

        accessories.append(accessory)

    return accessories
Example #17
0
async def setup_accessories_from_file(hass, path):
    """Load an collection of accessory defs from JSON data."""
    accessories_fixture = await hass.async_add_executor_job(
        load_fixture, os.path.join("homekit_controller", path)
    )
    accessories_json = json.loads(accessories_fixture)

    accessories = []

    for accessory_data in accessories_json:
        accessory = Accessory("Name", "Mfr", "Model", "0001", "0.1")
        accessory.services = []
        accessory.aid = accessory_data["aid"]
        for service_data in accessory_data["services"]:
            service = FakeService("public.hap.service.accessory-information")
            service.type = service_data["type"]
            service.iid = service_data["iid"]

            for char_data in service_data["characteristics"]:
                char = FakeCharacteristic(1, "23", None)
                char.type = char_data["type"]
                char.iid = char_data["iid"]
                char.perms = char_data["perms"]
                char.format = char_data["format"]
                if "description" in char_data:
                    char.description = char_data["description"]
                if "value" in char_data:
                    char.value = char_data["value"]
                if "minValue" in char_data:
                    char.minValue = char_data["minValue"]
                if "maxValue" in char_data:
                    char.maxValue = char_data["maxValue"]
                if "valid-values" in char_data:
                    char.valid_values = char_data["valid-values"]
                service.characteristics.append(char)

            accessory.services.append(service)

        accessories.append(accessory)

    return accessories
Example #18
0
async def setup_test_component(hass, services, capitalize=False, suffix=None):
    """Load a fake homekit accessory based on a homekit accessory model.

    If capitalize is True, property names will be in upper case.

    If suffix is set, entityId will include the suffix
    """
    domain = None
    for service in services:
        service_name = ServicesTypes.get_short(service.type)
        if service_name in HOMEKIT_ACCESSORY_DISPATCH:
            domain = HOMEKIT_ACCESSORY_DISPATCH[service_name]
            break

    assert domain, 'Cannot map test homekit services to homeassistant domain'

    accessory = Accessory('TestDevice', 'example.com', 'Test', '0001', '0.1')
    accessory.services.extend(services)

    pairing = await setup_test_accessories(hass, [accessory])
    entity = 'testdevice' if suffix is None else 'testdevice_{}'.format(suffix)
    return Helper(hass, '.'.join((domain, entity)), pairing, accessory)
Example #19
0
async def setup_test_component(hass, services, capitalize=False, suffix=None):
    """Load a fake homekit accessory based on a homekit accessory model.

    If capitalize is True, property names will be in upper case.

    If suffix is set, entityId will include the suffix
    """
    domain = None
    for service in services:
        service_name = ServicesTypes.get_short(service.type)
        if service_name in HOMEKIT_ACCESSORY_DISPATCH:
            domain = HOMEKIT_ACCESSORY_DISPATCH[service_name]
            break

    assert domain, "Cannot map test homekit services to Home Assistant domain"

    accessory = Accessory("TestDevice", "example.com", "Test", "0001", "0.1")
    accessory.services.extend(services)

    config_entry, pairing = await setup_test_accessories(hass, [accessory])
    entity = "testdevice" if suffix is None else "testdevice_{}".format(suffix)
    return Helper(hass, ".".join((domain, entity)), pairing, accessory,
                  config_entry)
Example #20
0
async def setup_test_component(hass, services, capitalize=False, suffix=None):
    """Load a fake homekit accessory based on a homekit accessory model.

    If capitalize is True, property names will be in upper case.

    If suffix is set, entityId will include the suffix
    """
    domain = None
    for service in services:
        service_name = ServicesTypes.get_short(service.type)
        if service_name in HOMEKIT_ACCESSORY_DISPATCH:
            domain = HOMEKIT_ACCESSORY_DISPATCH[service_name]
            break

    assert domain, 'Cannot map test homekit services to homeassistant domain'

    fake_controller = await setup_platform(hass)

    accessory = Accessory('TestDevice', 'example.com', 'Test', '0001', '0.1')
    accessory.services.extend(services)
    pairing = fake_controller.add([accessory])

    discovery_info = {
        'host': '127.0.0.1',
        'port': 8080,
        'properties': {
            ('MD' if capitalize else 'md'): 'TestDevice',
            ('ID' if capitalize else 'id'): '00:00:00:00:00:00',
            ('C#' if capitalize else 'c#'): 1,
        }
    }

    fire_service_discovered(hass, SERVICE_HOMEKIT, discovery_info)
    await hass.async_block_till_done()

    entity = 'testdevice' if suffix is None else 'testdevice_{}'.format(suffix)
    return Helper(hass, '.'.join((domain, entity)), pairing, accessory)
Example #21
0

if __name__ == '__main__':
    # setup logger
    logger = logging.getLogger('accessory')
    logger.setLevel(logging.INFO)
    ch = logging.StreamHandler()
    ch.setFormatter(logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger.addHandler(ch)
    logger.info('starting')

    try:
        httpd = AccessoryServer(os.path.expanduser('./demoserver.json'), logger)
        httpd.set_identify_callback(lambda)

        accessory = Accessory('Light', 'PheonixFi', 'Demoserver', '0001', '0.1')

        lightService = LightBulbService()
        # lightService.set_get_value_callback();
        lightService.append_characteristic(BrightnessCharacteristic(12345678901))
        # lightService.append_characteristic(HueCharacteristic(12345678902))
        accessory.services.append(lightService)
        httpd.add_accessory(accessory)

        httpd.publish_device()
        print('published device and start serving')

        httpd.serve_forever()


    except KeyboardInterrupt:
Example #22
0
def create_proxy(accessories_and_characteristics):
    """
    Create a proxy in front of a set of accessories, services and characteristics. This allows to follow the
    communication of a controller and an accessory (e.g. an iPhone and some HomeKit IP camera).

    :param accessories_and_characteristics: the accessory data as described in the spec on page 73 and following. This
    contains all the data that will be used to create the proxy.
    :return: a list of `Accessory` instances whose services and characteristics are replaced by proxied versions. That
    means characteristic's callback functions for getting and setting values relay those calls to the proxied
    characteristics.
    """
    accessories = []
    logging.info('%<------ creating proxy ------')
    for accessory in accessories_and_characteristics:
        proxy_accessory = Accessory(
            '',
            '',
            '',
            '',
            '',
        )
        aid = accessory['aid']
        proxy_accessory.aid = aid
        logging.info('accessory with aid=%s', aid)
        proxy_accessory.services = []
        accessories.append(proxy_accessory)

        for service in accessory['services']:
            service_iid = service['iid']
            service_type = service['type']
            short_type = ServicesTypes.get_short(service_type)
            logging.info('  %i.%i: >%s< (%s)', aid, service_iid, short_type,
                         service_type)

            proxy_service = ProxyService(service_iid, service_type)
            proxy_accessory.add_service(proxy_service)

            for characteristic in service['characteristics']:
                characteristic_iid = characteristic['iid']
                characteristic_type = characteristic['type']
                short_type = CharacteristicsTypes.get_short(
                    characteristic_type)
                characteristic_format = characteristic['format']
                characteristic_value = characteristic.get('value')
                characteristic_perms = characteristic['perms']
                logging.info('    %i.%i: %s >%s< (%s) [%s] %s', aid,
                             characteristic_iid, characteristic_value,
                             short_type, characteristic_type,
                             ','.join(characteristic_perms),
                             characteristic_format)

                proxy_characteristic = ProxyCharacteristic(
                    characteristic_iid, characteristic_type,
                    characteristic_format)
                proxy_service.append_characteristic(proxy_characteristic)
                if characteristic_value:
                    proxy_characteristic.value = characteristic_value
                proxy_characteristic.perms = characteristic_perms

                proxy_characteristic.set_set_value_callback(
                    generate_set_value_callback(accessory['aid'],
                                                proxy_characteristic))
                proxy_characteristic.set_get_value_callback(
                    generate_get_value_callback(accessory['aid'],
                                                proxy_characteristic))
    logging.info('%<------ finished creating proxy ------')
    return accessories
Example #23
0
import os.path

from homekit import HomeKitServer

from homekit.model import Accessory, LightBulbService


def light_switched(newval):
    print('=======>  light switched: {x}'.format(x=newval))


if __name__ == '__main__':
    try:
        httpd = HomeKitServer(os.path.expanduser('~/.homekit/demoserver.json'))

        accessory = Accessory('Testlicht')
        lightBulbService = LightBulbService()
        lightBulbService.set_on_set_callback(light_switched)
        accessory.services.append(lightBulbService)
        httpd.accessories.add_accessory(accessory)

        print(httpd.accessories.__str__())

        httpd.publish_device()
        print('published device and start serving')
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass
    print('unpublish device')
    httpd.unpublish_device()
    httpd.shutdown()
Example #24
0
    logger = logging.getLogger('accessory')
    logger.setLevel(logging.INFO)
    ch = logging.StreamHandler()
    ch.setFormatter(
        logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'))
    logger.addHandler(ch)
    logger.info('starting')

    config_file = os.path.expanduser(args.file)

    # create a server and an accessory an run it unless ctrl+c was hit
    try:
        httpd = AccessoryServer(config_file, logger)

        accessory = Accessory('Testlicht', 'lusiardi.de', 'Demoserver', '0001',
                              '0.1')
        lightBulbService = LightBulbService()
        lightBulbService.set_on_set_callback(light_switched)
        accessory.services.append(lightBulbService)
        httpd.add_accessory(accessory)

        httpd.publish_device()
        logger.info('published device and start serving')
        httpd.serve_forever()
    except KeyboardInterrupt:
        pass

    # unpublish the device and shut down
    logger.info('unpublish device')
    httpd.unpublish_device()
    httpd.shutdown()
    def test_list_accessories_and_characteristics(self):
        model_mixin.id_counter = 0

        c = Controller()

        a = Accessory(
            'test-dev-123',
            'TestCo',
            'Test Dev Pro',
            '00000',
            1
        )
        a.add_service(LightBulbService())

        manager = DeviceManager()
        manager._devices['00:00:00:00:00'] = Device(a)

        with mock.patch('homekit.controller.ble_impl.device.DeviceManager') as m:
            with mock.patch('homekit.controller.ble_impl.DeviceManager') as m2:
                m.return_value = manager
                m2.return_value = manager
                c.perform_pairing_ble('test-pairing', '00:00:00:00:00', '111-11-111')
                accessories = c.pairings['test-pairing'].list_accessories_and_characteristics()

        self.assertEqual(accessories, [
            {
                "aid": 1,
                "services": [
                    {
                        "characteristics": [
                            {
                                "iid": 3,
                                "type": "00000014-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "bool",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 4,
                                "type": "00000020-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "string",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 5,
                                "type": "00000021-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "string",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 6,
                                "type": "00000023-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "string",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 7,
                                "type": "00000030-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "string",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 8,
                                "type": "00000052-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "string",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            }
                        ],
                        "iid": 2,
                        "type": "0000003E-0000-1000-8000-0026BB765291"
                    },
                    {
                        "characteristics": [
                            {
                                "iid": 10,
                                "type": "00000025-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "bool",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            }
                        ],
                        "iid": 9,
                        "type": "00000043-0000-1000-8000-0026BB765291"
                    },
                    {
                        "characteristics": [
                            {
                                "iid": 12,
                                "type": "0000004C-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "data",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "iid": 13,
                                "type": "0000004E-0000-1000-8000-0026BB765291",
                                "perms": [],
                                "description": "",
                                "format": "data",
                                "unit": "unknown",
                                "range": None,
                                "step": None
                            },
                            {
                                "description": "",
                                "format": "data",
                                "iid": 14,
                                "perms": [],
                                "range": None,
                                "step": None,
                                "type": "00000050-0000-1000-8000-0026BB765291",
                                "unit": "unknown"}
                        ],
                        "iid": 11,
                        "type": "00000055-0000-1000-8000-0026BB765291"
                    }
                ]
            }
        ])