Fix offline board flooding: fail-fast probe in hardware driver poll()
All three hardware drivers (Olimex, generic_esp32, generic_esp8266) now
probe with the first request and bail immediately on failure.
Before: offline board with 4 relays + 3 inputs = 7 requests × 3 s timeout
= up to 21 s of blocking + 7 log lines per recheck cycle.
After: exactly 1 request × 3 s timeout regardless of I/O count.
This commit is contained in:
@@ -70,21 +70,35 @@ class GenericESP32Driver(BoardDriver):
|
|||||||
return bool(data["state"]) if data is not None else None
|
return bool(data["state"]) if data is not None else None
|
||||||
|
|
||||||
def poll(self, board: "Board") -> dict:
|
def poll(self, board: "Board") -> dict:
|
||||||
relay_states, input_states, online = {}, {}, False
|
_offline = {"relay_states": {}, "input_states": {}, "is_online": False}
|
||||||
|
relay_states, input_states = {}, {}
|
||||||
|
|
||||||
for n in range(1, board.num_relays + 1):
|
# Fail-fast probe — bail immediately if board is unreachable
|
||||||
|
if board.num_relays > 0:
|
||||||
|
probe = _get(f"{board.base_url}/relay/status?relay=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
relay_states["relay_1"] = bool(probe.get("state", False))
|
||||||
|
elif board.num_inputs > 0:
|
||||||
|
probe = _get(f"{board.base_url}/input/status?input=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
input_states["input_1"] = bool(probe.get("state", False))
|
||||||
|
else:
|
||||||
|
return _offline
|
||||||
|
|
||||||
|
for n in range(2, board.num_relays + 1):
|
||||||
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
||||||
online = True
|
|
||||||
|
|
||||||
for n in range(1, board.num_inputs + 1):
|
input_start = 2 if (board.num_relays == 0 and board.num_inputs > 0) else 1
|
||||||
|
for n in range(input_start, board.num_inputs + 1):
|
||||||
data = _get(f"{board.base_url}/input/status?input={n}")
|
data = _get(f"{board.base_url}/input/status?input={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
input_states[f"input_{n}"] = bool(data.get("state", False))
|
input_states[f"input_{n}"] = bool(data.get("state", False))
|
||||||
online = True
|
|
||||||
|
|
||||||
return {"relay_states": relay_states, "input_states": input_states, "is_online": online}
|
return {"relay_states": relay_states, "input_states": input_states, "is_online": True}
|
||||||
|
|
||||||
def register_webhook(self, board: "Board", callback_url: str) -> bool:
|
def register_webhook(self, board: "Board", callback_url: str) -> bool:
|
||||||
return _post(f"{board.base_url}/register?callback_url={callback_url}") is not None
|
return _post(f"{board.base_url}/register?callback_url={callback_url}") is not None
|
||||||
|
|||||||
@@ -60,21 +60,35 @@ class GenericESP8266Driver(BoardDriver):
|
|||||||
return bool(data["state"]) if data is not None else None
|
return bool(data["state"]) if data is not None else None
|
||||||
|
|
||||||
def poll(self, board: "Board") -> dict:
|
def poll(self, board: "Board") -> dict:
|
||||||
relay_states, input_states, online = {}, {}, False
|
_offline = {"relay_states": {}, "input_states": {}, "is_online": False}
|
||||||
|
relay_states, input_states = {}, {}
|
||||||
|
|
||||||
for n in range(1, board.num_relays + 1):
|
# Fail-fast probe — bail immediately if board is unreachable
|
||||||
|
if board.num_relays > 0:
|
||||||
|
probe = _get(f"{board.base_url}/relay/status?relay=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
relay_states["relay_1"] = bool(probe.get("state", False))
|
||||||
|
elif board.num_inputs > 0:
|
||||||
|
probe = _get(f"{board.base_url}/input/status?input=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
input_states["input_1"] = bool(probe.get("state", False))
|
||||||
|
else:
|
||||||
|
return _offline
|
||||||
|
|
||||||
|
for n in range(2, board.num_relays + 1):
|
||||||
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
||||||
online = True
|
|
||||||
|
|
||||||
for n in range(1, board.num_inputs + 1):
|
input_start = 2 if (board.num_relays == 0 and board.num_inputs > 0) else 1
|
||||||
|
for n in range(input_start, board.num_inputs + 1):
|
||||||
data = _get(f"{board.base_url}/input/status?input={n}")
|
data = _get(f"{board.base_url}/input/status?input={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
input_states[f"input_{n}"] = bool(data.get("state", False))
|
input_states[f"input_{n}"] = bool(data.get("state", False))
|
||||||
online = True
|
|
||||||
|
|
||||||
return {"relay_states": relay_states, "input_states": input_states, "is_online": online}
|
return {"relay_states": relay_states, "input_states": input_states, "is_online": True}
|
||||||
|
|
||||||
def register_webhook(self, board: "Board", callback_url: str) -> bool:
|
def register_webhook(self, board: "Board", callback_url: str) -> bool:
|
||||||
return _post(f"{board.base_url}/register?callback_url={callback_url}") is not None
|
return _post(f"{board.base_url}/register?callback_url={callback_url}") is not None
|
||||||
|
|||||||
@@ -83,26 +83,44 @@ class OlimexESP32C6EVBDriver(BoardDriver):
|
|||||||
# ── poll ──────────────────────────────────────────────────────────────────
|
# ── poll ──────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
def poll(self, board: "Board") -> dict:
|
def poll(self, board: "Board") -> dict:
|
||||||
|
_offline = {"relay_states": {}, "input_states": {}, "is_online": False}
|
||||||
|
|
||||||
|
# ── Connectivity probe ─────────────────────────────────────────────
|
||||||
|
# Try the very first endpoint. If the board doesn't reply we know
|
||||||
|
# it's offline and skip all remaining requests (saving N × 3 s worth
|
||||||
|
# of connect timeouts on every recheck cycle).
|
||||||
relay_states: dict = {}
|
relay_states: dict = {}
|
||||||
input_states: dict = {}
|
input_states: dict = {}
|
||||||
online = False
|
|
||||||
|
|
||||||
for n in range(1, board.num_relays + 1):
|
if board.num_relays > 0:
|
||||||
|
probe = _get(f"{board.base_url}/relay/status?relay=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
relay_states["relay_1"] = bool(probe.get("state", False))
|
||||||
|
elif board.num_inputs > 0:
|
||||||
|
probe = _get(f"{board.base_url}/input/status?input=1")
|
||||||
|
if probe is None:
|
||||||
|
return _offline
|
||||||
|
input_states["input_1"] = bool(probe.get("state", False))
|
||||||
|
else:
|
||||||
|
return _offline
|
||||||
|
|
||||||
|
# Board is reachable — collect remaining endpoints
|
||||||
|
for n in range(2, board.num_relays + 1):
|
||||||
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
data = _get(f"{board.base_url}/relay/status?relay={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
relay_states[f"relay_{n}"] = bool(data.get("state", False))
|
||||||
online = True
|
|
||||||
|
|
||||||
for n in range(1, board.num_inputs + 1):
|
input_start = 2 if (board.num_relays == 0 and board.num_inputs > 0) else 1
|
||||||
|
for n in range(input_start, board.num_inputs + 1):
|
||||||
data = _get(f"{board.base_url}/input/status?input={n}")
|
data = _get(f"{board.base_url}/input/status?input={n}")
|
||||||
if data is not None:
|
if data is not None:
|
||||||
input_states[f"input_{n}"] = bool(data.get("state", True))
|
input_states[f"input_{n}"] = bool(data.get("state", True))
|
||||||
online = True
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"relay_states": relay_states,
|
"relay_states": relay_states,
|
||||||
"input_states": input_states,
|
"input_states": input_states,
|
||||||
"is_online": online,
|
"is_online": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
# ── webhook registration ──────────────────────────────────────────────────
|
# ── webhook registration ──────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user