예제 #1
0
    def setup(self, async_zeroconf_instance):
        """Set up bridge and accessory driver."""
        ip_addr = self._ip_address or get_local_ip()
        persist_file = get_persist_fullpath_for_entry_id(
            self.opp, self._entry_id)

        self.driver = HomeDriver(
            self.opp,
            self._entry_id,
            self._name,
            self._entry_title,
            loop=self.opp.loop,
            address=ip_addr,
            port=self._port,
            persist_file=persist_file,
            advertised_address=self._advertise_ip,
            async_zeroconf_instance=async_zeroconf_instance,
        )

        # If we do not load the mac address will be wrong
        # as pyhap uses a random one until state is restored
        if os.path.exists(persist_file):
            self.driver.load()
            self.driver.state.config_version += 1
            if self.driver.state.config_version > 65535:
                self.driver.state.config_version = 1

        self.driver.persist()
예제 #2
0
async def async_setup_entry(opp, config_entry):
    """Set up an emulated roku server from a config entry."""
    config = config_entry.data

    if DOMAIN not in opp.data:
        opp.data[DOMAIN] = {}

    name = config[CONF_NAME]
    listen_port = config[CONF_LISTEN_PORT]
    host_ip = config.get(CONF_HOST_IP) or util.get_local_ip()
    advertise_ip = config.get(CONF_ADVERTISE_IP)
    advertise_port = config.get(CONF_ADVERTISE_PORT)
    upnp_bind_multicast = config.get(CONF_UPNP_BIND_MULTICAST)

    server = EmulatedRoku(
        opp,
        name,
        host_ip,
        listen_port,
        advertise_ip,
        advertise_port,
        upnp_bind_multicast,
    )

    opp.data[DOMAIN][name] = server

    return await server.setup()
예제 #3
0
async def _async_register_opp_zc_service(opp: OpenPeerPower,
                                         aio_zc: HaAsyncZeroconf,
                                         uuid: str) -> None:
    # Get instance UUID
    valid_location_name = _truncate_location_name_to_valid(
        opp.config.location_name)

    params = {
        "location_name": valid_location_name,
        "uuid": uuid,
        "version": __version__,
        "external_url": "",
        "internal_url": "",
        # Old base URL, for backward compatibility
        "base_url": "",
        # Always needs authentication
        "requires_api_password": True,
    }

    # Get instance URL's
    with suppress(NoURLAvailableError):
        params["external_url"] = get_url(opp, allow_internal=False)

    with suppress(NoURLAvailableError):
        params["internal_url"] = get_url(opp, allow_external=False)

    # Set old base URL based on external or internal
    params["base_url"] = params["external_url"] or params["internal_url"]

    host_ip = util.get_local_ip()

    try:
        host_ip_pton = socket.inet_pton(socket.AF_INET, host_ip)
    except OSError:
        host_ip_pton = socket.inet_pton(socket.AF_INET6, host_ip)

    _suppress_invalid_properties(params)

    info = ServiceInfo(
        ZEROCONF_TYPE,
        name=f"{valid_location_name}.{ZEROCONF_TYPE}",
        server=f"{uuid}.local.",
        addresses=[host_ip_pton],
        port=opp.http.server_port,
        properties=params,
    )

    _LOGGER.info("Starting Zeroconf broadcast")
    try:
        await aio_zc.async_register_service(info)
    except NonUniqueNameException:
        _LOGGER.error(
            "Open Peer Power instance with identical name present in the local network"
        )
예제 #4
0
async def async_setup_platform(opp: OpenPeerPower,
                               config,
                               async_add_entities,
                               discovery_info=None):
    """Set up DLNA DMR platform."""
    if config.get(CONF_URL) is not None:
        url = config[CONF_URL]
        name = config.get(CONF_NAME)
    elif discovery_info is not None:
        url = discovery_info["ssdp_description"]
        name = discovery_info.get("name")

    if DLNA_DMR_DATA not in opp.data:
        opp.data[DLNA_DMR_DATA] = {}

    if "lock" not in opp.data[DLNA_DMR_DATA]:
        opp.data[DLNA_DMR_DATA]["lock"] = asyncio.Lock()

    # build upnp/aiohttp requester
    session = async_get_clientsession(opp)
    requester = AiohttpSessionRequester(session, True)

    # ensure event handler has been started
    async with opp.data[DLNA_DMR_DATA]["lock"]:
        server_host = config.get(CONF_LISTEN_IP)
        if server_host is None:
            server_host = get_local_ip()
        server_port = config.get(CONF_LISTEN_PORT, DEFAULT_LISTEN_PORT)
        callback_url_override = config.get(CONF_CALLBACK_URL_OVERRIDE)
        event_handler = await async_start_event_handler(
            opp, server_host, server_port, requester, callback_url_override)

    # create upnp device
    factory = UpnpFactory(requester, non_strict=True)
    try:
        upnp_device = await factory.async_create_device(url)
    except (asyncio.TimeoutError, aiohttp.ClientError) as err:
        raise PlatformNotReady() from err

    # wrap with DmrDevice
    dlna_device = DmrDevice(upnp_device, event_handler)

    # create our own device
    device = DlnaDmrDevice(dlna_device, name)
    _LOGGER.debug("Adding device: %s", device)
    async_add_entities([device], True)
예제 #5
0
    def setup(self):
        """Set up bridge and accessory driver."""
        # pylint: disable=import-outside-toplevel
        from .accessories import HomeBridge, HomeDriver

        self.opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, self.stop)

        ip_addr = self._ip_address or get_local_ip()
        path = self.opp.config.path(HOMEKIT_FILE)
        self.driver = HomeDriver(
            self.opp,
            address=ip_addr,
            port=self._port,
            persist_file=path,
            advertised_address=self._advertise_ip,
        )
        self.bridge = HomeBridge(self.opp, self.driver, self._name)
        if self._safe_mode:
            _LOGGER.debug("Safe_mode selected")
            self.driver.safe_mode = True
예제 #6
0
    def __init__(self, opp, conf):
        """Initialize the instance."""
        self.opp = opp
        self.type = conf.get(CONF_TYPE)
        self.numbers = None
        self.store = None
        self.cached_states = {}
        self._exposed_cache = {}

        if self.type == TYPE_ALEXA:
            _LOGGER.warning(
                "Emulated Hue running in legacy mode because type has been "
                "specified. More info at https://goo.gl/M6tgz8")

        # Get the IP address that will be passed to the Echo during discovery
        self.host_ip_addr = conf.get(CONF_HOST_IP)
        if self.host_ip_addr is None:
            self.host_ip_addr = util.get_local_ip()
            _LOGGER.info(
                "Listen IP address not specified, auto-detected address is %s",
                self.host_ip_addr,
            )

        # Get the port that the Hue bridge will listen on
        self.listen_port = conf.get(CONF_LISTEN_PORT)
        if not isinstance(self.listen_port, int):
            self.listen_port = DEFAULT_LISTEN_PORT
            _LOGGER.info("Listen port not specified, defaulting to %s",
                         self.listen_port)

        # Get whether or not UPNP binds to multicast address (239.255.255.250)
        # or to the unicast address (host_ip_addr)
        self.upnp_bind_multicast = conf.get(CONF_UPNP_BIND_MULTICAST,
                                            DEFAULT_UPNP_BIND_MULTICAST)

        # Get domains that cause both "on" and "off" commands to map to "on"
        # This is primarily useful for things like scenes or scripts, which
        # don't really have a concept of being off
        self.off_maps_to_on_domains = conf.get(CONF_OFF_MAPS_TO_ON_DOMAINS)
        if not isinstance(self.off_maps_to_on_domains, list):
            self.off_maps_to_on_domains = DEFAULT_OFF_MAPS_TO_ON_DOMAINS

        # Get whether or not entities should be exposed by default, or if only
        # explicitly marked ones will be exposed
        self.expose_by_default = conf.get(CONF_EXPOSE_BY_DEFAULT,
                                          DEFAULT_EXPOSE_BY_DEFAULT)

        # Get domains that are exposed by default when expose_by_default is
        # True
        self.exposed_domains = set(
            conf.get(CONF_EXPOSED_DOMAINS, DEFAULT_EXPOSED_DOMAINS))

        # Calculated effective advertised IP and port for network isolation
        self.advertise_ip = conf.get(CONF_ADVERTISE_IP) or self.host_ip_addr

        self.advertise_port = conf.get(CONF_ADVERTISE_PORT) or self.listen_port

        self.entities = conf.get(CONF_ENTITIES, {})

        self._entities_with_hidden_attr_in_config = {}
        for entity_id in self.entities:
            hidden_value = self.entities[entity_id].get(CONF_ENTITY_HIDDEN)
            if hidden_value is not None:
                self._entities_with_hidden_attr_in_config[
                    entity_id] = hidden_value

        # Get whether all non-dimmable lights should be reported as dimmable
        # for compatibility with older installations.
        self.lights_all_dimmable = conf.get(CONF_LIGHTS_ALL_DIMMABLE)
예제 #7
0
 def update(self) -> None:
     """Fetch new state data for the sensor."""
     self._attr_state = get_local_ip()
예제 #8
0
def setup(opp, config):
    """Set up Zeroconf and make Open Peer Power discoverable."""
    zeroconf = Zeroconf()
    zeroconf_name = f"{opp.config.location_name}.{ZEROCONF_TYPE}"

    params = {
        "version": __version__,
        "base_url": opp.config.api.base_url,
        # Always needs authentication
        "requires_api_password": True,
    }

    host_ip = util.get_local_ip()

    try:
        host_ip_pton = socket.inet_pton(socket.AF_INET, host_ip)
    except socket.error:
        host_ip_pton = socket.inet_pton(socket.AF_INET6, host_ip)

    info = ServiceInfo(
        ZEROCONF_TYPE,
        zeroconf_name,
        None,
        addresses=[host_ip_pton],
        port=opp.http.server_port,
        properties=params,
    )

    def zeroconf_opp_start(_event):
        """Expose Open Peer Power on zeroconf when it starts.

        Wait till started or otherwise HTTP is not up and running.
        """
        _LOGGER.info("Starting Zeroconf broadcast")
        try:
            zeroconf.register_service(info)
        except NonUniqueNameException:
            _LOGGER.error(
                "Open Peer Power instance with identical name present in the local network"
            )

    opp.bus.listen_once(EVENT_OPENPEERPOWER_START, zeroconf_opp_start)

    def service_update(zeroconf, service_type, name, state_change):
        """Service state changed."""
        if state_change != ServiceStateChange.Added:
            return

        service_info = zeroconf.get_service_info(service_type, name)
        info = info_from_service(service_info)
        _LOGGER.debug("Discovered new device %s %s", name, info)

        # If we can handle it as a HomeKit discovery, we do that here.
        if service_type == HOMEKIT_TYPE and handle_homekit(opp, info):
            return

        for domain in ZEROCONF[service_type]:
            opp.add_job(
                opp.config_entries.flow.async_init(domain,
                                                   context={"source": DOMAIN},
                                                   data=info))

    for service in ZEROCONF:
        ServiceBrowser(zeroconf, service, handlers=[service_update])

    if HOMEKIT_TYPE not in ZEROCONF:
        ServiceBrowser(zeroconf, HOMEKIT_TYPE, handlers=[service_update])

    def stop_zeroconf(_):
        """Stop Zeroconf."""
        zeroconf.close()

    opp.bus.listen_once(EVENT_OPENPEERPOWER_STOP, stop_zeroconf)

    return True
예제 #9
0
async def async_setup(opp, config):
    """Set up the HTTP API and debug interface."""
    conf = config.get(DOMAIN)

    if conf is None:
        conf = HTTP_SCHEMA({})

    server_host = conf[CONF_SERVER_HOST]
    server_port = conf[CONF_SERVER_PORT]
    ssl_certificate = conf.get(CONF_SSL_CERTIFICATE)
    ssl_peer_certificate = conf.get(CONF_SSL_PEER_CERTIFICATE)
    ssl_key = conf.get(CONF_SSL_KEY)
    cors_origins = conf[CONF_CORS_ORIGINS]
    use_x_forwarded_for = conf.get(CONF_USE_X_FORWARDED_FOR, False)
    trusted_proxies = conf.get(CONF_TRUSTED_PROXIES, [])
    is_ban_enabled = conf[CONF_IP_BAN_ENABLED]
    login_threshold = conf[CONF_LOGIN_ATTEMPTS_THRESHOLD]
    ssl_profile = conf[CONF_SSL_PROFILE]

    server = OpenPeerPowerHTTP(
        opp,
        server_host=server_host,
        server_port=server_port,
        ssl_certificate=ssl_certificate,
        ssl_peer_certificate=ssl_peer_certificate,
        ssl_key=ssl_key,
        cors_origins=cors_origins,
        use_x_forwarded_for=use_x_forwarded_for,
        trusted_proxies=trusted_proxies,
        login_threshold=login_threshold,
        is_ban_enabled=is_ban_enabled,
        ssl_profile=ssl_profile,
    )

    async def stop_server(event):
        """Stop the server."""
        await server.stop()

    async def start_server(event):
        """Start the server."""
        opp.bus.async_listen_once(EVENT_OPENPEERPOWER_STOP, stop_server)
        await server.start()

        # If we are set up successful, we store the HTTP settings for safe mode.
        store = storage.Store(opp, STORAGE_VERSION, STORAGE_KEY)

        if CONF_TRUSTED_PROXIES in conf:
            conf_to_save = dict(conf)
            conf_to_save[CONF_TRUSTED_PROXIES] = [
                str(ip.network_address) for ip in conf_to_save[CONF_TRUSTED_PROXIES]
            ]
        else:
            conf_to_save = conf

        await store.async_save(conf_to_save)

    opp.bus.async_listen_once(EVENT_OPENPEERPOWER_START, start_server)

    opp.http = server

    host = conf.get(CONF_BASE_URL)

    if host:
        port = None
    elif server_host != DEFAULT_SERVER_HOST:
        host = server_host
        port = server_port
    else:
        host = opp_util.get_local_ip()
        port = server_port

    opp.config.api = ApiConfig(host, port, ssl_certificate is not None)

    return True
예제 #10
0
    def __init__(self, opp, driver, name, entity_id, aid, config):
        """Initialize a Camera accessory object."""
        self._ffmpeg = opp.data[DATA_FFMPEG]
        for config_key in CONFIG_DEFAULTS:
            if config_key not in config:
                config[config_key] = CONFIG_DEFAULTS[config_key]

        max_fps = config[CONF_MAX_FPS]
        max_width = config[CONF_MAX_WIDTH]
        max_height = config[CONF_MAX_HEIGHT]
        resolutions = [
            (w, h, fps)
            for w, h, fps in SLOW_RESOLUTIONS
            if w <= max_width and h <= max_height and fps < max_fps
        ] + [
            (w, h, max_fps)
            for w, h in RESOLUTIONS
            if w <= max_width and h <= max_height
        ]

        video_options = {
            "codec": {
                "profiles": [
                    VIDEO_CODEC_PARAM_PROFILE_ID_TYPES["BASELINE"],
                    VIDEO_CODEC_PARAM_PROFILE_ID_TYPES["MAIN"],
                    VIDEO_CODEC_PARAM_PROFILE_ID_TYPES["HIGH"],
                ],
                "levels": [
                    VIDEO_CODEC_PARAM_LEVEL_TYPES["TYPE3_1"],
                    VIDEO_CODEC_PARAM_LEVEL_TYPES["TYPE3_2"],
                    VIDEO_CODEC_PARAM_LEVEL_TYPES["TYPE4_0"],
                ],
            },
            "resolutions": resolutions,
        }
        audio_options = {
            "codecs": [
                {"type": "OPUS", "samplerate": 24},
                {"type": "OPUS", "samplerate": 16},
            ]
        }

        stream_address = config.get(CONF_STREAM_ADDRESS, get_local_ip())

        options = {
            "video": video_options,
            "audio": audio_options,
            "address": stream_address,
            "srtp": True,
            "stream_count": config[CONF_STREAM_COUNT],
        }

        super().__init__(
            opp,
            driver,
            name,
            entity_id,
            aid,
            config,
            category=CATEGORY_CAMERA,
            options=options,
        )

        self._char_motion_detected = None
        self.linked_motion_sensor = self.config.get(CONF_LINKED_MOTION_SENSOR)
        if self.linked_motion_sensor:
            state = self.opp.states.get(self.linked_motion_sensor)
            if state:
                serv_motion = self.add_preload_service(SERV_MOTION_SENSOR)
                self._char_motion_detected = serv_motion.configure_char(
                    CHAR_MOTION_DETECTED, value=False
                )
                self._async_update_motion_state(state)

        self._char_doorbell_detected = None
        self._char_doorbell_detected_switch = None
        self.linked_doorbell_sensor = self.config.get(CONF_LINKED_DOORBELL_SENSOR)
        if self.linked_doorbell_sensor:
            state = self.opp.states.get(self.linked_doorbell_sensor)
            if state:
                serv_doorbell = self.add_preload_service(SERV_DOORBELL)
                self.set_primary_service(serv_doorbell)
                self._char_doorbell_detected = serv_doorbell.configure_char(
                    CHAR_PROGRAMMABLE_SWITCH_EVENT,
                    value=0,
                )
                serv_stateless_switch = self.add_preload_service(
                    SERV_STATELESS_PROGRAMMABLE_SWITCH
                )
                self._char_doorbell_detected_switch = (
                    serv_stateless_switch.configure_char(
                        CHAR_PROGRAMMABLE_SWITCH_EVENT,
                        value=0,
                        valid_values={"SinglePress": DOORBELL_SINGLE_PRESS},
                    )
                )
                serv_speaker = self.add_preload_service(SERV_SPEAKER)
                serv_speaker.configure_char(CHAR_MUTE, value=0)

                self._async_update_doorbell_state(state)