No description, website, or topics provided.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
device
server
.gitignore
README.md

README.md

IoT Door Signs

Last updated June 30, 2017

Abstract

This is a project using an NodeMCU ESP8266, a Waveshare 4.3inch e-Paper display, and optionally a PCB from electronictrik to create an Internet of Things door sign. This variation uses MicroPython on the ESP8266, Flask on a Raspberry PI, and the Google Calendar API.

Bill of Materials

Here's what I used:

WARNING: The way the plug for the battery is drawn on the PCB led to some confusion. When running from battery power the first time, we fried our charger and ESP8266 beyond repair. Check for continuity before powering with a battery: the battery positive should be going to ‘B+’ on the charger and the battery negative should be going to ‘B-’.

File List

display_project
  README.md
  - device
    display.py
    display_deep_sleep.py
    eink.py    (from dhallgb)
    secret.py    (you make this)
  - server
    + env
    app.py
    client_secret.json    (from Google)
    helpers.py
    requirements.txt
    rooms.py    (you make this)

Getting MicroPython on the ESP8266

First you'll want to download a few things:

The device side of things has a few dependencies:

  • pip: Python package management
  • esptool: For flashing the ESP firmware
  • ampy: For managing files on the ESP

To determine the path to your ESP8266, start with it unplugged and run this in your terminal:

ls /dev

Now plug in your ESP8266 and run the ls /dev command again. You should see something new - for me the path to my ESP8266 is /dev/tty.SLAB_USBtoUART. Now let's flash the firmware (you'll need to replace the path to your device and the path to the firmware):

pip install esptool
esptool.py --port /dev/tty.SLAB_USBtoUART erase_flash
esptool.py --port /dev/tty.SLAB_USBtoUART --baud 115200 write_flash --flash_size=detect 0 esp8266-20170526-v1.9.bin

If you run into any issues, you may need to adjust the baud rate and make sure you're getting enough power to the ESP8266 (I had to use a powered USB hub for this). If you're still having issues, try these steps:

  • Start with the ESP8266 unpowered
  • Hold down the FLASH button
  • While holding down the button, plug in the ESP8266
  • While continuing to hold the button down, run the above esptool.py commands
  • When esptool.py connects, release the button

Now's a good time to create a secret.py file for your ESP8266:

# secret.py
WIFI_SSID = '<YOUR WIFI NETWORK>'
WIFI_PASS = '<YOUR WIFI PASSWORD>'
SERVER_ADDRESS = '<THE FLASK SERVER>'

Getting Python Files to the ESP8266

Now we're going to get the files on the ESP using ampy. The files we need are:

  • display.py or display_deep_sleep.py: this is my custom script for displaying room information
  • eink.py: this is the e-ink library by dhallgb
  • secret.py: this is the file you created above

The display.py file will be renamed main.py so that it gets run after booting:

pip install adafruit-ampy
ampy --port /dev/tty.SLAB_USBtoUART put display.py /main.py
ampy --port /dev/tty.SLAB_USBtoUART put eink.py
ampy --port /dev/tty.SLAB_USBtoUART put secret.py

When we restart the ESP, it will run /main.py and begin checking in with the Flask server. Realize that display.py will need to be modified according to your needs (same with the Flask server).

If you need to troubleshoot at this point, you may want to try booting with dhallgb's demo.py file:

ampy --port /dev/tty.SLAB_USBtoUART put demo.py /main.py

When you boot, you should see some fun displays. The demo is a good place to start to see how the e-Ink library works.

WARNING: Originally I was flashing display.py to /boot.py. I've found that it's best to leave /boot.py alone and use /main.py instead.

Setting Up the Flask Server

I'm not going to get too bogged down in documenting Google's API - their API is already well documented. Here are some resources to lead the way though:

The second link will walk you through getting your client_secret.json. Then you'll need a room directory so the Flask server can translate room names to calendarIds:

# rooms.py
rooms = {
  'moss': '<GOOGLE CALENDARID>',
}

With the Google stuff and a directory of rooms, we should be all set to start the Flask server. We're going to do this in a virtual environment per Flask's suggestion:

virtualenv env
source env/bin/activate
pip install -r requirements.txt
python app.py

The first time you do this, you'll be asked to login to your Google account via a browser popup. Google's code in helpers.py will save the credentials so that you won't be asked again in the future.

It's recommended that you don't rely on the Flask development server in production. For my prototyping needs it worked (mostly) fine, but a live launch will probably need something like Gunicorn and Nginx.

Some Code to Change

My code probably isn't going to work for you unless you have a room named Moss. Besides making secret.py, rooms.py, and getting client_secret.json, you'll probably want to change a few things:

# Timezones may need to be updated

# helpers.py
now = datetime.datetime.now(pytz.timezone("US/Pacific")).isoformat()
# app.py
res['todays_date'] = datetime.datetime.now(pytz.timezone("US/Pacific")).strftime('%-m/%-d')
# Each ESP8266 will need to be assigned a room name

# display.py
ROOM_NAME = 'moss'

Wrap Up

The ESP8266 reaches out to the Flask server via something like GET http://192.168.1.1/moss, the Flask server takes the parameter and converts it to the Google CalendarId, a request for the next three events of the day for that room is made with the Google Calendar Resource API, the Flask server formats the response before handing a small JSON file to the ESP8266, and then the ESP8266 displays the data.

The battery life isn't ideal, which is why I'm working on display_deep_sleep.py to put the ESP8266 into deep sleep in between API calls.

Hopefully this gives some pointers to anyone trying to work with an ESP8266 and E Ink display in MicroPython. Feel free to dig through the source code; I went through and commented everything so it should be pretty accessible.

Thanks for looking!