Skip to content

Commit

Permalink
Raised reading capture from weather to main enviro
Browse files Browse the repository at this point in the history
  • Loading branch information
ZodiusInfuser committed Nov 10, 2022
1 parent bac8625 commit 60d29ea
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 52 deletions.
70 changes: 65 additions & 5 deletions enviro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,14 +151,27 @@ def stop_activity_led():
print("")


import network
import network # TODO this was removed from 0.0.8
def connect_to_wifi():
""" TODO what it was changed to
if phew.is_connected_to_wifi():
logging.info(f"> already connected to wifi")
return True
"""

wifi_ssid = config.wifi_ssid
wifi_password = config.wifi_password

logging.info(f"> connecting to wifi network '{wifi_ssid}'")
""" TODO what it was changed to
ip = phew.connect_to_wifi(wifi_ssid, wifi_password, timeout_seconds=30)
if not ip:
logging.error(f"! failed to connect to wireless network {wifi_ssid}")
return False
logging.info(" - ip address: ", ip)
"""
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(wifi_ssid, wifi_password)
Expand Down Expand Up @@ -259,8 +272,33 @@ def wake_reason_name(wake_reason):

# get the readings from the on board sensors
def get_sensor_readings():
readings = get_board().get_sensor_readings()
seconds_since_last = 0
now_str = helpers.datetime_string()
if helpers.file_exists("last_time.txt"):
now = helpers.timestamp(now_str)

time_entries = []
with open("last_time.txt", "r") as timefile:
time_entries = timefile.read().split("\n")

# read the first line from the time file
last = now
for entry in time_entries:
if entry:
last = helpers.timestamp(entry)
break

seconds_since_last = now - last
logging.info(f" - seconds since last reading: {seconds_since_last}")


readings = get_board().get_sensor_readings(seconds_since_last)
readings["voltage"] = 0.0 # battery_voltage #Temporarily removed until issue is fixed

# write out the last time log
with open("last_time.txt", "w") as timefile:
timefile.write(now_str)

return readings

# save the provided readings into a todays readings data file
Expand All @@ -272,6 +310,7 @@ def save_reading(readings):
with open(readings_filename, "a") as f:
if new_file:
# new readings file so write out column headings first
#f.write("timestamp," + ",".join(readings.keys()) + "\r\n") # TODO what it was changed to
f.write("time," + ",".join(readings.keys()) + "\r\n")

# write sensor data
Expand All @@ -283,9 +322,19 @@ def save_reading(readings):

# save the provided readings into a cache file for future uploading
def cache_upload(readings):
""" TODO what it was changed to
payload = {
"nickname": config.nickname,
"timestamp": helpers.datetime_string(),
"readings": readings,
"model": model,
"uid": helpers.uid()
}
"""
uploads_filename = f"uploads/{helpers.datetime_string()}.json"
helpers.mkdir_safe("uploads")
with open(uploads_filename, "w") as upload_file:
#json.dump(payload, upload_file) # TODO what it was changed to
upload_file.write(ujson.dumps(readings))

# return the number of cached results waiting to be uploaded
Expand All @@ -305,7 +354,19 @@ def upload_readings():
destination = config.destination
exec(f"import enviro.destinations.{destination}")
destination_module = sys.modules[f"enviro.destinations.{destination}"]

""" TODO what it was changed to
for cache_file in os.ilistdir("uploads"):
with open(f"uploads/{cache_file[0]}", "r") as upload_file:
success = destination_module.upload_reading(json.load(upload_file))
if not success:
logging.error(f"! failed to upload '{cache_file[0]}' to {destination}")
return False
# remove the cache file now uploaded
logging.info(f" - uploaded {cache_file[0]} to {destination}")
os.remove(f"uploads/{cache_file[0]}")
"""
destination_module.upload_readings()

return True
Expand Down Expand Up @@ -340,7 +401,7 @@ def sleep():

# make sure the rtc flags are cleared before going back to sleep
logging.debug(" - clearing and disabling previous alarm")
rtc.clear_timer_flag()
rtc.clear_timer_flag() # TODO this was removed from 0.0.8
rtc.clear_alarm_flag()

# set alarm to wake us up for next reading
Expand Down Expand Up @@ -392,4 +453,3 @@ def sleep():

# reset the board
machine.reset()

107 changes: 106 additions & 1 deletion enviro/boards/grow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from breakout_ltr559 import BreakoutLTR559
from machine import Pin, PWM
from enviro import i2c
#from phew import logging # TODO from 0.0.8

bme280 = BreakoutBME280(i2c, 0x77)
ltr559 = BreakoutLTR559(i2c)
Expand Down Expand Up @@ -52,7 +53,7 @@ def moisture_readings(sample_time_ms=500):

return results

def get_sensor_readings():
def get_sensor_readings(seconds_since_last):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
Expand All @@ -73,6 +74,110 @@ def get_sensor_readings():
"moisture_2": round(moisture_levels[1], 2),
"moisture_3": round(moisture_levels[2], 2)
})

""" TODO from 0.0.8
pump_pins = [
Pin(12, Pin.OUT, value=0),
Pin(11, Pin.OUT, value=0),
Pin(10, Pin.OUT, value=0)
]
def moisture_readings():
results = []
for i in range(0, 3):
# count time for sensor to "tick" 25 times
sensor = moisture_sensor_pins[i]
last_value = sensor.value()
start = time.ticks_ms()
first = None
last = None
ticks = 0
while ticks < 10 and time.ticks_ms() - start <= 1000:
value = sensor.value()
if last_value != value:
if first == None:
first = time.ticks_ms()
last = time.ticks_ms()
ticks += 1
last_value = value
if not first or not last:
results.append(0.0)
continue
# calculate the average tick between transitions in ms
average = (last - first) / ticks
# scale the result to a 0...100 range where 0 is very dry
# and 100 is standing in water
#
# dry = 10ms per transition, wet = 80ms per transition
min_ms = 20
max_ms = 80
average = max(min_ms, min(max_ms, average)) # clamp range
scaled = ((average - min_ms) / (max_ms - min_ms)) * 100
results.append(round(scaled, 2))
return results
# make a semi convincing drip noise
def drip_noise():
piezo_pwm.duty_u16(32768)
for i in range(0, 10):
f = i * 20
piezo_pwm.freq((f * f) + 1000)
time.sleep(0.02)
piezo_pwm.duty_u16(0)
def water(moisture_levels):
from enviro import config
targets = [
config.moisture_target_1,
config.moisture_target_2,
config.moisture_target_3
]
for i in range(0, 3):
if moisture_levels[i] < targets[i]:
# determine a duration to run the pump for
duration = round((targets[i] - moisture_levels[i]) / 25, 1)
if config.auto_water:
logging.info(f"> running pump {i} for {duration} second (currently at {int(moisture_levels[i])}, target {targets[i]})")
pump_pins[i].value(1)
time.sleep(duration)
pump_pins[i].value(0)
else:
for j in range(0, i + 1):
drip_noise()
time.sleep(0.5)
def get_sensor_readings():
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
time.sleep(0.1)
bme280_data = bme280.read()
ltr_data = ltr559.get_reading()
moisture_levels = moisture_readings()
water(moisture_levels) # run pumps if needed
from ucollections import OrderedDict
return OrderedDict({
"temperature": round(bme280_data[0], 2),
"humidity": round(bme280_data[2], 2),
"pressure": round(bme280_data[1] / 100.0, 2),
"luminance": round(ltr_data[BreakoutLTR559.LUX], 2),
"moisture_1": round(moisture_levels[0], 2),
"moisture_2": round(moisture_levels[1], 2),
"moisture_3": round(moisture_levels[2], 2)
})
"""

def play_tone(frequency = None):
if frequency:
Expand Down
2 changes: 1 addition & 1 deletion enviro/boards/indoor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def colour_temperature_from_rgbc(r, g, b, c):
ct = 10000
return round(ct)

def get_sensor_readings():
def get_sensor_readings(seconds_since_last):
data = bme688.read()

temperature = round(data[0], 2)
Expand Down
4 changes: 2 additions & 2 deletions enviro/boards/urban.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from machine import Pin, ADC
from breakout_bme280 import BreakoutBME280
from pimoroni_i2c import PimoroniI2C
from enviro import logging
from phew import logging
from enviro import i2c

sensor_reset_pin = Pin(9, Pin.OUT, value=True)
Expand Down Expand Up @@ -31,7 +31,7 @@ def particulates(particulate_data, measure):
multiplier = 10 if measure >= PM0_3_PER_LITRE else 1
return ((particulate_data[measure * 2] << 8) | particulate_data[measure * 2 + 1]) * multiplier

def get_sensor_readings():
def get_sensor_readings(seconds_since_last):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
Expand Down
62 changes: 22 additions & 40 deletions enviro/boards/weather.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,59 +144,40 @@ def wind_direction():

return closest_index * 45

def timestamp(dt):
year = int(dt[0:4])
month = int(dt[5:7])
day = int(dt[8:10])
hour = int(dt[11:13])
minute = int(dt[14:16])
second = int(dt[17:19])
return time.mktime((year, month, day, hour, minute, second, 0, 0))

def rainfall():
def rainfall(seconds_since_last):
amount = 0
now_str = helpers.datetime_string()
if helpers.file_exists("last_time.txt"):
now = timestamp(now_str)
now = helpers.timestamp(helpers.datetime_string())

time_entries = []
with open("last_time.txt", "r") as timefile:
time_entries = timefile.read().split("\n")
if helpers.file_exists("rain.txt"):
with open("rain.txt", "r") as rainfile:
rain_entries = rainfile.read().split("\n")

# read the first line from the time file
last = now
for entry in time_entries:
# count how many rain ticks since the last reading
for entry in rain_entries:
if entry:
last = timestamp(entry)
break

logging.info(f" - seconds since last reading: {now - last}")

if helpers.file_exists("rain.txt"):
with open("rain.txt", "r") as rainfile:
rain_entries = rainfile.read().split("\n")

# count how many rain ticks since the last reading
for entry in rain_entries:
if entry:
ts = timestamp(entry)
if now - ts < now - last:
amount += RAIN_MM_PER_TICK
ts = helpers.timestamp(entry)
if now - ts < seconds_since_last:
amount += RAIN_MM_PER_TICK

per_second = 0
if seconds_since_last > 0:
per_second = amount / seconds_since_last

# write out adjusted rain log
with open("last_time.txt", "w") as timefile:
timefile.write(now_str)
# clear the rain log by overwriting it
with open("rain.txt", "w") as rainfile:
rainfile.write("")

return amount
return amount, per_second

def get_sensor_readings():
def get_sensor_readings(seconds_since_last):
# bme280 returns the register contents immediately and then starts a new reading
# we want the current reading so do a dummy read to discard register contents first
bme280.read()
time.sleep(0.1)
bme280_data = bme280.read()

ltr_data = ltr559.get_reading()
rain, rain_per_second = rainfall(seconds_since_last)

from ucollections import OrderedDict
return OrderedDict({
Expand All @@ -205,6 +186,7 @@ def get_sensor_readings():
"pressure": round(bme280_data[1] / 100.0, 2),
"light": round(ltr_data[BreakoutLTR559.LUX], 2),
"wind_speed": wind_speed(),
"rain": rainfall(),
"rain": rain,
"rain_per_second": rain_per_second,
"wind_direction": wind_direction()
})
Loading

0 comments on commit 60d29ea

Please sign in to comment.