Skip to content

Commit

Permalink
feat: prep for v0.10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Thrilleratplay committed May 4, 2021
1 parent 47cbd95 commit 6b9e5c3
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 49 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Changelog
All notable changes to this project will be documented in this file.

## 0.10.0
**Feat:**
- **Minimum and maximum temperature configurable.** Base on [SteveOnorato/moat_temp_hum_ble](https://github.com/SteveOnorato/moat_temp_hum_ble/). Thank you @SteveOnorato
- **Devices now related.** Thank you @natekspencer
**Fix:**
- **Catch Bluetooth adapter error and provide useful information.**
**Chore:**
- **Removed "CONF_HCITOOL_ACTIVE"**

**BREAKING CHANGE** - With the removal of `CONF_HCITOOL_ACTIVE` if `hcitool_active` is still in your config, Home Assistant will not start. Please remove this deprecated flag.

## 0.9.2
**Fix:**
- **Update bleson package to version 0.18, fixes non BLE spec device name errors**
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ sensor:
| `log_spikes` | Boolean | `False` | Puts information about each erroneous spike in the Home Assistant log. |
| `use_median` | Boolean | `False` | Use median as sensor output instead of mean (helps with "spiky" sensors). Please note that both the median and the mean values in any case are present as the sensor state attributes. |
| `hci_device`| string | `hci0` | HCI device name used for scanning. |
| `temp_range_min_celsius` | float | `-20.0` | Set the lower bound of reasonable measurements, in Celsius. Temperature measurements lower than this will be discarded. *Warning*: temperatures returned by the Govee device that are outside of the specified range may not be accurate. It is not advised to change this value.|
| `temp_range_max_celsius` | float | `60.0` | Set the upper bound of reasonable measurements, in Celsius. Temperature measurements higher than this will be discarded. *Warning*: temperatures returned by the Govee device that are outside of the specified range may not be accurate. It is not advised to change this value.|

Example with all defaults:
```
Expand Down
2 changes: 1 addition & 1 deletion custom_components/govee_ble_hci/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
"""Govee Thermometer/Humidity BLE HCI monitor sensor integration."""
REQUIREMENTS = ["bleson==0.1.6"]
REQUIREMENTS = ["bleson==0.1.8"]
30 changes: 27 additions & 3 deletions custom_components/govee_ble_hci/ble_ht.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
import logging

from .const import (
CONF_TMIN,
CONF_TMAX,
DEFAULT_TEMP_RANGE_MIN,
DEFAULT_TEMP_RANGE_MAX,
CONF_HMIN,
CONF_HMAX,
)
Expand All @@ -31,12 +31,16 @@ class BLE_HT_data:
_packet_data: List[BLE_HT_packet]
_decimal_places: Optional[int]
_log_spikes: bool
_min_temp: float
_max_temp: float

def __init__(self, mac: str, description: Optional[str]) -> None:
"""Init."""
self._mac = mac
self._desc = description
self._log_spikes = False
self._min_temp = DEFAULT_TEMP_RANGE_MIN
self._max_temp = DEFAULT_TEMP_RANGE_MAX
self.reset()

@property
Expand Down Expand Up @@ -113,6 +117,26 @@ def rssi(self, value: Optional[int]) -> None:
if isinstance(value, int) and value < 0:
self._rssi.append(value)

@property
def maximum_temperature(self) -> float:
"""Get upper bound of temperature."""
return self._max_temp

@maximum_temperature.setter
def maximum_temperature(self, value: float) -> None:
"""Set upper bound of temperature."""
self._max_temp = value

@property
def minimum_temperature(self) -> float:
"""Get lower bound of temperature."""
return self._min_temp

@minimum_temperature.setter
def minimum_temperature(self, value: float) -> None:
"""Set lower bound of temperature."""
self._min_temp = value

@property
def mean_temperature(self) -> Union[float, None]:
"""Mean temperature of values collected."""
Expand Down Expand Up @@ -167,7 +191,7 @@ def update(
new_packet = BLE_HT_packet()

# Check if temperature within bounds
if temperature is not None and CONF_TMAX >= temperature >= CONF_TMIN:
if temperature is not None and self._max_temp >= temperature >= self._min_temp:
new_packet.temperature = temperature
elif self._log_spikes:
err = "Temperature spike: {} ({})".format(temperature, self._mac)
Expand Down
28 changes: 15 additions & 13 deletions custom_components/govee_ble_hci/const.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
"""Constants for the Govee BLE HCI monitor sensor integration."""

DOMAIN = "govee_ble_hci"

# Configuration options
CONF_ROUNDING = "rounding"
CONF_DECIMALS = "decimals"
CONF_PERIOD = "period"
CONF_LOG_SPIKES = "log_spikes"
CONF_USE_MEDIAN = "use_median"
CONF_HCITOOL_ACTIVE = "hcitool_active"
CONF_HCI_DEVICE = "hci_device"
CONF_GOVEE_DEVICES = "govee_devices"
CONF_DEVICE_MAC = "mac"
CONF_DEVICE_NAME = "name"
CONF_GOVEE_DEVICES = "govee_devices"
CONF_HCI_DEVICE = "hci_device"
CONF_LOG_SPIKES = "log_spikes"
CONF_PERIOD = "period"
CONF_ROUNDING = "rounding"
CONF_TEMP_RANGE_MAX_CELSIUS = "temp_range_max_celsius"
CONF_TEMP_RANGE_MIN_CELSIUS = "temp_range_min_celsius"
CONF_USE_MEDIAN = "use_median"


# Default values for configuration options
DEFAULT_ROUNDING = True
DEFAULT_DECIMALS = 2
DEFAULT_PERIOD = 60
DEFAULT_HCI_DEVICE = "hci0"
DEFAULT_LOG_SPIKES = False
DEFAULT_PERIOD = 60
DEFAULT_ROUNDING = True
DEFAULT_TEMP_RANGE_MAX = 60.0
DEFAULT_TEMP_RANGE_MIN = -20.0
DEFAULT_USE_MEDIAN = False
DEFAULT_HCITOOL_ACTIVE = False
DEFAULT_HCI_DEVICE = "hci0"

"""Fixed constants."""

# Sensor measurement limits to exclude erroneous spikes from the results
CONF_TMIN = -20.0
CONF_TMAX = 60.0
CONF_HMIN = 0.0
CONF_HMAX = 99.9
4 changes: 2 additions & 2 deletions custom_components/govee_ble_hci/manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"domain": "govee_ble_hci",
"domain": "sensor",
"name": "Govee BLE HCI monitor sensor integration",
"documentation": "https://github.com/Home-Is-Where-You-Hang-Your-Hack/sensor.goveetemp_bt_hci",
"requirements": ["bleson==0.1.8"],
"dependencies": [],
"codeowners": ["@thrilleratplay"],
"version": "0.9.2"
"version": "0.10.0"
}
96 changes: 68 additions & 28 deletions custom_components/govee_ble_hci/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
from datetime import timedelta
import logging
import voluptuous as vol
from typing import List
from typing import List, Optional, Dict, Set, Tuple

from bleson import get_provider # type: ignore
from bleson.core.hci.constants import EVT_LE_ADVERTISING_REPORT # type: ignore
from bleson.core.types import BDAddress # type: ignore
from bleson.core.hci.type_converters import hex_string # type: ignore

from homeassistant.exceptions import HomeAssistantError # type: ignore
from homeassistant.components.sensor import PLATFORM_SCHEMA # type: ignore
import homeassistant.helpers.config_validation as cv # type: ignore
from homeassistant.helpers.entity import Entity # type: ignore
Expand All @@ -23,22 +24,26 @@
)

from .const import (
DEFAULT_ROUNDING,
DEFAULT_DECIMALS,
DEFAULT_PERIOD,
DEFAULT_LOG_SPIKES,
DEFAULT_USE_MEDIAN,
DEFAULT_HCI_DEVICE,
CONF_ROUNDING,
CONF_DECIMALS,
CONF_PERIOD,
CONF_LOG_SPIKES,
CONF_USE_MEDIAN,
CONF_HCITOOL_ACTIVE,
CONF_HCI_DEVICE,
CONF_GOVEE_DEVICES,
CONF_DEVICE_MAC,
CONF_DEVICE_NAME,
CONF_GOVEE_DEVICES,
CONF_HCI_DEVICE,
CONF_LOG_SPIKES,
CONF_PERIOD,
CONF_ROUNDING,
CONF_TEMP_RANGE_MAX_CELSIUS,
CONF_TEMP_RANGE_MIN_CELSIUS,
CONF_USE_MEDIAN,
DEFAULT_DECIMALS,
DEFAULT_HCI_DEVICE,
DEFAULT_LOG_SPIKES,
DEFAULT_PERIOD,
DEFAULT_ROUNDING,
DEFAULT_TEMP_RANGE_MAX,
DEFAULT_TEMP_RANGE_MIN,
DEFAULT_USE_MEDIAN,
DOMAIN,
)

from .govee_advertisement import GoveeAdvertisement
Expand All @@ -62,9 +67,14 @@
vol.Optional(CONF_PERIOD, default=DEFAULT_PERIOD): cv.positive_int,
vol.Optional(CONF_LOG_SPIKES, default=DEFAULT_LOG_SPIKES): cv.boolean,
vol.Optional(CONF_USE_MEDIAN, default=DEFAULT_USE_MEDIAN): cv.boolean,
vol.Optional(CONF_HCITOOL_ACTIVE): cv.boolean, # noqa
vol.Optional(CONF_GOVEE_DEVICES): vol.All([DEVICES_SCHEMA]),
vol.Optional(CONF_HCI_DEVICE, default=DEFAULT_HCI_DEVICE): cv.string,
vol.Optional(
CONF_TEMP_RANGE_MIN_CELSIUS, default=DEFAULT_TEMP_RANGE_MIN
): float,
vol.Optional(
CONF_TEMP_RANGE_MAX_CELSIUS, default=DEFAULT_TEMP_RANGE_MAX
): float,
}
)

Expand All @@ -78,12 +88,6 @@ def setup_platform(hass, config, add_entities, discovery_info=None) -> None:
"""Set up the sensor platform."""
_LOGGER.debug("Starting Govee HCI Sensor")

if hasattr(config, "CONF_HCITOOL_ACTIVE"):
_LOGGER.warning(
"CONF_HCITOOL_ACTIVE has been deprecated "
"and will be removed in a future release."
)

govee_devices: List[BLE_HT_data] = [] # Data objects of configured devices
sensors_by_mac = {} # HomeAssistant sensors by MAC address
adapter = None
Expand Down Expand Up @@ -117,9 +121,14 @@ def init_configureed_devices() -> None:
"""Initialize configured Govee devices."""
for conf_dev in config[CONF_GOVEE_DEVICES]:
# Initialize BLE HT data objects
mac = conf_dev["mac"]
device = BLE_HT_data(mac, conf_dev.get("name", None))
mac: str = conf_dev["mac"]
given_name = conf_dev.get("name", None)

device = BLE_HT_data(mac, given_name)
device.log_spikes = config[CONF_LOG_SPIKES]
device.maximum_temperature = config[CONF_TEMP_RANGE_MAX_CELSIUS]
device.minimum_temperature = config[CONF_TEMP_RANGE_MIN_CELSIUS]

if config[CONF_ROUNDING]:
device.decimal_places = config[CONF_DECIMALS]
govee_devices.append(device)
Expand Down Expand Up @@ -203,10 +212,21 @@ def update_ble_loop(now) -> None:

# Initalize bluetooth adapter and begin scanning
# XXX: will not work if there are more than 10 HCI devices
adapter = get_provider().get_adapter(int(config[CONF_HCI_DEVICE][-1]))
adapter._handle_meta_event = handle_meta_event
hass.bus.listen("homeassistant_stop", adapter.stop_scanning)
adapter.start_scanning()
try:
adapter = get_provider().get_adapter(int(config[CONF_HCI_DEVICE][-1]))
adapter._handle_meta_event = handle_meta_event
hass.bus.listen("homeassistant_stop", adapter.stop_scanning)
adapter.start_scanning()
except (RuntimeError, OSError, PermissionError) as error:
error_msg = "Error connecting to Bluetooth adapter: {}\n\n".format(error)
error_msg += "Bluetooth adapter troubleshooting:\n"
error_msg += " -If running HASS, ensure the correct HCI device is being"
error_msg += " used. Check by logging into HA command line and execute:\n"
error_msg += " gdbus introspect --system --dest org.bluez --object-path /org/bluez | fgrep -i hci\n"
error_msg += " -If running Home Assistant in Docker, "
error_msg += "make sure it run with the --privileged flag.\n"
# _LOGGER.error(error_msg)
raise HomeAssistantError(error_msg) from error

# Initialize configured Govee devices
init_configureed_devices()
Expand All @@ -228,6 +248,7 @@ def __init__(self, mac: str, name: str):
self._battery = None
self._unique_id = "t_" + mac.replace(":", "")
self._name = name
self._mac = mac.replace(":", "")
self._device_state_attributes = {}

@property
Expand All @@ -250,6 +271,15 @@ def device_class(self):
"""Return the unit of measurement."""
return DEVICE_CLASS_TEMPERATURE

@property
def device_info(self) -> Optional[Dict[str, Set[Tuple[str, str]]]]:
"""Temperature Device Info."""
return {
"identifiers": {(DOMAIN, self._mac)},
"name": self._name,
"manufacturer": "Govee",
}

@property
def should_poll(self) -> bool:
"""No polling needed."""
Expand Down Expand Up @@ -283,6 +313,7 @@ def __init__(self, mac: str, name: str):
self._battery = None
self._name = name
self._unique_id = "h_" + mac.replace(":", "")
self._mac = mac.replace(":", "")
self._device_state_attributes = {}

@property
Expand All @@ -305,6 +336,15 @@ def device_class(self):
"""Return the unit of measurement."""
return DEVICE_CLASS_HUMIDITY

@property
def device_info(self) -> Optional[Dict[str, Set[Tuple[str, str]]]]:
"""Humidity Device Info."""
return {
"identifiers": {(DOMAIN, self._mac)},
"name": self._name,
"manufacturer": "Govee",
}

@property
def should_poll(self) -> bool:
"""No polling needed."""
Expand All @@ -316,7 +356,7 @@ def device_state_attributes(self):
return self._device_state_attributes

@property
def unique_id(self):
def unique_id(self) -> str:
"""Return a unique ID."""
return self._unique_id

Expand Down
13 changes: 11 additions & 2 deletions info.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
{% if installed or pending_update %}

## 0.9.2
## 0.10.0
**Feat:**
- **Minimum and maximum temperature configurable.** Base on [SteveOnorato/moat_temp_hum_ble](https://github.com/SteveOnorato/moat_temp_hum_ble/). Thank you @SteveOnorato
- **Devices now related.** Thank you @natekspencer
**Fix:**
- **Update bleson package to version 0.18, fixes non BLE spec device name errors**
- **Catch Bluetooth adapter error and provide useful information.**
**Chore:**
- **Removed "CONF_HCITOOL_ACTIVE"**


**BREAKING CHANGE** - With the removal of `CONF_HCITOOL_ACTIVE` if `hcitool_active` is still in your config, Home Assistant will not start. Please remove this deprecated flag.


**NOTE** FOR THOSE WHO ARE UPGRADING FROM V0.5 - a restart of the host device is suggested after upgrading this component. The previous implementation may still have processes running or sockets open which.could cause unforeseeable issues. I apologize for the inconvenience and future updates should go much smoother.

Expand Down

0 comments on commit 6b9e5c3

Please sign in to comment.