GithubHelp home page GithubHelp logo

sompasauna / sompis-esp8266-sensor-fw Goto Github PK

View Code? Open in Web Editor NEW
0.0 2.0 1.0 45 KB

Firmware for ESP8266 based sensors

License: Creative Commons Attribution Share Alike 4.0 International

C 10.41% C++ 89.59%
esp8266 iot sauna-control sauna

sompis-esp8266-sensor-fw's Introduction

sompis-esp8266-sensor-fw

Firmware for the ESP8266 based temperature sensors for Sompasauna.

TLDR

  • ESP8266
  • DS18B20
  • AES-128-CBC + CRC16 plain text ascii protocol over UDP or TCP.
  • No MQTT

Usage

It's a platformio project, you can probably load it into it.

The API

The server side Ruby UDP/TCP API is at somppasauna/sompis-sensor-api.

Device

  • Esp8266-12E/F/.. chip
  • Possibly a breakout board
  • A bunch of resistors
  • A capacitor
  • Maybe a regulator?
  • Some way to feed it power!
  • A DS18B20 temperature sensor
  • A jump cable from GPIO16 to RST so it can wake up from deep sleep using a timer
  • A voltage divider between battery, ESP8266 ADC analog input and GND to measure battery charge level

Logic

  • Wake up with the wifi disabled
  • Read some bytes from the tiny real-time clock memory that survives deep sleeps so some values can be persisted between boots
  • Tell the sensor to start the temperature measuring, according to documentation, this takes 188ms. Some other stuff can be done while it's measuring in the background.
  • While it's working, do some preparations for connecting to the Wifi
  • Once the measurement is there, compare it to the previously reported value. If the temperature delta is less than 0.5c, don't bother reporting at all and just go to sleep.
  • If the temperature delta is over 0.5c, see if the device can connect to the primary wifi.
  • If the connection is succesfull, store the BSSID and wifi channel to use on the subsequent boots, it's a whole lot faster to connect when you set the channel and BSSID. A static IP is also used on the primary wifi.
  • If primary wifi won't connect, go to sleep. Unless it has failed 3 times already, then it's time to try the secondary wifi ap. And it that doesn't work, the tertiary. And so on.
  • At this point, some wifi should be connected or the device is sleeping. Let's go on.
  • Construct and encode a message using the ASCII line protocol
  • AES-128-CBC encrypt the message (it's like 15 bytes, shouldn't take a lot of cpu time)
  • Send it over UDP to a server listening on a fixed ip address (dns resolution takes time)
  • The server sends a response
  • AES-128 decrypt the response
  • The response usually just contains SLEEP xx, which orders the device to go to sleep for X seconds. This can be useful when there are multiple devices, they can be synced to report at the same time, so the mobile hotspot doesn't have to communicate all the time. This should save some battery. This can also be used to adjust the reporting rate in case it seems to drain too much battery or is happening too frequently / infrequently.
  • The response can also include an URL to a firmware upgrade in the form of FW http://firmware.url.example.com/fwxyz.bin, and the device will then update itself over HTTP.
  • The response for other type of devices could also include something like TOGGLE X where X could for example be a led / indicator / something. Or DISPLAY message if there was a message display somewhere.
  • If the device detects that the battery charge is getting low, it will go into power save mode where measurements are only reported if temperature delta is over 5 celsius.

MQTT, HTTP or other "popular" ways to publish / receive IoT data has not been used. The early versions used a Protocol Buffers based serialization, but with the encryption having 16 byte block size, it didn't make any traffic savings and was complicated to use.

MQTT has some drawbacks, such as generating about 6 kilobytes of traffic just to post one value. If any sort of response is expected, the device would have to subscribe to a message queue and wait a few seconds for a response. For HTTP, the headers alone are quite lenghty. Of course HTTPS and MQTTS should be used which adds even more. The ESP8266 WiFi and mobile data are both a bit slow and also the mobile hotspot is using a prepaid plan which has billing by the megabyte.

The protocol

  • The message is built as plain text: field_name:value|field_name2:value2. The "required" field name is D, which is the device id.
  • A CRC16 (xmodem) checksum is added to end of the message as 4 hex characters: D:1|t:23.25|b:3.823cf7g
  • A random initialization vector of 16 bytes is generated and used to AES-128-CBC encrypt the message.
  • The IV and the encrypted payload are concatenated and sent over UDP (or TCP if UDP fails on the WiFi currently in use) to the server
  • The server response has the same encryption scheme, but the syntax is something like ACTION value.

Contributing

Issues and PR's welcome. You're also welcome to Sompasauna, you can see the device in action while enjoying the sauna. For free. Around the clock. Every day.

License

License: CC BY-SA 4.0 Creative Commons Attribution-ShareAlike 4.0 International

sompis-esp8266-sensor-fw's People

Watchers

 avatar  avatar

Forkers

juhi24

sompis-esp8266-sensor-fw's Issues

The AES encryption is wrong (and wasteful)

The initialization vector should be random for each message.

This requires that the IV should be generated and embedded into every message (XOR or concat).

If concatenated, the minimum message size is 32 bytes. If xorred, 16 bytes.

A typical unencrypted server response message is 2 bytes, so the block cipher increases traffic by 8 - 16x. It's still quite small, so perhaps not a dealbreaker.

Need two messages to report two sensors

Because the protobuf definition uses the OneOf for sensor values, it's not possible to send multiple sensor readings in single message.

I assume a typical device with multiple sensors, such as the current temperature sensor, which can also report the battery level will operate like wake up -> read sensors -> report data -> go to sleep, so it would make sense to be able to send multiple readings in a single network transmission.

If you want to write multiple messages to a single file or stream, it is up to you to keep track of where one message ends and the next begins. The Protocol Buffer wire format is not self-delimiting, so protocol buffer parsers cannot determine where a message ends on their own.
The easiest way to solve this problem is to write the size of each message before you write the message itself. When you read the messages back in, you read the size, then read the bytes into a separate buffer, then parse from that buffer.

Sounds reasonable and does not require altering the protocol definition.

Calculated CRC does not seem to include leading zero

api_1       | D, [2019-04-04T07:07:00.076802 #1] DEBUG -- PARSER: Plain text: D:3|b:4.163|B:659|W:0|t:25.25|V:v6|R:31380
api_1       | D, [2019-04-04T07:07:00.076926 #1] DEBUG -- PARSER: Received CRC: 380 calculated CRC: 0380

Wifi ap cycling broken

The rtc.use_wifi_ap_idx will go too far because it's using sizeof(wifiaplist) which does not actually return the number of elements but the actual bytesize of the array.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.