Skip to content

Commit

Permalink
Updated grow to v0.0.8 and added specific provisioning page
Browse files Browse the repository at this point in the history
  • Loading branch information
ZodiusInfuser committed Nov 25, 2022
1 parent 2173d09 commit ed2496f
Show file tree
Hide file tree
Showing 7 changed files with 132 additions and 75 deletions.
74 changes: 6 additions & 68 deletions enviro/boards/grow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +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
from phew import logging

bme280 = BreakoutBME280(i2c, 0x77)
ltr559 = BreakoutLTR559(i2c)
Expand All @@ -16,66 +16,6 @@
Pin(13, Pin.IN, Pin.PULL_DOWN)
]

def moisture_readings(sample_time_ms=500):
# get initial sensor state
state = [sensor.value() for sensor in moisture_sensor_pins]

# create an array for each sensor to log the times when the sensor state changed
# then we can use those values to calculate an average tick time for each sensor
changes = [[], [], []]

start = time.ticks_ms()
while time.ticks_diff(time.ticks_ms(), start) <= sample_time_ms:
for i in range(0, len(state)):
now = moisture_sensor_pins[i].value()
if now != state[i]: # sensor output changed
# record the time of the change and update the state
changes[i].append(time.ticks_ms())
state[i] = now

# now we can average the readings for each sensor
results = []
for i in range(0, len(changes)):
# if no sensor connected to change then we have no readings, skip
if len(changes[i]) < 2:
results.append(0)
continue

# calculate the average tick between transitions in ms
average = time.ticks_diff(changes[i][-1], changes[i][0]) / (len(changes[i]) - 1)

# scale the result to a 0...100 range where 0 is very dry
# and 100 is standing in water
#
# dry = 20ms per transition, wet = 60ms per transition
scaled = (min(40, max(0, average - 20)) / 40) * 100
results.append(scaled)

return results

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()

moisture_levels = moisture_readings(2000)

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)
})

""" TODO from 0.0.8
pump_pins = [
Pin(12, Pin.OUT, value=0),
Pin(11, Pin.OUT, value=0),
Expand Down Expand Up @@ -133,9 +73,9 @@ def drip_noise():
def water(moisture_levels):
from enviro import config
targets = [
config.moisture_target_1,
config.moisture_target_2,
config.moisture_target_3
config.moisture_target_a,
config.moisture_target_b,
config.moisture_target_c
]

for i in range(0, 3):
Expand All @@ -153,7 +93,7 @@ def water(moisture_levels):
drip_noise()
time.sleep(0.5)

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 @@ -163,11 +103,10 @@ def get_sensor_readings():
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),
Expand All @@ -177,7 +116,6 @@ def get_sensor_readings():
"moisture_2": round(moisture_levels[1], 2),
"moisture_3": round(moisture_levels[2], 2)
})
"""

def play_tone(frequency = None):
if frequency:
Expand Down
6 changes: 3 additions & 3 deletions enviro/config_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,6 @@

# grow specific settings
auto_water = False
moisture_target_1 = 50
moisture_target_2 = 50
moisture_target_3 = 50
moisture_target_a = 50
moisture_target_b = 50
moisture_target_c = 50
2 changes: 1 addition & 1 deletion enviro/html/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
select {appearance: none; font-family: var(--theme-font); outline: none; background-color: var(--black); color: var(--white); border-radius: var(--input-radius); padding: 1rem 2rem; margin: 1rem 0; border: 0; cursor: pointer; font-size: 1.6rem;}
fieldset {display: grid;}
fieldset input[type="text"] {box-shadow: none !important;}
input[type="text"], input[type="email"], input[type="password"] {appearance: none; font-family: var(--theme-font); outline: none; background-color: var(--black); color: var(--white); border-radius: var(--input-radius); padding: 1rem 2rem; margin: 1rem 0; border: 0; cursor: pointer; font-size: 1.6rem;}
input[type="text"], input[type="email"], input[type="password"], input[type="number"] {appearance: none; font-family: var(--theme-font); outline: none; background-color: var(--black); color: var(--white); border-radius: var(--input-radius); padding: 1rem 2rem; margin: 1rem 0; border: 0; cursor: pointer; font-size: 1.6rem;}
input[type="checkbox"] {cursor: pointer; appearance: none;}
input[type="checkbox"]::before {content: ""; color: var(--white); line-height: 0.9rem; font-size: 1.6rem; border: solid 1px var(--grey); width: 1rem; height: 1rem; margin: 0rem 0.1rem 0rem 0rem; vertical-align: middle; display: inline-block; position: relative; top: -0.1rem;}
input[type="checkbox"]:checked::before {content: "×"; background-color: var(--black); border: solid 1px var(--black);}
Expand Down
2 changes: 1 addition & 1 deletion enviro/html/provision-step-4-destination.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ <h2>HTTP authentication credentials (optional).</h2>

<nav>
<button class="back" onclick="document.location = '/provision-step-3-logging'"><span></span></button>
<button type="submit" form="main">We're done! ➔</button>
<button type="submit" form="main">{{"Sensors ➔" if board == "grow" else "We're done! ➔"}}</button>
</nav>

</section>
Expand Down
90 changes: 90 additions & 0 deletions enviro/html/provision-step-grow-sensors.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{{render_template("enviro/html/header.html")}}

{{render_template("enviro/html/header-mini.html", board=board)}}

<section>
<form id="main" action="/provision-step-grow-sensors" method="post">
<h2>Let's set up your moisture sensors.</h2>
<p>Every plant likes a different amount of moisture in its soil! We've provided some default percentage values below to start you off, but later on you might want to come back and adjust these levels.</p>
</p>When the soil moisture level gets below the target, Grow will chirp at you with three unique tones to let you know which plant needs watering.</p>
<aside class="note">
If you want to turn these audio alerts off (or if you're not using all three channels), set the appropriate channels to 0.
</aside>

<br />

<h3>Channel A moisture target.</h3>
<fieldset>
<input id="moisture_target_a" name="moisture_target_a" type="number" min="0" max="100" placeholder="e.g. 50" value="{{config.moisture_target_a}}" />
</fieldset>

<h3>Channel B moisture target.</h3>
<fieldset>
<input id="moisture_target_b" name="moisture_target_b" type="number" min="0" max="100" placeholder="e.g. 50" value="{{config.moisture_target_b}}" />
</fieldset>

<h3>Channel C moisture target.</h3>
<fieldset>
<input id="moisture_target_c" name="moisture_target_c" type="number" min="0" max="100" placeholder="e.g. 50" value="{{config.moisture_target_c}}" />
</fieldset>

<br />

<h2>Do you want to Auto Water your plants?</h2>
<p>If you have pumps connected to your Enviro Grow, you can enable and disabling auto-watering below. Grow will automatically water your pots until the soil reaches the target moisture level set in the previous step.</p>

<ul id="auto_watering" class="picker">
<li data-auto-water="True">
Yes
</li>
<li data-auto-water="False" >
No
</li>
</ul>
<input type="hidden" id="auto_water" name="auto_water" value="{{config.auto_water}}" />

<script>
function clampTarget(target) {
document.getElementById(target).addEventListener("input", function(e) {
let caretPos = this.selectionStart
let value = document.getElementById(target).value
let clamped = Math.min(Math.max(parseInt(value), 0), 100)
if(clamped != value) {
caretPos -= 1
}
document.getElementById(target).value = clamped
this.selectionStart = this.selectionEnd = caretPos
})
}

function selectAutoWater(auto_water) {
document.querySelectorAll("#auto_watering >li").forEach((listItem) => {
if(listItem.dataset.autoWater == auto_water) {
listItem.classList.add("active")
}else{
listItem.classList.remove("active")
}
})
document.getElementById("auto_water").value = auto_water
}

document.querySelectorAll("#auto_watering >li").forEach((listItem) => {
listItem.addEventListener("click", function(e) {
selectAutoWater(listItem.dataset.autoWater)
})
})

clampTarget("moisture_target_a")
clampTarget("moisture_target_b")
clampTarget("moisture_target_c")
selectAutoWater("{{config.auto_water}}")
</script>
</form>

<nav>
<button class="back" onclick="document.location = '/provision-step-4-destination'"><span></span></button>
<button type="submit" form="main">We're done! ➔</button>
</nav>
</section>

{{render_template("enviro/html/footer.html")}}
31 changes: 30 additions & 1 deletion enviro/provisioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,40 @@ def provision_step_4_destination(request):

write_config()

return redirect(f"http://{DOMAIN}/provision-step-5-done")
if model == "grow":
return redirect(f"http://{DOMAIN}/provision-step-grow-sensors")
else:
return redirect(f"http://{DOMAIN}/provision-step-5-done")
else:
return render_template("enviro/html/provision-step-4-destination.html", board=model)


@server.route("/provision-step-grow-sensors", methods=["GET", "POST"])
def provision_step_grow_sensors(request):
if request.method == "POST":
config.auto_water = (request.form["auto_water"] == 'True')
try:
config.moisture_target_a = int(request.form["moisture_target_a"])
except ValueError:
pass

try:
config.moisture_target_b = int(request.form["moisture_target_b"])
except ValueError:
pass

try:
config.moisture_target_c = int(request.form["moisture_target_c"])
except ValueError:
pass

write_config()

return redirect(f"http://{DOMAIN}/provision-step-5-done")
else:
return render_template("enviro/html/provision-step-grow-sensors.html", board=model)


@server.route("/provision-step-5-done", methods=["GET", "POST"])
def provision_step_5_done(request):
config.provisioned = True
Expand Down
2 changes: 1 addition & 1 deletion phew
Submodule phew updated 1 files
+1 −1 phew/template.py

0 comments on commit ed2496f

Please sign in to comment.