Devin MuiAaron Huang
Published © MIT

nowo's ark - LTE Version

An inexpensive flood detection system for developing countries.

EasyWork in progress24 hours97

Things used in this project

Hardware components

ELEGOO UNO R3 Board ATmega328P ATMEGA16U2 with USB Cable
ELEGOO UNO R3 Board ATmega328P ATMEGA16U2 with USB Cable
×1
ELEGOO UNO R3 Project Complete Starter Kit
ELEGOO UNO R3 Project Complete Starter Kit
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
LED (generic)
LED (generic)
×1
Resistor 100 ohm
Resistor 100 ohm
×1
Breadboard (generic)
Breadboard (generic)
×1
PVC Pipe
×1
SORACOM Air Global IoT SIM
SORACOM Air Global IoT SIM
×1
Wio LTE US Version - 4G, Cat.1, GNSS, JavaScript(Espruino) Compatible
Seeed Wio LTE US Version - 4G, Cat.1, GNSS, JavaScript(Espruino) Compatible
×1

Software apps and online services

AWS EC2
Amazon Web Services AWS EC2

Hand tools and fabrication machines

3D Printer (generic)
3D Printer (generic)
Handsaw

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

3 projects • 5 followers
Wrote code instead of going to prom. From SF.
Aaron Huang

Aaron Huang

2 projects • 0 followers
Thanks to .

Comments

Add projectSign up / Login