def test_persist_cannot_write(async_zeroconf): with tempfile.NamedTemporaryFile(mode="r+") as file: with patch("pyhap.accessory_driver.HAPServer"): driver = AccessoryDriver(port=51234, persist_file=file.name) driver.persist_file = "/file/that/will/not/exist" with pytest.raises(OSError): driver.persist()
def __init__(self, hub_name, user, device, listen_address=None): logging.basicConfig(level=logging.INFO, format="[%(module)s] %(message)s") # Initialize my coup self.hub_name = hub_name coup = RemoteCoup(user, device) # Start the accessory on port 51826 if listen_address: self.driver = AccessoryDriver(port=51826, address=listen_address) else: self.driver = AccessoryDriver(port=51826) self.bridge = Bridge(self.driver, self.hub_name) # Setup run and coup lights while True: status = coup.get_status() if (status is None) or ('Coup' not in status) or ('Lights' not in status['Coup']): logger.error("Status has not been initialized or lights missing: Status = {0} at {1}".format(status, datetime.now())) else: for light in status['Coup']['Lights']: logger.info("Adding %s", light) runlight = RemoteGardenLight(self.driver, name=light, coup=coup) self.bridge.add_accessory(runlight) break time.sleep(5) # Change `get_accessory` to `get_bridge` if you want to run a Bridge. self.driver.add_accessory(accessory=self.bridge) # We want SIGTERM (terminate) to be handled by the driver itself, # so that it can gracefully stop the accessory, server and advertising. signal.signal(signal.SIGTERM, self.driver.signal_handler)
async def test_start_service_and_update_config(): """Test starting service and updating the config.""" with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock ), patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) acc = Accessory(driver, "TestAcc") driver.add_accessory(acc) await driver.async_start() assert driver.state.config_version == 2 driver.config_changed() assert driver.state.config_version == 3 driver.state.config_version = 65535 driver.config_changed() assert driver.state.config_version == 1 for _ in range(3): await asyncio.sleep(0) await driver.async_stop() await asyncio.sleep(0) assert not driver.loop.is_closed() assert driver.aio_stop_event.is_set()
def main(): # init logger logger = logging.getLogger('homekit-flux-led') formatter = logging.Formatter('[%(levelname)s %(asctime)s]: %(message)s') ch = logging.StreamHandler() ch.setFormatter(formatter) logger.addHandler(ch) # parse cli-arguments parser = argparse.ArgumentParser() parser.add_argument( '-v', '--verbose', help='DEBUG logging mode', action='store_true', ) args = parser.parse_args() # set loggin level if args.verbose: logger.setLevel(logging.DEBUG) logger.info('Logging level: DEBUG') else: logger.setLevel(logging.INFO) logger.info('Logging level: INFO') # scan for bulbs logger.debug('Scanning for lightbulbs') scanner = BulbScanner() scanner.scan() logger.debug(f'Found lightbulbs:') logger.debug(scanner.found_bulbs) # initialize AccessoryServer logger.debug('Create HomeKit-AccessoryServer...') driver = AccessoryDriver() bridge = Bridge(driver, 'MagicHome') logger.debug('HomeKit-AccessoryServer created successful.') for bulb in scanner.found_bulbs: # add bulbs to bridge logger bridge.add_accessory( FluxLED( driver, bulb['id'], bulb['ipaddr'], logger=logger, ), ) # add bridge to the driver driver.add_accessory(bridge) try: # start the server logger.info('Start server...') driver.start() except KeyboardInterrupt: logger.info('Stopping server...') driver.stop()
def hk_driver(): """Return a custom AccessoryDriver instance for HomeKit accessory init.""" with patch('pyhap.accessory_driver.Zeroconf'), \ patch('pyhap.accessory_driver.AccessoryEncoder'), \ patch('pyhap.accessory_driver.HAPServer'), \ patch('pyhap.accessory_driver.AccessoryDriver.publish'): return AccessoryDriver(pincode=b'123-45-678', address='127.0.0.1')
def test_external_zeroconf(): zeroconf = MagicMock() with patch("pyhap.accessory_driver.HAPServer"), patch( "pyhap.accessory_driver.AccessoryDriver.persist" ): driver = AccessoryDriver(port=51234, async_zeroconf_instance=zeroconf) assert driver.advertiser == zeroconf
def hk_driver(): """Return a custom AccessoryDriver instance for HomeKit accessory init.""" with patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryEncoder"), patch( "pyhap.accessory_driver.HAPServer"), patch( "pyhap.accessory_driver.AccessoryDriver.publish"): return AccessoryDriver(pincode=b"123-45-678", address="127.0.0.1")
async def test_idle_connection_cleanup(): """Test we cleanup idle connections.""" loop = asyncio.get_event_loop() addr_info = ("0.0.0.0", None) client_1_addr_info = ("1.2.3.4", 44433) with patch.object( hap_server, "IDLE_CONNECTION_CHECK_INTERVAL_SECONDS", 0), patch("pyhap.accessory_driver.AsyncZeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=loop) server = hap_server.HAPServer(addr_info, driver) await server.async_start(loop) check_idle = MagicMock() server.connections[client_1_addr_info] = MagicMock( check_idle=check_idle) for _ in range(3): await asyncio.sleep(0) assert check_idle.called check_idle.reset_mock() for _ in range(3): await asyncio.sleep(0) assert check_idle.called server.async_stop()
async def test_call_async_add_job_with_callback(driver, async_zeroconf): """Test calling async_add_job with a coroutine.""" with patch("pyhap.accessory_driver.HAPServer"), patch( "pyhap.accessory_driver.AccessoryDriver.persist" ), patch("pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) called = False @util.callback def callback_test(): nonlocal called called = True driver.async_add_job(callback_test) await asyncio.sleep(0) await asyncio.sleep(0) assert called is True
def start_homekit(mon=None, port=PORT, host=None, monitoring=True, handle_sigint=True): logging.basicConfig(level=logging.INFO) acc = CO2Accessory(mon=mon, pincode=PINCODE, monitoring=monitoring) # Start the accessory on selected port driver = AccessoryDriver(acc, port=port, address=host) # We want KeyboardInterrupts and SIGTERM (kill) to be handled by the driver itself, # so that it can gracefully stop the accessory, server and advertising. if handle_sigint: signal.signal(signal.SIGINT, driver.signal_handler) signal.signal(signal.SIGTERM, driver.signal_handler) # Start it! driver.start() return driver
def start_driver(self, event): """Start the accessory driver.""" from pyhap.accessory_driver import AccessoryDriver self._hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.stop_driver) import_types() _LOGGER.debug("Start adding accessories.") for state in self._hass.states.all(): acc = get_accessory(self._hass, state) if acc is not None: self.bridge.add_accessory(acc) ip_address = get_local_ip() path = self._hass.config.path(HOMEKIT_FILE) self.driver = AccessoryDriver(self.bridge, self._port, ip_address, path) _LOGGER.debug("Driver started") self.driver.start()
def test_persist_load(async_zeroconf): with tempfile.NamedTemporaryFile(mode="r+") as file: with patch("pyhap.accessory_driver.HAPServer"): driver = AccessoryDriver(port=51234, persist_file=file.name) driver.persist() pk = driver.state.public_key # Re-start driver with a "new" accessory. State gets loaded into # the new accessory. driver = AccessoryDriver(port=51234, persist_file=file.name) driver.load() assert driver.state.public_key == pk
def run_driver(hass): """Return a custom AccessoryDriver instance for HomeKit accessory init.""" with patch("pyhap.accessory_driver.AsyncZeroconf"), patch( "pyhap.accessory_driver.AccessoryEncoder"), patch( "pyhap.accessory_driver.HAPServer"), patch( "pyhap.accessory_driver.AccessoryDriver.publish"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"): yield AccessoryDriver(pincode=b"123-45-678", address="127.0.0.1", loop=hass.loop)
def test_persist_load(): def get_acc(): return Accessory("Test Accessory") fp = tempfile.NamedTemporaryFile(mode="r+") persist_file = fp.name fp.close() try: acc = get_acc() pk = acc.public_key # Create driver - state gets stored driver = AccessoryDriver(acc, 51234, persist_file=persist_file) # Re-start driver with a "new" accessory. State gets loaded into # the new accessory. del driver driver = AccessoryDriver(get_acc(), 51234, persist_file=persist_file) # Check pk is the same, i.e. that the state is indeed loaded. assert driver.accessory.public_key == pk finally: os.remove(persist_file)
async def test_we_can_connect(): """Test we can start, connect, and stop.""" loop = asyncio.get_event_loop() with patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist" ): driver = AccessoryDriver(loop=loop) driver.add_accessory(Accessory(driver, "TestAcc")) addr_info = ("0.0.0.0", None) server = hap_server.HAPServer(addr_info, driver) await server.async_start(loop) sock = server.server.sockets[0] assert server.connections == {} _, port = sock.getsockname() _, writer = await asyncio.open_connection("127.0.0.1", port) assert server.connections != {} server.async_stop() writer.close()
async def test_bridge_with_multiple_sync_run_at_interval_accessories(): with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock ), patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) bridge = Bridge(driver, "mybridge") acc = SyncIntervalAccessory(driver, "TestAcc", aid=2) acc2 = SyncIntervalAccessory(driver, "TestAcc2", aid=3) acc3 = SyncIntervalAccessory(driver, "TestAcc3", aid=4) bridge.add_accessory(acc) bridge.add_accessory(acc2) bridge.add_accessory(acc3) driver.add_accessory(bridge) driver.start_service() await asyncio.sleep(0.5) assert not driver.loop.is_closed() await driver.async_stop() assert acc.counter > 2 assert acc2.counter > 2 assert acc3.counter > 2
def create_driver(loop, core_alarm): config = core_alarm.config.get('homekit', {}) use_bridge = core_alarm.sensors or config.get('use_bridge', False) driver = AccessoryDriver(loop=loop, port=config.get('port', 51001)) alarm = Alarm(driver, core_alarm, config) alarm.set_info_service(model=core_alarm.model, manufacturer='Jablotron', serial_number=core_alarm.serial_number, firmware_revision=core_alarm.firmware_version) if use_bridge: bridge = Bridge(driver, display_name='Jablotron Bridge') bridge.set_info_service(model=core_alarm.model, manufacturer='Jablotron', serial_number=core_alarm.serial_number, firmware_revision=core_alarm.firmware_version) bridge.add_accessory(alarm) for s in core_alarm.sensors.values(): bridge.add_accessory(create_sensor_accessory(driver, s)) driver.add_accessory(bridge) else: driver.add_accessory(alarm) return driver
async def test_start_stop_async_acc(): """Verify run_at_interval closes the driver.""" with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock ), patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) run_event = asyncio.Event() class Acc(Accessory): @Accessory.run_at_interval(0) async def run(self): run_event.set() def setup_message(self): pass acc = Acc(driver, "TestAcc") driver.add_accessory(acc) driver.start_service() await asyncio.sleep(0) await run_event.wait() assert not driver.loop.is_closed() await driver.async_stop() assert not driver.loop.is_closed()
class HomeKit(): """Class to handle all actions between HomeKit and Home Assistant.""" def __init__(self, hass, port): """Initialize a HomeKit object.""" self._hass = hass self._port = port self.bridge = None self.driver = None def setup_bridge(self, pin): """Setup the bridge component to track all accessories.""" from .accessories import HomeBridge self.bridge = HomeBridge(BRIDGE_NAME, 'homekit.bridge', pin) def start_driver(self, event): """Start the accessory driver.""" from pyhap.accessory_driver import AccessoryDriver self._hass.bus.listen_once( EVENT_HOMEASSISTANT_STOP, self.stop_driver) import_types() _LOGGER.debug("Start adding accessories.") for state in self._hass.states.all(): acc = get_accessory(self._hass, state) if acc is not None: self.bridge.add_accessory(acc) ip_address = get_local_ip() path = self._hass.config.path(HOMEKIT_FILE) self.driver = AccessoryDriver(self.bridge, self._port, ip_address, path) _LOGGER.debug("Driver started") self.driver.start() def stop_driver(self, event): """Stop the accessory driver.""" _LOGGER.debug("Driver stop") if self.driver is not None: self.driver.stop()
async def test_start_from_async_stop_from_executor(): with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock ), patch("pyhap.accessory_driver.Zeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) run_event = asyncio.Event() class Acc(Accessory): @Accessory.run_at_interval(0) def run(self): # pylint: disable=invalid-overridden-method run_event.set() def setup_message(self): pass acc = Acc(driver, "TestAcc") driver.add_accessory(acc) driver.start_service() await run_event.wait() assert not driver.loop.is_closed() await driver.loop.run_in_executor(None, driver.stop) await driver.aio_stop_event.wait()
class Homekit(): """Class to handle all actions between homekit and Home Assistant.""" def __init__(self, hass, port): """Initialize a homekit object.""" self._hass = hass self._port = port self.bridge = None self.driver = None def setup_bridge(self, pin): """Setup the bridge component to track all accessories.""" from .accessories import HomeBridge self.bridge = HomeBridge(BRIDGE_NAME, pincode=pin) self.bridge.set_accessory_info('homekit.bridge') def start_driver(self, event): """Start the accessory driver.""" from pyhap.accessory_driver import AccessoryDriver self._hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, self.stop_driver) import_types() _LOGGER.debug("Start adding accessories.") for state in self._hass.states.all(): acc = get_accessory(self._hass, state) if acc is not None: self.bridge.add_accessory(acc) ip_address = get_local_ip() path = self._hass.config.path(HOMEKIT_FILE) self.driver = AccessoryDriver(self.bridge, self._port, ip_address, path) _LOGGER.debug("Driver started") self.driver.start() def stop_driver(self, event): """Stop the accessory driver.""" _LOGGER.debug("Driver stop") if self.driver is not None: self.driver.stop()
def driver(async_zeroconf): try: loop = asyncio.get_event_loop() except RuntimeError: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock), patch( "pyhap.accessory_driver.AccessoryDriver.persist"): yield AccessoryDriver(loop=loop)
def mock_hap(loop, mock_zeroconf): """Return a custom AccessoryDriver instance for HomeKit accessory init.""" with patch("pyhap.accessory_driver.AsyncZeroconf"), patch( "pyhap.accessory_driver.AccessoryEncoder" ), patch("pyhap.accessory_driver.HAPServer.async_stop"), patch( "pyhap.accessory_driver.HAPServer.async_start" ), patch("pyhap.accessory_driver.AccessoryDriver.publish"), patch( "pyhap.accessory_driver.AccessoryDriver.async_start"), patch( "pyhap.accessory_driver.AccessoryDriver.async_stop"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"): yield AccessoryDriver(pincode=b"123-45-678", address="127.0.0.1", loop=loop)
async def test_call_async_add_job_with_coroutine(driver): """Test calling async_add_job with a coroutine.""" with patch("pyhap.accessory_driver.HAPServer"), patch( "pyhap.accessory_driver.AccessoryDriver.persist" ), patch("pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) called = False async def coro_test(): nonlocal called called = True await driver.async_add_job(coro_test) assert called is True called = False await driver.async_add_job(coro_test()) assert called is True
def homekit(): # Start the accessory on port 51826 driver = AccessoryDriver(port=51826) # Change `get_accessory` to `get_bridge` if you want to run a Bridge. driver.add_accessory(accessory=get_accessory(driver)) # We want SIGTERM (kill) to be handled by the driver itself, # so that it can gracefully stop the accessory, server and advertising. signal.signal(signal.SIGTERM, driver.signal_handler) # Start it! driver.start()
def start_homekit(co2meter): # Start the accessory on port 51826 driver = AccessoryDriver(port=51826) driver.add_accessory(accessory=CO2Sensor( co2meter=co2meter, driver=driver, display_name="CO2 Sensor")) # We want SIGTERM (terminate) to be handled by the driver itself, # so that it can gracefully stop the accessory, server and advertising. signal.signal(signal.SIGTERM, driver.signal_handler) # Start it! driver.start()
def main(args): import logging import signal from pyhap.accessory_driver import AccessoryDriver logging.basicConfig(level=logging.INFO) driver = AccessoryDriver(port=args.port) accessory = MiFan(args, driver, 'Fanv2') driver.add_accessory(accessory=accessory) signal.signal(signal.SIGTERM, driver.signal_handler) driver.start()
def start_driver(self, event): """Start the accessory driver.""" from pyhap.accessory_driver import AccessoryDriver self._hass.bus.listen_once( EVENT_HOMEASSISTANT_STOP, self.stop_driver) import_types() _LOGGER.debug("Start adding accessories.") for state in self._hass.states.all(): acc = get_accessory(self._hass, state) if acc is not None: self.bridge.add_accessory(acc) ip_address = get_local_ip() path = self._hass.config.path(HOMEKIT_FILE) self.driver = AccessoryDriver(self.bridge, self._port, ip_address, path) _LOGGER.debug("Driver started") self.driver.start()
def main(): import logging import signal from pyhap.accessory_driver import AccessoryDriver logging.basicConfig(level=logging.INFO) driver = AccessoryDriver(port=51826) accessory = TV(driver, 'TV') driver.add_accessory(accessory=accessory) signal.signal(signal.SIGTERM, driver.signal_handler) driver.start()
async def test_bridge_run_stop(): with patch("pyhap.accessory_driver.HAPServer.async_stop", new_callable=AsyncMock), patch( "pyhap.accessory_driver.HAPServer.async_start", new_callable=AsyncMock ), patch("pyhap.accessory_driver.AsyncZeroconf"), patch( "pyhap.accessory_driver.AccessoryDriver.persist"), patch( "pyhap.accessory_driver.AccessoryDriver.load"): driver = AccessoryDriver(loop=asyncio.get_event_loop()) bridge = Bridge(driver, "Test Bridge") acc = TestAccessory(driver, "Test Accessory", aid=2) assert acc.available is True bridge.add_accessory(acc) acc2 = TestAccessory(driver, "Test Accessory 2") bridge.add_accessory(acc2) await bridge.run() await bridge.stop() assert acc.stopped is True assert acc2.stopped is True
def test_cfg_loader(config_dir): # start the accessory driver on port 51826 driver = AccessoryDriver(port=51826) # load accs loader = cfg_loader.CfgLoader(driver, config_dir) accs = loader.load_accessories(False) assert len(accs) == 2 assert 'topic_in' in \ accs[0].services[1].characteristics[0].properties.keys() assert 'topic_in' in \ accs[1].services[1].characteristics[0].properties.keys() # save accs loader.save_accessories() cfg = configparser.ConfigParser() cfg.optionxform = str fname = os.path.join('test_config', 'lamp.cfg') cfg.fname = fname cfg.read(fname) assert 'AID' in cfg['Accessory'].keys()
def main(cfg, reset, setup_systemd): # init logging logging.basicConfig(level=logging.INFO) if reset: # remove accessory.state os.remove('accessory.state') if setup_systemd: systmd() # create config if necessary if not os.path.exists(os.path.join(cfg, 'bridge.cfg')): create_cfg(cfg) # start the accessory driver on port 51826 driver = AccessoryDriver(port=51826) # create bridge bridge = MqttBridge(cfg, driver, 'MQTT') # load accs loader = cfg_loader.CfgLoader(driver, cfg) accs = loader.load_accessories(reset) for acc in accs: bridge.add_accessory(acc) loader.save_accessories() # add the bridge driver.add_accessory(accessory=bridge) signal.signal(signal.SIGTERM, driver.signal_handler) # start HomeKit driver.start() print('Returned') return 0
os.popen("chmod 777 /tmp/pi_player.sh") os.popen("/tmp/pi_player.sh &") else: print("Stopping all music...") os.popen("killall -9 -q pi_player.sh") os.popen("killall -9 -q omxplayer.bin") def next_track(self): print("Next track...") os.popen("killall -9 -q omxplayer.bin") print("Starting Pi Playlist...") playlist = PiPlaylist("Pi Playlist") driver = AccessoryDriver(playlist, port=51826) paired_devices = [] for k,v in playlist.paired_clients.items(): paired_devices.append(k) if len(sys.argv) > 1: if sys.argv[1] == "-unpair": print("Removing paired devices...") for p in paired_devices: playlist.remove_paired_client(p) else: playlist.music_folder = sys.argv[1] for p in paired_devices: print("Paired with: {}".format(p))