CHECKPOINT BEFORE SITE IS DELETED FROM PROJECT
@ -55,21 +55,21 @@ class DataCollector:
|
|||||||
# or push previous data
|
# or push previous data
|
||||||
return {"data": "TODO"}
|
return {"data": "TODO"}
|
||||||
|
|
||||||
# try:
|
try:
|
||||||
rsp = api_get(self.__NODE_H_ENDPOINT)
|
rsp = api_get(self.__NODE_H_ENDPOINT)
|
||||||
rsp_json = rsp.json()
|
rsp_json = rsp.json()
|
||||||
local_hmdt = rsp_json.get('value', False)
|
local_hmdt = rsp_json.get('value', False)
|
||||||
# except Exception:
|
except Exception as e:
|
||||||
# logging.error('Failed to get data from humidity node!!!')
|
logging.error(f'Failed to get data from humidity node!!!, {e}')
|
||||||
# local_hmdt = 0
|
local_hmdt = -50
|
||||||
|
|
||||||
try:
|
try:
|
||||||
rsp = api_get(self.__NODE_T_ENDPOINT)
|
rsp = api_get(self.__NODE_T_ENDPOINT)
|
||||||
rsp_json = rsp.json()
|
rsp_json = rsp.json()
|
||||||
local_temp = rsp_json.get('value', False)
|
local_temp = rsp_json.get('value', False)
|
||||||
except Exception:
|
except Exception as e:
|
||||||
logging.error('Failed to get data from local temp node!!!')
|
logging.error(f'Failed to get data from local temp node!!!, {e}')
|
||||||
local_temp = 0
|
local_temp = -50
|
||||||
|
|
||||||
weather_data = api_data.json()
|
weather_data = api_data.json()
|
||||||
station_data = weather_data.get('main', False)
|
station_data = weather_data.get('main', False)
|
||||||
|
|||||||
1811
data_processing/datasets(old)/exported_dataset.csv
Normal file
7
lora_nodes/master/irrigator/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM python:3.8
|
||||||
|
WORKDIR /code
|
||||||
|
COPY . .
|
||||||
|
RUN pip install requests
|
||||||
|
RUN pip install -r requirements.txt
|
||||||
|
EXPOSE 3333
|
||||||
|
CMD "/code/irrigator.py"
|
||||||
94
lora_nodes/master/irrigator/irrigator.py
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
#!/usr/local/bin/python
|
||||||
|
import board
|
||||||
|
import busio
|
||||||
|
import digitalio
|
||||||
|
import logging
|
||||||
|
from requests import get as api_get
|
||||||
|
|
||||||
|
import adafruit_rfm69
|
||||||
|
|
||||||
|
|
||||||
|
class LoRa:
|
||||||
|
__SIGNAL_FREQUENCY = 915.0
|
||||||
|
__ENCRYPTION_KEY = b"\x01\x01\x01\x01\x01\x01\x01\x01\x02\x02\x02\x02\x02\x02\x02\x02"
|
||||||
|
__PINS = {
|
||||||
|
'miso': board.MISO,
|
||||||
|
'mosi': board.MOSI,
|
||||||
|
'sck': board.SCK,
|
||||||
|
'cs': board.D22,
|
||||||
|
'rst': board.D27
|
||||||
|
}
|
||||||
|
__PACKET_WAIT = 2
|
||||||
|
__MAX_ATTEMPTS = 5
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
spi = busio.SPI(self.__PINS['sck'],
|
||||||
|
MOSI=self.__PINS['mosi'],
|
||||||
|
MISO=self.__PINS['miso'])
|
||||||
|
cs = digitalio.DigitalInOut(self.__PINS['cs'])
|
||||||
|
rst = digitalio.DigitalInOut(self.__PINS['rst'])
|
||||||
|
self.lora = adafruit_rfm69.RFM69(spi, cs, rst, self.__SIGNAL_FREQUENCY)
|
||||||
|
self.lora.encryption_key = self.__ENCRYPTION_KEY
|
||||||
|
logging.debug(f'Init\'d LoRa board with freq: {self.lora.frequency_mhz}, bitrate: {self.lora.bitrate / 1000} kbit/s, f. deviation: {self.lora.frequency_deviation/1000} khz, and encryption key: {self.lora.encryption_key}')
|
||||||
|
|
||||||
|
def receive_message(self):
|
||||||
|
logging.debug('Waiting for message...')
|
||||||
|
packets = self.lora.receive(timeout=self.__PACKET_WAIT)
|
||||||
|
if packets:
|
||||||
|
logging.debug(f'Got packets: {packets}')
|
||||||
|
return packets
|
||||||
|
return False
|
||||||
|
|
||||||
|
def send_message(self, message):
|
||||||
|
logging.debug(f'Sending message: {message}')
|
||||||
|
packets = bytes(message, 'utf-8')
|
||||||
|
self.lora.send(packets)
|
||||||
|
|
||||||
|
def send_and_wait(self, message):
|
||||||
|
attempt = 0
|
||||||
|
max_attempts = self.__MAX_ATTEMPTS
|
||||||
|
waiting_for_response = True
|
||||||
|
response = None
|
||||||
|
|
||||||
|
while waiting_for_response:
|
||||||
|
logging.debug(f'Attempt {attempt}...')
|
||||||
|
attempt += 1
|
||||||
|
|
||||||
|
self.send_message(message)
|
||||||
|
response = self.receive_message()
|
||||||
|
|
||||||
|
if attempt > max_attempts or response:
|
||||||
|
waiting_for_response = False
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class Irrigator:
|
||||||
|
__DATA_ENDPOINT = "http://todo.maxhunt/design/water"
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.com = LoRa()
|
||||||
|
self.yesterday_water = 0
|
||||||
|
|
||||||
|
def get_today_watering_vol(self):
|
||||||
|
endpoint = self.__DATA_ENDPOINT
|
||||||
|
rsp = api_get(endpoint)
|
||||||
|
if rsp.status_code != 200:
|
||||||
|
logging.error(f'Got code {rsp.status_code} from server, using yesterday\'s value')
|
||||||
|
return self.yesterday_water
|
||||||
|
today_water = rsp.json().get('value')
|
||||||
|
self.yesterday_water = today_water
|
||||||
|
return today_water
|
||||||
|
|
||||||
|
def send_watering_command(self, volume: int):
|
||||||
|
self.com.send_and_wait(f'iot_pmp_ctrl|{str(volume)}')
|
||||||
|
|
||||||
|
def mainloop(self):
|
||||||
|
while True:
|
||||||
|
watering_vol = self.get_today_watering_vol()
|
||||||
|
self.send_watering_command(watering_vol)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
irrigator = Irrigator()
|
||||||
|
irrigator.mainloop()
|
||||||
6
lora_nodes/master/irrigator/requirements.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
Adafruit-Blinka==5.9.1
|
||||||
|
adafruit-circuitpython-busdevice==5.0.1
|
||||||
|
adafruit-circuitpython-rfm69==2.1.0
|
||||||
|
Adafruit-PlatformDetect==2.23.0
|
||||||
|
Adafruit-PureIO==1.1.8
|
||||||
|
RPi.GPIO==0.7.0
|
||||||
@ -106,6 +106,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
@node.route("/hmdt")
|
@node.route("/hmdt")
|
||||||
def humidity():
|
def humidity():
|
||||||
|
global prev_hmdt
|
||||||
humidity = master.get_hmdt()
|
humidity = master.get_hmdt()
|
||||||
if humidity:
|
if humidity:
|
||||||
prev_hmdt = humidity
|
prev_hmdt = humidity
|
||||||
@ -114,6 +115,7 @@ if __name__ == "__main__":
|
|||||||
|
|
||||||
@node.route("/temp")
|
@node.route("/temp")
|
||||||
def temp():
|
def temp():
|
||||||
|
global prev_temp
|
||||||
temp = master.get_temp()
|
temp = master.get_temp()
|
||||||
if temp:
|
if temp:
|
||||||
prev_temp = temp
|
prev_temp = temp
|
||||||
|
|||||||
@ -63,7 +63,7 @@ class WateringPump:
|
|||||||
'''
|
'''
|
||||||
flow_rate = self.__FLOW_RATE
|
flow_rate = self.__FLOW_RATE
|
||||||
run_duration_seconds = volume*60/flow_rate
|
run_duration_seconds = volume*60/flow_rate
|
||||||
self.run_for(run_duration_seconds)
|
self.__run_for(run_duration_seconds)
|
||||||
|
|
||||||
def __run_for(self, duration: float):
|
def __run_for(self, duration: float):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
@ -125,7 +125,10 @@ class SensorNode:
|
|||||||
logging.debug(f'Decoded command: {command}')
|
logging.debug(f'Decoded command: {command}')
|
||||||
commands = str(command).split('|')
|
commands = str(command).split('|')
|
||||||
logging.debug(f'Processed commands: {commands}')
|
logging.debug(f'Processed commands: {commands}')
|
||||||
self.__instrucitons[commands[0]](commands[1])
|
try:
|
||||||
|
self.__instrucitons[commands[0]](commands[1])
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f'Exception: {e}')
|
||||||
|
|
||||||
def ping(self, *_):
|
def ping(self, *_):
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
@ -143,10 +146,10 @@ class SensorNode:
|
|||||||
|
|
||||||
def pump_control(self, volume):
|
def pump_control(self, volume):
|
||||||
water_qty = int(volume)
|
water_qty = int(volume)
|
||||||
logging.info(f'Running pump for {water_qty} ml.')
|
logging.info(f'Dispensing {water_qty} ml.')
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
self.com.send_message('OK')
|
self.com.send_message('OK')
|
||||||
self.pump.dispense(volume)
|
self.pump.dispense(water_qty)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
BIN
project media/0154B9EC-45B9-4BFC-9143-5A19A0AE13E0.JPG
Normal file
|
After Width: | Height: | Size: 1.3 MiB |
BIN
project media/17439CCA-8A93-4303-933B-59A431194B29.JPG
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
project media/87573994-8C9B-4D46-945B-DB478AB7F644.JPG
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
project media/F88F2801-3B5B-458E-83E0-C740C124A312.JPG
Normal file
|
After Width: | Height: | Size: 1.9 MiB |
BIN
project media/IMG_8993.JPG
Normal file
|
After Width: | Height: | Size: 3.6 MiB |
BIN
project media/IMG_9021.JPG
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
project media/IMG_9023.JPG
Normal file
|
After Width: | Height: | Size: 4.6 MiB |
BIN
project media/IMG_9024.JPG
Normal file
|
After Width: | Height: | Size: 4.5 MiB |
BIN
project media/IMG_9025.JPG
Normal file
|
After Width: | Height: | Size: 4.3 MiB |
BIN
project media/IMG_9026.JPG
Normal file
|
After Width: | Height: | Size: 7.7 MiB |
BIN
project media/IMG_9027.JPG
Normal file
|
After Width: | Height: | Size: 5.7 MiB |
BIN
project media/IMG_9028.JPG
Normal file
|
After Width: | Height: | Size: 7.7 MiB |
BIN
project media/IMG_9029.JPG
Normal file
|
After Width: | Height: | Size: 3.3 MiB |
BIN
project media/IMG_9030.JPG
Normal file
|
After Width: | Height: | Size: 2.8 MiB |
BIN
project media/IMG_9031.JPG
Normal file
|
After Width: | Height: | Size: 4.1 MiB |
BIN
project media/IMG_9032.JPG
Normal file
|
After Width: | Height: | Size: 3.9 MiB |
BIN
project media/IMG_9033.JPG
Normal file
|
After Width: | Height: | Size: 6.6 MiB |
BIN
project media/IMG_9034.JPG
Normal file
|
After Width: | Height: | Size: 5.8 MiB |
BIN
project media/IMG_9035.JPG
Normal file
|
After Width: | Height: | Size: 6.0 MiB |
BIN
project media/IMG_9036.JPG
Normal file
|
After Width: | Height: | Size: 6.1 MiB |
@ -9,20 +9,24 @@ app.set('view engine', 'ejs')
|
|||||||
app.set('views', __dirname + '/views')
|
app.set('views', __dirname + '/views')
|
||||||
|
|
||||||
|
|
||||||
app.get('/', function(request, responce){
|
// app.get('/', function(request, responce) {
|
||||||
responce.render('index.ejs')
|
// responce.render('index.ejs')
|
||||||
|
// })
|
||||||
|
|
||||||
|
app.get('/water', function(req, res) {
|
||||||
|
res.send({ success: true, value: 20 })
|
||||||
})
|
})
|
||||||
|
|
||||||
app.get('*', function(request, responce){
|
app.get('*', function(request, responce) {
|
||||||
responce.render('404.ejs')
|
res.redirect('siot.maxhunt.design');
|
||||||
})
|
})
|
||||||
|
|
||||||
app.post('*', function(request, responce){
|
app.post('*', function(request, responce) {
|
||||||
responce.status(404).send({success:false, error:"404"})
|
responce.status(404).send({ success: false, error: "404" })
|
||||||
})
|
})
|
||||||
|
|
||||||
var port = 5050
|
var port = 5050
|
||||||
|
|
||||||
app.listen(port, function() {
|
app.listen(port, function() {
|
||||||
console.log('Server running on port ' + port)
|
console.log('Server running on port ' + port)
|
||||||
})
|
})
|
||||||