Skip to content
Snippets Groups Projects
Commit ba1ecaca authored by David Huss's avatar David Huss :speech_balloon:
Browse files

Propper handling of network disconnect

parent 15e6e634
No related branches found
No related tags found
No related merge requests found
[project] [project]
name = "mediactl" name = "mediactl"
version = "0.1.0" version = "0.1.1"
description = "Add your description here" description = "Add your description here"
dependencies = [ dependencies = [
"fastapi[standard]>=0.114.2", "fastapi[standard]>=0.114.2",
......
import asyncio import asyncio
import aioping import aioping
import errno
from datetime import datetime from datetime import datetime
from typing import Union, List from typing import Union, List
from result import Ok, Err, Result, is_ok, is_err # noqa: F401 from result import Ok, Err, Result, is_ok, is_err # noqa: F401
...@@ -96,6 +97,7 @@ class PowerState(mediactl.EnumState): ...@@ -96,6 +97,7 @@ class PowerState(mediactl.EnumState):
on = "on" on = "on"
off = "off" off = "off"
unknown = "unknown" unknown = "unknown"
disconnected = "disconnected"
def is_on(self) -> bool: def is_on(self) -> bool:
return self in [PowerState.on] return self in [PowerState.on]
...@@ -103,6 +105,9 @@ class PowerState(mediactl.EnumState): ...@@ -103,6 +105,9 @@ class PowerState(mediactl.EnumState):
def is_off(self) -> bool: def is_off(self) -> bool:
return not self.is_on() return not self.is_on()
def is_disconnected(self) -> bool:
return self in [PowerState.disconnected]
class Channel(mediactl.WithLogger): class Channel(mediactl.WithLogger):
def __init__(self, number: int, logger=None): def __init__(self, number: int, logger=None):
...@@ -233,6 +238,17 @@ class Ahm16(mediactl.WithLogger): ...@@ -233,6 +238,17 @@ class Ahm16(mediactl.WithLogger):
else str(self.status["last-seen"]) else str(self.status["last-seen"])
) )
self.log_error(f"AHM could not_be_reached. Last seen: {last}") self.log_error(f"AHM could not_be_reached. Last seen: {last}")
except OSError as e:
if e.errno == errno.ENETUNREACH:
self.status["power"] = PowerState.disconnected
last = "never" if self.status["last-seen"] is None else str(self.status["last-seen"])
self.log_error(f"AHM Dante Network is down or AHM unreachable {e.errno}: {e.strerror}. Last seen: {last}")
else:
# Othernetwork‐level failure (no route, interface down, etc.)
self.status["power"] = PowerState.unknown
last = "never" if self.status["last-seen"] is None else str(self.status["last-seen"])
self.log_error(f"AHM ping OSError {e.errno}: {e.strerror}. Last seen: {last}")
async def get_status(self, name=False): async def get_status(self, name=False):
await self.ping() await self.ping()
......
...@@ -34,6 +34,15 @@ main { ...@@ -34,6 +34,15 @@ main {
display: none; display: none;
} }
@keyframes blink-red {
0%, 45% {
background-color: var(--color-red);
}
60%, 100% {
background-color: transparent;
}
}
header { header {
width: 100%; width: 100%;
border-bottom: 1px solid white; border-bottom: 1px solid white;
...@@ -90,6 +99,10 @@ header { ...@@ -90,6 +99,10 @@ header {
.warmup .status_text { color: var(--color-orange); } .warmup .status_text { color: var(--color-orange); }
.off .led { background-color: var(--color-red); } .off .led { background-color: var(--color-red); }
.off .status_text { color: var(--color-red); } .off .status_text { color: var(--color-red); }
.disconnected .led {
background-color: transparent;
animation: blink-red 1s infinite;
}
} }
main.disconnected{ main.disconnected{
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment