Compare commits
12 Commits
add_schedu
...
in_valve_s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d15bc0e5a6 | ||
|
|
ee828c544e | ||
|
|
28e5f7f1f0 | ||
|
|
ed8267b6ab | ||
|
|
99fdc768fc | ||
|
|
c47e1be364 | ||
|
|
8d9e42c147 | ||
|
|
279e0f8652 | ||
| 2395cc6ddf | |||
|
|
357acd6f91 | ||
|
|
6ea9933d60 | ||
| 7984783cdf |
3
.gitignore
vendored
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]
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ standard-minifiers # JS/CSS minifiers run for production mode
|
|||||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||||
|
|
||||||
autopublish # Publish all data to the clients (for prototyping)
|
|
||||||
insecure # Allow all DB writes from clients (for prototyping)
|
|
||||||
less
|
less
|
||||||
huttonr:bootstrap3
|
huttonr:bootstrap3
|
||||||
nimble:restivus
|
nimble:restivus
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
accounts-base@1.2.2
|
accounts-base@1.2.2
|
||||||
accounts-password@1.1.4
|
accounts-password@1.1.4
|
||||||
amplify@1.0.0
|
amplify@1.0.0
|
||||||
autopublish@1.0.4
|
|
||||||
autoupdate@1.2.4
|
autoupdate@1.2.4
|
||||||
babel-compiler@5.8.24_1
|
babel-compiler@5.8.24_1
|
||||||
babel-runtime@0.1.4
|
babel-runtime@0.1.4
|
||||||
@@ -38,7 +37,6 @@ http@1.1.1
|
|||||||
huttonr:bootstrap3@3.3.6_6
|
huttonr:bootstrap3@3.3.6_6
|
||||||
huttonr:bootstrap3-assets@3.3.6_2
|
huttonr:bootstrap3-assets@3.3.6_2
|
||||||
id-map@1.0.4
|
id-map@1.0.4
|
||||||
insecure@1.0.4
|
|
||||||
jquery@1.11.4
|
jquery@1.11.4
|
||||||
json@1.0.3
|
json@1.0.3
|
||||||
launch-screen@1.0.4
|
launch-screen@1.0.4
|
||||||
|
|||||||
@@ -9,5 +9,5 @@
|
|||||||
|
|
||||||
|
|
||||||
#bucket_image {
|
#bucket_image {
|
||||||
width: 30%;
|
width: 60%;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ function sensor_data_collection() {
|
|||||||
}, {
|
}, {
|
||||||
sort: {
|
sort: {
|
||||||
created_at: -1
|
created_at: -1
|
||||||
}
|
},
|
||||||
|
limit: 100
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
8
app/client/startup.js
Normal file
8
app/client/startup.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Tracker.autorun(function () {
|
||||||
|
var id = Session.get('controller_id');
|
||||||
|
if (id) {
|
||||||
|
Meteor.subscribe("sensor_data", id);
|
||||||
|
var hamo = Meteor.subscribe("controller_state", id);
|
||||||
|
console.log(hamo);
|
||||||
|
}
|
||||||
|
});
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
<div>Otpusni ventil: {{pretty_valve state.out_valve }}</div>
|
<div>Otpusni ventil: {{pretty_valve state.out_valve }}</div>
|
||||||
|
<div>Ulazni ventil/pumpa: {{pretty_valve state.in_valve }}</div>
|
||||||
<div>Zadnja komunikacija: {{ last_communication_time }}</div>
|
<div>Zadnja komunikacija: {{ last_communication_time }}</div>
|
||||||
{{/with}}
|
{{/with}}
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -1,12 +1,6 @@
|
|||||||
function controller_state() {
|
function controller_state() {
|
||||||
var controller = Session.get('controller_id');
|
var controllerId = Session.get('controller_id');
|
||||||
var result = {}
|
result = ControllerState.findOne({});
|
||||||
if (controller) {
|
|
||||||
result = ControllerState.findOne({
|
|
||||||
controller_id: controller
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
result = {}
|
result = {}
|
||||||
};
|
};
|
||||||
@@ -20,7 +14,8 @@ function sensor_data_collection() {
|
|||||||
}, {
|
}, {
|
||||||
sort: {
|
sort: {
|
||||||
created_at: -1
|
created_at: -1
|
||||||
}
|
},
|
||||||
|
limit: 1
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 = (parseInt(nextSensorReading.tankFull) === 0 && (!state.in_valve || state.in_valve === 'closed'));
|
||||||
|
|
||||||
|
if (shouldStartPumping) {
|
||||||
|
ControllerState.update({
|
||||||
|
controller_id: controllerId
|
||||||
|
}, {
|
||||||
|
'$set': {
|
||||||
|
'state.in_valve': 'opening',
|
||||||
|
'time': new Date(),
|
||||||
|
'set_by': 'server'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var shouldStopPumping = parseInt(nextSensorReading.tankFull) === 1 && (state.in_valve === 'open' || state.in_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: 5,
|
||||||
draining_period_unit: 'minutes'
|
draining_period_unit: 'minutes'
|
||||||
|
|
||||||
},
|
},
|
||||||
set_by: 'server'
|
set_by: 'server'
|
||||||
});
|
});
|
||||||
|
|||||||
18
app/server/publications.js
Normal file
18
app/server/publications.js
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// This code only runs on the server
|
||||||
|
Meteor.publish("sensor_data", function(controllerId) {
|
||||||
|
return SensorData.find({
|
||||||
|
controllerId: controllerId
|
||||||
|
}, {
|
||||||
|
sort: {
|
||||||
|
created_at: -1
|
||||||
|
},
|
||||||
|
limit: 100
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// This code only runs on the server
|
||||||
|
Meteor.publish("controller_state", function(controllerId) {
|
||||||
|
return ControllerState.find({
|
||||||
|
controller_id: controllerId
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user