First version
This commit is contained in:
111
upsmon.py
Normal file
111
upsmon.py
Normal file
@@ -0,0 +1,111 @@
|
||||
import sys
|
||||
import json
|
||||
import subprocess
|
||||
import logging
|
||||
from time import sleep
|
||||
from random import randint
|
||||
|
||||
import paho.mqtt.client as mqtt
|
||||
import paho.mqtt.enums as mqtt_enums
|
||||
|
||||
# Logger options
|
||||
LOGFILE = '/mnt/logs/UPSmon.log'
|
||||
|
||||
#CONSOLE_DEBUG = logging.DEBUG
|
||||
CONSOLE_DEBUG = logging.INFO
|
||||
#FILE_DEBUG = logging.ERROR
|
||||
#FILE_DEBUG = logging.WARNING
|
||||
FILE_DEBUG = logging.INFO
|
||||
#FILE_DEBUG = logging.DEBUG
|
||||
|
||||
LOG_FORMAT = ('%(asctime)s| %(levelname)-7s|%(funcName)-10s|%(lineno)-3d: %(message)-50s')
|
||||
LOG_TIME_FORMAT = ('%m-%d %H:%M:%S')
|
||||
LOGGER: logging.Logger
|
||||
|
||||
# UPSmon Config
|
||||
CMD: str = 'apcaccess'
|
||||
T_LONG: float = 15.0
|
||||
T_SHORT: float = 5.0
|
||||
EXPORT_KEYS: list[str] = [
|
||||
'UPSNAME', 'STATUS', 'LINEV', 'LOADPCT', 'BCHARGE', 'TIMELEFT', 'OUTPUTV', 'ITEMP', 'BATTV', 'LINEFREQ'
|
||||
]
|
||||
|
||||
def clean_data(v: str) -> float | str:
|
||||
if v.isalpha():
|
||||
return v
|
||||
return float(v.split(' ')[0])
|
||||
|
||||
def main() -> int:
|
||||
i: int = 0
|
||||
client: mqtt.Client = mqtt.Client(callback_api_version=mqtt_enums.CallbackAPIVersion.VERSION2,
|
||||
client_id=f"upsmon_{randint(1,100)}")
|
||||
|
||||
while client.connect(host='10.0.2.249', port=1883) != mqtt_enums.MQTTErrorCode.MQTT_ERR_SUCCESS:
|
||||
LOGGER.warning("MQTT Client retry connect")
|
||||
sleep(10.0)
|
||||
|
||||
LOGGER.info("MQTT Client connected")
|
||||
client.loop_start()
|
||||
|
||||
while client.is_connected():
|
||||
try:
|
||||
rv: bytes = subprocess.check_output(CMD, timeout=2.0)
|
||||
data_raw: list[list[str]] = [
|
||||
l.split(':', 1) for l in rv.decode(encoding='ascii').splitlines()
|
||||
]
|
||||
data = {
|
||||
k.strip().lower():clean_data(v.strip()) for k,v in data_raw if k.strip() in EXPORT_KEYS
|
||||
}
|
||||
LOGGER.debug(f"[{i}] {json.dumps(data, indent=2)}")
|
||||
|
||||
tag: str = str(data.pop('upsname'))
|
||||
client.publish(topic='monitoring/ups/status',
|
||||
payload=json.dumps(
|
||||
obj=(data, {"upsname":tag})
|
||||
))
|
||||
|
||||
sleep(T_LONG if data.get("STATUS", "ONLINE") == "ONLINE" else T_SHORT)
|
||||
i += 1
|
||||
except FileNotFoundError as f:
|
||||
LOGGER.error(f"{CMD} executable not found: {f}")
|
||||
return f.errno if f.errno else -1
|
||||
except subprocess.CalledProcessError as e:
|
||||
LOGGER.error(f"{CMD} failed with: {e}")
|
||||
return e.returncode
|
||||
except KeyboardInterrupt:
|
||||
LOGGER.warning("Stopping...")
|
||||
break
|
||||
except Exception as ee: # default case catch all
|
||||
LOGGER.error(f"Unexpected Exception: {ee}")
|
||||
return -2
|
||||
|
||||
LOGGER.info("MQTT Client Disconnected")
|
||||
client.disconnect()
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Enabling Logger
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
LOGGER.setLevel(logging.DEBUG)
|
||||
LOGGER.propagate = False
|
||||
formatter = logging.Formatter(LOG_FORMAT,LOG_TIME_FORMAT)
|
||||
|
||||
# File logging
|
||||
fh = logging.FileHandler(LOGFILE)
|
||||
fh.setLevel(FILE_DEBUG)
|
||||
fh.setFormatter(formatter)
|
||||
LOGGER.addHandler(fh)
|
||||
|
||||
# Console logging
|
||||
cl = logging.StreamHandler(sys.stdout)
|
||||
cl.setLevel(CONSOLE_DEBUG)
|
||||
cl.setFormatter(formatter)
|
||||
LOGGER.addHandler(cl)
|
||||
|
||||
LOGGER.warning("UPSmon started")
|
||||
|
||||
while main() != 0:
|
||||
LOGGER.warning("Restarting...")
|
||||
sleep(30.0)
|
||||
sys.exit(0)
|
||||
Reference in New Issue
Block a user