Add a server option for the Bluetooth read interval
The server read each Bluetooth device every 60 seconds, and each read is one scan and one connection. An adapter that fails after many connections had no way to get fewer of them. --bluetooth-interval sets the wait after a good Bluetooth read, and the default stays at 60 seconds. Clients receive the last read during the wait. A failed read still tries again after 60 seconds, or after the interval for a shorter one.
This commit is contained in:
@@ -123,6 +123,60 @@ def test_offline_bluetooth_does_not_retry_at_once_or_serve_stale_data(monkeypatc
|
||||
assert stop.waits == [60]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("interval,read,wait", [
|
||||
(300, JBDBMS(), 300),
|
||||
# A failed read retries after 60 seconds, or sooner with a shorter interval.
|
||||
(300, None, 60),
|
||||
(30, None, 30),
|
||||
])
|
||||
def test_bluetooth_interval_sets_the_wait_after_a_good_read(monkeypatch, interval, read, wait):
|
||||
state = server.DeviceState(
|
||||
ecoflow=initialise_device(ADDRESS, SERIAL, "test-user"), poll_seconds=interval,
|
||||
)
|
||||
monkeypatch.setattr(server, "collect_device_data", Mock(return_value=read))
|
||||
stop = StopAfter(1)
|
||||
server.poll_device(state, stop)
|
||||
assert state.data is read
|
||||
assert stop.waits == [wait]
|
||||
|
||||
|
||||
def _main_devices(monkeypatch, tmp_path, *arguments):
|
||||
"""Run main() until it starts to poll, and return the devices it registered."""
|
||||
start = Mock(side_effect=KeyboardInterrupt)
|
||||
monkeypatch.setattr(server, "start_polling", start)
|
||||
monkeypatch.setattr(server.signal, "signal", Mock())
|
||||
monkeypatch.setattr(server.atexit, "register", Mock())
|
||||
monkeypatch.setattr(server, "initialise_serial", Mock())
|
||||
monkeypatch.setattr(server.os.path, "isdir", lambda path: True)
|
||||
monkeypatch.setattr("sys.argv", [
|
||||
"bmspy-server", "--socket", str(tmp_path / "interval.sock"),
|
||||
"--device", f"river@{SPEC}", "--device", "pack:/dev/ttyUSB0", *arguments,
|
||||
])
|
||||
with pytest.raises((SystemExit, KeyboardInterrupt)):
|
||||
server.main()
|
||||
return start.call_args.args[0]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("arguments,interval", [((), 60), (("--bluetooth-interval", "300"), 300)])
|
||||
def test_bluetooth_interval_option_applies_to_bluetooth_devices(
|
||||
monkeypatch, tmp_path, arguments, interval,
|
||||
):
|
||||
devices = _main_devices(monkeypatch, tmp_path, *arguments)
|
||||
assert devices["river"].poll_seconds == interval
|
||||
assert devices["river"].ecoflow is not None
|
||||
assert devices["pack"].ecoflow is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize("value", ["0", "-5", "soon"])
|
||||
def test_bluetooth_interval_option_rejects_an_unusable_value(monkeypatch, capsys, value):
|
||||
monkeypatch.setattr(server.signal, "signal", Mock())
|
||||
monkeypatch.setattr("sys.argv", ["bmspy-server", "--bluetooth-interval", value])
|
||||
with pytest.raises(SystemExit) as exit_info:
|
||||
server.main()
|
||||
assert exit_info.value.code == 2
|
||||
assert "--bluetooth-interval" in capsys.readouterr().err
|
||||
|
||||
|
||||
def test_failed_serial_read_retries_soon_and_hides_a_short_failure(monkeypatch):
|
||||
data = JBDBMS()
|
||||
state = server.DeviceState(ser=Mock())
|
||||
|
||||
Reference in New Issue
Block a user