added home assistant sensor for grid power and fixed overall layout by refactoring

This commit is contained in:
2026-04-24 19:13:18 +05:30
parent ac985ececa
commit f419890f65
3 changed files with 107 additions and 50 deletions

View File

@@ -2,3 +2,4 @@ NTFY_Token=
device_name=
logging_level=DEBUG
shutdown_timer=30
HA_Token=

1
.gitignore vendored
View File

@@ -1 +1,2 @@
.env
venv

149
main.py
View File

@@ -30,9 +30,18 @@ if not logger.handlers:
ntfy_token = os.environ['NTFY_Token']
device_name = os.environ['device_name']
shutdown_timer = int(os.environ['shutdown_timer'])
ha_token = os.environ['HA_Token']
####################################################
#Globals
running = True
inverter_online = True
last_online = time.monotonic()
grid_online = True
def handle_shutdown(signum, frame):
global running
logger.info("Received shutdown signal, exiting...")
@@ -41,41 +50,97 @@ def handle_shutdown(signum, frame):
signal.signal(signal.SIGTERM, handle_shutdown)
signal.signal(signal.SIGINT, handle_shutdown)
def send_message(title: str, text: str):
try:
requests.post("https://ntfy.fieryeagle.org/Internet-Alerts",
data=text.encode("utf-8"),
headers={
"Title": title,
"Authorization": f"Bearer {ntfy_token}"
},
timeout=5)
except Exception as e:
logger.error(f"Failed to send notification: {e}")
def main():
with serial.Serial(device_name, 115200, timeout=1) as ser:
shutdown_triggered = False
def check_inverter(status: bool):
global inverter_online
global last_online
if status:
logger.debug("Inverter Online")
inverter_online = True
last_online = time.monotonic()
receiving_data = True
last_logged = -1
try:
return True
else:
if inverter_online:
logger.info("Running on UPS reserve")
inverter_online = False
return False
def check_grid(status: bool):
global grid_online
if status:
logger.debug("Grid Online")
if not grid_online:
logger.info("Grid restored")
send_message("Grid back online", "Systems restored")
try:
requests.post("https://home.fieryeagle.org/api/states/binary_sensor.grid_power",
headers={
"Authorization": f"Bearer {ha_token}",
"Content-Type": "application/json"
},
json={"state": "on"},
timeout=5
)
except Exception as e:
logger.error(f"Could not update HA sensor: {e}")
grid_online = True
return True
else:
if grid_online:
logger.info("Running on Inverter reserve")
send_message("Grid power offline", "Running on Inverter reserve")
try:
requests.post("https://home.fieryeagle.org/api/states/binary_sensor.grid_power",
headers={
"Authorization": f"Bearer {ha_token}",
"Content-Type": "application/json"
},
json={"state": "off"},
timeout=5
)
except Exception as e:
logger.error(f"Could not update HA sensor: {e}")
grid_online = False
return False
def main():
shutdown_triggered = False
try:
with serial.Serial(device_name, 115200, timeout=1) as ser:
global last_online
last_logged = -1
while running:
line = ser.readline().decode(errors="ignore").strip()
if line == "":
logger.warning("No serial data")
continue
if line != "" and not receiving_data:
receiving_data = True
logger.info("Serial data restored")
if line not in ("00", "01", "10", "11"):
logger.warning(f"Invalid serial data: {line}")
continue
if line == "0":
logger.debug("Inverter Online")
if not inverter_online:
logger.info("Inverter restored")
inverter_online = True
last_online = time.monotonic()
inverter_status = line[0] == "0"
grid_status = line[1] == "0"
elif line == "1":
if inverter_online:
inverter_online = False
logger.info("Running on UPS reserve")
elif line == "":
if receiving_data:
receiving_data = False
logger.warning("No serial data")
else:
logger.warning(f"Unexpected serial data: {line}")
check_inverter(inverter_status)
check_grid(grid_status)
if not inverter_online:
sec = int(time.monotonic() - last_online)
@@ -87,26 +152,16 @@ def main():
if sec >= shutdown_timer:
shutdown_triggered = True
break
if shutdown_triggered:
logger.info(f"Inverter offline for {shutdown_timer} seconds")
try:
requests.post(
"https://ntfy.fieryeagle.org/Internet-Alerts",
data="Inverter offline, shutting down".encode("utf-8"),
headers={
"Title": "Hydrogen running on reserve power",
"Authorization": f"Bearer {ntfy_token}"
},
timeout=5
)
except Exception as e:
logger.error(f"Failed to send notification: {e}")
os.system("shutdown now")
else:
logger.info("Exited cleanly (service stop)")
except serial.SerialException as e:
logger.error(f"Serial device error: {e}")
raise
except serial.SerialException as e:
logger.error(f"Serial error: {e}")
if shutdown_triggered:
logger.info(f"Inverter offline for {shutdown_timer} seconds")
send_message("Inverter offline", "Hydrogen running on reserve power, shutting down")
os.system("shutdown now")
else:
logger.info("Exited cleanly (service stop)")
if __name__ == "__main__":
main()