23 Commits

Author SHA1 Message Date
Senad Uka
d2db89ffc0 Disabled temperature graph 2016-05-17 07:05:54 +02:00
Senad Uka
ac76654e2a Added last valve open time 2016-05-08 05:17:12 +02:00
2772baafbc Merge pull request #18 from senaduka/add_low_temperature
Lower temperature forecast
2016-05-02 18:13:22 +02:00
Senad Uka
3e0733bf3d Lower temperature forecast 2016-05-02 18:10:54 +02:00
Senad Uka
d9fa0bf2f5 Calculator done 2016-05-02 15:18:02 +02:00
Senad Uka
abff71ac06 Calculator done 2016-05-02 14:09:09 +02:00
Senad Uka
5a4fdbbd00 reversed logic 2016-04-10 12:11:54 +02:00
Senad Uka
96c67a6d00 gitignore 2016-04-10 11:58:18 +02:00
Senad Uka
3b8fb3dce4 fixed bug with rpio 2016-04-10 11:57:13 +02:00
0b4a886de6 Merge pull request #16 from senaduka/add_weather_again
weather works
2016-04-10 10:56:23 +02:00
Senad Uka
79df9d05b4 weather works 2016-04-10 10:47:11 +02:00
4df30c3523 Merge pull request #15 from senaduka/graph_fixing
FIxed graphs / inverted the tankFull bit!
2016-04-09 09:48:02 +02:00
Senad Uka
f886530f5f upgraded mongo and packages 2016-04-09 07:51:11 +02:00
Senad Uka
98983ea50d FIxed bug with inverted the tankFull bit! 2016-04-09 07:29:24 +02:00
Senad Uka
c947980844 FIxed graphs / inverted the tankFull bit! 2016-04-09 07:11:08 +02:00
974f18e067 Merge pull request #14 from senaduka/pre_production_fixes
Pre production fixes
2016-03-26 10:29:01 +01:00
Senad Uka
534497e373 Fixed filling logic 2016-03-26 07:32:53 +01:00
Senad Uka
26052a9afc Created graphs without d3 ;) 2016-03-26 07:28:43 +01:00
Senad Uka
e9e808a1bc Merge pull request #13 from senaduka/image_vise
- fixed names to match barrell*
2016-03-25 20:19:17 +01:00
4197d06819 - fixed names to match barrell*
- added more tag to images
2016-03-22 21:54:13 +01:00
Senad Uka
36d1adc626 Fixed a typo 2016-03-20 08:00:14 +01:00
Senad Uka
2317ad3e61 Some css modifications 2016-03-20 07:54:20 +01:00
b2e619c2c9 Merge pull request #12 from senaduka/ui_modifications
Ui is completely changed
2016-03-19 09:30:36 +01:00
34 changed files with 616 additions and 234 deletions

3
.gitignore vendored
View File

@@ -58,3 +58,6 @@ docs/_build/
# PyBuilder
target/
# meteor
app.tar.gz

View File

@@ -10,3 +10,4 @@ notices-for-facebook-graph-api-2
1.2.0-meteor-platform-split
1.2.0-cordova-changes
1.2.0-breaking-changes
1.3.0-split-minifiers-package

View File

@@ -12,7 +12,6 @@ session # Client-side reactive dictionary for your app
jquery # Helpful client-side library
tracker # Meteor's client-side reactive programming library
standard-minifiers # JS/CSS minifiers run for production mode
es5-shim # ECMAScript 5 compatibility for older browsers.
ecmascript # Enable ECMAScript2015+ syntax in app code
@@ -26,3 +25,6 @@ percolate:synced-cron
rzymek:moment-locale-bs
peppelg:bootstrap-3-modal
fortawesome:fontawesome
mfpierre:chartist-js
standard-minifier-css
standard-minifier-js

View File

@@ -1 +1 @@
METEOR@1.2.1
METEOR@1.3.1

View File

@@ -1,90 +1,95 @@
accounts-base@1.2.2
accounts-password@1.1.4
accounts-base@1.2.5
accounts-password@1.1.7
allow-deny@1.0.3
amplify@1.0.0
autoupdate@1.2.4
babel-compiler@5.8.24_1
babel-runtime@0.1.4
base64@1.0.4
binary-heap@1.0.4
blaze@2.1.3
blaze-html-templates@1.0.1
blaze-tools@1.0.4
boilerplate-generator@1.0.4
caching-compiler@1.0.0
caching-html-compiler@1.0.2
callback-hook@1.0.4
check@1.1.0
coffeescript@1.0.11
ddp@1.2.2
ddp-client@1.2.1
ddp-common@1.2.2
ddp-rate-limiter@1.0.0
ddp-server@1.2.2
deps@1.0.9
diff-sequence@1.0.1
ecmascript@0.1.6
ecmascript-runtime@0.2.6
ejson@1.0.7
email@1.0.8
es5-shim@4.1.14
fastclick@1.0.7
autoupdate@1.2.7
babel-compiler@6.6.1
babel-runtime@0.1.7
base64@1.0.7
binary-heap@1.0.7
blaze@2.1.6
blaze-html-templates@1.0.3
blaze-tools@1.0.7
boilerplate-generator@1.0.7
caching-compiler@1.0.3
caching-html-compiler@1.0.5
callback-hook@1.0.7
check@1.1.3
coffeescript@1.0.16
ddp@1.2.4
ddp-client@1.2.4
ddp-common@1.2.4
ddp-rate-limiter@1.0.3
ddp-server@1.2.5
deps@1.0.11
diff-sequence@1.0.4
ecmascript@0.4.2
ecmascript-runtime@0.2.9
ejson@1.0.10
email@1.0.11
es5-shim@4.5.9
fastclick@1.0.10
fortawesome:fontawesome@4.5.0
geojson-utils@1.0.4
handlebars@1.0.4
hot-code-push@1.0.0
html-tools@1.0.5
htmljs@1.0.5
http@1.1.1
huttonr:bootstrap3@3.3.6_6
huttonr:bootstrap3-assets@3.3.6_2
id-map@1.0.4
jquery@1.11.4
json@1.0.3
launch-screen@1.0.4
less@2.5.1
livedata@1.0.15
localstorage@1.0.5
logging@1.0.8
meteor@1.1.10
meteor-base@1.0.1
minifiers@1.1.7
minimongo@1.0.10
mobile-experience@1.0.1
mobile-status-bar@1.0.6
momentjs:moment@2.11.2
mongo@1.1.3
mongo-id@1.0.1
nimble:restivus@0.8.7
fourseven:scss@3.4.1
geojson-utils@1.0.7
hot-code-push@1.0.3
html-tools@1.0.8
htmljs@1.0.8
http@1.1.4
huttonr:bootstrap3@3.3.6_10
huttonr:bootstrap3-assets@3.3.6_3
id-map@1.0.6
jquery@1.11.7
launch-screen@1.0.10
less@2.5.7
livedata@1.0.17
localstorage@1.0.8
logging@1.0.11
meteor@1.1.13
meteor-base@1.0.3
mfpierre:chartist-js@1.6.1
minifier-css@1.1.10
minifier-js@1.1.10
minimongo@1.0.13
mobile-experience@1.0.3
mobile-status-bar@1.0.11
modules@0.5.2
modules-runtime@0.6.2
momentjs:moment@2.12.0
mongo@1.1.6
mongo-id@1.0.3
nimble:restivus@0.8.10
npm-bcrypt@0.7.8_2
npm-mongo@1.4.39_1
observe-sequence@1.0.7
ordered-dict@1.0.4
npm-mongo@1.4.42
observe-sequence@1.0.10
ordered-dict@1.0.6
peppelg:bootstrap-3-modal@1.0.4
percolate:synced-cron@1.3.0
promise@0.5.1
random@1.0.5
rate-limit@1.0.0
reactive-dict@1.1.3
reactive-var@1.0.6
reload@1.1.4
retry@1.0.4
routepolicy@1.0.6
percolate:synced-cron@1.3.2
promise@0.6.6
random@1.0.8
rate-limit@1.0.3
reactive-dict@1.1.6
reactive-var@1.0.8
reload@1.1.7
retry@1.0.6
routepolicy@1.0.9
rzymek:moment-locale-bs@2.9.0
selaias:meteor-simpleweather@0.6.8
service-configuration@1.0.5
session@1.1.1
sha@1.0.4
simple:json-routes@2.0.1
spacebars@1.0.7
spacebars-compiler@1.0.7
srp@1.0.4
standard-minifiers@1.0.2
templating@1.1.5
templating-tools@1.0.0
tracker@1.0.9
selaias:meteor-simpleweather@0.7.0
service-configuration@1.0.8
session@1.1.4
sha@1.0.6
simple:json-routes@2.1.0
spacebars@1.0.10
spacebars-compiler@1.0.10
srp@1.0.7
standard-minifier-css@1.0.5
standard-minifier-js@1.0.5
templating@1.1.8
templating-tools@1.0.3
tracker@1.0.12
u2622:persistent-session@0.4.4
ui@1.0.8
underscore@1.0.4
url@1.0.5
webapp@1.2.3
webapp-hashing@1.0.5
ui@1.0.10
underscore@1.0.7
url@1.0.8
webapp@1.2.7
webapp-hashing@1.0.8

View File

@@ -2,13 +2,20 @@
padding: 40px 15px;
text-align: center;
}
.controller_selection {
padding-top: 10px;
}
#bucket_image {
width: 50%;
cursor: pointer;
@media all and (orientation: portrait) {
#bucket_image {
width: 90%;
cursor: pointer;
}
}
@media all and (orientation: landscape) {
#bucket_image {
width: 40%;
cursor: pointer;
}
}

View File

@@ -8,88 +8,88 @@
</div>
<div class="modal-body">
<select name="time_of_day" id="time_of_day">
<option value="00:00" selected={{ timeSelected "00:00" }}>00:00</option>
<option value="00:30" selected={{ timeSelected "00:30" }}>00:30</option>
<option value="01:00" selected={{ timeSelected "01:00" }}>01:00</option>
<option value="01:30" selected={{ timeSelected "01:30" }}>01:30</option>
<option value="02:00" selected={{ timeSelected "02:00" }}>02:00</option>
<option value="02:30" selected={{ timeSelected "02:30" }}>02:30</option>
<option value="03:00" selected={{ timeSelected "03:00" }}>03:00</option>
<option value="03:30" selected={{ timeSelected "03:30" }}>03:30</option>
<option value="04:00" selected={{ timeSelected "04:00" }}>04:00</option>
<option value="04:30" selected={{ timeSelected "04:30" }}>04:30</option>
<option value="05:00" selected={{ timeSelected "05:00" }}>05:00</option>
<option value="05:30" selected={{ timeSelected "05:30" }}>05:30</option>
<option value="06:00" selected={{ timeSelected "06:00" }}>06:00</option>
<option value="06:30" selected={{ timeSelected "06:30" }}>06:30</option>
<option value="07:00" selected={{ timeSelected "07:00" }}>07:00</option>
<option value="07:30" selected={{ timeSelected "07:30" }}>07:30</option>
<option value="08:00" selected={{ timeSelected "08:00" }}>08:00</option>
<option value="08:30" selected={{ timeSelected "08:30" }}>08:30</option>
<option value="09:00" selected={{ timeSelected "09:00" }}>09:00</option>
<option value="09:30" selected={{ timeSelected "09:30" }}>09:30</option>
<option value="10:00" selected={{ timeSelected "10:00" }}>10:00</option>
<option value="10:30" selected={{ timeSelected "10:30" }}>10:30</option>
<option value="11:00" selected={{ timeSelected "11:00" }}>11:00</option>
<option value="11:30" selected={{ timeSelected "11:30" }}>11:30</option>
<option value="12:00" selected={{ timeSelected "12:00" }}>12:00</option>
<option value="12:30" selected={{ timeSelected "12:30" }}>12:30</option>
<option value="13:00" selected={{ timeSelected "13:00" }}>13:00</option>
<option value="13:30" selected={{ timeSelected "13:30" }}>13:30</option>
<option value="14:00" selected={{ timeSelected "14:00" }}>14:00</option>
<option value="14:30" selected={{ timeSelected "14:30" }}>14:30</option>
<option value="15:00" selected={{ timeSelected "15:00" }}>15:00</option>
<option value="15:30" selected={{ timeSelected "15:30" }}>15:30</option>
<option value="16:00" selected={{ timeSelected "16:00" }}>16:00</option>
<option value="16:30" selected={{ timeSelected "16:30" }}>16:30</option>
<option value="17:00" selected={{ timeSelected "17:00" }}>17:00</option>
<option value="17:30" selected={{ timeSelected "17:30" }}>17:30</option>
<option value="18:00" selected={{ timeSelected "18:00" }}>18:00</option>
<option value="18:30" selected={{ timeSelected "18:30" }}>18:30</option>
<option value="19:00" selected={{ timeSelected "19:00" }}>19:00</option>
<option value="19:30" selected={{ timeSelected "19:30" }}>19:30</option>
<option value="20:00" selected={{ timeSelected "20:00" }}>20:00</option>
<option value="20:30" selected={{ timeSelected "20:30" }}>20:30</option>
<option value="21:00" selected={{ timeSelected "21:00" }}>21:00</option>
<option value="21:30" selected={{ timeSelected "21:30" }}>21:30</option>
<option value="22:00" selected={{ timeSelected "22:00" }}>22:00</option>
<option value="22:30" selected={{ timeSelected "22:30" }}>22:30</option>
<option value="23:00" selected={{ timeSelected "23:00" }}>23:00</option>
<option value="23:30" selected={{ timeSelected "23:30" }}>23:30</option>
</select>
<div>
<input type="checkbox" id="day_1" name="day_1" value="2" class="day_checkbox" checked="{{ dayChecked '2' }}" />
<label for="day_1">Ponedjeljak</label>
</div>
<div>
<input type="checkbox" id="day_2" name="day_2" value="3" class="day_checkbox" checked="{{ dayChecked '3' }}" />
<label for="day_2">Utorak</label>
</div>
<div>
<input type="checkbox" id="day_3" name="day_3" value="4" class="day_checkbox" checked="{{ dayChecked '4' }}" />
<label for="day_3">Srijeda</label>
</div>
<div>
<input type="checkbox" id="day_4" name="day_4" value="5" class="day_checkbox" checked="{{ dayChecked '5' }}" />
<label for="day_4">Četvrtak</label>
</div>
<div>
<input type="checkbox" id="day_5" name="day_5" value="6" class="day_checkbox" checked="{{ dayChecked '6' }}" />
<label for="day_5">Petak</label>
</div>
<div>
<input type="checkbox" id="day_6" name="day_6" value="7" class="day_checkbox" checked="{{ dayChecked '7' }}" />
<label for="day_6">Subota</label>
</div>
<div>
<input type="checkbox" id="day_7" name="day_7" value="1" class="day_checkbox" checked="{{ dayChecked '1' }}" />
<label for="day_7">Nedjelja</label>
</div>
<div>
<div class="form-group">
<select name="time_of_day" id="time_of_day" class="form-control">
<option value="00:00" selected={{ timeSelected "00:00" }}>00:00</option>
<option value="00:30" selected={{ timeSelected "00:30" }}>00:30</option>
<option value="01:00" selected={{ timeSelected "01:00" }}>01:00</option>
<option value="01:30" selected={{ timeSelected "01:30" }}>01:30</option>
<option value="02:00" selected={{ timeSelected "02:00" }}>02:00</option>
<option value="02:30" selected={{ timeSelected "02:30" }}>02:30</option>
<option value="03:00" selected={{ timeSelected "03:00" }}>03:00</option>
<option value="03:30" selected={{ timeSelected "03:30" }}>03:30</option>
<option value="04:00" selected={{ timeSelected "04:00" }}>04:00</option>
<option value="04:30" selected={{ timeSelected "04:30" }}>04:30</option>
<option value="05:00" selected={{ timeSelected "05:00" }}>05:00</option>
<option value="05:30" selected={{ timeSelected "05:30" }}>05:30</option>
<option value="06:00" selected={{ timeSelected "06:00" }}>06:00</option>
<option value="06:30" selected={{ timeSelected "06:30" }}>06:30</option>
<option value="07:00" selected={{ timeSelected "07:00" }}>07:00</option>
<option value="07:30" selected={{ timeSelected "07:30" }}>07:30</option>
<option value="08:00" selected={{ timeSelected "08:00" }}>08:00</option>
<option value="08:30" selected={{ timeSelected "08:30" }}>08:30</option>
<option value="09:00" selected={{ timeSelected "09:00" }}>09:00</option>
<option value="09:30" selected={{ timeSelected "09:30" }}>09:30</option>
<option value="10:00" selected={{ timeSelected "10:00" }}>10:00</option>
<option value="10:30" selected={{ timeSelected "10:30" }}>10:30</option>
<option value="11:00" selected={{ timeSelected "11:00" }}>11:00</option>
<option value="11:30" selected={{ timeSelected "11:30" }}>11:30</option>
<option value="12:00" selected={{ timeSelected "12:00" }}>12:00</option>
<option value="12:30" selected={{ timeSelected "12:30" }}>12:30</option>
<option value="13:00" selected={{ timeSelected "13:00" }}>13:00</option>
<option value="13:30" selected={{ timeSelected "13:30" }}>13:30</option>
<option value="14:00" selected={{ timeSelected "14:00" }}>14:00</option>
<option value="14:30" selected={{ timeSelected "14:30" }}>14:30</option>
<option value="15:00" selected={{ timeSelected "15:00" }}>15:00</option>
<option value="15:30" selected={{ timeSelected "15:30" }}>15:30</option>
<option value="16:00" selected={{ timeSelected "16:00" }}>16:00</option>
<option value="16:30" selected={{ timeSelected "16:30" }}>16:30</option>
<option value="17:00" selected={{ timeSelected "17:00" }}>17:00</option>
<option value="17:30" selected={{ timeSelected "17:30" }}>17:30</option>
<option value="18:00" selected={{ timeSelected "18:00" }}>18:00</option>
<option value="18:30" selected={{ timeSelected "18:30" }}>18:30</option>
<option value="19:00" selected={{ timeSelected "19:00" }}>19:00</option>
<option value="19:30" selected={{ timeSelected "19:30" }}>19:30</option>
<option value="20:00" selected={{ timeSelected "20:00" }}>20:00</option>
<option value="20:30" selected={{ timeSelected "20:30" }}>20:30</option>
<option value="21:00" selected={{ timeSelected "21:00" }}>21:00</option>
<option value="21:30" selected={{ timeSelected "21:30" }}>21:30</option>
<option value="22:00" selected={{ timeSelected "22:00" }}>22:00</option>
<option value="22:30" selected={{ timeSelected "22:30" }}>22:30</option>
<option value="23:00" selected={{ timeSelected "23:00" }}>23:00</option>
<option value="23:30" selected={{ timeSelected "23:30" }}>23:30</option>
</select>
</div>
<div class="form-group">
<div>
<input type="checkbox" id="day_1" name="day_1" value="2" class="day_checkbox form_control" checked="{{ dayChecked '2' }}" />
<label for="day_1">Ponedjeljak</label>
</div>
<div>
<input type="checkbox" id="day_2" name="day_2" value="3" class="day_checkbox form_control" checked="{{ dayChecked '3' }}" />
<label for="day_2">Utorak</label>
</div>
<div>
<input type="checkbox" id="day_3" name="day_3" value="4" class="day_checkbox form_control" checked="{{ dayChecked '4' }}" />
<label for="day_3">Srijeda</label>
</div>
<div>
<input type="checkbox" id="day_4" name="day_4" value="5" class="day_checkbox form_control" checked="{{ dayChecked '5' }}" />
<label for="day_4">Četvrtak</label>
</div>
<div>
<input type="checkbox" id="day_5" name="day_5" value="6" class="day_checkbox form_control" checked="{{ dayChecked '6' }}" />
<label for="day_5">Petak</label>
</div>
<div>
<input type="checkbox" id="day_6" name="day_6" value="7" class="day_checkbox form_control" checked="{{ dayChecked '7' }}" />
<label for="day_6">Subota</label>
</div>
<div>
<input type="checkbox" id="day_7" name="day_7" value="1" class="day_checkbox form_control" checked="{{ dayChecked '1' }}" />
<label for="day_7">Nedjelja</label>
</div>
</div>
</div>

View File

@@ -1,17 +0,0 @@
var options = {
location: 40.7127+','+ 74.0059, // New York
unit: 'c',
success: function(weather) {
html = '<h2><i class="sw icon-'+weather.code+'"></i> '
html += weather.temp+'&deg;'+weather.units.temp+'</h2>';
html += '<ul><li>'+weather.city+', '+weather.region +'</li>';
html += '<li class="currently">'+weather.currently+'</li>';
$("#weather").html(html);
},
error: function(error) {
$("#weather").html('<p>'+error+'</p>');
}
}
Weather.options = options

View File

@@ -1,4 +1,5 @@
<template name="state">
<div>&nbsp;</div>
<div class="col-md-12">
{{#with controller_state}}
<img src="{{ bucket_image }}" class="img-responsive center-block" id="bucket_image" />
@@ -7,13 +8,12 @@
{{#with last_sensor_reading}} <strong> {{ temperatureValue }} °C, {{ humidityValue }} % </strong> {{/with}}
</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>
Automatsko zalijevanje:<br /> <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>
{{/with}}
<div>
<button id="water_now" class="{{ water_now_button_class }}">Zalij sada</button>
<button id="stop_water_now" class="{{ stop_button_class }}">Prekini zalijevanje</button>
</div>
</div>
</template>

View File

@@ -46,15 +46,15 @@ Template.state.helpers({
var sensor = last_sensor_reading();
var stateObject = controller_state();
if (sensor) {
if (sensor.tankFull === 0 && stateObject.state.in_valve === 'open' && stateObject.state.out_valve === 'closed') return "/images/barellFillingUp.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"
if (parseInt(sensor.tankFull) === 0 && stateObject.state.in_valve === 'open' && stateObject.state.out_valve === 'closed') return "/images/barrellFillingUp.png";
else if (parseInt(sensor.tankFull) === 1 && (stateObject.state.out_valve === 'closed')) return "/images/barrellFull.png";
else if (parseInt(sensor.tankFull) === 1 && (stateObject.state.out_valve === 'opening')) return "/images/barrellStartWateringFull.png";
else if (parseInt(sensor.tankFull) === 1 && (stateObject.state.out_valve === 'open')) return "/images/barrellWateringFull.png";
else if (parseInt(sensor.tankFull) === 1 && (stateObject.state.out_valve === 'closing')) return "/images/barrellStopWateringFull.png";
else if (parseInt(sensor.tankFull) === 0 && (stateObject.state.out_valve === 'closed')) return "/images/barrellNotFull.png";
else if (parseInt(sensor.tankFull) === 0 && (stateObject.state.out_valve === 'opening')) return "/images/barrellStartWateringNotFull.png";
else if (parseInt(sensor.tankFull) === 0 && (stateObject.state.out_valve === 'open')) return "/images/barrellWateringNotFull.png"
else if (parseInt(sensor.tankFull) === 0 && (stateObject.state.out_valve === 'closing')) return "/images/barrellStopWateringNotFull.png"
else return "/images/statusAmber.png";
} else return "/images/statusRed.png";
},
@@ -80,10 +80,11 @@ Template.state.helpers({
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) {
if (!daysInNumbers || daysInNumbers.length == 0) {
return "Nikad"
}
else if (daysInNumbers.length == 7) {
return "Svaki dan"
} else {
return daysInNumbers.map(function(number) {
return days[number -1 ];
@@ -99,6 +100,8 @@ Template.state.helpers({
}
});
Template.state.events({
'click #water_now': function() {
var controller_id = Session.get('controller_id');

View File

@@ -8,9 +8,33 @@
</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 class="row">
<div class="col-md-12 chart">
<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><strong>Zadnje zaljevanje: {{ last_out_valve_open }}</strong>
</div>
<div><strong>Zadnje punjenje: {{ last_in_valve_open }}</strong>
</div>
</div>
</div>
<div class="row hidden">
<div class="col-md-12 chart">
<h3>Temperatura:</h3>
<div id="temperature_graph">
</div>
</div>
</div>
<div class="row hidden">
<div class="col-md-12 chart">
<h3>Vlažnost:</h3>
<div id="humidity_graph">
</div>
</div>
</div>
</div>
<div class="modal-footer">

View File

@@ -7,8 +7,153 @@ Template.state_details.helpers({
},
last_communication_time: function() {
return moment(this.time).fromNow();
},
last_out_valve_open: function() {
return moment(this.significantEvents.lastOutValveOpen).fromNow();
},
last_in_valve_open: function() {
return moment(this.significantEvents.lastInValveOpen).fromNow();
}
});
Template.state_details.events({
});
Template.state_details.events({});
Template.state_details.rendered = function() {
this.node = this.find('#temperature_graph'); // our d3 code goes here
var yScale = d3.scale.linear()
.domain([0, 4])
.range([10, 60]);
var xScale = d3.scale.linear()
.domain([0, self.duration])
.range([0, $(self.timelineWrapper).width()])
};
function sensor_data_collection() {
var controllerId = Session.get('controller_id');
return SensorData.find({
controllerId: controllerId
}, {
sort: {
created_at: 1
}
});
}
Template.state_details.rendered = function() {
var self = this;
/*
* add point when new temperature is added
*/
setTimeout(function() {
self.autorun(function() {
sensor_data_collection().observe({
added: function(reading) {
// buildTemperatureGraph();
// buildHumidityGraph()
}
});
});
}, 1000);
}
/*
* Function to draw the graph
*/
function buildTemperatureGraph() {
var unfilteredReadings = sensor_data_collection();
// we want to show only 11 points from all data
var breakingPoint = Math.floor(countValues(unfilteredReadings) / 10);
var sensorReadings = filterDataPoints(unfilteredReadings, breakingPoint);
var times = sensorReadings.map(function(reading) {
return moment(reading.created_at).format("HH:mm:ss");
});
var values = sensorReadings.map(function(reading) {
return reading.temperatureValue;
});
var breakingPoint = Math.floor(times.length / 11);
return new Chartist.Line('#temperature_graph', {
labels: times,
series: [values]
}, {
fullWidth: true,
chartPadding: {
right: 40
}
});
}
/*
* Function to draw the graph
*/
function buildHumidityGraph() {
var unfilteredReadings = sensor_data_collection();
// we want to show only 11 points from all data - filtering will add
// the last one so 10 + 1 = 11
var breakingPoint = Math.floor(countValues(unfilteredReadings) / 10);
var sensorReadings = filterDataPoints(unfilteredReadings, breakingPoint);
var times = sensorReadings.map(function(reading) {
return moment(reading.created_at).format("HH:mm:ss");
});
var values = sensorReadings.map(function(reading) {
return reading.humidityValue;
});
return new Chartist.Line('#humidity_graph', {
labels: times,
series: [values]
}, {
fullWidth: true,
chartPadding: {
right: 40
}
});
}
function filterDataPoints(data, breakingPoint) {
if (breakingPoint === 0) {
return data;
}
var result = [];
var index = 0;
var lastUnpushedRow = null;
data.forEach(function(row) {
if (index % breakingPoint === 0) {
result.push(row);
lastUnpushedRow = null;
} else {
lastUnpushedRow = row;
}
index++;
});
// in order to always have the latest value
if(lastUnpushedRow) {
result.push(lastUnpushedRow);
}
return result;
}
// dirty hack for the complicated way of getting
// acual number of values
function countValues(data) {
var count = 0;
data.forEach(function(row) {
count++;
});
return count;
};

9
app/client/weather.html Normal file
View File

@@ -0,0 +1,9 @@
<template name="weather">
<div>&nbsp;</div>
<div class="col-md-12">
<div class="text-center">
{{>simpleWeather}}
</div>
</div>
</template>

38
app/client/weather.js Normal file
View File

@@ -0,0 +1,38 @@
var options = {
location: 44.0123 + ',' + 18.19455, // New Visoko
unit: 'c',
success: function(weather) {
html = "<h2><i class='sw icon-" + weather.code + "'></i>";
html += weather.temp + '&deg;' + weather.units.temp + '</h2>';
html += '<ul><li>' + weather.city + ', ' + weather.region + '</li>';
html += "<li class='currently'>" + weather.currently + '</li>';
html += '<hr />';
for (var i = 0; i < 5; i++) {
var forecast = weather.forecast[i];
html += '<div>';
html += "<h2><i class='sw icon-" + forecast.code + "'></i>";
html += forecast.high + '&deg;' + weather.units.temp + '</h2>';
html += "<li class='currently'> Najniža dnevna: "+ forecast.low + ' &deg; ' + weather.units.temp + "<br />" + daysInBosnian[forecast.day] + ': ' + forecast.text + '</li>';
html += "</div>";
}
$('#weather').html(html);
},
error: function(error) {
$('#weather').html('<p>' + error + '</p>');
}
}
var daysInBosnian = {
'Sun': 'Nedjelja',
'Mon': 'Ponedjeljak',
'Tue': 'Utorak',
'Wed': 'Srijeda',
'Thu': 'Četvrtak',
'Fri': 'Petak',
'Sat': 'Subota'
};
Weather.options = options

Binary file not shown.

Before

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

View File

@@ -24,10 +24,12 @@ 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'));
console.log(nextSensorReading , state);
var shouldStartPumping = (!state.in_valve || state.in_valve === 'closed' || state.in_valve === 'closing') && ((parseInt(nextSensorReading.tankFull) === 0) && (state.out_valve === 'closed' || state.out_valve === 'closing'));
var shouldStopPumping = (state.in_valve === 'open' || state.in_valve === 'opening') && (parseInt(nextSensorReading.tankFull) === 1 || state.out_valve === 'open' || state.out_valve === 'opening');
if (shouldStartPumping) {
ControllerState.update({
@@ -35,14 +37,12 @@ function reactToSensorData(nextSensorReading) {
}, {
'$set': {
'state.in_valve': 'opening',
'significantEvents.lastInValveOpen': new Date(),
'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) {
} else if (shouldStopPumping) {
ControllerState.update({
controller_id: controllerId
}, {
@@ -102,3 +102,6 @@ function stateOrDefault(id) {
});
return stateEntry;
}
Meteor.sharedFunctions = Meteor.sharedFunctions || {};
Meteor.sharedFunctions.reactToSensorData = reactToSensorData;

View File

@@ -21,6 +21,15 @@ function setOutValveTo(controller_id, nextState) {
'set_by': 'server'
}
});
if(nextState === "open") {
ControllerState.update(state._id, {
'$set': {
'significantEvents.lastOutValveOpen': new Date(),
}
});
}
}
function openOutValve(controller_id) {
@@ -40,7 +49,9 @@ function openOutValve(controller_id) {
closeOutValve(controller_id);
}
});
console.log("Finished adding cron ", controller_id);
console.log(Meteor.sharedFunctions);
Meteor.sharedFunctions.reactToSensorData(last_sensor_reading(controller_id));
}
function closeOutValve(controller_id) {
@@ -51,6 +62,10 @@ function closeOutValve(controller_id) {
SyncedCron.remove(jobName);
setOutValveTo(controller_id, 'closing');
console.log("Finished clearing cron ", controller_id);
console.log(Meteor.sharedFunctions);
Meteor.sharedFunctions.reactToSensorData(last_sensor_reading(controller_id));
}
function clearLog() {
@@ -88,6 +103,28 @@ function saveControllerConfig(controller_id, time, days) {
});
}
function last_sensor_reading(controller_id) {
var result = null;
if (controller_id) {
result = SensorData.find({
controllerId: controller_id
}, {
sort: {
created_at: -1
},
limit: 1
});
}
if (result && result.count() > 0) {
return result.fetch()[0];
} else {
return {}
}
}
Meteor.methods({
openOutValve: openOutValve,
closeOutValve: closeOutValve,

View File

@@ -4,27 +4,10 @@ if (Meteor.isServer) {
SyncedCron.start();
});
// Global API configuration
var Api = new Restivus({
useDefaultAuth: true,
prettyJson: true
});
Api.addRoute('sensorData', {
authRequired: false
}, {
post: function() {
SensorData.insert({
temperatureValue: parseFloat(this.bodyParams.temperatureValue),
humidityValue: parseFloat(this.bodyParams.humidityValue),
tankFull: this.bodyParams.tankFull,
owner: this.bodyParams.owner,
created_at: new Date()
});
return [];
}
});
}

View File

@@ -8,7 +8,10 @@ import RPi.GPIO as GPIO
# Try to read the state of GPIO_PIN_TANKFULL
GPIO.setmode(GPIO.BCM)
GPIO.setup(config.GPIO_PIN_TANKFULL, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
tankFull = GPIO.input(config.GPIO_PIN_TANKFULL)
# tank sensor has inverse logic - 0 when it is full 1 when it is not
# so we are inverting its value here
tankFull = (GPIO.input(config.GPIO_PIN_TANKFULL) == GPIO.LOW)
GPIO.cleanup()
print 'Bacva puna: {}'.format(tankFull)
@@ -29,7 +32,7 @@ humidity, temperature = Adafruit_DHT.read_retry(SENSOR_TYPE, config.GPIO_PIN_DHT
# guarantee the timing of calls to read the sensor).
# If this happens try again!
if temperature is not None and humidity is not None:
response = requests.post(config.SENSORDATA_URL, json={"owner": owner, "temperatureValue": temperature, "humidityValue":humidity, "tankFull":tankFull,
response = requests.post(config.SENSORDATA_URL, json={"owner": owner, "temperatureValue": temperature, "humidityValue":humidity, "tankFull": "1" if tankFull else "0",
"controllerId": controller_id
})
print 'Temp={0:0.1f}*C'.format(temperature)

136
misc/calculator.html Normal file
View File

@@ -0,0 +1,136 @@
<html>
<head>
<meta charset="UTF-8">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS" crossorigin="anonymous"></script>
</head>
<body>
<div class="jumbotron">
<div class="lead text-center">
<img src="./zoblak.png" width="30%" />
<br /> Zoblak Agrar Plus se isplati za <span id="vrijemeZaBreakEven" class="bg-success"></span> mjeseci. U periodu od <span id="brojSezona"></span> godine ostvaruje uštedu u novcu od <span id="iznosUstede" class="bg-success"></span> KM, te uštedu u vremenu od <span id="satiUProjekciji" class="bg-success"></span> sati za podešeni slučaj.
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-6">
<p>Na troškove goriva mjesečno trošite <span id="iznosGoriva"></span> KM. Na rad potreban za zalijevanje trošite mjesečno <span id="satiMjesecno"></span> sati što uz zadanu satnicu iznosi <span id="plata"></span> KM. Zajedno to je <span id="ukupnoTroskovaMjesecno"></span> KM troška na zalijevanje. </p>
<p>Okvirna cijena Zoblak Agrar Plus iznosi <span id="bazaCijeneZoblaka"></span> KM + sistem navodnjavanja</p>
<p class="bg-primary">NAPOMENA: finalna cijena može biti niža ili viša i poznata je nakon izrade projekta).</p>
</div>
<div class="col-md-6 col-sm-6">
<form method="post">
<div class="form-group ">
<label class="control-label " for="number">
Vaša udaljenost od polja u km
</label>
<input class="form-control ulazni-parametar" id="pudaljenost" type="number" min="1" max="200" step="0.1" value="5" />
</div>
<div class="form-group ">
<label class="control-label " for="number1">
Prosjecna potro&scaron;nja automobila na 100 km
</label>
<input class="form-control ulazni-parametar" id="ppotrosnja" type="number" min="2" max="15" value="7" step="0.1" />
</div>
<div class="form-group ">
<label class="control-label " for="select">
Koliko često treba zaljevati kulturu?
</label>
<select class="select form-control" id="pfrekvencija_zalijevanja">
<option value="1">
Svaki dan
</option>
<option value="2">
Jednom u dva dana
</option>
<option value="3">
Jednom u tri dana
</option>
<option value="4">
Jednom u četiri dana
</option>
</select>
</div>
<div class="form-group ">
<label class="control-label " for="number2">
Koliko vremena traje put prema polju (u oba smijera) i jedan ciklus zalijevanja? U satima.
</label>
<input class="form-control ulazni-parametar" id="pvrijeme" type="number" min="2" max="10" value="1.5" step="0.5" />
</div>
<div class="form-group ">
<label class="control-label " for="number3">
Satnica osobe koja zalijeva u KM
</label>
<input class="form-control ulazni-parametar" id="psatnica" type="number" min="1" max="100" value="20" step="1" />
</div>
<div class="form-group ">
<label class="control-label " for="number3">
Trajanje sezone u mjesecima
</label>
<input class="form-control ulazni-parametar" id="psezona" type="number" min="1" max="12" value="4" step="1" />
</div>
<div class="form-group ">
<label class="control-label " for="number3">
Na koliko godina/sezona se kalkulacija vrši
</label>
<input class="form-control ulazni-parametar" id="pbroj_sezona" type="number" min="1" max="10" value="3" step="1" />
</div>
</form>
</div>
</div>
</div>
<script type="text/javascript">
function iskalkulisi() {
var udaljenost = parseFloat($('#pudaljenost').val()) || 10;
var potrosnja = parseFloat($('#ppotrosnja').val()) || 7;
var frekvencija = parseInt($('#pfrekvencija_zalijevanja').val()) || 2;
var vrijeme = parseFloat($('#pvrijeme').val()) || 1.5;
var satnica = parseFloat($('#psatnica').val()) || 20;
var sezona = parseInt($('#psezona').val()) || 4;
var brojSezona = parseInt($('#pbroj_sezona').val()) || 3;
var bazaCijeneZoblaka = 1000;
var bazaCijeneVentila = 0;
var bazaCijeneGoriva = 1.70;
var godisnjeOdrzavanjeZoblaka = 200;
// rezultati
var zalijevanjaMjesecno = Math.ceil(30 / frekvencija);
var satiMjesecno = Math.ceil(vrijeme) * zalijevanjaMjesecno;
var plata = satiMjesecno * satnica;
var iznosGoriva = Math.ceil((potrosnja / 100) * bazaCijeneGoriva * (udaljenost * 2) * zalijevanjaMjesecno);
var ukupnoTroskovaMjesecno = iznosGoriva + plata;
var trosakZoblaka = bazaCijeneZoblaka + godisnjeOdrzavanjeZoblaka * (brojSezona - 1);
var satiUProjekciji = satiMjesecno * sezona * brojSezona;
var novcaUProjekciji = ukupnoTroskovaMjesecno * sezona * brojSezona;
var iznosUstede = novcaUProjekciji - trosakZoblaka
var vrijemeZaBreakEven = Math.ceil(bazaCijeneZoblaka / ukupnoTroskovaMjesecno);
$('#vrijemeZaBreakEven').html(vrijemeZaBreakEven);
$('#brojSezona').html(brojSezona);
$('#iznosUstede').html(iznosUstede);
$('#satiUProjekciji').html(satiUProjekciji);
$('#iznosGoriva').html(iznosGoriva);
$('#satiMjesecno').html(satiMjesecno);
$('#plata').html(plata);
$('#ukupnoTroskovaMjesecno').html(ukupnoTroskovaMjesecno);
$('#bazaCijeneZoblaka').html(bazaCijeneZoblaka);
};
$(document).ready(function() {
iskalkulisi();
$(".ulazni-parametar").keyup(iskalkulisi);
$(".ulazni-parametar").change(iskalkulisi);
});
</script>
</body>
</html>

BIN
misc/zoblak.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB