Compare commits
No commits in common. "main" and "1.0.0" have entirely different histories.
|
|
@ -51,8 +51,7 @@ class HttpRequest:
|
||||||
# Encode the values in the dictionary
|
# Encode the values in the dictionary
|
||||||
encoded_content = {}
|
encoded_content = {}
|
||||||
for key, value in parsed_content.items():
|
for key, value in parsed_content.items():
|
||||||
encoded_value = re.sub(r'\%([0-9A-Fa-f]{2})', lambda m: chr(int(m.group(1), 16)), value)
|
encoded_value = re.sub(r'%([0-9A-Fa-f]{2})', lambda m: chr(int(m.group(1), 16)), value)
|
||||||
print("encoding ...", key, value, encoded_value)
|
|
||||||
encoded_content[key] = encoded_value
|
encoded_content[key] = encoded_value
|
||||||
|
|
||||||
return encoded_content
|
return encoded_content
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,2 @@
|
||||||
dev_api_url = 'api.growsystem.muellerdev.kozow.com'
|
|
||||||
api_url = 'api.growsystem.muellerdev.kozow.com'
|
api_url = 'api.growsystem.muellerdev.kozow.com'
|
||||||
read_secs = 15 * 60
|
read_secs = 1 * 60
|
||||||
token = "dummy"
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@ from gs.device_info import DeviceInfo
|
||||||
from gs.wlan_client import WlanClient
|
from gs.wlan_client import WlanClient
|
||||||
import json
|
import json
|
||||||
import gs.config.initial_config as ic
|
import gs.config.initial_config as ic
|
||||||
import helper.token_helper as th
|
|
||||||
|
|
||||||
|
|
||||||
class GrowSystemApi:
|
class GrowSystemApi:
|
||||||
|
|
@ -31,20 +30,16 @@ class GrowSystemApi:
|
||||||
})
|
})
|
||||||
print("activate ...", data)
|
print("activate ...", data)
|
||||||
response = self.http_client.post(self.base_url + "/api/device/activate", data)
|
response = self.http_client.post(self.base_url + "/api/device/activate", data)
|
||||||
print("REsponse ...", response.content)
|
print("REsponse ...", response)
|
||||||
return self._get_json_encoded(response.text)
|
return self._get_json_encoded(response.text)
|
||||||
|
|
||||||
|
def say_hello(self):
|
||||||
|
response = self.http_client.post(self.base_url + "/api/device", self._get_device_data())
|
||||||
|
print(response.text)
|
||||||
|
jsonResult = json.loads(response.text)
|
||||||
|
print(jsonResult)
|
||||||
|
return jsonResult;
|
||||||
|
|
||||||
def update_device_info(self, config):
|
|
||||||
device_id = self.device_info.get_device_id()
|
|
||||||
|
|
||||||
token = self.device_info.get_token()
|
|
||||||
|
|
||||||
print("update device info. Token ...", token)
|
|
||||||
url = self.base_url + "/api/device/" + str(device_id) + "/update-device-info/" + token
|
|
||||||
response = self.http_client.get(url)
|
|
||||||
print("Device Info Update Response ...", response.text)
|
|
||||||
return self._get_json_encoded(response.text)
|
|
||||||
|
|
||||||
def send_measurements(self, device_id, data):
|
def send_measurements(self, device_id, data):
|
||||||
url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log"
|
url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log"
|
||||||
response = self.http_client.post(url, data)
|
response = self.http_client.post(url, data)
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,18 @@
|
||||||
|
from gs.setup import Setup
|
||||||
from gs.device_info import DeviceInfo
|
from gs.device_info import DeviceInfo
|
||||||
|
from gs.sensor_data_manager import SensorDataManager
|
||||||
import os
|
import os
|
||||||
import ujson
|
import ujson
|
||||||
import machine
|
import machine
|
||||||
import time
|
import time
|
||||||
from gs.grow_system_api import GrowSystemApi
|
|
||||||
from gs.classes.sensors.ambilight_sensor import AmbilightSensor
|
from gs.classes.sensors.ambilight_sensor import AmbilightSensor
|
||||||
from gs.classes.sensors.dht22 import TemperatureHumiditySensor
|
from gs.classes.sensors.dht22 import TemperatureHumiditySensor
|
||||||
from gs.classes.sensors.moisture_sensor import MoistureSensor
|
from gs.classes.sensors.moisture_sensor import MoistureSensor
|
||||||
import gs.config.initial_config as ic
|
|
||||||
import helper.token_helper as th
|
|
||||||
|
|
||||||
class GrowSystem:
|
class GrowSystem:
|
||||||
|
|
||||||
version = "1.0.0.1"
|
version = "1.0"
|
||||||
|
|
||||||
initial_config = None
|
initial_config = None
|
||||||
|
|
||||||
|
|
@ -22,20 +22,29 @@ class GrowSystem:
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
print("Initialize Growsystem", self.version)
|
print("Initialize Growsystem", self.version)
|
||||||
self.initial_config = ic
|
|
||||||
self.gsapi = GrowSystemApi()
|
if not self._is_initial_config_existing():
|
||||||
|
print("No config existing. Start setup ...")
|
||||||
|
self._setup()
|
||||||
|
return
|
||||||
|
|
||||||
|
from gs.grow_system_api import GrowSystemApi as GSA
|
||||||
|
self.gsapi = GSA()
|
||||||
|
|
||||||
|
if self._is_config_existing():
|
||||||
|
print("Skip Setup. Config existing.")
|
||||||
|
self._initialize_sensors()
|
||||||
|
elif self._is_initial_config_existing():
|
||||||
|
print("Initial config only existing (no base config). Start activation ...")
|
||||||
|
self._activate()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
from gs.device_info import DeviceInfo
|
self.sensor_data_manager = SensorDataManager(self.device_info.get_device_id())
|
||||||
di = DeviceInfo()
|
|
||||||
from gs.sensor_data_manager import SensorDataManager
|
|
||||||
self.sensor_data_manager = SensorDataManager(di.get_device_id())
|
|
||||||
|
|
||||||
self._initialize_sensors()
|
|
||||||
print("Start reading sensors ...")
|
print("Start reading sensors ...")
|
||||||
|
|
||||||
read_secs = self.device_info.app_config().read_secs
|
read_secs = self.device_info.app_config().read_secs
|
||||||
print("Reading and sending every " + str(read_secs) + " seconds")
|
|
||||||
while True:
|
while True:
|
||||||
# Reset data
|
# Reset data
|
||||||
self.most_recent_values = []
|
self.most_recent_values = []
|
||||||
|
|
@ -50,42 +59,52 @@ class GrowSystem:
|
||||||
self.sensor_data_manager.handleData(self.most_recent_values)
|
self.sensor_data_manager.handleData(self.most_recent_values)
|
||||||
|
|
||||||
time.sleep(read_secs)
|
time.sleep(read_secs)
|
||||||
|
|
||||||
|
def _setup(self):
|
||||||
|
setup = Setup()
|
||||||
|
setup.setup_pico()
|
||||||
|
machine.reset
|
||||||
|
|
||||||
def activate(self):
|
def _activate(self):
|
||||||
print("Start activation!")
|
print("Start activation!")
|
||||||
|
import gs.config.initial_config as ic
|
||||||
self.initial_config = ic.config
|
self.initial_config = ic.config
|
||||||
device_config = self.gsapi.activate(self.initial_config)
|
device_config = self.gsapi.activate(self.initial_config)
|
||||||
print("Device Config:", device_config['data'], device_config['data']['token'])
|
#print("Device Config:", device_config['data'])
|
||||||
th.write_token(device_config['data']['token'])
|
|
||||||
self.write_device_infos(device_config['data'])
|
|
||||||
|
|
||||||
def update_device_info(self):
|
|
||||||
print("Start Device Info Update!")
|
|
||||||
self.initial_config = ic.config
|
|
||||||
device_config = self.gsapi.update_device_info(self.initial_config)
|
|
||||||
print("Device Config:", device_config['data'])
|
|
||||||
self.write_device_infos(device_config['data'])
|
|
||||||
|
|
||||||
def write_device_infos(self, device_config):
|
|
||||||
print("Function received data:", device_config)
|
|
||||||
if True:
|
if True:
|
||||||
sensors = device_config['sensors']
|
sensors = device_config['data']['sensors']
|
||||||
sensor_configs = []
|
sensor_configs = []
|
||||||
for sensor in sensors:
|
for sensor in sensors:
|
||||||
sensor_configs.append(sensor['config'])
|
sensor_configs.append(sensor['config'])
|
||||||
print(sensor['config'])
|
print(sensor['config'])
|
||||||
device_configs = {
|
device_configs = {
|
||||||
'name': device_config['name'],
|
'name': device_config['data']['name'],
|
||||||
'device_id': device_config['id'],
|
'device_id': device_config['data']['id'],
|
||||||
'token': device_config['token'],
|
'token': device_config['data']['token'],
|
||||||
'user_id': device_config['user_id'],
|
'user_id': device_config['data']['user_id'],
|
||||||
'sensors': sensor_configs
|
'sensors': sensor_configs
|
||||||
}
|
}
|
||||||
print("Update device_config.json with:", device_configs)
|
|
||||||
with open("/gs/config/device_config.json", "w") as f:
|
with open("/gs/config/device_config.json", "w") as f:
|
||||||
f.write(ujson.dumps(device_configs))
|
f.write(ujson.dumps(device_configs))
|
||||||
f.close()
|
if self._is_config_existing():
|
||||||
|
machine.reset
|
||||||
|
|
||||||
|
def _is_config_existing(self):
|
||||||
|
return self._is_file_existing('/gs/config/device_config.json')
|
||||||
|
|
||||||
|
def _is_initial_config_existing(self):
|
||||||
|
return self._is_file_existing('/gs/config/initial_config.py')
|
||||||
|
|
||||||
|
def _is_file_existing(self, filepath):
|
||||||
|
try:
|
||||||
|
f = open(filepath, "r")
|
||||||
|
f.close()
|
||||||
|
# continue with the file.
|
||||||
|
return True
|
||||||
|
except OSError: # open failed
|
||||||
|
# handle the file open cas
|
||||||
|
return False
|
||||||
|
|
||||||
def _initialize_sensors(self):
|
def _initialize_sensors(self):
|
||||||
# Init sensors
|
# Init sensors
|
||||||
|
|
|
||||||
|
|
@ -9,14 +9,12 @@ class HTTPClient:
|
||||||
url = 'https://' + url
|
url = 'https://' + url
|
||||||
try:
|
try:
|
||||||
# headers = {'Content-Type': 'application/json'}
|
# headers = {'Content-Type': 'application/json'}
|
||||||
print("GET request to: ", url)
|
|
||||||
response = urequests.get(url)
|
response = urequests.get(url)
|
||||||
if response.status_code == 200:
|
if response.status_code == 200:
|
||||||
print("Data sent, got response")
|
print("Data sent, got response")
|
||||||
return response
|
return response
|
||||||
else:
|
else:
|
||||||
print("Failed to get data. Status code:", response.status_code)
|
print("Failed to get data. Status code:", response.status_code)
|
||||||
return response
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Exception occurred:", e)
|
print("Exception occurred:", e)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,85 +77,16 @@ class LittleApache():
|
||||||
options = []
|
options = []
|
||||||
for w in self.available_wifis:
|
for w in self.available_wifis:
|
||||||
options.append('<option value="{}">{}</option>'.format(w, w))
|
options.append('<option value="{}">{}</option>'.format(w, w))
|
||||||
|
|
||||||
body = """
|
body = """
|
||||||
<!DOCTYPE html>
|
<h1>Setup Pico</h1>
|
||||||
<html lang="en">
|
<form method="post" action="save">
|
||||||
<head>
|
SSID: <select name="ssid">{}</select><br>
|
||||||
<meta charset="UTF-8">
|
Password: <input type="password" name="password"><br><br>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
ID: <input type="number" name="user_id"/><br/>
|
||||||
<title>Growsystem Setup</title>
|
PIN: <input type="number" name="pin" maxlength="4"><br>
|
||||||
<style>
|
|
||||||
body {{
|
|
||||||
font-family: Arial, sans-serif;
|
|
||||||
background-color: #f2f2f2;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 100vh;
|
|
||||||
}}
|
|
||||||
|
|
||||||
form {{
|
|
||||||
background-color: #fff;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
|
||||||
max-width: 400px;
|
|
||||||
width: 100%;
|
|
||||||
}}
|
|
||||||
|
|
||||||
h1 {{
|
|
||||||
text-align: center;
|
|
||||||
color: #333;
|
|
||||||
}}
|
|
||||||
|
|
||||||
input[type="submit"] {{
|
|
||||||
background-color: #4CAF50;
|
|
||||||
color: white;
|
|
||||||
padding: 10px 20px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 5px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 16px;
|
|
||||||
}}
|
|
||||||
|
|
||||||
input[type="submit"]:hover {{
|
|
||||||
background-color: #45a049;
|
|
||||||
}}
|
|
||||||
|
|
||||||
input[type="text"],
|
|
||||||
input[type="password"],
|
|
||||||
input[type="number"],
|
|
||||||
select {{
|
|
||||||
width: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 5px 0;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 5px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<h1>Growsystem Setup</h1>
|
|
||||||
<form method="post" action="save">
|
|
||||||
<label for="ssid">SSID:</label><br>
|
|
||||||
<select name="ssid" id="ssid">
|
|
||||||
{}
|
|
||||||
</select><br>
|
|
||||||
<label for="password">Password:</label><br>
|
|
||||||
<input type="password" name="password" id="password"><br><br>
|
|
||||||
<label for="user_id">ID:</label><br>
|
|
||||||
<input type="number" name="user_id" id="user_id"><br>
|
|
||||||
<label for="pin">PIN:</label><br>
|
|
||||||
<input type="number" name="pin" id="pin" maxlength="4"><br>
|
|
||||||
<input type="submit" value="Submit">
|
<input type="submit" value="Submit">
|
||||||
</form>
|
</form>
|
||||||
</body>
|
"""
|
||||||
</html>
|
|
||||||
"""
|
|
||||||
body = body.format(''.join(options))
|
body = body.format(''.join(options))
|
||||||
elif self.is_path_match(request, '/save', 'POST'):
|
elif self.is_path_match(request, '/save', 'POST'):
|
||||||
print("Save config path: ", request)
|
print("Save config path: ", request)
|
||||||
|
|
@ -168,6 +99,7 @@ select {{
|
||||||
body = f"""
|
body = f"""
|
||||||
<div>Unknown page</div>
|
<div>Unknown page</div>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
html = ''
|
html = ''
|
||||||
html_arr = [header, body, footer]
|
html_arr = [header, body, footer]
|
||||||
html = html.join(html_arr)
|
html = html.join(html_arr)
|
||||||
|
|
@ -177,4 +109,3 @@ select {{
|
||||||
return path == request.path and method == request.method
|
return path == request.path and method == request.method
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@ import ujson
|
||||||
import ure as re
|
import ure as re
|
||||||
import usocket as socket
|
import usocket as socket
|
||||||
import time
|
import time
|
||||||
from setup.little_apache import LittleApache
|
from gs.little_apache import LittleApache
|
||||||
|
|
||||||
|
|
||||||
class Setup:
|
class Setup:
|
||||||
|
|
@ -11,7 +11,6 @@ class Setup:
|
||||||
wlans = []
|
wlans = []
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
print("Start Pico Setup")
|
|
||||||
self.ap_ssid = "Growsystem 1.0"
|
self.ap_ssid = "Growsystem 1.0"
|
||||||
self.ap_password = "password"
|
self.ap_password = "password"
|
||||||
self.wlans = []
|
self.wlans = []
|
||||||
|
|
@ -84,4 +83,3 @@ class Setup:
|
||||||
# self.stop_ap_mode()
|
# self.stop_ap_mode()
|
||||||
# self.switch_to_client_mode()
|
# self.switch_to_client_mode()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
config_path = '/gs/config/'
|
|
||||||
|
|
||||||
def is_config_existing():
|
|
||||||
return is_file_existing(config_path + 'device_config.json')
|
|
||||||
|
|
||||||
def is_initial_config_existing():
|
|
||||||
return is_file_existing(config_path + 'initial_config.py')
|
|
||||||
|
|
||||||
def is_file_existing(filepath):
|
|
||||||
try:
|
|
||||||
f = open(filepath, "r")
|
|
||||||
f.close()
|
|
||||||
# continue with the file.
|
|
||||||
return True
|
|
||||||
except OSError: # open failed
|
|
||||||
# handle the file open cas
|
|
||||||
return False
|
|
||||||
|
|
||||||
def replace_value(filepath, prop, newvalue):
|
|
||||||
with open(filepath, 'r') as file:
|
|
||||||
config_lines = file.readlines()
|
|
||||||
file.close()
|
|
||||||
|
|
||||||
# Parse the config data into a dictionary
|
|
||||||
config_dict = {}
|
|
||||||
for line in config_lines:
|
|
||||||
if '=' in line:
|
|
||||||
key, value = line.strip().split('=')
|
|
||||||
config_dict[key.strip()] = value.strip()
|
|
||||||
# Add or Update the value of the property
|
|
||||||
config_dict[prop] = newvalue
|
|
||||||
|
|
||||||
# Write the modified data back to the file
|
|
||||||
with open(filepath, 'w') as file:
|
|
||||||
for key, value in config_dict.items():
|
|
||||||
file.write(f"{key} = {value}\n")
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import helper.file_helper as fh
|
|
||||||
|
|
||||||
app_config_path = '/gs/config/app.py'
|
|
||||||
|
|
||||||
def write_token(token):
|
|
||||||
print("Write new token: " + token)
|
|
||||||
fh.replace_value(app_config_path, 'token', '"' + token + '"')
|
|
||||||
#with open(app_config_path, "a") as app_config:
|
|
||||||
# app_config.write(token)
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import urequests
|
||||||
|
import json
|
||||||
|
|
||||||
|
class HTTPClient:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get(self, url):
|
||||||
|
url = 'https://' + url
|
||||||
|
try:
|
||||||
|
# headers = {'Content-Type': 'application/json'}
|
||||||
|
response = urequests.get(url)
|
||||||
|
if response.status_code == 200:
|
||||||
|
print("Data sent, got response")
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
print("Failed to get data. Status code:", response.status_code)
|
||||||
|
except Exception as e:
|
||||||
|
print("Exception occurred:", e)
|
||||||
|
|
||||||
|
def post(self, url, data):
|
||||||
|
url = 'https://' + url
|
||||||
|
try:
|
||||||
|
headers = {'Content-Type': 'application/json', 'Accept': 'application/json, text/plain, */*'}
|
||||||
|
json_data = json.dumps(data)
|
||||||
|
print("Send post request to: " + url)
|
||||||
|
response = urequests.post(url, data=json_data, headers=headers)
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response
|
||||||
|
else:
|
||||||
|
print("Failed to send data. Status code:", response.status_code)
|
||||||
|
print(response.text)
|
||||||
|
except Exception as e:
|
||||||
|
print("Exception occurred:", e)
|
||||||
|
|
||||||
44
main.py
44
main.py
|
|
@ -1,49 +1,11 @@
|
||||||
## Only start grow system
|
## Only start grow system
|
||||||
|
from gs.growsystem import GrowSystem
|
||||||
from time import sleep
|
from time import sleep
|
||||||
import helper.file_helper as fh
|
|
||||||
|
|
||||||
if False:
|
|
||||||
if not self._is_initial_config_existing():
|
|
||||||
print("No config existing. Start setup ...")
|
|
||||||
self._setup()
|
|
||||||
return
|
|
||||||
|
|
||||||
from gs.sensor_data_manager import SensorDataManager
|
|
||||||
self.sensor_data_manager = SensorDataManager(self.device_info.get_device_id())
|
|
||||||
from gs.grow_system_api import GrowSystemApi as GSA
|
|
||||||
self.gsapi = GSA()
|
|
||||||
|
|
||||||
if self._is_config_existing():
|
|
||||||
print("Skip Setup. Config existing.")
|
|
||||||
self._initialize_sensors()
|
|
||||||
elif self._is_initial_config_existing():
|
|
||||||
print("Initial config only existing (no base config). Start activation ...")
|
|
||||||
self._activate()
|
|
||||||
|
|
||||||
|
|
||||||
def setup():
|
|
||||||
from setup.setup import Setup
|
|
||||||
setup = Setup()
|
|
||||||
setup.setup_pico()
|
|
||||||
machine.reset
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# 1) Check and in case of update Growsystem
|
gs = GrowSystem()
|
||||||
# 2) Check if initial_config is existing -> Setup if not
|
gs.start()
|
||||||
|
|
||||||
if not fh.is_initial_config_existing():
|
|
||||||
setup()
|
|
||||||
else:
|
|
||||||
from gs.growsystem import GrowSystem
|
|
||||||
gs = GrowSystem()
|
|
||||||
# 3) if device info exists update Device Info else activate
|
|
||||||
if fh.is_config_existing():
|
|
||||||
gs.update_device_info()
|
|
||||||
else:
|
|
||||||
gs.activate()
|
|
||||||
# 4) Start growsystem
|
|
||||||
gs.start()
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
print("Keep running in main.py")
|
print("Keep running in main.py")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue