Beispiel #1
0
def test_loader_char():
    """Test if method returns a Characteristic object."""
    loader = Loader()

    with pytest.raises(KeyError):
        loader.get_char("Not a char")

    char_name = loader.get_char("Name")
    assert char_name is not None
    assert isinstance(char_name, Characteristic)
Beispiel #2
0
def test_loader_service():
    """Test if method returns a Service object."""
    loader = Loader()

    with pytest.raises(KeyError):
        loader.get_service("Not a service")

    serv_acc_info = loader.get_service("AccessoryInformation")
    assert serv_acc_info is not None
    assert isinstance(serv_acc_info, Service)
Beispiel #3
0
def test_get_loader():
    """Test if method returns the preloaded loader object."""
    loader = get_loader()
    assert isinstance(loader, Loader)
    assert loader.char_types is not ({} or None)
    assert loader.serv_types is not ({} or None)

    loader2 = Loader(path_char=CHARACTERISTICS_FILE,
                     path_service=SERVICES_FILE)
    assert loader.char_types == loader2.char_types
    assert loader.serv_types == loader2.serv_types

    assert get_loader() == loader
Beispiel #4
0
def test_loader_service_error():
    """Test if errors are thrown for invalid dictionary entries."""
    loader = Loader.from_dict(serv_dict={"Service": None})
    assert loader.char_types == {}
    assert loader.serv_types == {"Service": None}
    json_dicts = ({
        "RequiredCharacteristics": ["Char 1", "Char 2"]
    }, {
        "UUID": "123456"
    })

    for case in json_dicts:
        loader.serv_types["Service"] = case
        with pytest.raises(KeyError):
            loader.get_service("Service")
Beispiel #5
0
def test_loader_service_error():
    """Test if errors are thrown for invalid dictionary entries."""
    loader = Loader.from_dict(serv_dict={'Service': None})
    assert loader.char_types == {}
    assert loader.serv_types == {'Service': None}
    json_dicts = ({
        'RequiredCharacteristics': ['Char 1', 'Char 2']
    }, {
        'UUID': '123456'
    })

    for case in json_dicts:
        loader.serv_types['Service'] = case
        with pytest.raises(KeyError):
            loader.get_service('Service')
Beispiel #6
0
def test_loader_get_char_error():
    """Test if errors are thrown for invalid dictionary entries."""
    loader = Loader.from_dict(char_dict={'Char': None})
    assert loader.char_types == {'Char': None}
    assert loader.serv_types == {}
    json_dicts = ({
        'Format': 'int',
        'Permissions': 'read'
    }, {
        'Format': 'int',
        'UUID': '123456'
    }, {
        'Permissions': 'read',
        'UUID': '123456'
    })

    for case in json_dicts:
        loader.char_types['Char'] = case
        with pytest.raises(KeyError):
            loader.get_char('Char')
Beispiel #7
0
def test_loader_get_char_error():
    """Test if errors are thrown for invalid dictionary entries."""
    loader = Loader.from_dict(char_dict={"Char": None})
    assert loader.char_types == {"Char": None}
    assert loader.serv_types == {}
    json_dicts = (
        {
            "Format": "int",
            "Permissions": "read"
        },
        {
            "Format": "int",
            "UUID": "123456"
        },
        {
            "Permissions": "read",
            "UUID": "123456"
        },
    )

    for case in json_dicts:
        loader.char_types["Char"] = case
        with pytest.raises(KeyError):
            loader.get_char("Char")
Beispiel #8
0
    def __init__(self,
                 *,
                 address=None,
                 port=51234,
                 persist_file='accessory.state',
                 pincode=None,
                 encoder=None,
                 loader=None,
                 loop=None,
                 mac=None,
                 listen_address=None,
                 advertised_address=None,
                 interface_choice=None,
                 zeroconf_instance=None):
        """
        Initialize a new AccessoryDriver object.

        :param pincode: The pincode that HAP clients must prove they know in order
            to pair with this `Accessory`. Defaults to None, in which case a random
            pincode is generated. The pincode has the format "xxx-xx-xxx", where x is
            a digit.
        :type pincode: bytearray

        :param port: The local port on which the accessory will be accessible.
            In other words, this is the port of the HAPServer.
        :type port: int

        :param address: The local address on which the accessory will be accessible.
            In other words, this is the address of the HAPServer. If not given, the
            driver will try to select an address.
        :type address: str

        :param persist_file: The file name in which the state of the accessory
            will be persisted. This uses `expandvars`, so may contain `~` to
            refer to the user's home directory.
        :type persist_file: str

        :param encoder: The encoder to use when persisting/loading the Accessory state.
        :type encoder: AccessoryEncoder

        :param mac: The MAC address which will be used to identify the accessory.
            If not given, the driver will try to select a MAC address.
        :type mac: str

        :param listen_address: The local address on the HAPServer will listen.
            If not given, the value of the address parameter will be used.
        :type listen_address: str

        :param advertised_address: The address of the HAPServer announced via mDNS.
            This can be used to announce an external address from behind a NAT.
            If not given, the value of the address parameter will be used.
        :type advertised_address: str

        :param interface_choice: The zeroconf interfaces to listen on.
        :type InterfacesType: [InterfaceChoice.Default, InterfaceChoice.All]

        :param zeroconf_instance: A Zeroconf instance. When running multiple accessories or
            bridges a single zeroconf instance can be shared to avoid the overhead
            of processing the same data multiple times.
        """
        if loop is None:
            if sys.platform == 'win32':
                loop = asyncio.ProactorEventLoop()
            else:
                loop = asyncio.new_event_loop()

            executor_opts = {'max_workers': None}
            if sys.version_info >= (3, 6):
                executor_opts['thread_name_prefix'] = 'SyncWorker'

            self.executor = ThreadPoolExecutor(**executor_opts)
            loop.set_default_executor(self.executor)
        else:
            self.executor = None

        self.loop = loop

        self.accessory = None
        self.http_server_thread = None
        if zeroconf_instance is not None:
            self.advertiser = zeroconf_instance
        elif interface_choice is not None:
            self.advertiser = Zeroconf(interfaces=interface_choice)
        else:
            self.advertiser = Zeroconf()
        self.persist_file = os.path.expanduser(persist_file)
        self.encoder = encoder or AccessoryEncoder()
        self.topics = {}  # topic: set of (address, port) of subscribed clients
        self.topic_lock = threading.Lock(
        )  # for exclusive access to the topics
        self.loader = loader or Loader()
        self.aio_stop_event = asyncio.Event(loop=loop)
        self.stop_event = threading.Event()
        self.event_queue = (
            queue.SimpleQueue()
            if hasattr(queue, "SimpleQueue") else queue.Queue()  # pylint: disable=no-member
        )
        self.send_event_thread = None  # the event dispatch thread
        self.sent_events = 0
        self.accumulated_qsize = 0

        self.safe_mode = False

        self.mdns_service_info = None
        self.srp_verifier = None

        address = address or util.get_local_address()
        advertised_address = advertised_address or address
        self.state = State(address=advertised_address,
                           mac=mac,
                           pincode=pincode,
                           port=port)

        listen_address = listen_address or address
        network_tuple = (listen_address, self.state.port)
        self.http_server = HAPServer(network_tuple, self)
Beispiel #9
0
 def __init__(self):
     self.loader = Loader()
Beispiel #10
0
    def __init__(
        self,
        *,
        address=None,
        port=51234,
        persist_file="accessory.state",
        pincode=None,
        encoder=None,
        loader=None,
        loop=None,
        mac=None,
        listen_address=None,
        advertised_address=None,
        interface_choice=None,
        zeroconf_instance=None
    ):
        if loop is None:
            if sys.platform == "win32":
                loop = asyncio.ProactorEventLoop()
            else:
                loop = asyncio.new_event_loop()

            executor_opts = {"max_workers": None}
            if sys.version_info >= (3, 6):
                executor_opts["thread_name_prefix"] = "SyncWorker"

            self.executor = ThreadPoolExecutor(**executor_opts)
            loop.set_default_executor(self.executor)
            self.tid = threading.current_thread()
        else:
            self.tid = threading.main_thread()
            self.executor = None

        self.loop = loop

        self.accessory = None
        if zeroconf_instance is not None:
            self.advertiser = zeroconf_instance
        elif interface_choice is not None:
            self.advertiser = Zeroconf(interfaces=interface_choice)
        else:
            self.advertiser = Zeroconf()
        self.persist_file = os.path.expanduser(persist_file)
        self.encoder = encoder or AccessoryEncoder()
        self.topics = {}  # topic: set of (address, port) of subscribed clients
        self.loader = loader or Loader()
        self.aio_stop_event = asyncio.Event(loop=loop)
        self.stop_event = threading.Event()

        self.safe_mode = False

        self.mdns_service_info = None
        self.srp_verifier = None

        address = address or util.get_local_address()
        advertised_address = advertised_address or address
        self.state = State(
            address=advertised_address, mac=mac, pincode=pincode, port=port
        )

        listen_address = listen_address or address
        network_tuple = (listen_address, self.state.port)
        self.http_server = Server(network_tuple, self)
    def __init__(self,
                 *,
                 address=None,
                 port=51234,
                 persist_file='accessory.state',
                 pincode=None,
                 encoder=None,
                 loader=None,
                 loop=None):
        """
        Initialize a new AccessoryDriver object.

        :param pincode: The pincode that HAP clients must prove they know in order
            to pair with this `Accessory`. Defaults to None, in which case a random
            pincode is generated. The pincode has the format "xxx-xx-xxx", where x is
            a digit.
        :type pincode: bytearray

        :param port: The local port on which the accessory will be accessible.
            In other words, this is the port of the HAPServer.
        :type port: int

        :param address: The local address on which the accessory will be accessible.
            In other words, this is the address of the HAPServer. If not given, the
            driver will try to select an address.
        :type address: str

        :param persist_file: The file name in which the state of the accessory
            will be persisted. This uses `expandvars`, so may contain `~` to
            refer to the user's home directory.
        :type persist_file: str

        :param encoder: The encoder to use when persisting/loading the Accessory state.
        :type encoder: AccessoryEncoder
        """
        if sys.platform == 'win32':
            self.loop = loop or asyncio.ProactorEventLoop()
        else:
            self.loop = loop or asyncio.new_event_loop()

        executer_opts = {'max_workers': None}
        if sys.version_info >= (3, 6):
            executer_opts['thread_name_prefix'] = 'SyncWorker'

        self.executer = ThreadPoolExecutor(**executer_opts)
        self.loop.set_default_executor(self.executer)

        self.accessory = None
        self.http_server_thread = None
        self.advertiser = Zeroconf()
        self.persist_file = os.path.expanduser(persist_file)
        self.encoder = encoder or AccessoryEncoder()
        self.topics = {}  # topic: set of (address, port) of subscribed clients
        self.topic_lock = threading.Lock(
        )  # for exclusive access to the topics
        self.loader = loader or Loader()
        self.aio_stop_event = asyncio.Event(loop=self.loop)
        self.stop_event = threading.Event()
        self.event_queue = queue.Queue()  # (topic, bytes)
        self.send_event_thread = None  # the event dispatch thread
        self.sent_events = 0
        self.accumulated_qsize = 0

        self.mdns_service_info = None
        self.srp_verifier = None
        self.accessory_thread = None

        self.state = State(address=address, pincode=pincode, port=port)
        network_tuple = (self.state.address, self.state.port)
        self.http_server = HAPServer(network_tuple, self)
Beispiel #12
0
async def run_server():
    server = await asyncio.start_server(handle_client, 'localhost', 8888)
    async with server:
        await server.serve_forever()


# asyncio.run(run_server())

#
# def get_bridge(driver):
#     bridge = GardenBridge.GardenBridge(driver)
#
#     return bridge
#
#
glob.loader = Loader(path_char=HAP_PYTHON_CHARACTERISTICS_FILE,
                     path_service=HAP_PYTHON_SERVICES_FILE)

glob.driver = AccessoryDriver(port=51826,
                              persist_file=HAP_PYTHON_ACCESSORIES_FILE,
                              loader=glob.loader)

hub = load_hub_config(hub)

accessories = load_homekit_accessory_config(accessories)
setup_accessories(hub, accessories)

resource.setrlimit(resource.RLIMIT_NOFILE, (65536, 65536))

signal.signal(signal.SIGTERM, glob.driver.signal_handler)

glob.driver.start()