Compare commits
15 Commits
optimize_s
...
ui_modific
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
748dd19a87 | ||
|
|
21d364bf52 | ||
| 5cd8420bcf | |||
|
|
24a1b81b92 | ||
| 829d6cf338 | |||
| a8ac425832 | |||
|
|
d15bc0e5a6 | ||
|
|
ee828c544e | ||
|
|
28e5f7f1f0 | ||
|
|
ed8267b6ab | ||
|
|
99fdc768fc | ||
|
|
c47e1be364 | ||
|
|
8d9e42c147 | ||
|
|
279e0f8652 | ||
| 2395cc6ddf |
3
.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
|
# configuration
|
||||||
|
controller/config/__init__.py
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
|
|||||||
@@ -24,3 +24,5 @@ selaias:meteor-simpleweather
|
|||||||
u2622:persistent-session
|
u2622:persistent-session
|
||||||
percolate:synced-cron
|
percolate:synced-cron
|
||||||
rzymek:moment-locale-bs
|
rzymek:moment-locale-bs
|
||||||
|
peppelg:bootstrap-3-modal
|
||||||
|
fortawesome:fontawesome
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ ejson@1.0.7
|
|||||||
email@1.0.8
|
email@1.0.8
|
||||||
es5-shim@4.1.14
|
es5-shim@4.1.14
|
||||||
fastclick@1.0.7
|
fastclick@1.0.7
|
||||||
|
fortawesome:fontawesome@4.5.0
|
||||||
geojson-utils@1.0.4
|
geojson-utils@1.0.4
|
||||||
handlebars@1.0.4
|
handlebars@1.0.4
|
||||||
hot-code-push@1.0.0
|
hot-code-push@1.0.0
|
||||||
@@ -58,6 +59,7 @@ npm-bcrypt@0.7.8_2
|
|||||||
npm-mongo@1.4.39_1
|
npm-mongo@1.4.39_1
|
||||||
observe-sequence@1.0.7
|
observe-sequence@1.0.7
|
||||||
ordered-dict@1.0.4
|
ordered-dict@1.0.4
|
||||||
|
peppelg:bootstrap-3-modal@1.0.4
|
||||||
percolate:synced-cron@1.3.0
|
percolate:synced-cron@1.3.0
|
||||||
promise@0.5.1
|
promise@0.5.1
|
||||||
random@1.0.5
|
random@1.0.5
|
||||||
|
|||||||
@@ -9,5 +9,6 @@
|
|||||||
|
|
||||||
|
|
||||||
#bucket_image {
|
#bucket_image {
|
||||||
width: 60%;
|
width: 50%;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
<template name="settings">
|
<template name="settings">
|
||||||
<div class="col-md-3 col-md-offset-4">
|
<div class="modal fade">
|
||||||
<h1>Automatsko zaljevanje: </h1>
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Automatsko zaljevanje</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
<select name="time_of_day" id="time_of_day">
|
<select name="time_of_day" id="time_of_day">
|
||||||
<option value="00:00" selected={{ timeSelected "00:00" }}>00:00</option>
|
<option value="00:00" selected={{ timeSelected "00:00" }}>00:00</option>
|
||||||
<option value="00:30" selected={{ timeSelected "00:30" }}>00:30</option>
|
<option value="00:30" selected={{ timeSelected "00:30" }}>00:30</option>
|
||||||
@@ -82,7 +89,15 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<button id="save_settings" name="save_settings">Zapamti</button>
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="save_settings" class="btn btn-default" name="save_settings" data-dismiss="modal">Zapamti</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template name="start">
|
<template name="start">
|
||||||
<div class="col-lg-12 text-center">
|
<div class="col-lg-12 text-center form">
|
||||||
{{>state}}
|
{{>state}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,24 +1,19 @@
|
|||||||
<template name="state">
|
<template name="state">
|
||||||
<div class="col-md-3 col-md-offset-4">
|
<div class="col-md-12">
|
||||||
{{#with controller_state}}
|
{{#with controller_state}}
|
||||||
<h1>{{controller_id}}</h1>
|
<img src="{{ bucket_image }}" class="img-responsive center-block" id="bucket_image" />
|
||||||
<img src="{{ bucket_image }}" class="img-responsive center-block" id="bucket_image" /> {{#with last_sensor_reading}}
|
<div class="text-center">
|
||||||
<div>
|
{{controller_id}}:
|
||||||
<strong>{{ temperatureValue }} °C, {{ humidityValue }} % </strong>
|
{{#with last_sensor_reading}} <strong> {{ temperatureValue }} °C, {{ humidityValue }} % </strong> {{/with}}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div class="text-center">
|
||||||
|
Automatsko zaljevanje: <strong>{{ pretty_days config.automaticDaysOfWeek }} {{ pretty_time config.automaticDaysOfWeek config.automaticTimeOfDay }}</strong> <button id="run_settings" class="btn btn-default"> <i class="fa fa-wrench"></i> </button>
|
||||||
</div>
|
</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
<div>Otpusni ventil: {{pretty_valve state.out_valve }}</div>
|
|
||||||
<div>Zadnja komunikacija: {{ last_communication_time }}</div>
|
|
||||||
{{/with}}
|
|
||||||
<div>
|
<div>
|
||||||
<button id="water_now" class="{{ water_now_button_class }}">Zalij sada</button>
|
<button id="water_now" class="{{ water_now_button_class }}">Zalij sada</button>
|
||||||
<button id="stop_water_now" class="{{ stop_button_class }}">Prekini zalijevanje</button>
|
<button id="stop_water_now" class="{{ stop_button_class }}">Prekini zalijevanje</button>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-1">
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
function controller_state() {
|
function controller_state() {
|
||||||
var controllerId = Session.get('controller_id');
|
var controllerId = Session.get('controller_id');
|
||||||
result = ControllerState.findOne({});
|
result = ControllerState.findOne({});
|
||||||
console.log("jupiii", result);
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = {}
|
result = {}
|
||||||
};
|
};
|
||||||
@@ -45,37 +44,59 @@ Template.state.helpers({
|
|||||||
|
|
||||||
bucket_image: function() {
|
bucket_image: function() {
|
||||||
var sensor = last_sensor_reading();
|
var sensor = last_sensor_reading();
|
||||||
if (sensor && sensor.tankFull === "1") {
|
var stateObject = controller_state();
|
||||||
return "/images/barell_full.png";
|
if (sensor) {
|
||||||
} else {
|
if (sensor.tankFull === 0 && stateObject.state.in_valve === 'open' && stateObject.state.out_valve === 'closed') return "/images/barellFillingUp.png";
|
||||||
return "/images/barell_draining.png";
|
else if (sensor.tankFull === 1 && (stateObject.state.out_valve === 'closed')) return "/images/barellFull.png";
|
||||||
}
|
else if (sensor.tankFull === 1 && (stateObject.state.out_valve === 'opening')) return "/images/barellStartWateringFull.png";
|
||||||
|
else if (sensor.tankFull === 1 && (stateObject.state.out_valve === 'open')) return "/images/barellWateringFull.png";
|
||||||
|
else if (sensor.tankFull === 1 && (stateObject.state.out_valve === 'closing')) return "/images/barellStopWateringFull.png";
|
||||||
|
else if (sensor.tankFull === 0 && (stateObject.state.out_valve === 'closed')) return "/images/barellNotFull.png";
|
||||||
|
else if (sensor.tankFull === 0 && (stateObject.state.out_valve === 'opening')) return "/images/barellStartWateringNotFull.png";
|
||||||
|
else if (sensor.tankFull === 0 && (stateObject.state.out_valve === 'open')) return "/images/barellWateringNotFull.png"
|
||||||
|
else if (sensor.tankFull === 0 && (stateObject.state.out_valve === 'closing')) return "/images/barellStopWateringNotFull.png"
|
||||||
|
else return "/images/statusAmber.png";
|
||||||
|
} else return "/images/statusRed.png";
|
||||||
},
|
},
|
||||||
|
|
||||||
last_sensor_reading: last_sensor_reading,
|
last_sensor_reading: last_sensor_reading,
|
||||||
|
|
||||||
last_communication_time: function() {
|
|
||||||
return moment(controller_state().time).fromNow();
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
water_now_button_class: function() {
|
water_now_button_class: function() {
|
||||||
var stateObject = controller_state();
|
var stateObject = controller_state();
|
||||||
if (stateObject.state && (stateObject.state.out_valve === 'open' || stateObject.state.out_valve === 'opening')) {
|
if (stateObject.state && (stateObject.state.out_valve === 'open' || stateObject.state.out_valve === 'opening')) {
|
||||||
return 'hidden';
|
return 'hidden btn btn-success';
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return 'btn btn-success';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
stop_button_class: function() {
|
stop_button_class: function() {
|
||||||
var stateObject = controller_state();
|
var stateObject = controller_state();
|
||||||
if (stateObject.state && (stateObject.state.out_valve === 'closed' || stateObject.state.out_valve === 'closing')) {
|
if (stateObject.state && (stateObject.state.out_valve === 'closed' || stateObject.state.out_valve === 'closing')) {
|
||||||
return 'hidden';
|
return 'hidden btn btn-success';
|
||||||
} else {
|
} else {
|
||||||
return '';
|
return 'btn btn-success';
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
pretty_days: function(daysInNumbers) {
|
||||||
|
var days = ["Nedjelja", "Ponedjeljak", "Utorak", "Srijeda", "Četvrtak", "Petak", "Subota"];
|
||||||
|
if (daysInNumbers.length == 7) {
|
||||||
|
return "Svaki dan"
|
||||||
|
} else if (!daysInNumbers || daysInNumbers.length == 0) {
|
||||||
|
return "Nikad"
|
||||||
|
} else {
|
||||||
|
return daysInNumbers.map(function(number) {
|
||||||
|
return days[number -1 ];
|
||||||
|
}).join(", ");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pretty_time: function(daysInNumbers, time) {
|
||||||
|
if (!daysInNumbers || daysInNumbers.length == 0) {
|
||||||
|
return ""
|
||||||
|
} else {
|
||||||
|
return " u " + time;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.state.events({
|
Template.state.events({
|
||||||
@@ -87,6 +108,14 @@ Template.state.events({
|
|||||||
'click #stop_water_now': function() {
|
'click #stop_water_now': function() {
|
||||||
var controller_id = Session.get('controller_id');
|
var controller_id = Session.get('controller_id');
|
||||||
Meteor.call('closeOutValve', controller_id)
|
Meteor.call('closeOutValve', controller_id)
|
||||||
|
},
|
||||||
|
|
||||||
|
'click #run_settings': function() {
|
||||||
|
Modal.show('settings');
|
||||||
|
},
|
||||||
|
|
||||||
|
'click #bucket_image': function() {
|
||||||
|
Modal.show('state_details', controller_state());
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
24
app/client/state_details.html
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<template name="state_details">
|
||||||
|
<div class="modal fade">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<h4 class="modal-title">Detalji</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<div><strong>Otpusni ventil:</strong> {{pretty_valve state.out_valve }}</div>
|
||||||
|
<div><strong>Ulazni ventil/pumpa:</strong> {{pretty_valve state.in_valve }}</div>
|
||||||
|
<div><strong>Zadnja komunikacija: {{ last_communication_time }}</strong></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button id="close_details" class="btn btn-default" name="close_details" data-dismiss="modal">Zatvori</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
14
app/client/state_details.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Template.state_details.helpers({
|
||||||
|
pretty_valve: function(state) {
|
||||||
|
if (state === 'open') return "Otvoren";
|
||||||
|
if (state === 'opening') return "Otvara se";
|
||||||
|
if (state === 'closing') return "Zatvara se";
|
||||||
|
if (state === 'closed') return "Zatvoren";
|
||||||
|
},
|
||||||
|
last_communication_time: function() {
|
||||||
|
return moment(this.time).fromNow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.state_details.events({
|
||||||
|
});
|
||||||
@@ -4,7 +4,6 @@
|
|||||||
<li role="presentation" class="{{ class_for 'start' }}"><a href="#">Stanje</a></li>
|
<li role="presentation" class="{{ class_for 'start' }}"><a href="#">Stanje</a></li>
|
||||||
<li role="presentation" class="{{ class_for 'weather' }}"><a href="#">Vrijeme</a></li>
|
<li role="presentation" class="{{ class_for 'weather' }}"><a href="#">Vrijeme</a></li>
|
||||||
<li role="presentation" class="{{ class_for 'log' }}"><a href="#">Novosti</a></li>
|
<li role="presentation" class="{{ class_for 'log' }}"><a href="#">Novosti</a></li>
|
||||||
<li role="presentation" class="{{ class_for 'settings' }}"><a href="#">Podešavanje</a></li>
|
|
||||||
<li role="presentation" class="controller_selection"> <input type="number" id="controller" name="controller" value="{{ selected_controller }}" min="1" max="99999"> <button id="switch" name="switch">Prebaci</button>
|
<li role="presentation" class="controller_selection"> <input type="number" id="controller" name="controller" value="{{ selected_controller }}" min="1" max="99999"> <button id="switch" name="switch">Prebaci</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
BIN
app/public/images/barellFillingUp.png
Normal file
|
After Width: | Height: | Size: 71 KiB |
BIN
app/public/images/barellFull.png
Normal file
|
After Width: | Height: | Size: 61 KiB |
BIN
app/public/images/barellNotFull.png
Normal file
|
After Width: | Height: | Size: 59 KiB |
BIN
app/public/images/barellStartWateringFull.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
BIN
app/public/images/barellStartWateringNotFull.png
Normal file
|
After Width: | Height: | Size: 69 KiB |
BIN
app/public/images/barellStopWateringFull.png
Normal file
|
After Width: | Height: | Size: 109 KiB |
BIN
app/public/images/barellStopWateringNotFull.png
Normal file
|
After Width: | Height: | Size: 103 KiB |
BIN
app/public/images/barellWateringFull.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
app/public/images/barellWateringNotFull.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 53 KiB |
BIN
app/public/images/statusAmber.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
app/public/images/statusBlue.png
Normal file
|
After Width: | Height: | Size: 5.0 KiB |
BIN
app/public/images/statusGreen.png
Normal file
|
After Width: | Height: | Size: 4.9 KiB |
BIN
app/public/images/statusRed.png
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
@@ -9,7 +9,7 @@ Api.addRoute('sensorData', {
|
|||||||
authRequired: false
|
authRequired: false
|
||||||
}, {
|
}, {
|
||||||
post: function() {
|
post: function() {
|
||||||
console.log("Body params", this.bodyParams);
|
reactToSensorData(this.bodyParams);
|
||||||
SensorData.insert({
|
SensorData.insert({
|
||||||
temperatureValue: parseFloat(this.bodyParams.temperatureValue),
|
temperatureValue: parseFloat(this.bodyParams.temperatureValue),
|
||||||
humidityValue: parseFloat(this.bodyParams.humidityValue),
|
humidityValue: parseFloat(this.bodyParams.humidityValue),
|
||||||
@@ -23,16 +23,49 @@ Api.addRoute('sensorData', {
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function reactToSensorData(nextSensorReading) {
|
||||||
|
console.log("reacting to sensor");
|
||||||
|
var controllerId = nextSensorReading.controllerId;
|
||||||
|
var state = stateOrDefault(controllerId).state;
|
||||||
|
var shouldStartPumping = (!state.in_valve || state.in_valve === 'closed') && ((parseInt(nextSensorReading.tankFull) === 0) && (state.out_valve === 'closed' || state.out_valve === 'closing'));
|
||||||
|
|
||||||
|
if (shouldStartPumping) {
|
||||||
|
ControllerState.update({
|
||||||
|
controller_id: controllerId
|
||||||
|
}, {
|
||||||
|
'$set': {
|
||||||
|
'state.in_valve': 'opening',
|
||||||
|
'time': new Date(),
|
||||||
|
'set_by': 'server'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var shouldStopPumping = (state.in_valve === 'open' || state.in_valve === 'opening') && (parseInt(nextSensorReading.tankFull) === 1 || state.out_valve === 'open' || state.out_valve === 'opening');
|
||||||
|
|
||||||
|
if (shouldStopPumping) {
|
||||||
|
ControllerState.update({
|
||||||
|
controller_id: controllerId
|
||||||
|
}, {
|
||||||
|
'$set': {
|
||||||
|
'state.in_valve': 'closing',
|
||||||
|
'time': new Date(),
|
||||||
|
'set_by': 'server'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Api.addRoute('state/:id', {
|
Api.addRoute('state/:id', {
|
||||||
authRequired: false
|
authRequired: false
|
||||||
}, {
|
}, {
|
||||||
post: function() {
|
post: function() {
|
||||||
console.log("Body params", this.bodyParams);
|
console.log("setting state", this.bodyParams);
|
||||||
return ControllerState.update({
|
return ControllerState.update({
|
||||||
controller_id: this.urlParams.id
|
controller_id: this.urlParams.id
|
||||||
}, {
|
}, {
|
||||||
'$set': {
|
'$set': {
|
||||||
'state.out_valve': this.bodyParams.out_valve,
|
'state.out_valve': this.bodyParams.out_valve,
|
||||||
|
'state.in_valve': this.bodyParams.in_valve,
|
||||||
'time': new Date(),
|
'time': new Date(),
|
||||||
'set_by': 'client'
|
'set_by': 'client'
|
||||||
}
|
}
|
||||||
@@ -43,6 +76,7 @@ Api.addRoute('state/:id', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function stateOrDefault(id) {
|
function stateOrDefault(id) {
|
||||||
var stateEntry = ControllerState.findOne({
|
var stateEntry = ControllerState.findOne({
|
||||||
controller_id: id,
|
controller_id: id,
|
||||||
@@ -52,13 +86,13 @@ function stateOrDefault(id) {
|
|||||||
stateEntry = ControllerState.insert({
|
stateEntry = ControllerState.insert({
|
||||||
controller_id: id,
|
controller_id: id,
|
||||||
state: {
|
state: {
|
||||||
out_valve: 'closed'
|
out_valve: 'closed',
|
||||||
|
in_valve: 'closed'
|
||||||
},
|
},
|
||||||
time: new Date(),
|
time: new Date(),
|
||||||
config: {
|
config: {
|
||||||
draining_period_amount: 5,
|
draining_period_amount: 60,
|
||||||
draining_period_unit: 'minutes'
|
draining_period_unit: 'minutes'
|
||||||
|
|
||||||
},
|
},
|
||||||
set_by: 'server'
|
set_by: 'server'
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,8 @@
|
|||||||
GPIO_PIN_DHT = 4 # BCM
|
GPIO_PIN_DHT = 4 # BCM
|
||||||
SENSORDATA_URL = 'http://tfm.meteor.com/api/v1.0/sensorData'
|
SENSORDATA_URL = 'http://tfm.meteor.com/api/v1.0/sensorData'
|
||||||
GPIO_PIN_TANKFULL = 20 # BCM
|
GPIO_PIN_TANKFULL = 20 # BCM
|
||||||
GPIO_PIN_VALVE = 21 # BCM
|
GPIO_PIN_OUT_VALVE = 21 # BCM
|
||||||
|
GPIO_PIN_IN_VALVE = 18 # BCM
|
||||||
API_BASE_URL = 'http://tfm.meteor.com/api/v1.0'
|
API_BASE_URL = 'http://tfm.meteor.com/api/v1.0'
|
||||||
CONTROLLER_ID = '120' # every controller must have a different one
|
CONTROLLER_ID = '120' # every controller must have a different one
|
||||||
STATE_FILE = '/var/run/controller_state'
|
STATE_FILE = '/var/run/controller_state'
|
||||||
@@ -7,29 +7,56 @@ class Changer(object):
|
|||||||
self.local_state = local_state
|
self.local_state = local_state
|
||||||
self.remote_state = remote_state
|
self.remote_state = remote_state
|
||||||
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
|
GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme
|
||||||
GPIO.setup(config.GPIO_PIN_VALVE, GPIO.OUT)
|
GPIO.setup(config.GPIO_PIN_OUT_VALVE, GPIO.OUT)
|
||||||
|
GPIO.setup(config.GPIO_PIN_IN_VALVE, GPIO.OUT)
|
||||||
self.states = {
|
|
||||||
'opening': self.open_valve,
|
|
||||||
'closing': self.close_valve,
|
|
||||||
'open': self.open_valve,
|
|
||||||
'closed': self.close_valve
|
|
||||||
|
|
||||||
|
self.out_valve_states = {
|
||||||
|
'opening': self.open_out_valve,
|
||||||
|
'closing': self.close_out_valve,
|
||||||
|
'open': self.open_out_valve,
|
||||||
|
'closed': self.close_out_valve
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.in_valve_states = {
|
||||||
|
'opening': self.open_in_valve,
|
||||||
|
'closing': self.close_in_valve,
|
||||||
|
'open': self.open_in_valve,
|
||||||
|
'closed': self.close_in_valve
|
||||||
|
}
|
||||||
|
|
||||||
|
def safe_remote_state(self, key):
|
||||||
|
if key in ['out_valve', 'in_valve']:
|
||||||
|
return self.remote_state.get(key, 'closed')
|
||||||
|
else:
|
||||||
|
return self.remote_state.get(key,'');
|
||||||
|
|
||||||
def process_change(self):
|
def process_change(self):
|
||||||
self.validate_states()
|
self.validate_states()
|
||||||
change = self.states.get(self.remote_state['out_valve'], None )
|
|
||||||
if change is not None:
|
out_valve_change = self.out_valve_states.get(self.safe_remote_state('out_valve'), None )
|
||||||
change()
|
if out_valve_change is not None:
|
||||||
|
out_valve_change()
|
||||||
|
|
||||||
|
in_valve_change = self.in_valve_states.get(self.safe_remote_state('in_valve'), None )
|
||||||
|
if in_valve_change is not None:
|
||||||
|
in_valve_change()
|
||||||
|
|
||||||
return self.local_state
|
return self.local_state
|
||||||
|
|
||||||
def open_valve(self):
|
def open_in_valve(self):
|
||||||
GPIO.output(config.GPIO_PIN_VALVE, GPIO.HIGH)
|
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.HIGH)
|
||||||
|
self.local_state['in_valve'] = 'open'
|
||||||
|
|
||||||
|
def close_in_valve(self):
|
||||||
|
GPIO.output(config.GPIO_PIN_IN_VALVE, GPIO.LOW)
|
||||||
|
self.local_state['in_valve'] = 'closed'
|
||||||
|
|
||||||
|
def open_out_valve(self):
|
||||||
|
GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.HIGH)
|
||||||
self.local_state['out_valve'] = 'open'
|
self.local_state['out_valve'] = 'open'
|
||||||
|
|
||||||
def close_valve(self):
|
def close_out_valve(self):
|
||||||
GPIO.output(config.GPIO_PIN_VALVE, GPIO.LOW)
|
GPIO.output(config.GPIO_PIN_OUT_VALVE, GPIO.LOW)
|
||||||
self.local_state['out_valve'] = 'closed'
|
self.local_state['out_valve'] = 'closed'
|
||||||
|
|
||||||
def validate_states(self):
|
def validate_states(self):
|
||||||
|
|||||||