Devin MuiAaron Huang
Published © MIT

nowo's ark - LTE Version

An inexpensive flood detection system for developing countries.

BeginnerWork in progress24 hours933

Things used in this project

Story

Read more

Custom parts and enclosures

Disk.ipt

Disk.stl

Lid.ipt

Lid.stl

Support.ipt

Support.stl

Clip.ipt

Clip.stl

Schematics

Fritzing

screen_shot_2019-05-26_at_1_13_47_am_oeqs9ktclz_rbtpV1tJJi.png

Code

app.js

JavaScript
var express = require('express')
var mongoose = require('mongoose')
var secrets = require('./secrets.js')

mongoose.Promise = require('bluebird')

var twilio = require('twilio')
var client = new twilio(secrets.accountId, secrets.authToken)

var opt = {
	useNewUrlParser: true,
	useFindAndModify: false
}

mongoose.connect('mongodb://localhost/nowo', opt)
mongoose.set('useCreateIndex', true)

var subscriptionSchema = mongoose.Schema({
	number: String,
	location: {
		longitude: Number,
		latitude: Number,
		address: String
	}
}, {
	timestamps: true
})

var dataSchema = mongoose.Schema({
	location: {
		longitude: Number,
		latitude: Number
	},
	device: {
		type: mongoose.Schema.Types.ObjectId,
		ref: 'Device'
	}
}, {
	timestamps: true
})

var Subscription = mongoose.model('Subscription', subscriptionSchema)
var Device = mongoose.model('Device', deviceSchema)
var Data = mongoose.model('Data', dataSchema)

var app = express()

app.use(express.json())
app.use(express.urlencoded({ extended: false }))

app.post('/subscribe', function(req, res){
	Subscription.findOne({ number: req.body.From }, function(err, subscription){
		if(err) res.json({
			status: 'fail',
			data: err
		})

		// twilio automatically manages the stop/start functionality for us
		if(subscription) {
			client.messages.create({
				body: 'You have already subscribed to the flood detection system. Send STOP if you would like to stop receiving flood alerts.',
				to: req.body.From,
				from: secrets.number
			})
			.then(function(){
				res.json({
					status: 'fail',
					data: 'subscriber already exists!'
				})
			})
		} else { // necessary else statements bc of node's async nature
			new Subscription({
				number: req.body.From
			}).save(function(err){
				client.messages.create({
					body: 'You have subscribed to the flood detection system! Send STOP if you would like to stop receiving flood alerts.',
					to: req.body.From,
					from: secrets.number
				})
				.then(function(){
					res.json({
						status: 'success',
						data: 'subscribed'
					})
				})
			})
		}
	})
})

app.post('/data', function(req, res){
	Subscription.find({}, function(err, subscriptions){
		if(err) res.json({
			status: 'fail',
			data: err
		})

		for(var subscription of subscriptions){
			console.log(subscription)
			client.messages.create({
				body: 'A flood has been detected! Please evacuate quickly! Send STOP if you would like to stop receiving flood alerts.',
				to: subscription.number,
				from: secrets.number
			})
		}

		res.json({
			status: 'success',
			data: 'subscribers notified'
		})
	})
})

app.listen(3000, function(){
	console.log('listening on port 3000')
})

hardware.ino

Arduino
const int buttonPin = 8;
int startMillis;
int currentMillis;
int timer = 3000;
const int ledPin = 9;

void setup() {
  Serial.begin(9600);
  Serial.println("serial started");
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  startMillis = 0;
}

void loop() {
    currentMillis = millis();
    
    if(currentMillis - startMillis > timer){
      if(digitalRead(buttonPin)){
        Serial.println("on");
        startMillis = currentMillis;
        digitalWrite(ledPin, HIGH);
      } else {
        digitalWrite(ledPin, LOW);
      }
    }
}

lte.ino

Arduino
#include "wio_tracker.h"

const int buttonPin = 20;
int startMillis;
int currentMillis;
int timer = 3000;

char message[256] = "A flood has been detected! Please evacuate quickly! Send STOP if you would like to stop receiving flood alerts.";
char number[12] = "number";

WioTracker wio = WioTracker();

void setup() {
  wio.Power_On();
  SerialUSB.println("Power On!");
  SerialUSB.println("Wait for network registered...");

  if(!wio.waitForNetworkRegister())
  {
    SerialUSB.println("Network error!");
    return;
  } else {
    SerialUSB.println("Network ready!");
  }

  pinMode(buttonPin, INPUT);
  startMillis = 0;

}

void loop() {
  currentMillis = millis();
  
  if(currentMillis - startMillis > timer){
    if(digitalRead(buttonPin)){
      startMillis = currentMillis;
      // if button is pressed, send message to number
      if(wio.sendSMS(number, message))
      {
        SerialUSB.println("Send OK!");
      }
      else
      {
        SerialUSB.println("Send Error!");
      }
    }
  }
}

controller.py

Python
import requests
import serial
import traceback

from time import sleep

# establish serial connection with arduino
ser = serial.Serial('/dev/cu.usbmodem141401', 9600)
url = "http://localhost:3000/data"

while True:
	try:
		line = ser.readline()
		if 'on' in line:
			print('flood detected!')
			r = requests.post(url, data={'status': True })
			sleep(3)

	except:
		traceback.print_exc()

GitHub

Credits

Devin Mui

Devin Mui

4 projects • 13 followers
My favorite data structure is a linked list 🐍. What's yours? Undergraduate CS @ University of Southern California 22'
Aaron Huang

Aaron Huang

2 projects • 6 followers
Thanks to .

Comments