Skip to content

Instantly share code, notes, and snippets.

@a-h
Last active November 11, 2018 21:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save a-h/fcb965eface84857658a67b848a2da11 to your computer and use it in GitHub Desktop.
Save a-h/fcb965eface84857658a67b848a2da11 to your computer and use it in GitHub Desktop.
Updated door sensor
#include <WiFiServerSecure.h>
#include <WiFiClientSecure.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WiFiUdp.h>
#include <ESP8266WiFiType.h>
#include <ESP8266WiFiAP.h>
#include <WiFiClient.h>
#include <WiFiServer.h>
#include <ESP8266WiFiScan.h>
#include <ESP8266WiFiGeneric.h>
#include <ESP8266WiFiSTA.h>
#include "RestClient.h"
#include "Debounce.h"
// Uses:
// * https://github.com/wkoch/Debounce
// * https://github.com/esp8266/Arduino/tree/master/doc/esp8266wifi
// * https://github.com/csquared/arduino-restclient
// To install libraries:
// * cd ~/Documents/Arduino/libraries
// * git clone <repo>
// * (For https://github.com/csquared/arduino-restclient, git clone https://github.com/csquared/arduino-restclient RestClient)
const char *ssid = "xxxxxx";
const char *password = "xxxxxxx";
RestClient client = RestClient("xxxxxxx", 443, 1);
const char *eventDoorOpened = "{ \"event\": \"door_opened\" }";
const char *eventDoorClosed = "{ \"event\": \"door_closed\" }";
const int buzzerPin = D0;
const int inPin = D1;
const bool shouldUseBuzzer = true;
const bool shouldSendMessages = true;
void setup()
{
pinMode(buzzerPin, OUTPUT);
pinMode(inPin, INPUT);
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(1000);
Serial.print("Connecting..");
}
Serial.println("Connected...");
}
Debounce doorSwitch(inPin); // the number of the input pin, D1 is set for the ESP8266.
int previousState = -1;
void loop()
{
int newState = doorSwitch.read();
if (previousState == -1) {
// On the first iteration, just set it to the latest value and don't trigger an event.
// This makes the device succeptible to a power outage making it not work.
previousState = newState;
}
if (newState != previousState) {
if (newState == HIGH) {
Serial.println("Door was closed");
if (shouldUseBuzzer) {
Serial.print("Buzzing closed...");
buzzClosed();
}
if (shouldSendMessages) {
postSecure(eventDoorClosed);
}
} else {
Serial.println("Door was opened");
if (shouldUseBuzzer) {
Serial.print("Buzzing open...");
buzzOpened();
}
if (shouldSendMessages) {
postSecure(eventDoorOpened);
}
}
}
previousState = newState;
}
void postSecure(const char *event)
{
String response = "";
Serial.println("Posting...");
int statusCode = client.post("/dev/sensor/detect", event, &response);
Serial.println("Results (status / response)...");
Serial.println(statusCode);
Serial.println(response);
}
void buzz(int pin, int frequency, int duration) {
analogWriteFreq(frequency);
analogWrite(pin, 1000);
delay(duration);
analogWrite(pin, 0);
}
void buzzOpened() {
buzz(buzzerPin, 250, 450);
buzz(buzzerPin, 500, 350);
buzz(buzzerPin, 750, 350);
}
void buzzClosed() {
buzz(buzzerPin, 750, 450);
buzz(buzzerPin, 500, 350);
buzz(buzzerPin, 250, 350);
}
'use strict';
var AWS = require('aws-sdk');
var moment = require("moment");
var nunjucks = require("nunjucks");
module.exports.detect = detect;
module.exports.display = display;
const tableName = "doorTable";
function display(event, context, callback) {
const dynamodb = new AWS.DynamoDB();
const qs = event.queryStringParameters || {};
let day = qs.day || moment().format('YYYY-MM-DD');
var params = {
ExpressionAttributeValues: {
":v1": { S: day }
},
KeyConditionExpression: "#id = :v1",
TableName: tableName,
ExpressionAttributeNames: {
"#id": "day"
}
};
dynamodb.query(params).promise()
.catch(function (err) {
console.log({ err, msg: "error querying database records" });
callback(err, null);
return;
})
.then(function (data) {
nunjucks.configure('templates', { autoescape: true });
const view = nunjucks.render('index.html', {
day,
data: JSON.stringify(data.Items)
});
callback(null, {
statusCode: 200,
headers: {
"Content-Type": "text/html",
},
body: view,
});
})
.catch(function (err) {
console.log({ err, msg: "error rendering templates" });
callback(err, null);
});
}
const response = {
statusCode: 200,
body: JSON.stringify({ ok: true }),
};
function detect(event, context, callback) {
console.log(event.body);
var e = JSON.parse(event.body);
console.log({ "msg": "writing to dynamodb" });
var dynamodb = new AWS.DynamoDB();
dynamodb.putItem(
{
"TableName": tableName,
"Item": {
"day": { "S": moment().format('YYYY-MM-DD') },
"time": { "S": moment().format() },
"week": { "S": moment().format('YYYY w') },
"year": { "S": moment().format('YYYY') },
"event": { "S": e.event },
}
}).promise()
.then(function (result) {
console.log({ recordsWritten: 1 });
})
.catch(function (err) {
console.log({ err, msg: "error writing database records" });
})
.then(function () {
callback(null, response)
});
}
<html>
<head>
<title>Door data</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.bundle.js" type="text/javascript"></script>
<style type="text/css">
body {
font-family: sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript">
var data = {{data|safe}};
</script>
<h1>{{day}}</h1>
<div style="max-width:800px; max-height:400px">
<canvas id="myChart" width="800" height="400"></canvas>
</div>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var xy = data.map(function(item) {
return {
x: item.time.S,
y: item.event.S == "door_opened" ? 1 : 0,
};
})
var x = new Chart(document.getElementById("myChart"), {
type: 'scatter',
data: {
datasets: [{
label: "Door",
data: xy,
}]
},
options: {
scales: {
xAxes: [{
type: 'time',
}],
},
},
});
</script>
</body>
</html>
service: alarm-web
provider:
name: aws
runtime: nodejs6.10
stage: dev
region: eu-west-1
iamRoleStatements:
- Effect: "Allow"
Action:
- "dynamodb:PutItem"
- "dynamodb:GetItem"
- "dynamodb:Query"
Resource: "arn:aws:dynamodb:eu-west-1:*:table/doorTable"
functions:
detect:
handler: handler.detect
events:
- http:
path: sensor/detect
method: post
display:
handler: handler.display
events:
- http:
path: /
method: get
package:
include:
- templates/**
resources:
Resources:
doorTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: doorTable
AttributeDefinitions:
- AttributeName: day
AttributeType: S
- AttributeName: time
AttributeType: S
KeySchema:
- AttributeName: day
KeyType: HASH
- AttributeName: time
KeyType: RANGE
ProvisionedThroughput:
ReadCapacityUnits: 2
WriteCapacityUnits: 2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment