Files
HP_InHand_IG502/Pub_Sub/ek_facility/thingsboard/pub/sendData.py
2025-03-13 16:01:03 -05:00

267 lines
11 KiB
Python

# Enter your python code.
import json, os, time, shutil
from datetime import datetime as dt
from common.Logger import logger
from quickfaas.remotebus import publish
from quickfaas.global_dict import get as get_params
from quickfaas.global_dict import _set_global_args
from mobiuspi_lib.gps import GPS
def reboot():
#basic = Basic()
logger.info("!" * 10 + "REBOOTING DEVICE" + "!"*10)
r = os.popen("kill -s SIGHUP `cat /var/run/python/supervisord.pid`").read()
logger.info(f"REBOOT : {r}")
def checkFileExist(filename):
path = "/var/user/files"
if not os.path.exists(path):
logger.info("no folder making files folder in var/user")
os.makedirs(path)
with open(path + "/" + filename, "a") as f:
json.dump({}, f)
if not os.path.exists(path + "/" + filename):
logger.info("no creds file making creds file")
with open(path + "/" + filename, "a") as f:
json.dump({}, f)
def convertDStoJSON(ds):
j = dict()
for x in ds:
j[x["key"]] = x["value"]
return j
def convertJSONtoDS(j):
d = []
for key in j.keys():
d.append({"key": key, "value": j[key]})
return d
def checkCredentialConfig():
logger.info("CHECKING CONFIG")
cfgpath = "/var/user/cfg/device_supervisor/device_supervisor.cfg"
credspath = "/var/user/files/creds.json"
cfg = dict()
with open(cfgpath, "r") as f:
cfg = json.load(f)
clouds = cfg.get("clouds")
logger.info(clouds)
#if not configured then try to configure from stored values
if clouds[0]["args"]["clientId"] == "unknown" or clouds[0]["args"]["username"] == "unknown" or not clouds[0]["args"]["passwd"] or clouds[0]["args"]["passwd"] == "unknown":
checkFileExist("creds.json")
with open(credspath, "r") as c:
creds = json.load(c)
if creds:
logger.info("updating config with stored data")
clouds[0]["args"]["clientId"] = creds["clientId"]
clouds[0]["args"]["username"] = creds["userName"]
clouds[0]["args"]["passwd"] = creds["password"]
cfg["clouds"] = clouds
cfg = checkParameterConfig(cfg)
with open(cfgpath, "w", encoding='utf-8') as n:
json.dump(cfg, n, indent=1, ensure_ascii=False)
reboot()
else:
#assuming clouds is filled out, if data is different then assume someone typed in something new and store it, if creds is empty fill with clouds' data
checkFileExist("creds.json")
with open(credspath, "r") as c:
logger.info("updating stored file with new data")
cfg = checkParameterConfig(cfg)
with open(cfgpath, "w", encoding='utf-8') as n:
json.dump(cfg, n, indent=1, ensure_ascii=False)
creds = json.load(c)
if creds:
if creds["clientId"] != clouds[0]["args"]["clientId"]:
creds["clientId"] = clouds[0]["args"]["clientId"]
if creds["userName"] != clouds[0]["args"]["username"]:
creds["userName"] = clouds[0]["args"]["username"]
if creds["password"] != clouds[0]["args"]["passwd"]:
creds["password"] = clouds[0]["args"]["passwd"]
else:
creds["clientId"] = clouds[0]["args"]["clientId"]
creds["userName"] = clouds[0]["args"]["username"]
creds["password"] = clouds[0]["args"]["passwd"]
with open(credspath, "w") as cw:
json.dump(creds,cw)
def checkParameterConfig(cfg):
logger.info("Checking Parameters!!!!")
paramspath = "/var/user/files/params.json"
cfgparams = convertDStoJSON(cfg.get("labels"))
#check stored values
checkFileExist("params.json")
with open(paramspath, "r") as f:
logger.info("Opened param storage file")
params = json.load(f)
if params:
if cfgparams != params:
#go through each param
#if not "unknown" and cfg and params aren't the same take from cfg likely updated manually
#if key in cfg but not in params copy to params
logger.info("equalizing params between cfg and stored")
for key in cfgparams.keys():
try:
if cfgparams[key] != params[key] and cfgparams[key] != "unknown":
params[key] = cfgparams[key]
except:
params[key] = cfgparams[key]
cfg["labels"] = convertJSONtoDS(params)
_set_global_args(convertJSONtoDS(params))
with open(paramspath, "w") as p:
json.dump(params, p)
else:
with open(paramspath, "w") as p:
logger.info("initializing param file with params in memory")
json.dump(convertDStoJSON(get_params()), p)
cfg["labels"] = get_params()
return cfg
def getGPS():
# Create a gps instance
gps = GPS()
# Retrieve GPS information
position_status = gps.get_position_status()
logger.debug("position_status: ")
logger.debug(position_status)
latitude = position_status["latitude"].split(" ")
longitude = position_status["longitude"].split(" ")
lat_dec = int(latitude[0][:-1]) + (float(latitude[1][:-1])/60)
lon_dec = int(longitude[0][:-1]) + (float(longitude[1][:-1])/60)
if latitude[2] == "S":
lat_dec = lat_dec * -1
if longitude[2] == "W":
lon_dec = lon_dec * -1
#lat_dec = round(lat_dec, 7)
#lon_dec = round(lon_dec, 7)
logger.info("HERE IS THE GPS COORDS")
logger.info(f"LATITUDE: {lat_dec}, LONGITUDE: {lon_dec}")
speedKnots = position_status["speed"].split(" ")
speedMPH = float(speedKnots[0]) * 1.151
return (f"{lat_dec:.8f}",f"{lon_dec:.8f}",f"{speedMPH:.2f}")
def chunk_payload(payload, chunk_size=20):
if "values" in payload:
# Original format: {"ts": ..., "values": {...}}
chunked_values = list(payload["values"].items())
for i in range(0, len(chunked_values), chunk_size):
yield {
"ts": payload["ts"],
"values": dict(chunked_values[i:i+chunk_size])
}
else:
# New format: {"key1": "value1", "key2": "value2"}
chunked_keys = list(payload.keys())
for i in range(0, len(chunked_keys), chunk_size):
yield {k: payload[k] for k in chunked_keys[i:i+chunk_size]}
def saveStoredAlarms(alarms):
try:
with open('/var/user/files/storedAlarms.json', 'w') as f:
json.dump(alarms, f, indent=4)
except (IOError, OSError, json.JSONEncodeError) as e:
logger.error(f"Error saving totalizers to /var/user/files/storedAlarms.json: {e}")
def getStoredAlarms():
storedAlarms = {}
try:
with open('/var/user/files/storedAlarms.json', 'r') as f:
storedAlarms = json.load(f)
except FileNotFoundError:
storedAlarms = {
"compressor_ambient_temp_hihi_alm": -1,
"compressor_ambient_temp_hi_alm": -1,
"compressor_ambient_temp_lo_alm": -1,
"compressor_ambient_temp_lolo_alm": -1
}
saveStoredAlarms(storedAlarms)
except json.JSONDecodeError:
timestamp = dt.now().strftime("%Y%m%d_%H%M%S")
# Split the file path and insert the timestamp before the extension
file_name, file_extension = os.path.splitext('/var/user/files/storedAlarms.json')
backup_file_path = f"{file_name}_{timestamp}{file_extension}"
shutil.copyfile('/var/user/files/storedAlarms.json', backup_file_path)
logger.error(f"Error decoding JSON. A backup of the file is created at {backup_file_path}. Initializing totalizers.")
storedAlarms = {
"compressor_ambient_temp_hihi_alm": -1,
"compressor_ambient_temp_hi_alm": -1,
"compressor_ambient_temp_lo_alm": -1,
"compressor_ambient_temp_lolo_alm": -1
}
saveStoredAlarms(storedAlarms)
return storedAlarms
def checkAlarms(name, value):
#function checks if the alarm has been active for 30 mins, if so it also adds a reset alarm
#to renotify users an alarm is present
storedAlarms = getStoredAlarms()
now = time.time()
#if currently alarmed but not stored then store alarm
if value == 1 and storedAlarms.get(name) == -1:
storedAlarms[name] = now
saveStoredAlarms(storedAlarms)
return None
#if currently alarmed and alarm greater than 30 mins then add a reset to payload and reset stored time
if value == 1 and now - storedAlarms.get(name) > 1770:
storedAlarms[name] = now
saveStoredAlarms(storedAlarms)
return name
# if currently not alarms but storedAlarm is active reset stored alarm
if value == 0 and storedAlarms.get(name) > 0:
storedAlarms[name] = -1
saveStoredAlarms(storedAlarms)
return None
return None
def sendData(message):
logger.debug(message)
"""
try:
checkCredentialConfig()
except Exception as e:
logger.error(e)
"""
now = (round(dt.timestamp(dt.now())/60)*60)*1000
payload = {"ts": now, "values": {}}
attributes_payload = {}
resetAlarms = []
alarmResetPayload = {"ts": now-1000, "values": {}}
for measure in message["measures"]:
try:
logger.debug(measure)
if measure["health"] == 1:
if "_spt" in measure["name"]:
attributes_payload[measure["name"]] = measure["value"]
if measure["name"] in ["compressor_ambient_temp_hihi_alm","compressor_ambient_temp_hi_alm","compressor_ambient_temp_lo_alm", "compressor_ambient_temp_lolo_alm"]:
resetAlarms.append(checkAlarms(measure["name"], measure["value"]))
payload["values"][measure["name"]] = measure["value"]
except Exception as e:
logger.error(e)
logger.debug(payload)
"""
try:
payload["values"]["latitude"], payload["values"]["longitude"], payload["values"]["speed"] = getGPS()
except:
logger.error("Could not get GPS coordinates")
"""
for alarm in resetAlarms:
if alarm:
alarmResetPayload["values"][alarm] = 0
if alarmResetPayload["values"]:
publish(__topic__, json.dumps(alarmResetPayload), __qos__)
time.sleep(2)
for chunk in chunk_payload(payload=payload, chunk_size=20):
publish(__topic__, json.dumps(chunk), __qos__)
time.sleep(2)
attributes_payload["latestReportTime"] = (round(dt.timestamp(dt.now())))*1000
attributes_payload["connected"] = 1
for chunk in chunk_payload(payload=attributes_payload):
publish("v1/devices/me/attributes", json.dumps(chunk), __qos__)
time.sleep(2)