configuration in json and offline client support

Program will now work even if some of rpi are offline.
Server settings are now saved in settings.json for easier update on servers.
Uploaded more testing files.
Also slight improvments of formating and comenting of the code
This commit is contained in:
Untriex Programming 2021-03-12 17:26:05 +01:00
parent a8152f9ca3
commit 1df6405a3d
7 changed files with 84 additions and 43 deletions

@ -2,14 +2,17 @@ from datetime import datetime
class Log(): class Log():
def __init__(self, save_e=True, save_w=False, save_m=False, print_e=True, print_w=True, print_m=False, debug=False): def __init__(self, settings=None):
self.save_error = save_e if settings is None:
self.save_warning = save_w settings = {"save_error": True, "print_error": True, "save_warning": True, "print_warning": True,
self.save_messages = save_m "save_message": False, "print_message": True, "enable_debug": False}
self.print_error = print_e self.save_error = settings["save_error"]
self.print_warning = print_w self.save_warning = settings["save_warning"]
self.print_messages = print_m self.save_messages = settings["save_message"]
self.debug_e = debug self.print_error = settings["print_error"]
self.print_warning = settings["print_warning"]
self.print_messages = settings["print_message"]
self.debug_e = settings["enable_debug"]
def error(self, error): def error(self, error):
if self.print_error: if self.print_error:

BIN
files/test.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 354 KiB

@ -1 +1 @@
toto je test číslo 1 toto je test číslo 1 zo serveru s ID 2

@ -1 +1 @@
toto je test n. 2 toto je test n. 2 zo serveru ID2

@ -1,3 +0,0 @@
2021-03-10 12:20:52.490547 -> ERROR: heartbeat > list indices must be integers or slices, not str
2021-03-10 12:29:03.690483 -> ERROR: heartbeat > list indices must be integers or slices, not str

78
main.py

@ -8,33 +8,34 @@ import json
import os import os
import threading import threading
app = FastAPI() with open("settings.json", "r") as f: #loading settings
settings = json.load(f)
sensors = { IP = settings["IP"]
ID = settings["ID"]
location = settings["location"]
app = FastAPI() #init of FastAPI
log = engine.Log(settings["log"]) # init of LOG
offline = []
time_to_heartbeat = settings["time_to_heartbeat"] # Raspberry will be requesting heartbeat every __ seconds
time_to_heartbeat_offline = settings["time_to_heartbeat_offline"] # Raspberry will be requesting heartbeat every __ seconds from offline rpi
# json variables
filesystem = { # Here will be files saved on this raspberry
"otvaracie_hod": ["t", {"pon": "10-25"}, {"uto": "10-25"}],
"prehliadka": ["pdf", "/files/prehliadka.pdf"],
"fotky_hrad": ["png_z", ["/files/hrad1.png", "/files/hrad2.png"]]
}
heartbeat_table = settings["heartbeat_table"]
sensors = { # List of "live" data like tempeature, etc.
"teplota": 24, "teplota": 24,
"vlhkosť": 25, "vlhkosť": 25,
"počet ľudí": 10, "počet ľudí": 10,
"doba čakania": 2 "doba čakania": 2
} }
log = engine.Log(print_m=True, debug=False)
time_to_heartbeat = 20 # Seconds
location = "2"
ID = 2
IP = "192.168.1.99"
filesystem = {
"otvaracie_hod": ["t", {"pon": "10-25"}, {"uto": "10-25"}],
"prehliadka": ["pdf", "/files/prehliadka.pdf"],
"fotky_hrad": ["png_z", ["/files/hrad1.png", "/files/hrad2.png"]]
}
heartbeat_table = {
"ID": [1],
"IP": ["192.168.1.231"],
"location": ["1"],
"file_system": ["x"],
"last_heartbeat": [20]
}
heartbeat_table["ID"].append(ID) heartbeat_table["ID"].append(ID)
heartbeat_table["IP"].append(IP) heartbeat_table["IP"].append(IP)
heartbeat_table["location"].append(location) heartbeat_table["location"].append(location)
@ -44,7 +45,7 @@ heartbeat_table["last_heartbeat"].append(time_to_heartbeat)
# Todo better "host" ID handeling # Todo better "host" ID handeling
class Server_table(BaseModel): class Server_table(BaseModel): # table of content for heartbeat request
ID: list ID: list
IP: list IP: list
location: list location: list
@ -54,7 +55,7 @@ class Server_table(BaseModel):
@app.post("/heartbeat") @app.post("/heartbeat")
def heartbeat(s_table: Server_table, request: Request): def heartbeat(s_table: Server_table, request: Request):
log.message(f"heartbeat requested: {request.client.host}:{request.client.port}") log.message(f"server requested heartbeat {request.client.host}:{request.client.port}")
log.debug(f"Recieved server table: {s_table}") log.debug(f"Recieved server table: {s_table}")
try: try:
for position, server_id in enumerate(s_table.ID): for position, server_id in enumerate(s_table.ID):
@ -64,7 +65,8 @@ def heartbeat(s_table: Server_table, request: Request):
heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(server_id)] = s_table.last_heartbeat[ heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(server_id)] = s_table.last_heartbeat[
position] position]
log.debug(f"updated {server_id}`s heartbeat to {s_table.last_heartbeat[position]}") log.debug(f"updated {server_id}`s heartbeat to {s_table.last_heartbeat[position]}")
# Todo update filesystem too. Now updating only last heartbeat heartbeat_table["file_system"][heartbeat_table["ID"].index(server_id)] = s_table.file_system[
position]
elif server_id == ID: elif server_id == ID:
log.debug(f"Updated my heartbeat from {s_table.last_heartbeat[position]} to {time_to_heartbeat}") log.debug(f"Updated my heartbeat from {s_table.last_heartbeat[position]} to {time_to_heartbeat}")
heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(ID)] = time_to_heartbeat heartbeat_table["last_heartbeat"][heartbeat_table["ID"].index(ID)] = time_to_heartbeat
@ -76,6 +78,9 @@ def heartbeat(s_table: Server_table, request: Request):
heartbeat_table["last_heartbeat"].append(s_table.last_heartbeat[position]) heartbeat_table["last_heartbeat"].append(s_table.last_heartbeat[position])
except Exception as error: except Exception as error:
log.error(f"heartbeat > {error}") log.error(f"heartbeat > {error}")
if heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)] in offline:
offline.remove(heartbeat_table["ID"][heartbeat_table["IP"].index(request.client.host)])
log.message(f"{request.client.host} gone online")
return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location} return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location}
@ -91,7 +96,8 @@ def get_file(IDx: int, file: str):
if IDx == ID: if IDx == ID:
return FileResponse(f"files/{file}") return FileResponse(f"files/{file}")
elif IDx in heartbeat_table["ID"]: elif IDx in heartbeat_table["ID"]:
r = requests.get(f"""http://{heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]}:8000/files/{IDx}/{file}""") r = requests.get(
f"""http://{heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]}:8000/files/{IDx}/{file}""")
r.encoding = "utf-8" r.encoding = "utf-8"
if os.path.isdir(f"cache/{IDx}"): if os.path.isdir(f"cache/{IDx}"):
if os.path.isfile(f"cache/{IDx}/{file}"): if os.path.isfile(f"cache/{IDx}/{file}"):
@ -105,7 +111,6 @@ def get_file(IDx: int, file: str):
with open(f"cache/{IDx}/{file}", "wb") as save: with open(f"cache/{IDx}/{file}", "wb") as save:
save.write(bytes(r.content)) save.write(bytes(r.content))
return FileResponse(f"cache/{IDx}/{file}") return FileResponse(f"cache/{IDx}/{file}")
# Todo Get files function for client (phone/ther rpi)
@app.post("/update") @app.post("/update")
@ -113,12 +118,12 @@ def update_sensors():
pass pass
# Todo Make option to upload "live data" manually to rpi # Todo Make option to upload "live data" manually to rpi
def send_heartbeat(ip):
def send_heartbeat(ip, id):
global heartbeat_table global heartbeat_table
log.message(f"requesting heartbeat from {ip}") log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""")
cache_request = requests.post(f"http://{ip}:8000/heartbeat", data=json.dumps(heartbeat_table)) cache_request = requests.post(f"http://{ip}:8000/heartbeat", data=json.dumps(heartbeat_table))
heartbeat_table = dict(cache_request.json()[0]) heartbeat_table = dict(cache_request.json()[0])
#Todo test heartbeat table update
log.debug(json.dumps(cache_request.json(), indent=4)) log.debug(json.dumps(cache_request.json(), indent=4))
@ -127,8 +132,18 @@ def mainloop():
for device_number, device_ID in enumerate(heartbeat_table["ID"]): for device_number, device_ID in enumerate(heartbeat_table["ID"]):
if device_ID != ID: if device_ID != ID:
if heartbeat_table["last_heartbeat"][device_number] < 0: if heartbeat_table["last_heartbeat"][device_number] < 0:
send_heartbeat(heartbeat_table["IP"][device_number]) try:
heartbeat_table["last_heartbeat"][int(device_number)] = int(time_to_heartbeat) + 5 send_heartbeat(heartbeat_table["IP"][device_number], heartbeat_table["ID"][device_number])
except requests.exceptions.ConnectionError:
if heartbeat_table["ID"][device_number] not in offline:
log.warning(f"""{heartbeat_table["IP"][device_number]} disconnected/is not available""")
offline.append(heartbeat_table["ID"][device_number])
heartbeat_table["last_heartbeat"][int(device_number)] = int(time_to_heartbeat_offline)
else:
if heartbeat_table["ID"][device_number] in offline:
offline.remove(heartbeat_table["ID"][device_number])
log.message(f"""{heartbeat_table["IP"][device_number]} gone online""")
heartbeat_table["last_heartbeat"][int(device_number)] = int(time_to_heartbeat) + 5
log.debug(f"""{device_ID} : time to heartbeat : {heartbeat_table["last_heartbeat"][device_number]}""") log.debug(f"""{device_ID} : time to heartbeat : {heartbeat_table["last_heartbeat"][device_number]}""")
heartbeat_table["last_heartbeat"][device_number] -= 1 heartbeat_table["last_heartbeat"][device_number] -= 1
time.sleep(1) time.sleep(1)
@ -136,3 +151,6 @@ def mainloop():
thread_1 = threading.Thread(target=mainloop, daemon=True) thread_1 = threading.Thread(target=mainloop, daemon=True)
thread_1.start() thread_1.start()
# Todo in next release: disconnect offline client after set time
# Todo better formating code + comments

23
settings.json Normal file

@ -0,0 +1,23 @@
{
"ID": 0,
"IP": "192.168.1.99",
"location": "izba",
"time_to_heartbeat": 20,
"time_to_heartbeat_offline": 25,
"log": {
"save_error": true,
"print_error": true,
"save_warning": true,
"print_warning": true,
"save_message": false,
"print_message": true,
"enable_debug": false
},
"heartbeat_table": {
"ID": [],
"IP": [],
"location": [],
"file_system": [],
"last_heartbeat": []
}
}