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():
def __init__(self, save_e=True, save_w=False, save_m=False, print_e=True, print_w=True, print_m=False, debug=False):
self.save_error = save_e
self.save_warning = save_w
self.save_messages = save_m
self.print_error = print_e
self.print_warning = print_w
self.print_messages = print_m
self.debug_e = debug
def __init__(self, settings=None):
if settings is None:
settings = {"save_error": True, "print_error": True, "save_warning": True, "print_warning": True,
"save_message": False, "print_message": True, "enable_debug": False}
self.save_error = settings["save_error"]
self.save_warning = settings["save_warning"]
self.save_messages = settings["save_message"]
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):
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

76
main.py

@ -8,33 +8,34 @@ import json
import os
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,
"vlhkosť": 25,
"počet ľudí": 10,
"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["IP"].append(IP)
heartbeat_table["location"].append(location)
@ -44,7 +45,7 @@ heartbeat_table["last_heartbeat"].append(time_to_heartbeat)
# Todo better "host" ID handeling
class Server_table(BaseModel):
class Server_table(BaseModel): # table of content for heartbeat request
ID: list
IP: list
location: list
@ -54,7 +55,7 @@ class Server_table(BaseModel):
@app.post("/heartbeat")
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}")
try:
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[
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:
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
@ -76,6 +78,9 @@ def heartbeat(s_table: Server_table, request: Request):
heartbeat_table["last_heartbeat"].append(s_table.last_heartbeat[position])
except Exception as 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}
@ -91,7 +96,8 @@ def get_file(IDx: int, file: str):
if IDx == ID:
return FileResponse(f"files/{file}")
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"
if os.path.isdir(f"cache/{IDx}"):
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:
save.write(bytes(r.content))
return FileResponse(f"cache/{IDx}/{file}")
# Todo Get files function for client (phone/ther rpi)
@app.post("/update")
@ -113,12 +118,12 @@ def update_sensors():
pass
# Todo Make option to upload "live data" manually to rpi
def send_heartbeat(ip):
def send_heartbeat(ip, id):
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))
heartbeat_table = dict(cache_request.json()[0])
#Todo test heartbeat table update
log.debug(json.dumps(cache_request.json(), indent=4))
@ -127,7 +132,17 @@ def mainloop():
for device_number, device_ID in enumerate(heartbeat_table["ID"]):
if device_ID != ID:
if heartbeat_table["last_heartbeat"][device_number] < 0:
send_heartbeat(heartbeat_table["IP"][device_number])
try:
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]}""")
heartbeat_table["last_heartbeat"][device_number] -= 1
@ -136,3 +151,6 @@ def mainloop():
thread_1 = threading.Thread(target=mainloop, daemon=True)
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": []
}
}