Human error prevention, sensor updates, etc.
This commit is contained in:
parent
03246b5f43
commit
154a52e30d
@ -1,6 +1,8 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
class Log:
|
class Log:
|
||||||
@ -46,7 +48,7 @@ class Update:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
with open("version.json", "r") as f: # loading settings
|
with open("version.json", "r") as f: # loading settings
|
||||||
version = json.load(f)
|
version = json.load(f)
|
||||||
self.url = version["url"]
|
self.url = "https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json"
|
||||||
self.version = version["version"]
|
self.version = version["version"]
|
||||||
self.id = version["id"]
|
self.id = version["id"]
|
||||||
|
|
||||||
@ -54,4 +56,69 @@ class Update:
|
|||||||
return json.loads(requests.get(self.url).text)
|
return json.loads(requests.get(self.url).text)
|
||||||
|
|
||||||
def get_version(self):
|
def get_version(self):
|
||||||
return {"version": self.version, "id": self.id}
|
return {"version": self.version, "id": self.id}
|
||||||
|
|
||||||
|
|
||||||
|
class Scan:
|
||||||
|
def __init__(self):
|
||||||
|
self.cache_exist = os.path.isdir("cache")
|
||||||
|
self.files_exist = os.path.isdir("files")
|
||||||
|
if os.path.isfile("update.zip"):
|
||||||
|
os.remove("update.zip")
|
||||||
|
self.filesystem_exist = os.path.isfile("filesystem.json")
|
||||||
|
self.settings_exist = os.path.isfile("settings.json")
|
||||||
|
self.version_exist = os.path.isfile("version.json")
|
||||||
|
self.errors = []
|
||||||
|
self.state_list = {
|
||||||
|
"error": [],
|
||||||
|
"files": [], # 0 = does not exist, 1 = cant read, 2 = some values missing
|
||||||
|
"filesystem": [],
|
||||||
|
"settings": [],
|
||||||
|
"version": [],
|
||||||
|
"system": []
|
||||||
|
}
|
||||||
|
|
||||||
|
def check_to_go(self):
|
||||||
|
filesystem = ""
|
||||||
|
if self.cache_exist is False:
|
||||||
|
os.mkdir("cache")
|
||||||
|
if self.filesystem_exist is False:
|
||||||
|
self.state_list["error"].append("filesystem")
|
||||||
|
self.state_list["filesystem"].append(0)
|
||||||
|
self.errors.append("Filesystem is missing")
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
with open("filesystem.json", "r") as f:
|
||||||
|
filesystem = json.load(f)
|
||||||
|
except:
|
||||||
|
self.state_list["error"].append("filesystem")
|
||||||
|
self.state_list["filesystem"].append(1)
|
||||||
|
self.errors.append("Filesystem is corrupted")
|
||||||
|
else:
|
||||||
|
filesystem_keys = filesystem.keys()
|
||||||
|
for check in ["ID", "location", "description", "files"]:
|
||||||
|
if check not in filesystem_keys:
|
||||||
|
self.state_list["error"].append("filesystem")
|
||||||
|
self.state_list["filesystem"].append(2)
|
||||||
|
if self.files_exist is False:
|
||||||
|
self.state_list["error"].append("files")
|
||||||
|
self.state_list["files"].append(0)
|
||||||
|
self.errors.append("Files folder does not exists")
|
||||||
|
elif filesystem:
|
||||||
|
for file in dict(filesystem)["files"]:
|
||||||
|
if not os.path.isfile(f"""files/{dict(file)["name"]}{dict(file)["format"]}"""):
|
||||||
|
self.errors.append(f"""{dict(file)["name"]}{dict(file)["format"]} does not exists in file folder.""")
|
||||||
|
if "files" not in self.state_list["error"]:
|
||||||
|
self.state_list["error"].append("files")
|
||||||
|
self.state_list["files"].append(2)
|
||||||
|
if self.settings_exist is False:
|
||||||
|
self.state_list["error"].append("settings")
|
||||||
|
self.state_list["settings"].append(0)
|
||||||
|
if self.version_exist is False:
|
||||||
|
self.state_list["error"].append("version")
|
||||||
|
self.state_list["version"].append(0)
|
||||||
|
|
||||||
|
|
||||||
|
def fix_version(self):
|
||||||
|
subprocess.check_output(["python3", "system.py", "update"])
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"ID": "0",
|
"ID": 0,
|
||||||
"location": "izba",
|
"location": "izba",
|
||||||
"description": {
|
"description": {
|
||||||
"title": "legionrpi",
|
"title": "legionrpi",
|
||||||
|
132
server/main.py
132
server/main.py
@ -1,20 +1,29 @@
|
|||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import engine
|
import engine
|
||||||
import requests
|
import requests
|
||||||
import uuid
|
import uuid
|
||||||
|
import subprocess
|
||||||
from fastapi import FastAPI, Request
|
from fastapi import FastAPI, Request
|
||||||
from fastapi.middleware.cors import CORSMiddleware
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
from fastapi.responses import FileResponse
|
from fastapi.responses import FileResponse
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
check = engine.Scan()
|
||||||
|
check.check_to_go()
|
||||||
|
if check.state_list["error"]:
|
||||||
|
for error in check.errors:
|
||||||
|
print(error)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
with open("settings.json", "r") as f: # loading settings
|
with open("settings.json", "r") as f: # loading settings
|
||||||
settings = json.load(f)
|
settings = json.load(f)
|
||||||
|
|
||||||
with open("filesystem.json", "r") as f: # loading settings
|
with open("filesystem.json", "r") as f: # loading filesystem
|
||||||
filesystem = json.load(f)
|
filesystem = json.load(f)
|
||||||
|
|
||||||
IP = settings["IP"]
|
IP = settings["IP"]
|
||||||
@ -32,7 +41,6 @@ app.add_middleware(
|
|||||||
allow_methods=["*"],
|
allow_methods=["*"],
|
||||||
allow_headers=["*"],
|
allow_headers=["*"],
|
||||||
)
|
)
|
||||||
|
|
||||||
log = engine.Log(settings["log"]) # init of LOG
|
log = engine.Log(settings["log"]) # init of LOG
|
||||||
update = engine.Update()
|
update = engine.Update()
|
||||||
offline = []
|
offline = []
|
||||||
@ -44,12 +52,7 @@ time_to_heartbeat_offline = settings[
|
|||||||
|
|
||||||
# json variables
|
# json variables
|
||||||
heartbeat_table = settings["heartbeat_table"]
|
heartbeat_table = settings["heartbeat_table"]
|
||||||
sensors = { # List of "live" data like tempeature, etc.
|
sensors = {}
|
||||||
"teplota": 24,
|
|
||||||
"vlhkosť": 25,
|
|
||||||
"počet ľudí": 10,
|
|
||||||
"doba čakania": 2
|
|
||||||
}
|
|
||||||
|
|
||||||
messages = []
|
messages = []
|
||||||
|
|
||||||
@ -68,9 +71,14 @@ class ServerTable(BaseModel): # table of content for heartbeat request
|
|||||||
last_heartbeat: list
|
last_heartbeat: list
|
||||||
|
|
||||||
|
|
||||||
|
class Sensor(BaseModel):
|
||||||
|
name: str
|
||||||
|
value: str
|
||||||
|
|
||||||
|
|
||||||
@app.get("/")
|
@app.get("/")
|
||||||
def read_root():
|
def read_root():
|
||||||
return {"Hello": "World"}
|
return "wikispot"
|
||||||
|
|
||||||
|
|
||||||
@app.post("/heartbeat")
|
@app.post("/heartbeat")
|
||||||
@ -107,19 +115,35 @@ def heartbeat(s_table: ServerTable, request: Request):
|
|||||||
return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location}
|
return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location}
|
||||||
|
|
||||||
|
|
||||||
@app.get("/sensors")
|
@app.get("/{IDx}/sensors")
|
||||||
def get_sensors(request: Request):
|
def get_sensors(IDx: int, request: Request):
|
||||||
|
global sensors
|
||||||
log.message(f"sensor data sent to {request.client.host}:{request.client.port}")
|
log.message(f"sensor data sent to {request.client.host}:{request.client.port}")
|
||||||
log.debug(f"sensor data: {sensors}")
|
log.debug(f"sensor data: {sensors}")
|
||||||
return sensors
|
if IDx == ID:
|
||||||
|
return sensors
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
r = requests.get(f"""http://{heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]}:8000/{IDx}/sensors""")
|
||||||
|
return r.json()
|
||||||
|
except Exception as error:
|
||||||
|
log.error(f"Sensor data download from {IDx} failed.\n ERROR: {error}")
|
||||||
|
return f"Sensor data download from {IDx} failed.\n ERROR: {error}"
|
||||||
|
|
||||||
|
|
||||||
@app.get("/files/{IDx}/{file}")
|
@app.get("/files/{IDx}/{file}")
|
||||||
def get_file(IDx: int, file: str):
|
def get_file(IDx: int, file: str, request: Request):
|
||||||
|
log.debug(f"""{request.client} requested {file} from {"this server" if IDx == ID else f"id {IDx}"}""")
|
||||||
server_ip = heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]
|
server_ip = heartbeat_table["IP"][heartbeat_table["ID"].index(IDx)]
|
||||||
if IDx == ID:
|
if IDx == ID:
|
||||||
return FileResponse(f"files/{file}")
|
if os.path.isfile(f"files/{file}"):
|
||||||
elif IDx in heartbeat_table["ID"]:
|
return FileResponse(f"files/{file}")
|
||||||
|
else:
|
||||||
|
return f"File {file} does not exist."
|
||||||
|
if IDx not in heartbeat_table["ID"]:
|
||||||
|
log.error(f"{request.client} tried to access id ({IDx}) that does not exist.")
|
||||||
|
return f"ERROR: {IDx} does not exist."
|
||||||
|
else:
|
||||||
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}"):
|
||||||
with open(f"cache/{IDx}/{file}", "rb") as compared_file:
|
with open(f"cache/{IDx}/{file}", "rb") as compared_file:
|
||||||
@ -128,32 +152,44 @@ def get_file(IDx: int, file: str):
|
|||||||
m.update(line)
|
m.update(line)
|
||||||
rr = requests.get(f"""http://{server_ip}:8000/compare/{file}""")
|
rr = requests.get(f"""http://{server_ip}:8000/compare/{file}""")
|
||||||
if rr.text.strip('"') != str(m.hexdigest()):
|
if rr.text.strip('"') != str(m.hexdigest()):
|
||||||
log.message(f"{file} on server {server_ip} is changed.")
|
log.warning(f"{file} on server {server_ip} is changed.")
|
||||||
else:
|
else:
|
||||||
log.debug(f"returning cached file cache/{IDx}{file}")
|
log.debug(f"returning cached file cache/{IDx}{file}")
|
||||||
return FileResponse(f"cache/{IDx}/{file}")
|
return FileResponse(f"cache/{IDx}/{file}")
|
||||||
else:
|
else:
|
||||||
os.mkdir(f"cache/{IDx}")
|
os.mkdir(f"cache/{IDx}")
|
||||||
log.message(f"downloading {file} from {server_ip}")
|
|
||||||
r = requests.get(f"http://{server_ip}:8000/files/{IDx}/{file}")
|
r = requests.get(f"http://{server_ip}:8000/files/{IDx}/{file}")
|
||||||
|
if "does not exist" in r.text:
|
||||||
|
log.error(f"{request.client} tried to access file ({file}) on id {IDx} that does not exist.")
|
||||||
|
return f"ERROR: {file} does not exist."
|
||||||
|
log.message(f"Downloaded {file} from {server_ip}")
|
||||||
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}")
|
||||||
|
|
||||||
|
|
||||||
@app.post("/update")
|
@app.post("/update_sensor")
|
||||||
def update_sensors():
|
def update_sensors(data: Sensor, request: Request):
|
||||||
pass
|
global sensors
|
||||||
# Todo Make option to upload "live data" manually to rpi
|
if data.name in sensors:
|
||||||
|
log.message(f"{request.client.host} updated sensor {data.name} with value {data.value}")
|
||||||
|
sensors[data.name] = data.value
|
||||||
|
else:
|
||||||
|
log.warning(f"{request.client} created new sensor.\n SENSOR: {data}")
|
||||||
|
sensors[data.name] = data.value
|
||||||
|
return f"Successfuly made"
|
||||||
|
|
||||||
|
|
||||||
@app.get("/compare/{file}")
|
@app.get("/compare/{file}")
|
||||||
def comparision(file: str):
|
def comparision(file: str):
|
||||||
with open(f"files/{file}", "rb") as compared_file:
|
try:
|
||||||
m = hashlib.md5()
|
with open(f"files/{file}", "rb") as compared_file:
|
||||||
for line in compared_file:
|
m = hashlib.md5()
|
||||||
m.update(line)
|
for line in compared_file:
|
||||||
return m.hexdigest()
|
m.update(line)
|
||||||
|
return m.hexdigest()
|
||||||
|
except FileNotFoundError:
|
||||||
|
return f"ERROR {file} does not exist"
|
||||||
|
|
||||||
|
|
||||||
@app.get("/devices_list")
|
@app.get("/devices_list")
|
||||||
@ -161,12 +197,41 @@ def get_devices_list():
|
|||||||
return [{"connected_id": ID}, *heartbeat_table["file_system"]]
|
return [{"connected_id": ID}, *heartbeat_table["file_system"]]
|
||||||
|
|
||||||
|
|
||||||
@app.get("/admin/{command}")
|
@app.get("/admin/get/{command}")
|
||||||
def admin(command: str):
|
def admin_get(command: str):
|
||||||
if command == "get_updates":
|
if command == "get_updates":
|
||||||
return [update.get_version(), update.get_updates()]
|
return [update.get_version(), update.get_updates()]
|
||||||
if "update-" in command:
|
if "update-" in command:
|
||||||
os.system(f"""python3 system.py update -version {command.split("-")[1]}""")
|
state = []
|
||||||
|
version = command.split("-")[1]
|
||||||
|
for rpi in heartbeat_table["IP"]:
|
||||||
|
if rpi != IP:
|
||||||
|
r = requests.get(f"""http://{rpi}:8000/admin/get/update_one-{version}""")
|
||||||
|
if r.text.strip('"').split("\\n")[0] == "SUCCESS":
|
||||||
|
log.message(f"{rpi} was updated to {version}")
|
||||||
|
else:
|
||||||
|
log.warning(f"""{rpi} failed to update. Manual update may be needed for proper working of network.
|
||||||
|
Response from server: {r.text}""")
|
||||||
|
state.append({rpi: r.text.strip('"').split("\\n")})
|
||||||
|
# Todo Remove development comments
|
||||||
|
# subprocess.check_output(f"""python3 system.py update -version {version}""")
|
||||||
|
log.message(f"All devices in network should be updated to {version}")
|
||||||
|
state.append({IP: "updated"})
|
||||||
|
return state
|
||||||
|
if "update_one-" in command:
|
||||||
|
state = subprocess.check_output(["python3", "system.py", "update", "-version", f"""{command.split("-")[1]}"""])
|
||||||
|
log.warning(state.decode("utf-8"))
|
||||||
|
return state.decode("utf-8")
|
||||||
|
if command == "setting":
|
||||||
|
return settings
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("admin/post/{command}")
|
||||||
|
def admin_post(command: str, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Todo upload of update file and settings
|
||||||
|
|
||||||
|
|
||||||
@app.get("/messages/get")
|
@app.get("/messages/get")
|
||||||
@ -183,11 +248,16 @@ def get_messages():
|
|||||||
def get_messages(m_sender: str = None, message: str = None):
|
def get_messages(m_sender: str = None, message: str = None):
|
||||||
if m_sender and message:
|
if m_sender and message:
|
||||||
messages.append({"sender": m_sender, "message": message})
|
messages.append({"sender": m_sender, "message": message})
|
||||||
return "successfull"
|
return "successful"
|
||||||
else:
|
else:
|
||||||
return "Empty message/sender"
|
return "Empty message/sender"
|
||||||
|
|
||||||
|
|
||||||
|
@app.get("/debug")
|
||||||
|
def debug_esp():
|
||||||
|
return "test successful"
|
||||||
|
|
||||||
|
|
||||||
def send_heartbeat(ip, id):
|
def send_heartbeat(ip, id):
|
||||||
global heartbeat_table
|
global heartbeat_table
|
||||||
log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""")
|
log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""")
|
||||||
@ -238,6 +308,8 @@ def mainloop():
|
|||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
|
||||||
|
print(f"""Starting WikiSpot V{update.get_version()["version"]}""")
|
||||||
|
print("GitHub: https://github.com/Tucan444/Mabasej_Team")
|
||||||
thread_1 = threading.Thread(target=mainloop, daemon=True)
|
thread_1 = threading.Thread(target=mainloop, daemon=True)
|
||||||
thread_1.start()
|
thread_1.start()
|
||||||
|
|
||||||
|
@ -6,16 +6,18 @@ import requests
|
|||||||
|
|
||||||
arguments = sys.argv
|
arguments = sys.argv
|
||||||
arguments.remove(sys.argv[0])
|
arguments.remove(sys.argv[0])
|
||||||
|
url = "https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json"
|
||||||
|
|
||||||
if len(arguments) == 0:
|
if len(arguments) == 0:
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
command = arguments[0]
|
command = arguments[0]
|
||||||
if command in ["u", "update"]:
|
if command in ["u", "update"]:
|
||||||
with open("version.json", "r") as f: # loading settings
|
try:
|
||||||
version = json.load(f)
|
server_version = json.loads(requests.get(url).text)
|
||||||
url = version["url"]
|
except Exception as error:
|
||||||
server_version = json.loads(requests.get(url).text)
|
print(f"CAN'T DOWNLOAD VERSION LIST. ERROR: {error}")
|
||||||
|
sys.exit()
|
||||||
if "-version" in arguments:
|
if "-version" in arguments:
|
||||||
try:
|
try:
|
||||||
version_download = arguments[arguments.index("-version") + 1]
|
version_download = arguments[arguments.index("-version") + 1]
|
||||||
@ -27,23 +29,32 @@ if command in ["u", "update"]:
|
|||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
version_download = 0
|
||||||
|
try:
|
||||||
|
with open("version.json", "r") as f: # loading settings
|
||||||
|
version = json.load(f)
|
||||||
|
except:
|
||||||
|
version = {"id": 0}
|
||||||
for ver, data in enumerate(server_version.values()):
|
for ver, data in enumerate(server_version.values()):
|
||||||
if data["id"] > version["id"]:
|
if data["id"] > version["id"] and ver > version_download:
|
||||||
version_download = list(server_version.keys())[ver]
|
version_download = list(server_version.keys())[ver]
|
||||||
|
try:
|
||||||
|
with open("update.zip", "wb") as save:
|
||||||
|
save.write(
|
||||||
|
bytes(requests.get(
|
||||||
|
f"https://github.com/UntriexTv/test_directory/releases/download/{version_download}/update.zip").content))
|
||||||
|
except Exception as error:
|
||||||
|
print(f"FAILED TO DOWNLOAD UPDATE. ERROR: {error}")
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
with open("update.zip", "wb") as save:
|
|
||||||
save.write(
|
|
||||||
bytes(requests.get(
|
|
||||||
f"https://github.com/UntriexTv/test_directory/releases/download/{version_download}/update.zip").content))
|
|
||||||
print("Download succefull")
|
|
||||||
print("Extracting update")
|
|
||||||
if not os.path.isdir("update"):
|
if not os.path.isdir("update"):
|
||||||
os.mkdir("update")
|
os.mkdir("update")
|
||||||
with zipfile.ZipFile("update.zip", "r") as zip_ref:
|
with zipfile.ZipFile("update.zip", "r") as zip_ref:
|
||||||
zip_ref.extractall("")
|
zip_ref.extractall("update")
|
||||||
os.rmdir("update")
|
os.rmdir("update")
|
||||||
os.remove("update.zip")
|
os.remove("update.zip")
|
||||||
print(f"update to {version_download} was succefull.")
|
print("SUCCESS")
|
||||||
|
print(f"""Update from version {version["version"]} to {version_download} was sucesfull""")
|
||||||
|
|
||||||
if command == "clean":
|
if command == "clean":
|
||||||
if arguments[1] == "all":
|
if arguments[1] == "all":
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"version": "0.6",
|
"version": "0.9",
|
||||||
"id": 4,
|
"id": 6
|
||||||
"url": "https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json"
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user