Skip to main content

Green, green grass of /home


We were somewhat taken aback by the public backlash we faced after the publication of our last post, Have-ocado.  No, people weren't overly offended by the highly preposterous manner in which 2 × ESP32 microcontrollers were bound together in holy matrimony using EEPROMs.  Nor were they aghast by repeated and unnecessary references to 90 Day FiancĂ©, the paragon of inadvertent brainless TV viewing.

In fact, to the small subsection of society for whom avocados symbolise the sanctity of human life and existential purpose, the thought of even one being deliberately set alight caused moral outrage.  And for that, we would like to take this opportunity to sincerely apologise.  Furthermore, if you are that non-existent complainant, we also recommend that you abandon this post at this very juncture. Because what follows below, is likely to make you question the entire future of humanity.

For those electing to read on, the context surrounding the experiment was this:

Of course, we were indeed cobbling together a highly available temperature sensor using a pair of ESP32 microcontrollers... because we were dead serious about ripening our avocados from Ocado for a number of days more, at room temperature - and have the readings open in Excel to prove it.   In fact, we built a "cluster" which could supposedly withstand a single ESP32 or battery supply failure.  Through sickness and health, these soulmates for life dispatched temperature readings to AWS IoT Core, which in turn were stored in a DynamoDB table using the Rules Engine, and lastly, notified us of gossip of zero social value using Lambda and Simple Email Service.

Yes, that's right.  It all - rather anticlimactically - culminated in snail mail.

But, what about the fire?  We don't hear you ask.  Unsatisfied with the aesthetics, an avocado was grotesquely surrounded by flammables and amateurishly set on fire (it turns out, avocados are possibly the least combustible fruit in our biosphere).  The wider point being; resiliency of your guacamole supply chain needs to be considered in all aspects of the solution.

Please don't forget to implement high availability of the avocados themselves by deploying a hot swappable spare.

If you have been following this (multi-)perplexing logic so far, you are doing rather quite well. Because - honestly - this trail of thought is turning a little too eccentric, even by our standards.

Well. Hold. On. Tight.

...Because we're about to prod this IoT blog series along on to the next level of madness.  We have taken note of the results from the highly accurate polling of our site's readership (with a sample size of 1 person, give or take 1).  The people person have has has their definitive say on the matter.  We must enact the will of the people and accept that even a single green, ginormous berry-carrying fruit on fire is one too many.  And accordingly, we will interpret this outcome in a way that conveniently suits our ideology, as an overwhelming mandate to make further enhancements to our system to counter this highly improbable situation.

What's more, it's an unmissable opportunity to tinker with another "green" thingummy (this variant from AWS) to help war-game this avocalyptic scenario that is so unspeakable, not even our politicians have formulated advice on.

En-list 'em all:

Yes, we're back to rummaging through our messy electronics drawer for brand new sensors to tinker with.
  • We'll be using a single ESP32 to prove our point.  It's cheap (so we won't lose too much sleep if the silicone catches fire and emits a strange smell).  Also, it's powerful (enough) for our needs.  And it can run MicroPython, the favourite tool of the trade for people who find C or C++ to be an alphabet soup.
  • ...So why would we need a Raspberry Pi?  Aren't we just sending sensor readings directly back to AWS IoT Core, like we were doing before? Absolutely, we could.  But it transpires that monitoring whether avocados spontaneously combust or not is an issue of significant national importance.  And for that reason, we'll be using AWS Greengrass running on a Raspberry Pi to bring some of those Cloud-based AWS IoT capabilities back down towards the peaty soil, closer to our avocados.  "Stretch" is the officially supported version of the RaspbianOS operating system for running AWS Greengrass Core.  We better stick to that then if we don't want bad things to happen.
  • Now... let's get acquainted with a few new gizmos.  We have on hand a cheap and cheerful flame detector, in a handy module format.  And - quite likely - an even cheaper active piezo buzzer.  These two widgets will be used to complete our highly unsophisticated monitoring system.
  • We also have a temperature sensor, but you probably guessed that much.

A brief history of thyme:

This is very much a follow-up to our previous instalments in the I-O-Tea series - Frozen Pi. And - obviously - Have-ocado.

Going back further, we were introduced to these microprocessors back in Raspberry Bye, Hello. We even hacked a Gro-Egg display using one for no reason whatsoever (as we keep proudly reminding you).

Eat your greens:

Unlike certain important bodies and institutions underpinning our lives - say the Parliament - we have a plan.  And the only things we need to squabble with, are our avocados (they would quite like to have a say on their future too).
  • Attach the temperature sensor and flame detector to the ESP32.  Let's run a couple of tests in MicroPython to see if we can detect rather high temperatures and... well... flames.
  • Carefully read the available documentation on Greengrass.  There. Is. A. Lot. Once we think we know what goes where (and why), we'll install it on a spare Rapsberry Pi we happen to have lying around the house.
  • We'll attach the active buzzer to the Raspberry Pi.  Can we make it make annoying buzzing sounds through Python?  Good.
  • We bring it all together.  And by that, we mean get the ESP32 to talk to our local Greengrass Core device, and for the Greengrass Core device to talk to AWS IoT Core.  We'll then - using a local Lambda function - get Greengrass Core to alert us locally of a flame being detected, while sensor readings can continue to flow over the Internet to DynamoDB via IoT Core.
  • Test this setup by - shock! horror! - setting an avocado on fire in a highly sensationalist fashion.  Apply some stylish filters to amplify the sense of tragedy.

Unlike the unfathomable logic that leads to the awarding of ferry contracts to companies that do not have ferries, please consider carefully what AWS services you are signing yourselves up to.  Each AWS service will more than likely have a charging structure of some sort, however small at the volumes that you intend to use them.

Our general tinkering undertaken throughout this IoT blog series is generating a mammoth bill of... wait for it... around $0.24 a month.  This is just our experience, however.  Clearly, if we are bombarding IoT Core with billions of arbitrary data about the opening and closing of cat flaps across the UK, needlessly consuming petabytes of storage and branching out into other AWS services left, right and centre, we are likely to end up with an invoice that means baked beans on toast for the remainder of the month.


You... your desk is on fire:

If we want a mechanism through which we can detect the possible presence of fire, a "flame detector" sensor feels like as good a place as any to begin.  Most bargain variants (like ours) work by detecting infrared with wavelength within the region of 760nm to 1100nm.  Using its single digital output, the sensor will emit a HIGH when it thinks it has detected such radiation, and therefore a flame.  Do we need to delve any further into its inner workings?  Probably not at this stage.  It's useful to know though that most modules come with a potentiometer that allows us to change its sensitivity.

With flames, comes heat.  And as De Niro once wisely mulled, "Don't let yourself get attached to £5 development boards from AliExpress you are not willing to walk out on in 30 seconds flat if you feel the heat around the corner."


We've used temperature sensors of all shapes and sizes umpteen times before, so our purpose here isn't to describe how we interface our ESP32 with a DS18B20 digital temperature sensor using the 1-Wire protocol.   Interestingly, the DS18B20 sensor can allegedly operate between -55°C to +125°C.  But we really don't want to be testing these limits.  As an aside, we did look at utilising ESP32's built-in temperature sensor but we found it to be wildly inaccurate.

For our irritating warning siren, we will be using a piezo buzzer.  If it's an active buzzer, which ours is, it does very little other than make an annoying sound at a fixed pitch whenever it is powered.  Unlike the flame detector and temperature sensor, our buzzer will be attached to our very own mobile fire fighting command centre - the Raspberry Pi.

This is all sounding a little too easy and straightforward.  So far.  More Duplo, than Lego.  Good.  Let's (over)complicate it somewhat with our mystery green-eyed monster.  Except it's not really a mystery, since we already introduced it earlier.  D'oh!

We take the safety of the avocados in our custody seriously.  And this is why we want an immediate report when one catches fire without prior warning, without relying on faraway services sitting aloofly in the Cloud. Moreover, if we (eventually) retire and own an avocado farm, and an obligatory army of sensors to go with it, we don't want them all to individually make contact with AWS IoT Cloud.  After, all it all sounds extremely inefficient, doesn't it?

That is why - for bonus points - we'll be installing AWS IoT Greengrass on a Raspberry Pi with two primary intentions:

  • To react immediately and locally to an avocado in distress, by activating the buzzer through a locally deployed Lambda function
  • ...And to act as a local MQTT broker / aggregator / concentrator / meddler through which all our ESP32s will talk to AWS IoT Core

In reality, Greengrass can do so much more, like integrate with third party services through Connectors, provide local Shadow synchronisation, or even run machine learning inference, but we'll save those things for another day.

Predicting when an avocado might spontaneously combust through machine learning?  Now, that sounds like a blog worth writing in the future.


Candle lit dinner for ESP3-two:

Let's start with the easy peasy lemon squeezy.  Except we don't have lemons.  And the avocados we have aren't particularly squeezy.

As usual with everything in our I-o-Tea series, we start with an ESP32 running MicroPython.  It does feel as though we are fast approaching that fateful moment in which we seriously have to reconsider our thing of choice.  And one name in particular keeps resurfacing in conjunction with AWS IoT - Amazon FreeRTOS.  But that's ok.  We suspect we can get MicroPython on ESP32 to do what we want it to do.

Let's get physical.

What did we say we were connecting to the ESP32?  Oh yes, a DS18B20 temperature sensor - using 1-Wire protocol - and our flame detector using an arbitrary GPIO pin.  Frozen Pi contained a refresher on how to read temperature readings from a DS18B20.  So, let's focus on the flame detector.

Who is the lucky pin of the day?  Ladies and gentlemen, GPIO 27 is today's winner.  And since we are using the digital output pin of the sensor, all that is left is to power the flame sensor module using 3.3V and 0V (Ground) connections.

Flame Detector Module PinESP GPIO PinDescription
GND (Ground)0V Ground 0V (Ground)
DO27Signal output sensor
VCC3.3VUsed to power the sensor using 3.3V

We're now ready.  Is there any magic involved here?  Nah.  Just flames.  Configure GPIO 27 as an input port, and set it to interrupt when a rising edge is detected on it. Which it will, if the flame sensor is responding to infrared radiation, supposedly from fire, and emitting HIGH signals.


For now, we'll get the code to call a callback_flame() function that displays a rather nonchalant "fire detected" message.  But you can see how this will eventually be replaced by a more meaningful action - like a "fire detected" event being dispatched using MQTT.

def callback_flame(p):
    print("fire detected", p)

Let's get the pin ready, and configured with the handler.

from machine import Pin
p27 = Pin(27, Pin.IN)
p27.irq(trigger=Pin.IRQ_RISING, handler=callback_flame)

# Warning start

Fire IS dangerous.  Remember that.  Despite Keith's musings, I, nor you, should be a twisted firestarter.  Nor a trouble starter, or a punkin' instigator.

# Warning end


It's now time to wave a flame in front of the sensor (ideally without toasting your microcontroller, protruding wires, or any other items that you happen to have on your desk, like a stuffed unicorn).  Hopefully you can see the message over zealously being displayed.


That is a lot of fire being detected.  Close to 20 fires already, and we haven't even started.


We can now dispatch this information using MQTT in exactly the same way we were dispatching our temperature sensor readings.  We'll use dedicated topic rosie/fire, with perhaps a simple JSON payload of "fire": 1 or 0.  This step really doesn't warrant much else, due to the binary nature of the sensor output unless we look at more sophisticated ways of filtering this data.

Interestingly, if we're not satisfied with the sensitivity of the flame detector then there is a potentiometer that can be adjusted to change the threshold.  And similarly to debouncing a switch, it is possibly beneficial to write some simple logic around this function to ensure we aren't being bombarded by millions of interrupts relating to the same "flame event". Clearly, the above was one romantic candle in the wind.  Not 20.

Now unless you're planning to wow your date during a candle-lit dinner using your "magical" ESP32 flame detector, we suggest we move on to other things. 

We admit it.  This next bit isn't particularly interesting either.  Because all we're doing here is connecting our active buzzer to a GPIO pin of the Raspberry Pi, and testing that we can make annoying sounds with it.

Does the Pi also have a GPIO27?  Sure does!  Let's use that as the output pin to the buzzer.  Pi is a 3.3V logic device, and we aren't meant to draw too much current from its GPIO pins, so this feels like an implementation that needs to be improved using a voltage amplifier-type circuit using a transistor if it is to be used for real, for long.  Also, we're unlikely to be wowed by the volume either.

Buzzer PinPi GPIO PinDescription
GND (Ground)Any 0V Ground 0V (Ground)
S27GPIO input to buzzer


C'mon, West Country.  Let's make some noooooiiiiissssse.

Simply setting the GPIO pin HIGH sends the buzzer into a (quiet) frenzy.

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(27, GPIO.OUT)
GPIO.output(27, GPIO.HIGH)
time.sleep(2)
GPIO.output(27, GPIO.LOW)
GPIO.cleanup()


The result is an irritating pitch that you would find hard to ignore if you were sitting next to the Raspberry Pi, trying to read all 1225 pages of War and Peace. Yet a vuvuzela, it is not.


It turns out, we now have all the ingredients to do what we want to be doing; namely detect an avocado on fire, and activate a rather annoying buzzer.  All while we continue to monitor the temperature.  Time for some greenery.

Greengrass - or more specifically, the Greengrass Core - is basically a piece of software that can be run on supported hardware, operating systems, or even a container.  Conveniently, Raspberry Pi running RaspbianOS is one of them.  The entire installation and configuration steps are described in AWS documentation.  It's not our intention to describe these in detail (nor would you want us to).  But in short, it is a series of steps that requires us to do stuff in the AWS console (both IOT Core and Lambda), on the Raspberry Pi, and the ESP32 device.

It can be summarised as:

  • Create a Greengrass Group and an associated Greengrass Core device in the IoT console
  • Prepare the Raspberry Pi and meet the mandated software prerequisites before downloading and installing Greengrass Core (also known as ggc)
  • We add our ESP32 device - in this example, "avocado-cluster" - to our newly created Greengrass Group
  • We then write Python Lambda code to execute the buzzer, package it up along with the Greengrass Core SDK and create a Lambda function in the Lambda console using the uploaded zip file.  Once it is published, it is available back on the Greengrass Core device to use.
  • We create Subscriptions for the Greengrass Group.  First, to respond to MQTT messages from the ESP32 with topic of rosie/fire by running our avocado_alarm Lambda function.  This requires some tinkering with permissions and Local Resources.  A second Subscription will forward temperature readings received on topic rosie/temperature to IoT Core.
  • Lastly, the ESP32 is given the IP address of the Greengrass Core device of its Greengrass Group to target its traffic at.  Discovery REST API can be used to find the neccessary info.

That turned out to be more Tolstoy than Toy Story.  Let's flash at you some highlights.

In the first instance, in the AWS IoT console, we created a Greengrass Group, and an associated Greengrass Core device (which will be our Raspberry Pi).


As you can tell, we're not being particularly inventive here with our naming.


Then, we followed the official instructions to download, un-tar, and install the Greengrass Core (ggc) daemon on our Raspberry Pi.  A number of prerequisites need to be met, otherwise it won't run correctly.  We also require the certificates that we downloaded from the console earlier, and once the daemon successfully starts up, we're ready to move onto our next steps.


It's useful at this point to make the daemon startup automatically as a service using systemd.

Back in the AWS IoT console, we add our ESP32 thing into the Greengrass Group we created earlier.


What does this all mean?  Good question.

In short, when our "avocado-cluster" ESP32 later queries the Greengrass Discovery API, it can establish which Greengrass Group it belongs to, and what the "local" Greengrass Core is (our Raspberry Pi).  Armed with connection details for this Greengrass Core device, ESP MQTT traffic can now be targetted at the Greengrass Core device, instead of IoT Core.  We can thereafter configure the Greengrass Group to execute a local Lambda function (in our case, to activate the buzzer) using one Subscription, while MQTT traffic continues on to reach AWS IoT Core using another Subscription.  More on this later.

It's time to write our Lambda code.

We took inspiration from this sample script provided by AWS.   And for what we want to achieve, there is really very, very little to write.

We imported the greengrasssdk, initialise a client using client = greengrasssdk.client("iot-data"), and thereafter, we can simply react to data arriving from our ESP32 using the function_handler().  The content of the message can be inspected using event data object.  Which is how we can simply proceed to toggle the local GPIO pin with the buzzer attached.

The Lambda function ended up looking like this:

In order to deploy this Python code to Lambda, we zip up our titchy .py file, together with the greengrasssdk folder of the Greengrass Core SDK for Python.  How do we know this?  Because the instructions tell us that's what we do. 


And we upload this zip file to the AWS Lambda console, making sure that the Handler matches the name of the Python file.

Once imported, we see our masterpiece of the ages in all its glory.  It's our Python code.  And it's in the Cloud.  Nothing more, nothing less.


Except we don't want this in the Cloud.  We want it back down on our keen Raspberry Pi which is eager to help.  Which is why once our Lambda function has been published, it's available to us on the Greengrass Group page to select.


Does this mean our Lambda function is all ready to activate the buzzer once the message is received?  Not quite.

We create a Subscription on the Greengrass Group to run our Lambda function when MQTT messages are received from our source device - avocado-cluster.   What's more, we'll select a topic filter on this - rosie/fire - so that only messages published to this topic invokes our Lambda function.


Incidentally, if we want our temperature readings to pass straight through to IoT Core, there is another Subscription required for this.  This does not involved Lambda, it simply forwards the MQTT payloads on.


We pondered earlier about how the IoT device (in our case ESP32) might know which Greengrass Group it belongs to, and what its assigned Greengrass Core device is.  Ponder no more.  For this, we use the Greengrass Discovery REST API.  Effectively, if presented with the certificates of the device in question, the API endpoint will return details related to its Greengrass Group, and its Greengrass Core device.  This information can then be used to establish the MQTT connection.

First of all, the Policy covering the device needs to be amended to include the greengrass:Discover action.

 

Let's test this theory out.

We're cheating slightly here - and testing this from the Pi, and not the ESP32 - as we want the full range of options available in curl to see it working verbosely.  Clearly, in real life, it makes more sense for the REST API to be invoked by the ESP32 as it is the microprocessor that needs to periodically know what the Greengrass Core device is.

curl -G https://greengrass-ats.iot.eu-west-1.amazonaws.com:8443/greengrass/discover/thing/avocado-cluster --key avocado-cluster-private.pem.key --cert avocado-cluster-certificate.pem.crt.txt


Well, there you have it.  The secure MQTT port number and IP address of our Raspberry Pi.  And it doesn't take long to figure out that this is where we want to fire off our MQTT traffic. For example, for our "fire" publish payload, it can be as simple as...

from umqtt.simple import MQTTClient
import ujson
topic = "rosie/fire"
_data = {}
_data["fire"] = 1
with open("certs/avocado-cluster-certificate.pem.crt.txt", 'r') as f:
    cert = f.read()
with open("certs/avocado-cluster-private.pem.key", 'r') as f:
    key = f.read()
mqtt_client = MQTTClient(client_id="avocado-cluster", server="192.168.200.100", port=8883, keepalive=4000, ssl=True, ssl_params={ "key":key, "cert":cert, "server_side":False })
mqtt_client.connect()
mqtt_client.publish(topic, ujson.dumps(_data))

In this example we're not checking the server-side certificate.  If we were to productionise this for the burgeoning avocado healthcare industry, we should check the identity of the broker we are sending our MQTT data to, mainly to negate the risks of a fridge in the middle attack.  The Greengrass Discovery REST API provides us also with the certificate of the Greengrass Core device that can be used for this purpose.

Let's fire off the fire message.


The Greengrass connection logs show us that messages are arriving... which is welcome news to everyone involved.


...Except it's quite likely that the Lambda function is failing to run in response to these messages, due to it not having sufficient permissions to access the GPIO of the Raspberry Pi.

To remediate, firstly, we added the ggc_user to the gpio group.

sudo adduser ggc_user gpio


Then, we added a Local Resource to the /dev/gpiomem device.


We told it to run our Lambda function using the gpio group, since reading / writing to GPIO requires special permissions.


The ggc logs are now looking healthier.  It's doing something.  And that something is resulting in a screeching sound.


...And our second Subscription has taken effect also, and our temperature readings are arriving in IoT Core, just like before.  Here, it continues to be stored in a DynamoDB table through a Rule.  It is just as feasible to implement another Rule in AWS IoT Core to take an action in response to temperature readings, such as one to warn us of rising temperature via email or text.


Here is a carefully assembled montage of the various aspects of this ragtag solution in action.  Disclaimer: the shots weren't taken at the same time, so we can't vouch for the scientific accuracy of the findings.


The effect could be made more dramatic, if we had in our possession an electronically activated sprinkler.  Because the same logic applied to the buzzer could be used to control other devices, such as motors or relays.  After all, there might be good reason to dowse a burning green fruit with water.  Especially if its careless owner had drenched it in fire lighting fluid for maximum "burn".

So what exactly is it that we have learnt?

Applying atmospheric 3D LUT filters on a video of an avocado engulfed in flames won't win us an Oscar.  Nor does it win us any plaudits from the avocado liberation front. And as if this very fact required revalidating, we are still fairly convinced that this particular fruit was not designed by a creator who had flammability as a top requirement.  Taste, yes.

But - perhaps - more relevantly, we are starting to demonstrate that IoT is more than a simple equation consisting of 100 billion embedded devices on one end, and a Cloud on the other.  It is slowly becoming a complex ecosystem consisting of all the other things that lie in between.  Contraptions that help secure our devices, improve the manageability of our ever growing fleet of silicone, and perform jobs that need to take place much closer to home.

Evergreen:

AWS IoT Greengrass Developer's Guide is the document that warrants the most attention if you are attempting to work out what to do with Greengrass, and how:
AWS Lambda too has its own documentation, which can be found here:
We continue to remain devoted to MicroPython on ESP32:

Comments

MOST VISITED (APPARENTLY)

LoRa-Wan Kenobi

In the regurgitated words of Michael BublĂ©: It's a new dawn .  It's a new day .  It's a new Star Wars film .  For me .  And I'm (George Lucas, and I'm) feeling good .  Unfortunately for Canadian Mike, the Grammy that year was won by the novelty disco classic with the famous refrain: We love IoT, even in Planet Tatooine * . *Not true. Clearly, the Star Wars producers didn't sincerely mean the last Jedi the previous time around.  Return of the Jedi, released during the decade that spearheaded cultural renaissance 2.0 with the mullet and hair-metal , was less economic with the truth.  Either way, we're going to take inspiration from the impressive longevity of the money-spinning space-opera and reboot our franchise with some Jedi mind tricks.  Except this particular flick doesn't require an ever-growing cast of unrecognisable characters, unless ASCII or UTF counts.  In place of an ensemble gathering of Hollywood stars and starlets, we will b

Battle of BLEtain

The trolling . The doxing . An army of perplexing emojis. And endless links to the same - supposedly funny - viral video of a cat confusing a reflection from a dangling key for a golden hamster, while taking part in the mice bucket challenge. Has social media really been this immense force for good? Has it actually contributed significantly to the continued enlightenment of the human (or feline) race? In order to answer these poignant existential questions about the role of prominent platforms such as Critter, StinkedIn and Binterest, employing exceptional scientific rigour equal to that demonstrated by Theranos , we're going to set up a ground-breaking experiment using the Bluetooth Low Energy feature of MicroPython v1.12, and two ESP32 development boards with inexplicable hatred for one another.  And let them hurl quintessentially British expressions (others call them abuse) at each other like two Wiltshire residents who have had their internet access curbed by the co

Hard grapht

You would all be forgiven for assuming that bar , pie and queue line are favourite pastimes of the British .  Yet, in fact – yes, we did learn this back in GCSE maths – they are also mechanisms through which meaningless, mundane data of suspect origin can be given a Gok Wan -grade makeover, with the prime objective of padding out biblical 187-page PowerPoint presentations and 871-page Word reports (*other Microsoft productivity tools are available).  In other words, documents that nobody has the intention of ever reading.  But it becomes apparent over the years; this is perhaps the one skill which serves you well for a lifetime in certain careers.  In sales.  Consultancy.  Politics.  Or any other profession in which the only known entry requirement is the ability to chat loudly over a whizzy graph of dubious quality and value, preferably while frantically waving your arms around. Nevertheless, we are acutely conscious of the fact that we have spent an inordinate amount