// Global API configuration var Api = new Restivus({ version: 'v1.0', useDefaultAuth: true, prettyJson: true }); Api.addRoute('sensorData', { authRequired: false }, { post: function() { reactToSensorData(this.bodyParams); var sensorObject = { temperatureValue: parseFloat(this.bodyParams.temperatureValue), humidityValue: parseFloat(this.bodyParams.humidityValue), temperatures: this.bodyParams.temperatures, tankLevel0: this.bodyParams.tankLevel0, tankLevel1: this.bodyParams.tankLevel1, tankLevel2: this.bodyParams.tankLevel2, tankLevel3: this.bodyParams.tankLevel3, tankLevel4: this.bodyParams.tankLevel4, tankFull: this.bodyParams.tankFull, startPumpingAt: this.bodyParams.startPumpingAt, stopPumpingAt: this.bodyParams.stopPumpingAt, owner: this.bodyParams.owner, controllerId: this.bodyParams.controllerId, lastBoxContact: new Date(), created_at: new Date() }; SensorData.insert(sensorObject); reactToAlarmData(this.bodyParams.controllerId); return []; } }); Api.addRoute('alarm/:id/phonePing', { authRequired: false }, { post: function() { ControllerState.update({ controller_id: this.urlParams.id }, { '$set': { 'lastPhoneContact': new Date(), } }); var state = stateOrDefault(this.urlParams.id).state; if(state.alarmTriggered) { return { 'alarmTriggered': state.alarmTriggered, 'tooHot': state.alarmReasons.tooHot, 'tooCold': state.alarmReasons.tooCold, 'phoneSilent': state.alarmReasons.phoneSilent, 'boxSilent': state.alarmReasons.boxSilent }; } else { return {}; } } }); reactToSensorData = function(nextSensorReading) { var controllerId = nextSensorReading.controllerId; console.log("reacting to sensor ", nextSensorReading); var stateObject = stateOrDefault(controllerId); var state = stateObject.state; var config = stateObject.config; var startPumpingLevelReached; if (nextSensorReading.startPumpingAt == 'TANKLEVEL0') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel0) === 0) else if (nextSensorReading.startPumpingAt == 'TANKLEVEL1') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel1) === 0) else if (nextSensorReading.startPumpingAt == 'TANKLEVEL2') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel2) === 0) else if (nextSensorReading.startPumpingAt == 'TANKLEVEL3') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel3) === 0) else if (nextSensorReading.startPumpingAt == 'TANKLEVEL4') startPumpingLevelReached = (parseInt(nextSensorReading.tankLevel4) === 0) else startPumpingLevelReached = true; var shouldStartAutomaticPumping = (!state.in_valve || state.in_valve === 'closed') && ((parseInt(nextSensorReading.tankFull) === 0) && startPumpingLevelReached && (state.out_valve === 'closed' || state.out_valve === 'closing')); console.log("State: ", state); var shouldStartPumping = shouldStartAutomaticPumping && config && !config.manualInflow; console.log("shouldStartAutomaticPumping: ", shouldStartAutomaticPumping); console.log("shouldStartPumping: ", shouldStartPumping); if (shouldStartPumping) { ControllerState.update({ controller_id: controllerId }, { '$set': { 'state.in_valve': 'opening', 'time': new Date(), 'set_by': 'server' } }); } var stopPumpingLevelReached; if (nextSensorReading.stopPumpingAt == 'TANKLEVEL0') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel0) === 1) else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL1') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel1) === 1) else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL2') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel2) === 1) else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL3') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel3) === 1) else if (nextSensorReading.stopPumpingAt == 'TANKLEVEL4') stopPumpingLevelReached = (parseInt(nextSensorReading.tankLevel4) === 1) else stopPumpingLevelReached = false; var shouldStopAutomaticPumping = (state.in_valve === 'open' || state.in_valve === 'opening') && (parseInt(nextSensorReading.tankFull) === 1 || stopPumpingLevelReached || state.out_valve === 'open' || state.out_valve === 'opening'); var shouldStopPumping = shouldStopAutomaticPumping && config && !config.manualInflow; console.log("shouldStopPumping: ", shouldStopPumping); if (shouldStopPumping) { ControllerState.update({ controller_id: controllerId }, { '$set': { 'state.in_valve': 'closing', 'time': new Date(), 'set_by': 'server' } }); } } Api.addRoute('state/:id', { authRequired: false }, { post: function() { console.log("setting state", this.bodyParams); return ControllerState.update({ controller_id: this.urlParams.id }, { '$set': { 'state.out_valve': this.bodyParams.out_valve, 'state.in_valve': this.bodyParams.in_valve, 'state.picture_requested': this.bodyParams.picture_requested, 'time': new Date(), 'set_by': 'client' } }); }, get: function() { return stateOrDefault(this.urlParams.id).state; } }); Api.addRoute('picture/:id', { authRequired: false }, { post: function() { console.log("setting picture", this.bodyParams); return Picture.upsert({ controller_id: this.urlParams.id }, { '$set': { 'picture_base64': this.bodyParams.picture_base64, 'time': new Date() } }); } }); function base64_to_buffer(base64string) { var buf; if (typeof Buffer.from === "function") { buf = Buffer.from(base64string, 'base64'); } else { buf = new Buffer(base64string, 'base64'); } return buf; } function stateOrDefault(id) { var stateEntry = ControllerState.findOne({ controller_id: id }); if (stateEntry === undefined) { stateEntry = ControllerState.insert({ controller_id: id, state: { out_valve: 'closed', in_valve: 'closed', alarmTriggered: false, alarmReasons: { tooHot: false, tooCold: false, boxSilent: false, phoneSilent: false } }, time: new Date(), config: { draining_period_amount: 40, draining_period_unit: 'minutes', manualInflow: true }, features: { start: false, weather: false, surveillance: true, log: true, alarm: true }, set_by: 'server' }); }; var stateEntry = ControllerState.findOne({ controller_id: id, }); return stateEntry; }