Human error prevention, sensor updates, etc.

This commit is contained in:
Untriex Programming 2021-04-09 15:03:59 +02:00
parent 03246b5f43
commit 154a52e30d
5 changed files with 198 additions and 49 deletions

@ -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",

@ -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"
} }