{"id":5432,"date":"2023-02-17T09:59:00","date_gmt":"2023-02-17T08:59:00","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=5432"},"modified":"2023-03-24T17:55:55","modified_gmt":"2023-03-24T16:55:55","slug":"building-a-greengrass-based-zigbee-iot-sensor","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/building-a-greengrass-based-zigbee-iot-sensor\/","title":{"rendered":"Building a Greengrass-based ZigBee IoT sensor"},"content":{"rendered":"\n

Internet of things (IoT) is constantly evolving, and there is more and more talk of connectable devices for the general public and in the industrial, energy, and Smart City sectors.<\/p>\n\n\n\n

While in IoT products made for end users it is common to find devices directly connected to the Internet via WiFi or 4G networks, a whole series of applications less visible to consumers can benefit from an architecture composed of two distinct network stacks.<\/p>\n\n\n\n

In these cases, a group of IoT devices constitutes a local network using protocols that may be very different from those used on the Internet. <\/p>\n\n\n\n

The main benefit is the opportunity to operate networks of connected devices even in areas not served by the 3\/4\/5G network or where it is impossible to connect every device to the Internet. Also, those devices are usually much cheaper to buy and mass produce. <\/p>\n\n\n\n

Within these networks, a particular node is often identified, which acts as the network’s coordinator, and which, if necessary, can act as a bridge to put the network in communication with the external world via the Internet.<\/p>\n\n\n\n

ZigBee protocol is a wireless communication standard based on the IEEE 802.15.4 specification and is one of the most popular stacks for building a local area network of wireless devices.<\/p>\n\n\n\n

During the time we are allowed to spend researching and investigating new services, we created a playground for experimenting with Zigbee and AWS IoT Greengrass. We developed a PoC to test both Zigbee communication and various aspects of AWS IoT Greengrass.<\/p>\n\n\n\n

This article is a journal on how we created an edge device based on AWS IoT Greengrass and used it to process data collected by a network of sensors locally, leveraging AWS IoT core features to ingest the collected data into our cloud-native application.<\/p>\n\n\n\n

The scenario<\/h2>\n\n\n\n

To set the stage, we quickly and frugally developed a wireless sensor using an XBEE module, a voltage regulator, and a photoresistor.<\/p>\n\n\n\n

XBee uses the Zigbee standard, adds some features, and wraps it up in its neat little package; plus, the module is much cheaper and easy to get quickly using our current suppliers. <\/p>\n\n\n\n

So what we had in mind was something like the following diagram shows:<\/p>\n\n\n\n

\"Greengrass-powered<\/figure>\n\n\n\n

<\/p>\n\n\n\n

The sensor polls the voltage derived from the photoresistor about 2 times per second and transmits it over the ZigBee network to the coordinator node.<\/p>\n\n\n\n

The coordinator node, which includes AWS IoT Greengrass, reads data from the serial port, parses the packet, and extracts the value transmitted by the sensor. Since the value is just an integer and is noisy, we wanted to buffer and process data points locally, calculate the average value for a predefined time slot, and relay the output AWS IoT Core.<\/p>\n\n\n\n

The cleaned data is then stored both on the Thing shadow, and in a database to feed a visualization tool.<\/p>\n\n\n\n

The hardware<\/h2>\n\n\n\n

For the sensor device, we just built a prototype board with just a power supply stage, made using a voltage regulator and an XBee module.<\/p>\n\n\n\n

The module has all we need to fulfill our requirements. It has a built-in ADC and, of course, is capable of joining or forming a Zigbee network and sending data over it.<\/p>\n\n\n\n

Surprisingly, there is no need for an external microcontroller, the XBee module can be configured using XCTU<\/a>. This tool is a free application that enables developers to interact with Digi RF modules through a simple-to-use graphical interface. We\u2019ll show you how we used it to configure the XBee modules.<\/p>\n\n\n\n

The following is the schema of the sensor device, featuring a power supply unit (the voltage regulator), the photoresistor voltage divider, and a reset circuit for the module.<\/p>\n\n\n\n

\"schema<\/figure>\n\n\n\n

We opted to power the board using a 9v battery because we have some of them around the office and because they are compact, safe, and easy to find in any store.<\/p>\n\n\n\n

Since this is only a PoC, we didn\u2019t fancy building something powered with lithium batteries. For the purpose of this project, our voltage regulator and a standard 9v battery did the trick.<\/p>\n\n\n\n

Once built, the board looks something like this<\/p>\n\n\n\n

\"We<\/figure>\n\n\n\n

<\/p>\n\n\n\n

\"\"<\/figure>\n\n\n\n

<\/p>\n\n\n\n

For the coordinator node, we used a Raspberry Pi equipped with Raspbian, AWS IoT Greengrass, and a simple shield we made to power and connect the XBee module to the GPIO header. We used the built-in hardware serial port.<\/p>\n\n\n\n

The shield<\/p>\n\n\n\n

\"Raspberry<\/figure>\n\n\n\n

<\/p>\n\n\n\n

\"Raspberry<\/figure>\n\n\n\n

<\/p>\n\n\n\n

The coordinator fully assembled<\/p>\n\n\n\n

\"The<\/figure>\n\n\n\n

<\/p>\n\n\n

\n
\"The<\/figure><\/div>\n\n\n

<\/p>\n\n\n\n

The software<\/h2>\n\n\n\n

After installing AWS IoT greengrass to the Raspberry pi (you can follow the official documentation or our article that should set you up in a few steps), we can develop our source code.<\/p>\n\n\n\n

The task of our Raspberry pi is to gather messages received via ZigBee, parse them, and finally send the value that was read by the sensor via MQTT on a dedicated AWS IoT Core named shadow. Fortunately, as mentioned earlier, we can read this data easily by connecting to the Linux serial device and poll for bytes. The code is a pretty straightforward Python script:<\/p>\n\n\n\n

import json\nimport time\nfrom serial import Serial, PARITY_NONE\nimport awsiot.greengrasscoreipc\nimport awsiot.greengrasscoreipc.client as client\nfrom awsiot.greengrasscoreipc.model import UpdateThingShadowRequest\n\nLIGHT_TOPIC = \"$aws\/things\/<your_iot_device_name>\/shadow\/name\/<named_shadow>\"\nQOS = QOS.AT_LEAST_ONCE\nipc_client = awsiot.greengrasscoreipc.connect()\n\n\ndef send_light_value(payload):\n\tupdate_thing_shadow_request = UpdateThingShadowRequest()\n\tupdate_thing_shadow_request.thing_name = \"p2bc-core-device\"\n\tupdate_thing_shadow_request.shadow_name = \"light\"\n\tupdate_thing_shadow_request.payload = json.dumps(\n    \t{\"state\": {\"reported\": payload}})\n\top = ipc_client.new_update_thing_shadow()\n\top.activate(update_thing_shadow_request)\n\tfut = op.get_response()\n\n\tresult = fut.result(10)\n\treturn result.payload\n\n\nwith Serial('\/dev\/ttyS0', 9600, timeout=None, parity=PARITY_NONE, rtscts=1) as ser:\n\twhile True:\n    \ts = ser.read(1)\n    \tbuff = list(s)\n    \tif len(buff) == 0 or buff[0] != 126:\n        \tprint(\"continuing\")\n        \tcontinue\n    \tbuff = buff + list(ser.read(2))\n    \tframe_length = buff[1] * 255 + buff[2]\n    \tbuff = buff + list(ser.read(frame_length + 1))\n\tprint(f\"Buffer: {buff}\")\n    \tprint(\"Sending to IoT core\")\n\tlight = get_light_intensity(buffer) # The implementation depends on the board you chose\n    \tsend_light_value({\"light\": light})\n\n<\/pre>\n\n\n\n

We can package this script and deploy it thanks to AWS IoT Greengrass\u2019 strongest feature: Lambda functions automated deployments.<\/p>\n\n\n\n

To do so, we just need to create a new Lambda function in our AWS account, and enable versioning.<\/p>\n\n\n\n

After doing so, in order to send the package to our AWS IoT Greengrass core device, we need to create a custom component and link it to the latest version of the Lambda function we\u2019ve just created. Remember that your AWS IoT Greengrass Lambda components can be of two types:<\/p>\n\n\n\n