Add MQTT and gateway discovery
This commit is contained in:
@@ -4,6 +4,7 @@ from flask import jsonify
|
||||
from flask import send_from_directory
|
||||
from flask_cors import CORS
|
||||
from flask_cors import cross_origin
|
||||
from check_update import check_for_update
|
||||
|
||||
|
||||
class API:
|
||||
@@ -17,43 +18,44 @@ class API:
|
||||
self.app.config['CORS_HEADERS'] = 'Content-Type'
|
||||
|
||||
# --------Static Routes-------
|
||||
@self.app.route('/')
|
||||
@self.app.route('/api')
|
||||
@cross_origin()
|
||||
def serve_root():
|
||||
workdir, filename = os.path.split(os.path.abspath(__file__))
|
||||
update = check_for_update()
|
||||
root_dict = {
|
||||
"version": "24-07-03",
|
||||
"mode": 1,
|
||||
"version": {
|
||||
"version": os.getenv('VERSION'),
|
||||
"update_available": update.update_available if update is not None else None,
|
||||
"up_to_date": update.up_to_date if update is not None else None,
|
||||
"develop_version": update.development if update is not None else None,
|
||||
},
|
||||
"mode": os.getenv('MODE'),
|
||||
"name": os.getenv('NAME'),
|
||||
"info": {
|
||||
"files_size_sum": self.get_file_size()
|
||||
"files_size_sum": self.get_file_size(),
|
||||
"files": os.listdir(f'{workdir}/data')
|
||||
}
|
||||
}
|
||||
return jsonify(root_dict)
|
||||
|
||||
@self.app.route('/api/json/<path:path>')
|
||||
@cross_origin()
|
||||
def serve_json(path):
|
||||
return send_from_directory(f'{workdir}/data', path)
|
||||
|
||||
@self.app.route('/charts')
|
||||
@cross_origin()
|
||||
def serve_index():
|
||||
return send_from_directory('/src', 'chart.html')
|
||||
|
||||
@self.app.route('/json')
|
||||
@cross_origin()
|
||||
def serve_get_list_of_json():
|
||||
workdir, filename = os.path.split(os.path.abspath(__file__))
|
||||
return jsonify(os.listdir(f'{workdir}/data'))
|
||||
|
||||
@self.app.route('/json/<path:path>')
|
||||
@cross_origin()
|
||||
def serve_json(path):
|
||||
|
||||
return send_from_directory(f'{workdir}/data', path)
|
||||
|
||||
# --------Helpers-------
|
||||
def get_file_size(self):
|
||||
workdir, filename = os.path.split(os.path.abspath(__file__))
|
||||
files = os.listdir(f'{workdir}/data')
|
||||
sizes = 0.0
|
||||
sizes = 0
|
||||
for file in files:
|
||||
if file.endswith('.json'):
|
||||
sizes += round(int(os.path.getsize(f'{workdir}/data/{file}')), 2)
|
||||
|
||||
if file.endswith('.json'): sizes += os.path.getsize(f'{workdir}/data/{file}')
|
||||
return sizes
|
||||
|
||||
|
||||
|
||||
74
python/src/check_update.py
Normal file
74
python/src/check_update.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import os
|
||||
import json
|
||||
import requests
|
||||
|
||||
DEBUG = True if os.environ.get('DEBUG') is not None else False
|
||||
|
||||
|
||||
class State:
|
||||
def __init__(self, version_int:int):
|
||||
self.version_int:int = version_int
|
||||
self.version_str:str = f"{str(version_int)[0]}{str(version_int)[1]}-{str(version_int)[2]}{str(version_int)[3]}-{str(version_int)[4]}{str(version_int)[5]}"
|
||||
self.update_available:bool = False
|
||||
self.up_to_date:bool = False
|
||||
self.development:bool = False
|
||||
|
||||
|
||||
class Release:
|
||||
def __init__(self, data:dict):
|
||||
self.name = data['name']
|
||||
self.tag_name = data['tag_name']
|
||||
self.description = data['description']
|
||||
self.created_at = data['created_at']
|
||||
self.released_at = data['released_at']
|
||||
self.upcoming_release = data['upcoming_release']
|
||||
self.version_int = int(self.tag_name.replace("-", ""))
|
||||
|
||||
|
||||
def check_for_update():
|
||||
try: version_current = int(os.getenv('VERSION').replace("-", ""))
|
||||
except:
|
||||
print("Error getting current version")
|
||||
return
|
||||
project_id = 58341398
|
||||
request = f"https://gitlab.com/api/v4/projects/{project_id}/releases"
|
||||
response = requests.get(url=request, timeout=1)
|
||||
if not response.ok: return
|
||||
|
||||
releases_json = json.loads(response.text)
|
||||
# Date, Object
|
||||
latest = [0, None]
|
||||
for release_json in releases_json:
|
||||
release = Release(release_json)
|
||||
if release.version_int > latest[0]:
|
||||
latest[0] = release.version_int
|
||||
latest[1] = release
|
||||
print(repr(latest)) if DEBUG else {}
|
||||
|
||||
release = latest[1]
|
||||
if release.version_int > version_current:
|
||||
state = State(release.version_int)
|
||||
state.update_available = True
|
||||
return state
|
||||
|
||||
elif release.version_int == version_current:
|
||||
state = State(release.version_int)
|
||||
state.up_to_date = True
|
||||
return state
|
||||
|
||||
else:
|
||||
state = State(release.version_int)
|
||||
state.development = True
|
||||
return state
|
||||
|
||||
|
||||
def print_state(state:State):
|
||||
if state is None: return
|
||||
print(f"Current version: {os.getenv('VERSION')}")
|
||||
if state.update_available:
|
||||
print(f"Update available: {state.version_str}")
|
||||
if state.up_to_date:
|
||||
print(f"Up to date")
|
||||
if state.development:
|
||||
print(f"Development Version")
|
||||
print("")
|
||||
@@ -4,8 +4,11 @@ import FindMyIP
|
||||
import ipaddress
|
||||
import threading
|
||||
import requests
|
||||
import os
|
||||
|
||||
DEBUG = True if os.environ.get('DEBUG') is not None else False
|
||||
max_threads = 50
|
||||
port = 8000
|
||||
final = {}
|
||||
|
||||
|
||||
@@ -15,41 +18,37 @@ def check_port(ip, port):
|
||||
# sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
|
||||
socket.setdefaulttimeout(2.0) # seconds (float)
|
||||
result = sock.connect_ex((ip, port))
|
||||
if result == 0:
|
||||
# print("Port is open")
|
||||
final[ip] = "OPEN"
|
||||
else:
|
||||
# print("Port is closed/filtered")
|
||||
final[ip] = "CLOSED"
|
||||
if result == 0: final[ip] = True
|
||||
else: final[ip] = False
|
||||
sock.close()
|
||||
|
||||
except:
|
||||
final[ip] = "EXCEPTION"
|
||||
pass
|
||||
|
||||
|
||||
port = 8000
|
||||
local_ip = FindMyIP.internal()
|
||||
local_ip = local_ip.split('.')[:-1]
|
||||
local_ip.append("0")
|
||||
local_ip = '.'.join(local_ip)
|
||||
def scan_for_gateways():
|
||||
local_ip = FindMyIP.internal()
|
||||
local_ip = local_ip.split('.')[:-1]
|
||||
local_ip.append("0")
|
||||
local_ip = '.'.join(local_ip)
|
||||
print(f"Scan on {local_ip}/24 for port {port}") if DEBUG else {}
|
||||
|
||||
print(f"Scan on {local_ip}/24 for port {port}")
|
||||
for ip in ipaddress.IPv4Network(f'{local_ip}/24'):
|
||||
threading.Thread(target=check_port, args=[str(ip), port]).start()
|
||||
# limit the number of threads.
|
||||
while threading.active_count() > max_threads: sleep(1)
|
||||
|
||||
for ip in ipaddress.IPv4Network(f'{local_ip}/24'):
|
||||
threading.Thread(target=check_port, args=[str(ip), port]).start()
|
||||
# sleep(0.1)
|
||||
sorted_ips = dict(sorted(final.items(), key=lambda item: tuple(map(int, item[0].split('.')))))
|
||||
|
||||
# limit the number of threads.
|
||||
while threading.active_count() > max_threads:
|
||||
sleep(1)
|
||||
|
||||
sorted_ips = dict(sorted(final.items(), key=lambda item: tuple(map(int, item[0].split('.')))))
|
||||
|
||||
for ip, state in sorted_ips.items():
|
||||
if state == "OPEN":
|
||||
try:
|
||||
response = requests.get(f'http://{ip}:{port}/')
|
||||
if response.status_code == 200:
|
||||
print(ip, state)
|
||||
print(response.text)
|
||||
except:pass
|
||||
gateways = []
|
||||
for ip, state in sorted_ips.items():
|
||||
if state:
|
||||
try:
|
||||
response = requests.get(f'http://{ip}:{port}/api')
|
||||
# TODO: Check if the API is for real a gateway
|
||||
if response.status_code == 200:
|
||||
print(ip, response.json()) if DEBUG else {}
|
||||
gateways.append([ip, response.json()])
|
||||
except:pass
|
||||
return gateways
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@ import os
|
||||
from discovery import start_discovery
|
||||
from log_data import log_to_json
|
||||
from loop import start_loop
|
||||
from check_update import check_for_update
|
||||
from check_update import print_state
|
||||
|
||||
INTERVAL = 40
|
||||
TIMEOUT = 20
|
||||
@@ -17,8 +19,13 @@ if DEBUG:
|
||||
print(f"timeout: {timeout}")
|
||||
print(f"DOCKER: {DOCKER}")
|
||||
print(f"DEBUG: {DEBUG}")
|
||||
print(f"VERSION: {os.getenv('VERSION')}")
|
||||
print("")
|
||||
|
||||
update_state = check_for_update()
|
||||
print_state(update_state)
|
||||
|
||||
|
||||
if DOCKER:
|
||||
print("Running in docker")
|
||||
|
||||
|
||||
@@ -1 +1,15 @@
|
||||
# TODO
|
||||
import paho.mqtt.client as MQTT
|
||||
|
||||
topic_root = "/atc_mithermometer_gateway"
|
||||
|
||||
mqtt = MQTT.Client(mqtt.CallbackAPIVersion.VERSION2)
|
||||
mqtt.connect("192.168.178.140", 1883, 60)
|
||||
|
||||
|
||||
def publish_measurement(mac):
|
||||
topic = f"{topic_root}/measurements/{mac}"
|
||||
topic_temp = f"{topic}/temperature"
|
||||
topic_humid = f"{topic}/humidity"
|
||||
topic_battery = f"{topic}/battery"
|
||||
|
||||
mqtt.publish(topic_temp, )
|
||||
|
||||
Reference in New Issue
Block a user