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= device_name=
logging_level=DEBUG logging_level=DEBUG
shutdown_timer=30 shutdown_timer=30
HA_Token=

1
.gitignore vendored
View File

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

149
main.py
View File

@@ -30,9 +30,18 @@ if not logger.handlers:
ntfy_token = os.environ['NTFY_Token'] ntfy_token = os.environ['NTFY_Token']
device_name = os.environ['device_name'] device_name = os.environ['device_name']
shutdown_timer = int(os.environ['shutdown_timer']) shutdown_timer = int(os.environ['shutdown_timer'])
ha_token = os.environ['HA_Token']
####################################################
#Globals
running = True running = True
inverter_online = True
last_online = time.monotonic()
grid_online = True
def handle_shutdown(signum, frame): def handle_shutdown(signum, frame):
global running global running
logger.info("Received shutdown signal, exiting...") logger.info("Received shutdown signal, exiting...")
@@ -41,41 +50,97 @@ def handle_shutdown(signum, frame):
signal.signal(signal.SIGTERM, handle_shutdown) signal.signal(signal.SIGTERM, handle_shutdown)
signal.signal(signal.SIGINT, 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(): def check_inverter(status: bool):
with serial.Serial(device_name, 115200, timeout=1) as ser: global inverter_online
shutdown_triggered = False global last_online
if status:
logger.debug("Inverter Online")
inverter_online = True inverter_online = True
last_online = time.monotonic() last_online = time.monotonic()
receiving_data = True return True
last_logged = -1
try: 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: while running:
line = ser.readline().decode(errors="ignore").strip() line = ser.readline().decode(errors="ignore").strip()
if line == "":
logger.warning("No serial data")
continue
if line != "" and not receiving_data: if line not in ("00", "01", "10", "11"):
receiving_data = True logger.warning(f"Invalid serial data: {line}")
logger.info("Serial data restored") continue
if line == "0": inverter_status = line[0] == "0"
logger.debug("Inverter Online") grid_status = line[1] == "0"
if not inverter_online:
logger.info("Inverter restored")
inverter_online = True
last_online = time.monotonic()
elif line == "1": check_inverter(inverter_status)
if inverter_online: check_grid(grid_status)
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}")
if not inverter_online: if not inverter_online:
sec = int(time.monotonic() - last_online) sec = int(time.monotonic() - last_online)
@@ -87,26 +152,16 @@ def main():
if sec >= shutdown_timer: if sec >= shutdown_timer:
shutdown_triggered = True shutdown_triggered = True
break break
if shutdown_triggered: except serial.SerialException as e:
logger.info(f"Inverter offline for {shutdown_timer} seconds") logger.error(f"Serial error: {e}")
try:
requests.post( if shutdown_triggered:
"https://ntfy.fieryeagle.org/Internet-Alerts", logger.info(f"Inverter offline for {shutdown_timer} seconds")
data="Inverter offline, shutting down".encode("utf-8"), send_message("Inverter offline", "Hydrogen running on reserve power, shutting down")
headers={ os.system("shutdown now")
"Title": "Hydrogen running on reserve power", else:
"Authorization": f"Bearer {ntfy_token}" logger.info("Exited cleanly (service stop)")
},
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
if __name__ == "__main__": if __name__ == "__main__":
main() main()