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
import json
import requests
import os
import subprocess
class Log:
@ -46,7 +48,7 @@ class Update:
def __init__(self):
with open("version.json", "r") as f: # loading settings
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.id = version["id"]
@ -54,4 +56,69 @@ class Update:
return json.loads(requests.get(self.url).text)
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",
"description": {
"title": "legionrpi",

@ -1,20 +1,29 @@
import hashlib
import json
import os
import sys
import threading
import time
import engine
import requests
import uuid
import subprocess
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
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
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)
IP = settings["IP"]
@ -32,7 +41,6 @@ app.add_middleware(
allow_methods=["*"],
allow_headers=["*"],
)
log = engine.Log(settings["log"]) # init of LOG
update = engine.Update()
offline = []
@ -44,12 +52,7 @@ time_to_heartbeat_offline = settings[
# json variables
heartbeat_table = settings["heartbeat_table"]
sensors = { # List of "live" data like tempeature, etc.
"teplota": 24,
"vlhkosť": 25,
"počet ľudí": 10,
"doba čakania": 2
}
sensors = {}
messages = []
@ -68,9 +71,14 @@ class ServerTable(BaseModel): # table of content for heartbeat request
last_heartbeat: list
class Sensor(BaseModel):
name: str
value: str
@app.get("/")
def read_root():
return {"Hello": "World"}
return "wikispot"
@app.post("/heartbeat")
@ -107,19 +115,35 @@ def heartbeat(s_table: ServerTable, request: Request):
return heartbeat_table, {"ID": ID, "file_system": filesystem, "location": location}
@app.get("/sensors")
def get_sensors(request: Request):
@app.get("/{IDx}/sensors")
def get_sensors(IDx: int, request: Request):
global sensors
log.message(f"sensor data sent to {request.client.host}:{request.client.port}")
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}")
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)]
if IDx == ID:
return FileResponse(f"files/{file}")
elif IDx in heartbeat_table["ID"]:
if os.path.isfile(f"files/{file}"):
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.isfile(f"cache/{IDx}/{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)
rr = requests.get(f"""http://{server_ip}:8000/compare/{file}""")
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:
log.debug(f"returning cached file cache/{IDx}{file}")
return FileResponse(f"cache/{IDx}/{file}")
else:
os.mkdir(f"cache/{IDx}")
log.message(f"downloading {file} from {server_ip}")
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:
save.write(bytes(r.content))
return FileResponse(f"cache/{IDx}/{file}")
@app.post("/update")
def update_sensors():
pass
# Todo Make option to upload "live data" manually to rpi
@app.post("/update_sensor")
def update_sensors(data: Sensor, request: Request):
global sensors
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}")
def comparision(file: str):
with open(f"files/{file}", "rb") as compared_file:
m = hashlib.md5()
for line in compared_file:
m.update(line)
return m.hexdigest()
try:
with open(f"files/{file}", "rb") as compared_file:
m = hashlib.md5()
for line in compared_file:
m.update(line)
return m.hexdigest()
except FileNotFoundError:
return f"ERROR {file} does not exist"
@app.get("/devices_list")
@ -161,12 +197,41 @@ def get_devices_list():
return [{"connected_id": ID}, *heartbeat_table["file_system"]]
@app.get("/admin/{command}")
def admin(command: str):
@app.get("/admin/get/{command}")
def admin_get(command: str):
if command == "get_updates":
return [update.get_version(), update.get_updates()]
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")
@ -183,11 +248,16 @@ def get_messages():
def get_messages(m_sender: str = None, message: str = None):
if m_sender and message:
messages.append({"sender": m_sender, "message": message})
return "successfull"
return "successful"
else:
return "Empty message/sender"
@app.get("/debug")
def debug_esp():
return "test successful"
def send_heartbeat(ip, id):
global heartbeat_table
log.message(f"""sending heartbeat to {ip}({"offline" if id in offline else "online"})""")
@ -238,6 +308,8 @@ def mainloop():
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.start()

@ -6,16 +6,18 @@ import requests
arguments = sys.argv
arguments.remove(sys.argv[0])
url = "https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json"
if len(arguments) == 0:
sys.exit()
command = arguments[0]
if command in ["u", "update"]:
with open("version.json", "r") as f: # loading settings
version = json.load(f)
url = version["url"]
server_version = json.loads(requests.get(url).text)
try:
server_version = json.loads(requests.get(url).text)
except Exception as error:
print(f"CAN'T DOWNLOAD VERSION LIST. ERROR: {error}")
sys.exit()
if "-version" in arguments:
try:
version_download = arguments[arguments.index("-version") + 1]
@ -27,23 +29,32 @@ if command in ["u", "update"]:
sys.exit()
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()):
if data["id"] > version["id"]:
if data["id"] > version["id"] and ver > version_download:
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"):
os.mkdir("update")
with zipfile.ZipFile("update.zip", "r") as zip_ref:
zip_ref.extractall("")
zip_ref.extractall("update")
os.rmdir("update")
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 arguments[1] == "all":

@ -1,5 +1,4 @@
{
"version": "0.6",
"id": 4,
"url": "https://raw.githubusercontent.com/UntriexTv/test_directory/main/ver.json"
"version": "0.9",
"id": 6
}