bunch of bugs
This commit is contained in:
@@ -35,8 +35,9 @@ both actions through `on_event: [_notify, _cloud_logger]`. A single action name
|
|||||||
such as `on_event: _notify` remains supported.
|
such as `on_event: _notify` remains supported.
|
||||||
|
|
||||||
Arrival detection emits `arrived` and `departed` for individual device IDs. It
|
Arrival detection emits `arrived` and `departed` for individual device IDs. It
|
||||||
also emits `empty` with ID `house` after the last present device departs. Initial
|
also emits `empty` with ID `house` after the last present device departs, and
|
||||||
startup state never generates these transition events.
|
`first_arrival` with the arriving device ID when an empty house becomes occupied.
|
||||||
|
Initial startup state never generates these transition events.
|
||||||
|
|
||||||
Plugin modules, factories, configuration sections, and event actions are all
|
Plugin modules, factories, configuration sections, and event actions are all
|
||||||
declared under `controller`. The controller contains no plugin-specific imports
|
declared under `controller`. The controller contains no plugin-specific imports
|
||||||
|
|||||||
@@ -1,2 +1,4 @@
|
|||||||
{"timestamp":"2026-08-23T06:09:35.779477+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"departed","id":"ignace","text":""}}
|
{"timestamp":"2026-08-23T06:09:35.779477+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"departed","id":"ignace","text":""}}
|
||||||
{"timestamp":"2026-08-23T06:10:47.665139+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"arrived","id":"ignace","text":""}}
|
{"timestamp":"2026-08-23T06:10:47.665139+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"arrived","id":"ignace","text":""}}
|
||||||
|
{"timestamp":"2026-08-26T16:16:16.951086+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"departed","id":"ignace","text":"2026-08-26T16:16:16.949395+00:00 _arrival_detection: departed (ignace)","datetime":"2026-08-26T16:16:16.949395+00:00"}}
|
||||||
|
{"timestamp":"2026-08-26T16:16:17.474743+00:00","remote_addr":"127.0.0.1","event":{"sender":"_arrival_detection","event":"empty","id":"house","text":"2026-08-26T16:16:17.473318+00:00 _arrival_detection: empty (house)","datetime":"2026-08-26T16:16:17.473318+00:00"}}
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ class ArrivalMonitor:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def _process_states(self, states: dict[str, bool]) -> None:
|
def _process_states(self, states: dict[str, bool]) -> None:
|
||||||
|
arrivals: list[dict] = []
|
||||||
for device in self.devices:
|
for device in self.devices:
|
||||||
present = states[device["mac"]]
|
present = states[device["mac"]]
|
||||||
LOG.debug(
|
LOG.debug(
|
||||||
@@ -154,6 +155,8 @@ class ArrivalMonitor:
|
|||||||
}
|
}
|
||||||
_record_event(self.config, event, device["mac"])
|
_record_event(self.config, event, device["mac"])
|
||||||
self.on_event(event)
|
self.on_event(event)
|
||||||
|
if transition == "arrived":
|
||||||
|
arrivals.append(device)
|
||||||
|
|
||||||
known_states = [detector.state for detector in self.detectors.values()]
|
known_states = [detector.state for detector in self.detectors.values()]
|
||||||
if all(state is not None for state in known_states):
|
if all(state is not None for state in known_states):
|
||||||
@@ -167,6 +170,16 @@ class ArrivalMonitor:
|
|||||||
}
|
}
|
||||||
_record_event(self.config, event)
|
_record_event(self.config, event)
|
||||||
self.on_event(event)
|
self.on_event(event)
|
||||||
|
elif self._house_occupied is False and occupied:
|
||||||
|
first = arrivals[0]
|
||||||
|
event = {
|
||||||
|
"sender": "_arrival_detection",
|
||||||
|
"event": "first_arrival",
|
||||||
|
"id": first["id"],
|
||||||
|
"text": "",
|
||||||
|
}
|
||||||
|
_record_event(self.config, event, first["mac"])
|
||||||
|
self.on_event(event)
|
||||||
self._house_occupied = occupied
|
self._house_occupied = occupied
|
||||||
|
|
||||||
def _run(self) -> None:
|
def _run(self) -> None:
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
from pprint import pprint
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ def on_event(config: dict, message: dict) -> None:
|
|||||||
timestamp = datetime.now(timezone.utc).isoformat()
|
timestamp = datetime.now(timezone.utc).isoformat()
|
||||||
values = {**message, "datetime": timestamp}
|
values = {**message, "datetime": timestamp}
|
||||||
messages = config.get("messages", {})
|
messages = config.get("messages", {})
|
||||||
template = messages.get(
|
template = config.get(
|
||||||
message["event"],
|
message["event"],
|
||||||
config.get("message", "{datetime} {sender}: {event} ({id})"),
|
config.get("message", "{datetime} {sender}: {event} ({id})"),
|
||||||
)
|
)
|
||||||
@@ -71,6 +71,7 @@ def on_event(config: dict, message: dict) -> None:
|
|||||||
"datetime": timestamp,
|
"datetime": timestamp,
|
||||||
"text": message.get("text") or str(template).format(**values),
|
"text": message.get("text") or str(template).format(**values),
|
||||||
}
|
}
|
||||||
|
pprint(payload)
|
||||||
send_event(
|
send_event(
|
||||||
payload,
|
payload,
|
||||||
event_url=str(config.get("event_url", "")),
|
event_url=str(config.get("event_url", "")),
|
||||||
|
|||||||
@@ -1,3 +1,16 @@
|
|||||||
2026-08-22T22:27:23+02:00 ARRIVAL name=Ignace mac=ce:68:53:a8:fc:07
|
2026-08-22T22:27:23+02:00 ARRIVAL name=Ignace mac=ce:68:53:a8:fc:07
|
||||||
2026-08-23T08:09:35+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
2026-08-23T08:09:35+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
2026-08-23T08:10:47+02:00 ARRIVED id=ignace mac=ce:68:53:a8:fc:07
|
2026-08-23T08:10:47+02:00 ARRIVED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-23T15:17:07+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-23T15:23:46+02:00 ARRIVED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T17:46:51+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T17:46:51+02:00 EMPTY id=house
|
||||||
|
2026-08-26T17:50:34+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T17:50:34+02:00 EMPTY id=house
|
||||||
|
2026-08-26T17:57:07+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T17:57:08+02:00 EMPTY id=house
|
||||||
|
2026-08-26T18:01:41+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T18:01:41+02:00 EMPTY id=house
|
||||||
|
2026-08-26T18:05:14+02:00 ARRIVED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T18:16:16+02:00 DEPARTED id=ignace mac=ce:68:53:a8:fc:07
|
||||||
|
2026-08-26T18:16:16+02:00 EMPTY id=house
|
||||||
|
|||||||
+6
-4
@@ -30,7 +30,7 @@ arrival_detection:
|
|||||||
verify_tls: true
|
verify_tls: true
|
||||||
hosts_oid: lanhosts
|
hosts_oid: lanhosts
|
||||||
# Log every router/API call and its result without logging credentials.
|
# Log every router/API call and its result without logging credentials.
|
||||||
debug: false
|
debug: true
|
||||||
|
|
||||||
devices:
|
devices:
|
||||||
- id: ignace
|
- id: ignace
|
||||||
@@ -53,15 +53,16 @@ notify:
|
|||||||
filter:
|
filter:
|
||||||
# Empty accept lists allow all values. Ignore lists always take precedence.
|
# Empty accept lists allow all values. Ignore lists always take precedence.
|
||||||
accept:
|
accept:
|
||||||
events: [empty]
|
events: [empty, first_arrival]
|
||||||
ids: []
|
ids: []
|
||||||
ignore:
|
ignore:
|
||||||
events: [arrived, departed]
|
events: [departed]
|
||||||
ids: []
|
ids: []
|
||||||
# Available placeholders: {sender}, {event}, {id}, {text}.
|
# Available placeholders: {sender}, {event}, {id}, {text}.
|
||||||
message: "{sender}: {event} ({id})"
|
message: "{sender}: {event} ({id})"
|
||||||
messages:
|
messages:
|
||||||
arrived: "{id} arrived home"
|
arrived: "{id} arrived home"
|
||||||
|
first_arrival: "{id} is the first to arrive home"
|
||||||
departed: "{id} left home"
|
departed: "{id} left home"
|
||||||
empty: "The house is empty"
|
empty: "The house is empty"
|
||||||
# May also be supplied through the NTFY_TOPIC_URL environment variable.
|
# May also be supplied through the NTFY_TOPIC_URL environment variable.
|
||||||
@@ -70,7 +71,8 @@ notify:
|
|||||||
|
|
||||||
cloud_logger:
|
cloud_logger:
|
||||||
enabled: true
|
enabled: true
|
||||||
event_url: http://www.suy.nl/home_logger/event
|
# event_url: http://www.suy.nl/home_logger/event
|
||||||
|
event_url: http://127.0.0.1:29651/home_logger/event
|
||||||
timeout: 10
|
timeout: 10
|
||||||
filter:
|
filter:
|
||||||
# Empty accept lists allow all values. Ignore lists always take precedence.
|
# Empty accept lists allow all values. Ignore lists always take precedence.
|
||||||
|
|||||||
+37
-1
@@ -78,7 +78,43 @@ class ArrivalDetectorTests(unittest.TestCase):
|
|||||||
"event": "arrived",
|
"event": "arrived",
|
||||||
"id": "ignace",
|
"id": "ignace",
|
||||||
"text": "",
|
"text": "",
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"sender": "_arrival_detection",
|
||||||
|
"event": "first_arrival",
|
||||||
|
"id": "ignace",
|
||||||
|
"text": "",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
@patch("lib._arrival_detection._build_router")
|
||||||
|
def test_first_arrival_fires_only_when_empty_house_becomes_occupied(
|
||||||
|
self, _build_router
|
||||||
|
):
|
||||||
|
events = []
|
||||||
|
monitor = ArrivalMonitor(
|
||||||
|
{
|
||||||
|
"devices": [
|
||||||
|
{"id": "ignace", "mac": "00:00:00:00:00:01"},
|
||||||
|
{"id": "janine", "mac": "00:00:00:00:00:02"},
|
||||||
|
],
|
||||||
|
"polling": {"absent_after": 1, "present_after": 1},
|
||||||
|
},
|
||||||
|
events.append,
|
||||||
|
)
|
||||||
|
first = "00:00:00:00:00:01"
|
||||||
|
second = "00:00:00:00:00:02"
|
||||||
|
monitor._process_states({first: False, second: False})
|
||||||
|
monitor._process_states({first: True, second: False})
|
||||||
|
monitor._process_states({first: True, second: True})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
[(event["event"], event["id"]) for event in events],
|
||||||
|
[
|
||||||
|
("arrived", "ignace"),
|
||||||
|
("first_arrival", "ignace"),
|
||||||
|
("arrived", "janine"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user