Attention notifier based on ESP2866 WiFi module

Attention notifier based on ESP2866 WiFi module
19/05/2019 Ernestas Konopliovas
In Arduino

Once, my girlfriend sent me this Twitter post:

…and I accepted the challenge.
However, I understood that creating an app will not be an universal solution, because she uses iPhone and as soon as I do not have an Apple Developer License (that means my app will not last on her phone longer than 48 hours), I decided to create a website, that will be available on all devices, all versions and mainly, all around the world. Here is what it turned into.

Short description

For hardware part, I have chosen Wemos D1 R2 WiFi board because it already had an integrated ESP2866 module in it.

For software, I decided to use Python web server as soon as it works with Web Sockets, and to use some simple html and js for a tiny website.

For the visible part of the process, I bought a box/lamp with replaceable letters.

The best idea to make it online was to connect it to the cloud. So this mini-server is deployed at Heroku cloud service, connected to my home WiFi and can be reached from any device with the internet connection. Last but not least, it was a perfect gift for my girlfriend 🙂

How it looks like inside
Demonstration
Code, I used

Python web server:

from flask import Flask, request, render_template
from flask_sockets import Sockets
import gevent
import time
import json

'''
Setting up the webserver
'''
app = Flask(__name__)
app.debug = True

'''
Setting up the websocket
'''
sockets = Sockets(app)

'''
Multiple clients handling
'''
clients = list()

'''
Client object
'''

class Client:
def __init__(self):
self.queue = gevent.queue.Queue()
def put(self, v):
self.queue.put_nowait(v)
def get(self):
return self.queue.get()
'''
User-defined function for sending data on the websocket to all clients
'''

def send_all(msg):
for client in clients:
client.put(msg)

'''
Reading from websocket
'''

def read_ws(ws, client):
while not ws.closed:
gevent.sleep(0)
try:
msg = ws.receive()
print "WS RECEIVED: %s" % msg
if(msg is None):
client.put(msg)
else:
send_all(msg)
except:
print "WS ERROR: read_ws exception"

'''
Adding a route to the websockets server to "subscribe" clients
'''
@sockets.route('/subscribe')
def subscribe_socket(ws):
client = Client()
clients.append(client)
print '# Clients: {}'.format(len(clients))
g = gevent.spawn( read_ws, ws, client)
# If data is received by the queue, send it to the websocket
try:
while g:
msg = client.get()
if msg is not None:
ws.send(msg)
else:
break
except Exception as e:
print "WS ERROR: %s" % e
finally:
ws.close()
clients.remove(client)
gevent.kill(g)

'''
Adding a route to the webserver
'''
@app.route('/')
def index():
return render_template("index.html") # rendering index.html in 'templates' dir

Arduino code:


#include <ESP8266WiFi.h>
#include <WebSocketsClient.h>
#include <Servo.h>

//Declaring servo
Servo servo;

// Connecting to the internet
char * ssid = "Your wifi SSID";
char * password = "Your wifi password";
int servo_position = 0;

// Setting up the websocket client
WebSocketsClient webSocket;

void setup() {

pinMode(BUILTIN_LED, OUTPUT);
servo.attach(D6);
Serial.begin(115200);
// WiFi.mode(WIFI_STA); //use this option, if you are connecting to personal hotspot
WiFi.begin(ssid, password);
Serial.println("");
while(WiFi.status()!=WL_CONNECTED) {
Serial.print(".");
delay(500);
}
blinkTheLed(2);
servo.write(servo_position);

Serial.println("");
Serial.println("Connected to WiFi.");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());

// webSocket.begin("172.20.10.12", 8000, "/subscribe"); //webSocket for local testing

webSocket.begin("Your Heroku cloud app name.herokuapp.com", 80, "/subscribe");
webSocket.onEvent(webSocketEvent);
webSocket.setReconnectInterval(10);

}

void loop() {
webSocket.loop();
}

void webSocketEvent(WStype_t type, uint8_t *payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
Serial.printf("Socket disconnected!n");
break;
case WStype_CONNECTED:
Serial.printf("Socket connected to url: %sn", payload);
servo.detach();
break;
case WStype_TEXT:
if((char)payload[0] == '1'){
Serial.println("Received button push!");
webSocket.sendTXT("done");
notify();
}
else if((char)payload[0] == '3'){
Serial.println("New connection!");
webSocket.sendTXT("connected");
}

break;
}
}

void blinkTheLed(int howManyTimes){
for(int i = 0; i < howManyTimes; i++){
digitalWrite(BUILTIN_LED, HIGH);
delay(150);
digitalWrite(BUILTIN_LED, LOW);
delay(150);
}
}

//Method that is called when notification arrives
void notify(){
int a = 320; //blinking start interval

for(int i = 0; i < 15; i++){
digitalWrite(BUILTIN_LED, HIGH);
delay(a);
digitalWrite(BUILTIN_LED, LOW);
delay(a);
a = a - 18;
}

digitalWrite(BUILTIN_LED, HIGH);
wave(3);
delay(6000);
digitalWrite(BUILTIN_LED, LOW);
}

//Method that is used to simulate heart waving with servo
void wave(int howManyTimes){
servo.attach(D6);

for(int i = 0; i < howManyTimes; i++){
for (servo_position = 0; servo_position <=165; servo_position +=1){
servo.write(servo_position);
delay(3);

}

for (servo_position=165; servo_position >= 0; servo_position -=1){
servo.write(servo_position);
delay(3);
}
}
servo.detach(); //important to use this line. Otherwise servo motor will make noise after certain time.
}

Comments (2)

  1. I love anything and everything that is written well… yeah you got some good content going on there for sure.

  2. Oliva 1 month ago

    Normally I don’t learn post on blogs, however I would
    like to say that this write-up very compelled me to check
    out and do so! Your writing taste has been surprised me.
    Thank you, very nice post.

Leave a reply

Your email address will not be published. Required fields are marked *

*