Nareshkumar Rao 7 months ago
parent
commit
771f81a9f6
  1. 6
      growpi.toml
  2. 73
      html/growpi/src/App.vue
  3. 7
      html/growpi/src/main.js
  4. 15
      src/config.rs
  5. 25
      src/control.rs

6
growpi.toml

@ -28,3 +28,9 @@ resistor = "R2"
[water_pump_settings]
grams_per_millisecond = 0.05280999839305878
[controller_settings]
temperature_set_point_upper = 35.0
temperature_set_point_lower = 28.0
temperature_loop_mins = 60
soil_loop_hours = 12

73
html/growpi/src/App.vue

@ -1,5 +1,6 @@
<script>
import Button from 'primevue/button';
import InputNumber from 'primevue/inputnumber';
import ToggleButton from 'primevue/togglebutton';
export default {
data() {
@ -10,9 +11,10 @@ export default {
water_state: false,
water_primed: false,
fan_state: false,
pumpAmount: 150,
};
},
components: { ToggleButton, Button },
components: { ToggleButton, Button, InputNumber },
methods: {
async updateInfo() {
let info = await receiveInfo();
@ -21,15 +23,20 @@ export default {
this.pump_state = to_bool(info.pump_state);
this.temperature = info.temperature;
this.soil_moisture = info.soil_moisture;
console.log(info);
},
async sendSwitch(name, state) {
await fetch("http://192.168.0.107:2205/switch/" + name + "/" + to_state(state));
await this.updateInfo();
},
async pumpWater() {
console.log("Pumping: " + this.pumpAmount);
await fetch("http://192.168.0.107:2205/pump/" + this.pumpAmount);
await this.updateInfo();
}
},
created() {
setTimeout(this.updateInfo, 1000);
this.updateInfo();
setInterval(this.updateInfo, 1000);
}
}
@ -60,29 +67,75 @@ function to_bool(state) {
</script>
<template>
<h1>GrowPi!</h1>
<table>
<table class="main-table">
<tr>
<td>Temperature</td>
<td>
{{ Math.round(temperature * 100) / 100 }}°C
</td>
</tr>
<tr>
<td>Soil Moisture</td>
<td>
{{ Math.round(soil_moisture * 1000) / 10 }}%
</td>
</tr>
<tr>
<td>Lights</td>
<td>
<ToggleButton :modelValue="light_state" something="hi" @change="sendSwitch('lights', !light_state)" onLabel="On"
offLabel="Off" />
<ToggleButton class="whole-cell" :modelValue="light_state" something="hi"
@change="sendSwitch('lights', !light_state)" onLabel="On" offLabel="Off" />
</td>
</tr>
<tr>
<td>Fan</td>
<td>
<ToggleButton :modelValue="fan_state" @change="sendSwitch('fan', !fan_state)" onLabel="On" offLabel="Off" />
<ToggleButton class="whole-cell" :modelValue="fan_state" @change="sendSwitch('fan', !fan_state)" onLabel="On"
offLabel="Off" />
</td>
</tr>
<tr>
<td>Pump</td>
<td>
<div class="whole-cell">
<ToggleButton v-model="water_primed" onLabel="Ready" offLabel="Click to Prime" />
<Button @change="sendSwitch('pump', !water_state); water_primed = false;" :disabled="!water_primed"
<Button @click="pumpWater(); water_primed = false;" :disabled="!water_primed && !water_state"
label="Pump Water" />
{{ water_state ? "Pump active" : "Pump inactive" }}
</div>
<br /><br />
<InputNumber class="whole-cell" v-model="pumpAmount" :allowEmpty="false" inputId="integeronly" suffix=" grams"
:min="100" :max="300" />
</td>
</tr>
</table>
</template>
<style></style>
<style>
html,
body {
height: 100%;
}
html {
display: table;
margin: auto;
}
body {
display: table-cell;
vertical-align: middle;
}
.main-table {
border-collapse: collapse;
}
.main-table td {
border-style: solid;
padding: 1em;
border-width: 1px;
}
.whole-cell {
width: 100%;
}
</style>

7
html/growpi/src/main.js

@ -1,9 +1,10 @@
import 'primevue/resources/themes/aura-light-green/theme.css'
import 'primevue/resources/themes/aura-dark-green/theme.css'
import { createApp } from 'vue'
import PrimeVue from 'primevue/config'
import App from './App.vue'
createApp(App).mount('#app')
App.use(PrimeVue)
const app = createApp(App)
app.use(PrimeVue)
app.mount('#app')

15
src/config.rs

@ -44,6 +44,14 @@ pub struct BoardSettings {
pub logic_level: f32,
}
#[derive(Serialize, Deserialize)]
pub struct ControllerSettings {
pub temperature_set_point_upper: f32,
pub temperature_set_point_lower: f32,
pub temperature_loop_mins: u64,
pub soil_loop_hours: u64,
}
#[derive(Serialize, Deserialize)]
pub struct Configuration {
pub board_settings: BoardSettings,
@ -51,6 +59,7 @@ pub struct Configuration {
pub soil_moisture_settings: SoilMoistureSettings,
pub thermistor_settings: ThermistorSettings,
pub water_pump_settings: WaterPumpSettings,
pub controller_settings: ControllerSettings,
}
impl Configuration {
@ -93,6 +102,12 @@ impl Default for Configuration {
water_pump_settings: WaterPumpSettings {
grams_per_millisecond: 0.05281,
},
controller_settings: ControllerSettings {
temperature_set_point_upper: 35.,
temperature_set_point_lower: 28.,
temperature_loop_mins: 60,
soil_loop_hours: 12,
},
}
}
}

25
src/control.rs

@ -12,24 +12,41 @@ use crate::{
async fn temperature_control(program_state: ProgramStateShared) -> GenericResult<()> {
let mut program_state = program_state.lock().map_err(lock_err)?;
let config = &program_state.config.controller_settings;
let current_temperature = sensors::get_temperature(&program_state.config)?;
if current_temperature > 28. {
if current_temperature > config.temperature_set_point_upper {
actuators::switch_fan(crate::io::RelaySwitchState::On, &mut program_state)?;
} else {
} else if current_temperature < config.temperature_set_point_lower {
actuators::switch_fan(crate::io::RelaySwitchState::Off, &mut program_state)?;
}
Ok(())
}
async fn temperature_control_loop(program_state: ProgramStateShared) {
let loop_duration = program_state
.lock()
.map(|program_state| {
program_state
.config
.controller_settings
.temperature_loop_mins
})
.unwrap_or(1);
loop {
let _ = temperature_control(program_state.clone()).await;
tokio::time::sleep(Duration::from_mins(1)).await;
tokio::time::sleep(Duration::from_mins(loop_duration)).await;
}
}
async fn soil_moisture_control_loop(program_state: ProgramStateShared) {
let loop_duration = program_state
.lock()
.map(|program_state| program_state.config.controller_settings.soil_loop_hours)
.unwrap_or(1);
loop {
tokio::time::sleep(Duration::from_days(1)).await;
tokio::time::sleep(Duration::from_hours(loop_duration)).await;
}
}

Loading…
Cancel
Save