did a lot. upto activation working (exklusive config save)
This commit is contained in:
1 parent
1f6d92a54c
commit
148928f88c
38 files changed
+1095
-128
No files matched your search
@@ -0,0 +1,72 @@
|
||||
import json
|
||||
import ure as re
|
||||
|
||||
|
||||
class HttpRequest:
|
||||
|
||||
METHOD = {
|
||||
"GET": "GET",
|
||||
"POST": "POST"
|
||||
}
|
||||
|
||||
method = ''
|
||||
path = ''
|
||||
raw_content = ''
|
||||
headers = {}
|
||||
|
||||
def __init__(self, request):
|
||||
self.original_request = request
|
||||
# self.method = method
|
||||
# self.path = path
|
||||
# self.headers = headers
|
||||
# self.raw_content = content
|
||||
print("http request initialized")
|
||||
self.parse_request(request)
|
||||
|
||||
def parse_request(self, request):
|
||||
# Split the request into lines
|
||||
lines = request.decode().split('\r\n')
|
||||
|
||||
# Extract method, path, and HTTP version from the first line
|
||||
self.method, self.path, _ = lines[0].split()
|
||||
|
||||
# Parse headers
|
||||
for line in lines[1:]:
|
||||
if not line:
|
||||
break # Empty line indicates end of headers
|
||||
key, value = line.split(': ', 1)
|
||||
self.headers[key] = value
|
||||
|
||||
# Content is assumed to be in the last line
|
||||
self.raw_content = lines[-1]
|
||||
|
||||
def get_content_json(self):
|
||||
# Parse the POST request content into a dictionary
|
||||
parsed_content = {}
|
||||
pairs = self.raw_content.split('&')
|
||||
for pair in pairs:
|
||||
key, value = pair.split('=')
|
||||
parsed_content[key] = value
|
||||
|
||||
# Encode the values in the dictionary
|
||||
encoded_content = {}
|
||||
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_content[key] = encoded_value
|
||||
|
||||
return encoded_content
|
||||
|
||||
def __str__(self):
|
||||
return {
|
||||
"method": self.method,
|
||||
"headers": self.headers,
|
||||
"content": self.raw_content,
|
||||
"content_json": self.get_content_json()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
api_url = 'https://growsystem.muellerdev.kozow.com/api/'
|
||||
@@ -13,6 +13,10 @@ class GrowSystemApi:
|
||||
|
||||
def __init__(self):
|
||||
self.base_url = self.device_info.server_url
|
||||
|
||||
def activate(self, config):
|
||||
response = self.http_client.post(self.base_url + "/api/device/activate", self._get_device_data())
|
||||
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())
|
||||
@@ -29,3 +33,6 @@ class GrowSystemApi:
|
||||
def _get_device_data(self):
|
||||
return self.device_info.get_all_device_infos()
|
||||
|
||||
def _get_json_encoded(self, text):
|
||||
return json.loads(text)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
from gs.setup import Setup
|
||||
import os
|
||||
|
||||
|
||||
class GrowSystem:
|
||||
|
||||
version = "1.0"
|
||||
|
||||
def __init__(self):
|
||||
print("Initialize Growsystem", self.version)
|
||||
if self._is_config_existing():
|
||||
print("Skip Setup. Config existing.")
|
||||
elif self._is_initial_config_existing():
|
||||
self._activate()
|
||||
else:
|
||||
print("No config existing. Start setup ...")
|
||||
self._setup()
|
||||
|
||||
def _setup(self):
|
||||
setup = Setup()
|
||||
setup.setup_pico()
|
||||
|
||||
def _activate(self):
|
||||
print("Start activation!")
|
||||
|
||||
def _is_config_existing(self):
|
||||
return self._is_file_existing('/gs/config/config.py')
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
import json
|
||||
import ure as re
|
||||
|
||||
|
||||
class HttpRequest:
|
||||
|
||||
METHOD = {
|
||||
"GET": "GET",
|
||||
"POST": "POST"
|
||||
}
|
||||
|
||||
method = ''
|
||||
path = ''
|
||||
raw_content = ''
|
||||
headers = {}
|
||||
|
||||
def __init__(self, request):
|
||||
self.original_request = request
|
||||
# self.method = method
|
||||
# self.path = path
|
||||
# self.headers = headers
|
||||
# self.raw_content = content
|
||||
print("http request initialized")
|
||||
self.parse_request(request)
|
||||
|
||||
def parse_request(self, request):
|
||||
# Split the request into lines
|
||||
lines = request.decode().split('\r\n')
|
||||
|
||||
# Extract method, path, and HTTP version from the first line
|
||||
self.method, self.path, _ = lines[0].split()
|
||||
|
||||
# Parse headers
|
||||
for line in lines[1:]:
|
||||
if not line:
|
||||
break # Empty line indicates end of headers
|
||||
key, value = line.split(': ', 1)
|
||||
self.headers[key] = value
|
||||
|
||||
# Content is assumed to be in the last line
|
||||
self.raw_content = lines[-1]
|
||||
|
||||
def get_content_json(self):
|
||||
# Parse the POST request content into a dictionary
|
||||
parsed_content = {}
|
||||
pairs = self.raw_content.split('&')
|
||||
for pair in pairs:
|
||||
key, value = pair.split('=')
|
||||
parsed_content[key] = value
|
||||
|
||||
# Encode the values in the dictionary
|
||||
encoded_content = {}
|
||||
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_content[key] = encoded_value
|
||||
|
||||
return encoded_content
|
||||
|
||||
def __str__(self):
|
||||
return {
|
||||
"method": self.method,
|
||||
"headers": self.headers,
|
||||
"content": self.raw_content,
|
||||
"content_json": self.get_content_json()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
api_url = 'https://growsystem.muellerdev.kozow.com/api/'
|
||||
@@ -0,0 +1 @@
|
||||
config = {"pin": "4628", "password": "95%04-MM", "ssid": "Oppa-95.lan"}
|
||||
@@ -0,0 +1,68 @@
|
||||
import network
|
||||
|
||||
|
||||
class DeviceInfo:
|
||||
|
||||
# Device Infos
|
||||
name = "Dev Device 1"
|
||||
|
||||
token = "PC]-0Bmp83h7F5#U!D6KJ(A&"
|
||||
|
||||
#server_url = 'api.growsystem.muelleronline.org'
|
||||
server_url = 'api.growsystem.muellerdev.kozow.com'
|
||||
|
||||
wlan_ssid = 'Oppa-95.lan'
|
||||
wlan_pw = '95%04-MM'
|
||||
|
||||
sensors = [
|
||||
{
|
||||
'type': 'moisture',
|
||||
'pin_int': 26
|
||||
},
|
||||
{
|
||||
'type': 'ambilight',
|
||||
'pin_int': 8, # for compatibility only
|
||||
'pin_int_sda': 8,
|
||||
'pin_int_scl': 9
|
||||
},
|
||||
|
||||
|
||||
# {
|
||||
# 'type': 'dht22',
|
||||
# 'pin_int': 15
|
||||
# }
|
||||
]
|
||||
|
||||
engines = [
|
||||
{
|
||||
'type': 'pump',
|
||||
'pins': [15]
|
||||
}
|
||||
]
|
||||
|
||||
read_secs = 5
|
||||
# Device Infos End
|
||||
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
|
||||
def get_macaddress(self):
|
||||
return self._format_mac(self.wlan.config('mac').hex())
|
||||
|
||||
def get_ipaddress(self):
|
||||
return self.wlan.ifconfig()[0]
|
||||
|
||||
def get_all_device_infos(self):
|
||||
return {
|
||||
'name': self.name,
|
||||
'mac_address': self.get_macaddress(),
|
||||
'ip_address': self.get_ipaddress(),
|
||||
'token': self.token}
|
||||
|
||||
def _format_mac(self, mac):
|
||||
# Split the MAC address into pairs of two characters each
|
||||
pairs = [mac[i:i+2] for i in range(0, len(mac), 2)]
|
||||
# Join the pairs with colons to create the formatted MAC address
|
||||
formatted_mac = ":".join(pairs)
|
||||
return formatted_mac
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
from gs.http_client import HTTPClient
|
||||
from gs.device_info import DeviceInfo
|
||||
from gs.wlan_client import WlanClient
|
||||
import json
|
||||
import gs.config.initial_config as ic
|
||||
|
||||
|
||||
class GrowSystemApi:
|
||||
|
||||
http_client = HTTPClient()
|
||||
|
||||
device_info = DeviceInfo()
|
||||
|
||||
base_url = ''
|
||||
|
||||
def __init__(self):
|
||||
self.base_url = self.device_info.server_url
|
||||
self.connect_wifi(ic.config['ssid'], ic.config['password'])
|
||||
|
||||
def activate(self, config):
|
||||
data = self._get_device_data()
|
||||
data.update({
|
||||
'user_id': 1,
|
||||
'pin': config['pin']
|
||||
})
|
||||
print("activate ...", data)
|
||||
response = self.http_client.post(self.base_url + "/api/device/activate", data)
|
||||
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 send_measurements(self, device_id, data):
|
||||
url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log"
|
||||
response = self.http_client.post(url, data)
|
||||
return json.loads(response.text)
|
||||
|
||||
def _get_device_data(self):
|
||||
return self.device_info.get_all_device_infos()
|
||||
|
||||
def _get_json_encoded(self, text):
|
||||
return json.loads(text)
|
||||
|
||||
def connect_wifi(self, ssid, password):
|
||||
print("Connect WLAN")
|
||||
self.wlan_client = WlanClient(ssid, password)
|
||||
self.wlan_client.connect()
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
from gs.setup import Setup
|
||||
import os
|
||||
|
||||
|
||||
class GrowSystem:
|
||||
|
||||
version = "1.0"
|
||||
|
||||
initial_config = None
|
||||
|
||||
def __init__(self):
|
||||
print("Initialize Growsystem", self.version)
|
||||
|
||||
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.")
|
||||
elif self._is_initial_config_existing():
|
||||
print("Initial config only existing (no base config). Start activation ...")
|
||||
self._activate()
|
||||
|
||||
def _setup(self):
|
||||
setup = Setup()
|
||||
setup.setup_pico()
|
||||
|
||||
def _activate(self):
|
||||
print("Start activation!")
|
||||
import gs.config.initial_config as ic
|
||||
self.initial_config = ic.config
|
||||
device_config = self.gsapi.activate(self.initial_config)
|
||||
print("Device Config:", device_config)
|
||||
|
||||
def _is_config_existing(self):
|
||||
return self._is_file_existing('/gs/config/config.py')
|
||||
|
||||
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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import socket
|
||||
from gs.classes.http_request import HttpRequest
|
||||
|
||||
|
||||
class LittleApache():
|
||||
|
||||
available_wifis = []
|
||||
keep_webserver_alive = True
|
||||
|
||||
|
||||
def __init__(self, net):
|
||||
self.net = net
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
self.s = socket.socket()
|
||||
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.s.bind(addr)
|
||||
self.s.listen()
|
||||
# print('Listening on', addr)
|
||||
|
||||
def start(self):
|
||||
print("Webserver started. Connect to: " + self.net.ifconfig()[0])
|
||||
print(self.net.ifconfig())
|
||||
|
||||
while self.keep_webserver_alive:
|
||||
try:
|
||||
conn, addr = self.s.accept()
|
||||
#print('Got a connection from', addr)
|
||||
|
||||
# Receive and parse the request
|
||||
request = conn.recv(1024)
|
||||
# print("Request (RAW)", request)
|
||||
http_request = HttpRequest(request)
|
||||
self.http_request = http_request
|
||||
request = str(request)
|
||||
# print('Request content = %s' % request)
|
||||
#try:
|
||||
# request = request.split()[1]
|
||||
# print('Request:', request)
|
||||
#except IndexError:
|
||||
# pass
|
||||
response = self.response(http_request)
|
||||
# Send the HTTP response and close the connection
|
||||
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
|
||||
conn.send(response)
|
||||
conn.close()
|
||||
except OSError as e:
|
||||
conn.close()
|
||||
print('Connection closed')
|
||||
return self
|
||||
|
||||
def response(self, request: HttpRequest):
|
||||
#print("Webpage: ", request)
|
||||
print("Request method: ", request.method, "Request path: ", request.path)
|
||||
|
||||
header = f"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Growsystem</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
"""
|
||||
|
||||
footer = f"""
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
body = ""
|
||||
|
||||
if self.is_path_match(request, '/test1'):
|
||||
body = f"""
|
||||
<div>Test 1!!!</div>
|
||||
"""
|
||||
elif (self.is_path_match(request, '') or self.is_path_match(request, '/')):
|
||||
options = []
|
||||
for w in self.available_wifis:
|
||||
options.append('<option value="{}">{}</option>'.format(w, w))
|
||||
body = """
|
||||
<h1>Setup Pico</h1>
|
||||
<form method="post" action="save">
|
||||
SSID: <select name="ssid">{}</select><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
PIN: <input type="text" name="pin" maxlength="4"><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
"""
|
||||
body = body.format(''.join(options))
|
||||
elif self.is_path_match(request, '/save', 'POST'):
|
||||
print("Save config path: ", request)
|
||||
self.keep_webserver_alive = False
|
||||
body = """
|
||||
<h1>Setup Pico</h1>
|
||||
<div>Setup abgeschlossen. Bitte ein paar Sekunden warten, dann neu starten.</div>
|
||||
"""
|
||||
else:
|
||||
body = f"""
|
||||
<div>Unknown page</div>
|
||||
"""
|
||||
|
||||
html = ''
|
||||
html_arr = [header, body, footer]
|
||||
html = html.join(html_arr)
|
||||
return str(html)
|
||||
|
||||
def is_path_match(self, request, path, method='GET'):
|
||||
return path == request.path and method == request.method
|
||||
|
||||
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
import network
|
||||
import ujson
|
||||
import ure as re
|
||||
import usocket as socket
|
||||
import time
|
||||
from gs.little_apache import LittleApache
|
||||
|
||||
|
||||
class Setup:
|
||||
|
||||
wlans = []
|
||||
|
||||
def __init__(self):
|
||||
self.ap_ssid = "Growsystem 1.0"
|
||||
self.ap_password = "password"
|
||||
self.wlans = []
|
||||
self.selected_ssid = ""
|
||||
self.wlan_password = ""
|
||||
self.pin = ""
|
||||
|
||||
def scan_wlans(self):
|
||||
print("Scan for WiFis")
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
self.wlans = [w[0].decode() for w in wlan.scan()]
|
||||
print("Detected WiFis: ", self.wlans)
|
||||
wlan.active(False)
|
||||
|
||||
def start_ap_mode(self):
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(False)
|
||||
wlan_config = {
|
||||
"ssid": self.ap_ssid,
|
||||
"pw": self.ap_password
|
||||
}
|
||||
print("Switch to ap mode with data:", wlan_config)
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.config(essid=self.ap_ssid, password=self.ap_password)
|
||||
ap.active(True)
|
||||
self.net = ap
|
||||
print("Connect with your browser to:", ap.ifconfig()[0])
|
||||
|
||||
def stop_ap_mode(self):
|
||||
print("Stop ap mode")
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
|
||||
def get_initial_config_webserver(self):
|
||||
self.la = LittleApache(self.net)
|
||||
self.la.available_wifis = self.wlans
|
||||
self.la.start()
|
||||
config = self.la.http_request.get_content_json()
|
||||
print("start webserver end:", config)
|
||||
return config
|
||||
|
||||
def save_config(self, config):
|
||||
config = {
|
||||
"ssid": config['ssid'],
|
||||
"password": config['password'],
|
||||
"pin": config['pin']
|
||||
}
|
||||
print("Save config:", config)
|
||||
with open("/gs/config/initial_config.py", "w") as f:
|
||||
f.write("config = " + ujson.dumps(config))
|
||||
|
||||
def switch_to_client_mode(self):
|
||||
print("Switch to client mode")
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.connect(self.selected_ssid, self.wlan_password)
|
||||
while not wlan.isconnected():
|
||||
time.sleep(1)
|
||||
print("Connected to", self.selected_ssid)
|
||||
|
||||
def setup_pico(self):
|
||||
self.scan_wlans()
|
||||
self.start_ap_mode()
|
||||
config = self.get_initial_config_webserver()
|
||||
self.save_config(config)
|
||||
# self.stop_ap_mode()
|
||||
# self.switch_to_client_mode()
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
import machine
|
||||
import network
|
||||
import time
|
||||
# network.country('DE')
|
||||
|
||||
|
||||
class WlanClient:
|
||||
|
||||
ssid = ''
|
||||
pw = ''
|
||||
wlan = None
|
||||
# Status-LED
|
||||
led_onboard = machine.Pin('LED', machine.Pin.OUT)
|
||||
led_onboard.value(False)
|
||||
|
||||
def __init__(self, ssid, pw):
|
||||
# print("Hello from wlan class")
|
||||
self.ssid = ssid
|
||||
self.pw = pw
|
||||
self.wlan = network.WLAN(network.STA_IF)
|
||||
|
||||
def connect(self):
|
||||
if not self.is_connected():
|
||||
print('No WLAN connected. Connecting ...' + self.ssid + ' ' + self.pw)
|
||||
self.wlan.active(True)
|
||||
self.wlan.connect(self.ssid, self.pw)
|
||||
for i in range(10):
|
||||
if self.wlan.status() < 0 or self.wlan.status() >= 3:
|
||||
break
|
||||
time.sleep(1)
|
||||
# led_value = self.led_onboard.value() == 1
|
||||
# self.led_onboard.value(led_value)
|
||||
if self.wlan.isconnected():
|
||||
net_config = self.wlan.ifconfig()
|
||||
print("NetConfig:")
|
||||
print(net_config)
|
||||
|
||||
def is_connected(self):
|
||||
return self.wlan.isconnected()
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
import socket
|
||||
from gs.classes.http_request import HttpRequest
|
||||
|
||||
|
||||
class LittleApache():
|
||||
|
||||
available_wifis = []
|
||||
keep_webserver_alive = True
|
||||
|
||||
|
||||
def __init__(self, net):
|
||||
self.net = net
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
self.s = socket.socket()
|
||||
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.s.bind(addr)
|
||||
self.s.listen()
|
||||
# print('Listening on', addr)
|
||||
|
||||
def start(self):
|
||||
print("Webserver started. Connect to: " + self.net.ifconfig()[0])
|
||||
print(self.net.ifconfig())
|
||||
|
||||
while self.keep_webserver_alive:
|
||||
try:
|
||||
conn, addr = self.s.accept()
|
||||
#print('Got a connection from', addr)
|
||||
|
||||
# Receive and parse the request
|
||||
request = conn.recv(1024)
|
||||
# print("Request (RAW)", request)
|
||||
http_request = HttpRequest(request)
|
||||
self.http_request = http_request
|
||||
request = str(request)
|
||||
# print('Request content = %s' % request)
|
||||
#try:
|
||||
# request = request.split()[1]
|
||||
# print('Request:', request)
|
||||
#except IndexError:
|
||||
# pass
|
||||
response = self.response(http_request)
|
||||
# Send the HTTP response and close the connection
|
||||
conn.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
|
||||
conn.send(response)
|
||||
conn.close()
|
||||
except OSError as e:
|
||||
conn.close()
|
||||
print('Connection closed')
|
||||
return self
|
||||
|
||||
def response(self, request: HttpRequest):
|
||||
#print("Webpage: ", request)
|
||||
print("Request method: ", request.method, "Request path: ", request.path)
|
||||
|
||||
header = f"""
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Growsystem</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
<body>
|
||||
"""
|
||||
|
||||
footer = f"""
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
body = ""
|
||||
|
||||
if self.is_path_match(request, '/test1'):
|
||||
body = f"""
|
||||
<div>Test 1!!!</div>
|
||||
"""
|
||||
elif (self.is_path_match(request, '') or self.is_path_match(request, '/')):
|
||||
options = []
|
||||
for w in self.available_wifis:
|
||||
options.append('<option value="{}">{}</option>'.format(w, w))
|
||||
body = """
|
||||
<h1>Setup Pico</h1>
|
||||
<form method="post" action="save">
|
||||
SSID: <select name="ssid">{}</select><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
PIN: <input type="text" name="pin" maxlength="4"><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
"""
|
||||
body = body.format(''.join(options))
|
||||
elif self.is_path_match(request, '/save', 'POST'):
|
||||
print("Save config path: ", request)
|
||||
self.keep_webserver_alive = False
|
||||
body = """
|
||||
<h1>Setup Pico</h1>
|
||||
<div>Setup abgeschlossen. Bitte ein paar Sekunden warten, dann neu starten.</div>
|
||||
"""
|
||||
else:
|
||||
body = f"""
|
||||
<div>Unknown page</div>
|
||||
"""
|
||||
|
||||
html = ''
|
||||
html_arr = [header, body, footer]
|
||||
html = html.join(html_arr)
|
||||
return str(html)
|
||||
|
||||
def is_path_match(self, request, path, method='GET'):
|
||||
return path == request.path and method == request.method
|
||||
|
||||
|
||||
@@ -1,63 +1,12 @@
|
||||
# GrowSystem
|
||||
# Author: Maik Müller (maik@muelleronlineorg)
|
||||
|
||||
# WIP!
|
||||
# This file should do only:
|
||||
# - first start check and actions if not configured
|
||||
# - provide constants for settings
|
||||
# - eventually necessary system settings
|
||||
# - init wlan connection
|
||||
# - Call base class, permitting the configured constants
|
||||
import network
|
||||
import urequests
|
||||
from grow_system import GrowSystem
|
||||
from wlan import WlanClient
|
||||
from http_client import HTTPClient
|
||||
from device_info import DeviceInfo
|
||||
from setup import Setup
|
||||
## Only start grow system
|
||||
from gs.growsystem import GrowSystem
|
||||
from time import sleep
|
||||
|
||||
|
||||
settings = {
|
||||
'wlan_ssid': 'Oppa-95.lan',
|
||||
'wlan_pw': '95%04-MM',
|
||||
'moisture_sensor': {
|
||||
'pin_int': 26
|
||||
},
|
||||
'temperature_humidity_sensor': {
|
||||
'pin_int': 15
|
||||
},
|
||||
'pump_pin_int': 24
|
||||
}
|
||||
|
||||
|
||||
def wlan_scan():
|
||||
# Client-Betrieb
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
# WLAN-Interface aktivieren
|
||||
wlan.active(True)
|
||||
# WLANs ausgeben
|
||||
found_wlans = wlan.scan()
|
||||
return found_wlans
|
||||
|
||||
|
||||
# Press the green button in the gutter to run the script.
|
||||
if __name__ == '__main__':
|
||||
pico_setup = Setup()
|
||||
pico_setup.setup_pico()
|
||||
gs = GrowSystem()
|
||||
|
||||
if false:
|
||||
#print(wlan_scan())
|
||||
print("Connect WLAN")
|
||||
wlanClient = WlanClient(settings['wlan_ssid'], settings['wlan_pw'])
|
||||
wlanClient.connect()
|
||||
print("")
|
||||
|
||||
di = DeviceInfo()
|
||||
print("Device Infos:")
|
||||
print(di.get_all_device_infos())
|
||||
print("")
|
||||
|
||||
print("Start grow system")
|
||||
gs = GrowSystem(settings)
|
||||
gs.start()
|
||||
|
||||
while True:
|
||||
print("Keep running in main.py")
|
||||
sleep(5)
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,38 @@
|
||||
from http_client import HTTPClient
|
||||
from device_info import DeviceInfo
|
||||
import json
|
||||
|
||||
|
||||
class GrowSystemApi:
|
||||
|
||||
http_client = HTTPClient()
|
||||
|
||||
device_info = DeviceInfo()
|
||||
|
||||
base_url = ''
|
||||
|
||||
def __init__(self):
|
||||
self.base_url = self.device_info.server_url
|
||||
|
||||
def activate(self, config):
|
||||
response = self.http_client.post(self.base_url + "/api/device/activate", self._get_device_data())
|
||||
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 send_measurements(self, device_id, data):
|
||||
url = self.base_url + "/api/device/" + str(device_id) + "/sensor-log"
|
||||
response = self.http_client.post(url, data)
|
||||
return json.loads(response.text)
|
||||
|
||||
def _get_device_data(self):
|
||||
return self.device_info.get_all_device_infos()
|
||||
|
||||
def _get_json_encoded(self, text):
|
||||
return json.loads(text)
|
||||
|
||||
@@ -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)
|
||||
|
||||
File renamed without changes.
@@ -0,0 +1,63 @@
|
||||
# GrowSystem
|
||||
# Author: Maik Müller (maik@muelleronlineorg)
|
||||
|
||||
# WIP!
|
||||
# This file should do only:
|
||||
# - first start check and actions if not configured
|
||||
# - provide constants for settings
|
||||
# - eventually necessary system settings
|
||||
# - init wlan connection
|
||||
# - Call base class, permitting the configured constants
|
||||
import network
|
||||
import urequests
|
||||
from grow_system import GrowSystem
|
||||
from wlan import WlanClient
|
||||
from http_client import HTTPClient
|
||||
from device_info import DeviceInfo
|
||||
from setup import Setup
|
||||
|
||||
|
||||
settings = {
|
||||
'wlan_ssid': 'Oppa-95.lan',
|
||||
'wlan_pw': '95%04-MM',
|
||||
'moisture_sensor': {
|
||||
'pin_int': 26
|
||||
},
|
||||
'temperature_humidity_sensor': {
|
||||
'pin_int': 15
|
||||
},
|
||||
'pump_pin_int': 24
|
||||
}
|
||||
|
||||
|
||||
def wlan_scan():
|
||||
# Client-Betrieb
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
# WLAN-Interface aktivieren
|
||||
wlan.active(True)
|
||||
# WLANs ausgeben
|
||||
found_wlans = wlan.scan()
|
||||
return found_wlans
|
||||
|
||||
|
||||
# Press the green button in the gutter to run the script.
|
||||
if __name__ == '__main__':
|
||||
pico_setup = Setup()
|
||||
pico_setup.setup_pico()
|
||||
|
||||
if false:
|
||||
#print(wlan_scan())
|
||||
print("Connect WLAN")
|
||||
wlanClient = WlanClient(settings['wlan_ssid'], settings['wlan_pw'])
|
||||
wlanClient.connect()
|
||||
print("")
|
||||
|
||||
di = DeviceInfo()
|
||||
print("Device Infos:")
|
||||
print(di.get_all_device_infos())
|
||||
print("")
|
||||
|
||||
print("Start grow system")
|
||||
gs = GrowSystem(settings)
|
||||
gs.start()
|
||||
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,113 @@
|
||||
import network
|
||||
import ujson
|
||||
import ure as re
|
||||
import usocket as socket
|
||||
import time
|
||||
|
||||
class Setup:
|
||||
def __init__(self):
|
||||
self.ap_ssid = "Growsystem"
|
||||
self.ap_password = "12345678"
|
||||
self.wlans = []
|
||||
self.selected_ssid = ""
|
||||
self.wlan_password = ""
|
||||
self.pin = ""
|
||||
self.html = """
|
||||
<html>
|
||||
<head><title>Pico Setup</title></head>
|
||||
<body>
|
||||
<h1>Setup Pico</h1>
|
||||
<form method="post">
|
||||
SSID: <select name="ssid">{}</select><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
PIN: <input type="text" name="pin" maxlength="4"><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
def scan_wlans(self):
|
||||
print("Scan WLANs")
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
self.wlans = [w[0].decode() for w in wlan.scan()]
|
||||
print("Found:", self.wlans)
|
||||
wlan.active(False)
|
||||
|
||||
def start_ap_mode(self):
|
||||
self.ap = network.WLAN(network.AP_IF)
|
||||
self.ap.active(True)
|
||||
while self.ap.active() == False:
|
||||
pass
|
||||
self.ap.config(essid=self.ap_ssid, password=self.ap_password)
|
||||
print("AP SSID:", self.ap.config("essid"))
|
||||
# print("AP Password:", self.ap.config("password"))
|
||||
|
||||
def stop_ap_mode(self):
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
|
||||
def start_webserver(self):
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
s = socket.socket()
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
print("Listening on", addr)
|
||||
while True:
|
||||
conn, addr = s.accept()
|
||||
print("Got a connection from", addr)
|
||||
request = conn.recv(1024)
|
||||
print("Content =", request)
|
||||
conn.send("HTTP/1.1 200 OK\n")
|
||||
conn.send("Content-Type: text/html\n")
|
||||
conn.send("Connection: close\n\n")
|
||||
conn.sendall(self.html.format(''.join(['<option value="{}">{}</option>'.format(w, w) for w in self.wlans])))
|
||||
conn.close()
|
||||
|
||||
def parse_request(self, request):
|
||||
request = request.decode()
|
||||
ssid_match = re.search("ssid=([^&]+)", request)
|
||||
if ssid_match:
|
||||
self.selected_ssid = ssid_match.group(1)
|
||||
password_match = re.search("password=([^&]+)", request)
|
||||
if password_match:
|
||||
self.wlan_password = password_match.group(1)
|
||||
pin_match = re.search("pin=([^&]+)", request)
|
||||
if pin_match:
|
||||
self.pin = pin_match.group(1)
|
||||
|
||||
def save_config(self):
|
||||
config = {
|
||||
"ssid": self.selected_ssid,
|
||||
"password": self.wlan_password,
|
||||
"pin": self.pin
|
||||
}
|
||||
with open("initial_config.py", "w") as f:
|
||||
f.write("config = " + ujson.dumps(config))
|
||||
|
||||
def switch_to_client_mode(self):
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
wlan.connect(self.selected_ssid, self.wlan_password)
|
||||
while not wlan.isconnected():
|
||||
time.sleep(1)
|
||||
print("Connected to", self.selected_ssid)
|
||||
|
||||
def setup_pico(self):
|
||||
print("Start PICO setup")
|
||||
self.scan_wlans()
|
||||
self.start_ap_mode()
|
||||
self.start_webserver()
|
||||
while True:
|
||||
conn, addr = self.s.accept()
|
||||
request = conn.recv(1024)
|
||||
self.parse_request(request)
|
||||
self.save_config()
|
||||
conn.close()
|
||||
break # Assuming only one request is handled
|
||||
self.stop_ap_mode()
|
||||
self.switch_to_client_mode()
|
||||
|
||||
File renamed without changes.
@@ -3,90 +3,68 @@ import ujson
|
||||
import ure as re
|
||||
import usocket as socket
|
||||
import time
|
||||
from gs.little_apache import LittleApache
|
||||
|
||||
|
||||
class Setup:
|
||||
|
||||
wlans = []
|
||||
|
||||
def __init__(self):
|
||||
self.ap_ssid = "Growsystem"
|
||||
self.ap_password = "12345678"
|
||||
self.ap_ssid = "Growsystem 1.0"
|
||||
self.ap_password = "password"
|
||||
self.wlans = []
|
||||
self.selected_ssid = ""
|
||||
self.wlan_password = ""
|
||||
self.pin = ""
|
||||
self.html = """
|
||||
<html>
|
||||
<head><title>Pico Setup</title></head>
|
||||
<body>
|
||||
<h1>Setup Pico</h1>
|
||||
<form method="post">
|
||||
SSID: <select name="ssid">{}</select><br>
|
||||
Password: <input type="password" name="password"><br>
|
||||
PIN: <input type="text" name="pin" maxlength="4"><br>
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
def scan_wlans(self):
|
||||
print("Scan WLANs")
|
||||
print("Scan for WiFis")
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(True)
|
||||
self.wlans = [w[0].decode() for w in wlan.scan()]
|
||||
print("Found:", self.wlans)
|
||||
print("Detected WiFis: ", self.wlans)
|
||||
wlan.active(False)
|
||||
|
||||
def start_ap_mode(self):
|
||||
self.ap = network.WLAN(network.AP_IF)
|
||||
self.ap.active(True)
|
||||
while self.ap.active() == False:
|
||||
pass
|
||||
self.ap.config(essid=self.ap_ssid, password=self.ap_password)
|
||||
print("AP SSID:", self.ap.config("essid"))
|
||||
# print("AP Password:", self.ap.config("password"))
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
wlan.active(False)
|
||||
wlan_config = {
|
||||
"ssid": self.ap_ssid,
|
||||
"pw": self.ap_password
|
||||
}
|
||||
print("Switch to ap mode with data:", wlan_config)
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.config(essid=self.ap_ssid, password=self.ap_password)
|
||||
ap.active(True)
|
||||
self.net = ap
|
||||
print("Connect with your browser to:", ap.ifconfig()[0])
|
||||
|
||||
def stop_ap_mode(self):
|
||||
print("Stop ap mode")
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
|
||||
def start_webserver(self):
|
||||
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
|
||||
s = socket.socket()
|
||||
s.bind(addr)
|
||||
s.listen(1)
|
||||
print("Listening on", addr)
|
||||
while True:
|
||||
conn, addr = s.accept()
|
||||
print("Got a connection from", addr)
|
||||
request = conn.recv(1024)
|
||||
print("Content =", request)
|
||||
conn.send("HTTP/1.1 200 OK\n")
|
||||
conn.send("Content-Type: text/html\n")
|
||||
conn.send("Connection: close\n\n")
|
||||
conn.sendall(self.html.format(''.join(['<option value="{}">{}</option>'.format(w, w) for w in self.wlans])))
|
||||
conn.close()
|
||||
def get_initial_config_webserver(self):
|
||||
self.la = LittleApache(self.net)
|
||||
self.la.available_wifis = self.wlans
|
||||
self.la.start()
|
||||
config = self.la.http_request.get_content_json()
|
||||
print("start webserver end:", config)
|
||||
return config
|
||||
|
||||
def parse_request(self, request):
|
||||
request = request.decode()
|
||||
ssid_match = re.search("ssid=([^&]+)", request)
|
||||
if ssid_match:
|
||||
self.selected_ssid = ssid_match.group(1)
|
||||
password_match = re.search("password=([^&]+)", request)
|
||||
if password_match:
|
||||
self.wlan_password = password_match.group(1)
|
||||
pin_match = re.search("pin=([^&]+)", request)
|
||||
if pin_match:
|
||||
self.pin = pin_match.group(1)
|
||||
|
||||
def save_config(self):
|
||||
def save_config(self, config):
|
||||
config = {
|
||||
"ssid": self.selected_ssid,
|
||||
"password": self.wlan_password,
|
||||
"pin": self.pin
|
||||
"ssid": config['ssid'],
|
||||
"password": config['password'],
|
||||
"pin": config['pin']
|
||||
}
|
||||
with open("initial_config.py", "w") as f:
|
||||
print("Save config:", config)
|
||||
with open("/gs/config/initial_config.py", "w") as f:
|
||||
f.write("config = " + ujson.dumps(config))
|
||||
|
||||
def switch_to_client_mode(self):
|
||||
print("Switch to client mode")
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.active(False)
|
||||
wlan = network.WLAN(network.STA_IF)
|
||||
@@ -97,17 +75,10 @@ class Setup:
|
||||
print("Connected to", self.selected_ssid)
|
||||
|
||||
def setup_pico(self):
|
||||
print("Start PICO setup")
|
||||
self.scan_wlans()
|
||||
self.start_ap_mode()
|
||||
self.start_webserver()
|
||||
while True:
|
||||
conn, addr = self.s.accept()
|
||||
request = conn.recv(1024)
|
||||
self.parse_request(request)
|
||||
self.save_config()
|
||||
conn.close()
|
||||
break # Assuming only one request is handled
|
||||
self.stop_ap_mode()
|
||||
self.switch_to_client_mode()
|
||||
config = self.get_initial_config_webserver()
|
||||
self.save_config(config)
|
||||
# self.stop_ap_mode()
|
||||
# self.switch_to_client_mode()
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import network
|
||||
import time
|
||||
import socket
|
||||
|
||||
ssid="Growsystem"
|
||||
password="12345678"
|
||||
|
||||
def web_page():
|
||||
html = """<html><head><meta name="viewport" content="width=device-width, initial-scale=1"></head>
|
||||
<body><h1>Hello World</h1></body></html>
|
||||
"""
|
||||
return html
|
||||
|
||||
# if you do not see the network you may have to power cycle
|
||||
# unplug your pico w for 10 seconds and plug it in again
|
||||
def ap_mode(ssid, password):
|
||||
"""
|
||||
Description: This is a function to activate AP mode
|
||||
|
||||
Parameters:
|
||||
|
||||
ssid[str]: The name of your internet connection
|
||||
password[str]: Password for your internet connection
|
||||
|
||||
Returns: Nada
|
||||
"""
|
||||
# Just making our internet connection
|
||||
ap = network.WLAN(network.AP_IF)
|
||||
ap.config(essid=ssid, password=password)
|
||||
ap.active(True)
|
||||
|
||||
while ap.active() == False:
|
||||
pass
|
||||
print('AP Mode Is Active, You can Now Connect')
|
||||
print('IP Address To Connect to:: ' + ap.ifconfig()[0])
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #creating socket object
|
||||
s.bind(('', 80))
|
||||
s.listen(5)
|
||||
|
||||
while True:
|
||||
conn, addr = s.accept()
|
||||
print('Got a connection from %s' % str(addr))
|
||||
request = conn.recv(1024)
|
||||
print('Content = %s' % str(request))
|
||||
response = web_page()
|
||||
conn.send(response)
|
||||
conn.close()
|
||||
|
||||
ap_mode('Growsystem95','PASSWORD')
|
||||
Reference in new issue
Block a user