Skip to content

Commit

Permalink
update blitzortung to edb2f1c
Browse files Browse the repository at this point in the history
  • Loading branch information
pinkywafer committed Jul 21, 2020
1 parent 4940759 commit 7aeb204
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 119 deletions.
117 changes: 74 additions & 43 deletions custom_components/blitzortung/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,23 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from .mqtt import MQTT
from .geohash_utils import geohash_overlap

from . import const
from .const import DOMAIN, PLATFORMS, CONF_RADIUS
from .const import (
CONF_RADIUS,
DOMAIN,
PLATFORMS,
DEFAULT_RADIUS,
CONF_IDLE_RESET_TIMEOUT,
DEFAULT_IDLE_RESET_TIMEOUT,
DEFAULT_UPDATE_INTERVAL,
)
from .geohash_utils import geohash_overlap
from .mqtt import MQTT, MQTT_CONNECTED, MQTT_DISCONNECTED
from .version import __version__


_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = vol.Schema(
Expand All @@ -40,14 +49,18 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry):

latitude = config_entry.options.get(CONF_LATITUDE, hass.config.latitude)
longitude = config_entry.options.get(CONF_LONGITUDE, hass.config.longitude)
radius = config_entry.options.get(const.CONF_RADIUS, const.DEFAULT_RADIUS)
radius = config_entry.options.get(CONF_RADIUS, DEFAULT_RADIUS)
idle_reset_seconds = config_entry.options.get(
CONF_IDLE_RESET_TIMEOUT, DEFAULT_IDLE_RESET_TIMEOUT
) * 60

coordinator = BlitzortungDataUpdateCoordinator(
hass,
latitude,
longitude,
radius,
const.DEFAULT_UPDATE_INTERVAL,
idle_reset_seconds,
DEFAULT_UPDATE_INTERVAL,
server_stats=config.get(const.SERVER_STATS),
)

Expand Down Expand Up @@ -78,7 +91,9 @@ async def async_update_options(hass, config_entry):

async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
"""Unload a config entry."""
coordinator = hass.data[DOMAIN][config_entry.entry_id]
coordinator = hass.data[DOMAIN].pop(config_entry.entry_id)
await coordinator.disconnect()
_LOGGER.info("disconnected")

# cleanup platforms
unload_ok = all(
Expand All @@ -89,15 +104,7 @@ async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry):
]
)
)
if not unload_ok:
return False

await coordinator.disconnect()
_LOGGER.info("disconnected")

hass.data[DOMAIN].pop(config_entry.entry_id)

return True
return unload_ok


async def async_migrate_entry(hass, entry):
Expand All @@ -116,25 +123,39 @@ async def async_migrate_entry(hass, entry):
CONF_RADIUS: radius,
}
entry.version = 2
return True
if entry.version == 2:
entry.options = dict(entry.options)
entry.options[CONF_IDLE_RESET_TIMEOUT] = DEFAULT_IDLE_RESET_TIMEOUT
entry.version = 3
return True


class BlitzortungDataUpdateCoordinator(DataUpdateCoordinator):
def __init__(
self, hass, latitude, longitude, radius, update_interval, server_stats=False
self,
hass,
latitude,
longitude,
radius,
idle_reset_seconds,
update_interval,
server_stats=False,
):
"""Initialize."""
self.hass = hass
self.latitude = latitude
self.longitude = longitude
self.radius = radius
self.idle_reset_seconds = idle_reset_seconds
self.server_stats = server_stats
self.last_time = 0
self.sensors = []
self.callbacks = []
self.geohash_overlap = geohash_overlap(
self.latitude, self.longitude, self.radius
)
self._unlisten = None
self._disconnect_callbacks = []
self.unloading = False

_LOGGER.info(
"lat: %s, lon: %s, radius: %skm, geohashes: %s",
Expand All @@ -144,17 +165,19 @@ def __init__(
self.geohash_overlap,
)

# lat_delta = radius * 360 / 40000
# lon_delta = lat_delta / math.cos(latitude * math.pi / 180.0)

# west = longitude - lon_delta
# east = longitude + lon_delta

# north = latitude + lat_delta
# south = latitude - lat_delta

self.mqtt_client = MQTT(hass, "blitzortung.ha.sed.pl", 1883,)

self._disconnect_callbacks.append(
async_dispatcher_connect(
self.hass, MQTT_CONNECTED, self._on_connection_change
)
)
self._disconnect_callbacks.append(
async_dispatcher_connect(
self.hass, MQTT_DISCONNECTED, self._on_connection_change
)
)

super().__init__(
hass,
_LOGGER,
Expand All @@ -163,6 +186,12 @@ def __init__(
update_method=self._do_update,
)

def _on_connection_change(self, *args, **kwargs):
if self.unloading:
return
for sensor in self.sensors:
sensor.async_write_ha_state()

def compute_polar_coords(self, lightning):
dy = (lightning["lat"] - self.latitude) * math.pi / 180
dx = (
Expand All @@ -187,17 +216,18 @@ async def connect(self):
)
if self.server_stats:
await self.mqtt_client.async_subscribe(
"$SYS/broker/clients/connected", self.on_mqtt_message, qos=0
"$SYS/broker/#", self.on_mqtt_message, qos=0
)
await self.mqtt_client.async_subscribe(
"component/hello", self.on_hello_message, qos=0
)
self._unlisten = self.async_add_listener(lambda *args: None)
self._disconnect_callbacks.append(self.async_add_listener(lambda: None))

async def disconnect(self):
self.unloading = True
await self.mqtt_client.async_disconnect()
if self._unlisten:
self._unlisten()
for cb in self._disconnect_callbacks:
cb()

def on_hello_message(self, message, *args):
def parse_version(version_str):
Expand All @@ -223,33 +253,34 @@ def parse_version(version_str):
)

def on_mqtt_message(self, message, *args):
for sensor in self.sensors:
sensor.on_message(message)
for callback in self.callbacks:
callback(message)
if message.topic.startswith("blitzortung/1.1"):
lightning = json.loads(message.payload)
self.compute_polar_coords(lightning)
if lightning[const.ATTR_LIGHTNING_DISTANCE] < self.radius:
_LOGGER.debug("ligntning data: %s", lightning)
self.last_time = lightning["time"]
self.last_time = time.time()
for sensor in self.sensors:
sensor.update_lightning(lightning)

def register_sensor(self, sensor):
self.sensors.append(sensor)

def register_message_receiver(self, message_cb):
self.callbacks.append(message_cb)

@property
def is_inactive(self):
dt = time.time() - self.last_time / 1e9
return dt > const.INACTIVITY_RESET_SECONDS
return bool(
self.idle_reset_seconds
and (time.time() - self.last_time) >= self.idle_reset_seconds
)

@property
def is_connected(self):
return self.mqtt_client.connected

async def _do_update(self):
is_inactive = self.is_inactive
if not self.is_connected or is_inactive:
for sensor in self.sensors:
if is_inactive:
sensor.update_lightning(None)
sensor.async_write_ha_state()
for sensor in self.sensors:
sensor.tick()
17 changes: 14 additions & 3 deletions custom_components/blitzortung/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
import voluptuous as vol
import homeassistant.helpers.config_validation as cv

from .const import DOMAIN, CONF_RADIUS, DEFAULT_RADIUS
from .const import (
DOMAIN,
CONF_RADIUS,
DEFAULT_RADIUS,
CONF_IDLE_RESET_TIMEOUT,
DEFAULT_IDLE_RESET_TIMEOUT,
)

DEFAULT_CONF_NAME = "Blitzortung"


class DomainConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for blitzortung."""

VERSION = 2
VERSION = 3
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH

async def async_step_user(self, user_input=None):
Expand Down Expand Up @@ -40,7 +46,6 @@ def __init__(self, config_entry: config_entries.ConfigEntry):
self.config_entry = config_entry

async def async_step_init(self, user_input=None):
print("HERE", self.config_entry.options)
if user_input is not None:
return self.async_create_entry(title="", data=user_input)

Expand All @@ -66,6 +71,12 @@ async def async_step_init(self, user_input=None):
CONF_RADIUS, DEFAULT_RADIUS
),
): int,
vol.Optional(
CONF_IDLE_RESET_TIMEOUT,
default=self.config_entry.options.get(
CONF_IDLE_RESET_TIMEOUT, DEFAULT_IDLE_RESET_TIMEOUT,
),
): int,
}
),
)
5 changes: 3 additions & 2 deletions custom_components/blitzortung/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
"http://data{data_host_nr}.blitzortung.org/Data/Protected/last_strikes.php"
)
CONF_RADIUS = "radius"
INACTIVITY_RESET_SECONDS = 3600 * 2
DEFAULT_UPDATE_INTERVAL = datetime.timedelta(seconds=300)
DEFAULT_IDLE_RESET_TIMEOUT = 120
CONF_IDLE_RESET_TIMEOUT = "idle_reset_timeout"
DEFAULT_UPDATE_INTERVAL = datetime.timedelta(seconds=60)
NUMBER_OF_EVENTS = 200
REQUEST_TIMEOUT = 10
MAX_RETRIES = 3
Expand Down
2 changes: 1 addition & 1 deletion custom_components/blitzortung/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"config_flow": true,
"documentation": "https://github.com/mrk-its/homeassistant-blitzortung",
"issue_tracker": "https://github.com/mrk-its/homeassistant-blitzortung/issues",
"requirements": [],
"requirements": ["paho-mqtt>=1.5.0"],
"after_dependencies": [],
"dependencies": [
"persistent_notification"
Expand Down
6 changes: 3 additions & 3 deletions custom_components/blitzortung/mqtt.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
DEFAULT_KEEPALIVE = 60
PROTOCOL_311 = "3.1.1"
DEFAULT_PROTOCOL = PROTOCOL_311
MQTT_CONNECTED = "mqtt_connected"
MQTT_DISCONNECTED = "mqtt_disconnected"
MQTT_CONNECTED = "blitzortung_mqtt_connected"
MQTT_DISCONNECTED = "blitzortung_mqtt_disconnected"


MAX_RECONNECT_WAIT = 300 # seconds
Expand Down Expand Up @@ -301,7 +301,7 @@ def _mqtt_on_disconnect(self, _mqttc, _userdata, result_code: int) -> None:
"""Disconnected callback."""
self.connected = False
dispatcher_send(self.hass, MQTT_DISCONNECTED)
_LOGGER.warning(
_LOGGER.info(
"Disconnected from MQTT server %s:%s (%s)",
self.host,
self.port,
Expand Down
Loading

0 comments on commit 7aeb204

Please sign in to comment.