Skip to content

Commit

Permalink
Allow for scan in UI
Browse files Browse the repository at this point in the history
  • Loading branch information
hcoohb committed Sep 26, 2020
1 parent 59f4daa commit e78a7eb
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 33 deletions.
90 changes: 63 additions & 27 deletions custom_components/yeelight_bt/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,93 @@
from homeassistant import config_entries
from homeassistant.const import CONF_NAME, CONF_MAC
import voluptuous as vol
from homeassistant.helpers import device_registry as dr, config_validation as cv
from homeassistant.helpers import device_registry as dr

from .const import DOMAIN
from .const import DOMAIN, CONF_ENTRY_METHOD, CONF_ENTRY_SCAN, CONF_ENTRY_MANUAL

from .yeelightbt import (
discover_yeelight_lamps,
BTLEDisconnectError,
BTLEManagementError,
)

_LOGGER = logging.getLogger(__name__)


class SimpleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
class Yeelight_btConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # type: ignore
"""Handle a config flow for yeelight_bt."""

VERSION = 1
VERSION = 2
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL

@property
def data_schema(self):
"""Return the data schema for integration."""
return vol.Schema(
{
vol.Required(CONF_NAME): str,
vol.Required(CONF_MAC): str,
}
)
return vol.Schema({vol.Required(CONF_NAME): str, vol.Required(CONF_MAC): str})

async def async_step_user(self, user_input=None):
"""Handle the initial step."""
"""Handle a flow initialized by the user."""

if user_input is None:
schema = {
vol.Required(CONF_ENTRY_METHOD): vol.In(
[CONF_ENTRY_SCAN, CONF_ENTRY_MANUAL]
)
}
return self.async_show_form(step_id="user", data_schema=vol.Schema(schema))
method = user_input[CONF_ENTRY_METHOD]
_LOGGER.debug(f"Method selected: {method}")
if method == CONF_ENTRY_SCAN:
return await self.async_step_scan()
else:
self.devices = []
return await self.async_step_device()

async def async_step_scan(self, user_input=None):
"""Handle the discovery by scanning."""
errors = {}
_LOGGER.debug(f"User_input: {user_input}")
if user_input is None:
return self.async_show_form(step_id="scan")
_LOGGER.debug("Starting a scan for Yeelight Bt devices")
try:
devices = await self.hass.async_add_executor_job(discover_yeelight_lamps)
except BTLEDisconnectError as err:
_LOGGER.error(f"Bluetooth connection error while trying to scan: {err}")
errors["base"] = "BTLEDisconnectError"
return self.async_show_form(step_id="scan", errors=errors)
except BTLEManagementError as err:
_LOGGER.error(f"Bluetooth connection error while trying to scan: {err}")
errors["base"] = "BTLEManagementError"
return self.async_show_form(step_id="scan", errors=errors)

if not devices:
return self.async_abort(reason="no_devices_found")
self.devices = [f"{dev['mac']} ({dev['model']})" for dev in devices]
# TODO: filter existing devices ?

return await self.async_step_device()

async def async_step_device(self, user_input=None):
"""Handle setting up a device."""
# _LOGGER.debug(f"User_input: {user_input}")
if not user_input:
return self.async_show_form(step_id="user", data_schema=self.data_schema)
schema_mac = str
if self.devices:
schema_mac = vol.In(self.devices)
schema = vol.Schema(
{vol.Required(CONF_NAME): str, vol.Required(CONF_MAC): schema_mac}
)
return self.async_show_form(step_id="device", data_schema=schema)

user_input[CONF_MAC] = user_input[CONF_MAC][:17]
unique_id = dr.format_mac(user_input[CONF_MAC])
_LOGGER.debug(f"UniqueID: {unique_id}")
_LOGGER.debug(f"Yeelight UniqueID: {unique_id}")

await self.async_set_unique_id(unique_id)
self._abort_if_unique_id_configured()

# try:
# #Check if we can connect to the lamp here
# await client.cdc_reports.status_by_coordinates(
# user_input[CONF_LATITUDE], user_input[CONF_LONGITUDE]
# )
# except FluNearYouError as err:
# _LOGGER.error("Error while configuring integration: %s", err)
# errors["base"] = "auth_error"
# return self.async_show_form(
# step_id="user", errors=errors
# )

return self.async_create_entry(title=user_input[CONF_NAME], data=user_input)

async def async_step_import(self, import_info):
"""Handle import from config file."""
return await self.async_step_user(import_info)
return await self.async_step_device(import_info)
3 changes: 3 additions & 0 deletions custom_components/yeelight_bt/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@

DOMAIN = "yeelight_bt"
PLATFORM = "light"
CONF_ENTRY_METHOD = "entry_method"
CONF_ENTRY_SCAN = "Scan"
CONF_ENTRY_MANUAL = "Enter MAC manually"
24 changes: 21 additions & 3 deletions custom_components/yeelight_bt/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,32 @@
"step": {
"user": {
"title": "Yeelight Bluetooth",
"description": "Control a Xiaomi Yeelight bluetooth bedside lamp.",
"description": "Control a Yeelight bluetooth bedside lamp. Select to scan for devices or enter the mac Address manually.",
"data": {
"entry_method": "Method to be used:"
}
},
"scan": {
"title": "Yeelight Bluetooth",
"description": "Make sure the lamp is not connected to other devices or it may not be discoverable (A reset may also help). Are you ready to start scanning?"
},
"device": {
"title": "Yeelight Bluetooth",
"description": "Enter a name for the device and the MAC address for the lamp. To finish the pairing step, you may need to push the small button on the lamp if it `pulses`.",
"data": {
"name": "Lamp Name",
"mac": "MAC address"
}
}
},
"error": {"general_error": "There was an unknown error." },
"abort": {"already_configured": "This mac address is already registered."}
"error": {
"general_error": "There was an unknown error.",
"BTLEDisconnectError": "Bluetooth connection error while trying to scan. Make sure nothing else is using bluetooth.",
"BTLEManagementError": "Could not start a bluetooth scan. It is very likely some permission errors. Follow directions from github repo."
},
"abort": {
"already_configured": "This mac address is already registered.",
"no_devices_found": "No devices found during this scan. Enusre the lamp is not connected to another app. Reseting the lamp may help"
}
}
}
11 changes: 8 additions & 3 deletions custom_components/yeelight_bt/yeelightbt.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

# 3rd party imports
import bluepy # for BLE transmission

from bluepy.btle import BTLEDisconnectError, BTLEManagementError # noqa

NOTIFY_UUID = "8f65073d-9f57-4aaa-afea-397d19d5bbeb"
CONTROL_UUID = "aa7d3f34-2d4f-41e0-807f-52fbf8cf7443"
Expand Down Expand Up @@ -537,9 +537,14 @@ def __init__(self):
for dev in devices:
# _LOGGER.debug(f"found {dev.addr} = {dev.getScanData()}")
for (adtype, desc, value) in dev.getScanData():
model = ""
if "XMCTD" in value:
_LOGGER.info(f"found Yeelight lamp with mac: {dev.addr}")
lamp_list.append(Lamp(dev.addr))
model = MODEL_BEDSIDE
if "yeelight_ms" in value:
model = MODEL_CANDELA
if model:
lamp_list.append({"mac": dev.addr, "model": model})
_LOGGER.info(f"found {model} with mac: {dev.addr}, value:{value}")
return lamp_list


Expand Down

0 comments on commit e78a7eb

Please sign in to comment.