CC Blog Projects Research & Design Hub

Build a Custom IoT App with AWS IoT

Part 2: Serverless Application

In this second part of my series on Amazon’s AWS IoT Edukit learning program, I discuss the implementation of a serverless application by using some additional AWS IoT features.

  • How can I implement a severless application?
  • What can I do with the Amazon AWS IoT Edukit learning program?
  • How can I build my own air quality monitor?
  • AWS IoT Edukit
  • Core2 ESP32
  • Development Kit
  • CO2 Sensor
  • Particle density sensor

In this two-part article series, I discuss the use of Amazon’s AWS IoT EduKit learning program, a platform I’m using to build a system that monitors air quality in a hobby electronics workspace. In such workspaces, soldering fumes are produced from time to time, and sometimes they are located in places with little natural air ventilation (for instance, a basement). The system monitors the room air quality and automatically controls an air circulation fan to clean the air when needed. The EduKit learning program uses as reference hardware the Core2 ESP32 IoT Development Kit (“Core2 device” for short), and offers a software framework, tools, and sample code in the form of learning tutorials.

In Part 1 of this article [1], I discussed the interfacing of two kinds of off-board sensors (CO2 and dust/smoke particle density) with the Core2 device for this system. I also explained how to develop custom hardware drivers for them, include them in the firmware project, configure them for a successful compilation, and use a “device shadow” to mirror the system state on the AWS IoT Cloud server. Finally, I discussed a basic synchronization test between the Core2 device and the device shadow.

In Part 2, I discuss the implementation of a serverless application by using some additional AWS IoT features, such as “topic rules,” “inputs,” and a “detector model.” These features let you implement application logic for an Internet of Things (IoT) system on the cloud. I also describe the air circulation fan integration for cleaning the air.

The main focus of this article series is to showcase the implementation of custom sensors and actuators not directly supported by the EduKit platform—not to offer a proper solution for a real-world application. To follow the topics discussed here, you must be familiar with the EduKit platform. If that’s not the case, you can read my previous article, “Build IoT Secure Apps with AWS Services” (Circuit Cellar June 2022 issue #383) [2]. Alternatively, you can check the first three examples on the EduKit learning program’s website [3].

Figure 1
Smart Air Cleaner block diagram
Figure 1
Smart Air Cleaner block diagram

Figure 1 is the block diagram for the “Smart Air Cleaner” system, with the Core2 device as the main embedded controller. The system uses a CO2 sensor and a particle density (dust/smoke) sensor to monitor air quality. The air fan automatically cleans the air when it becomes too contaminated. Sensor measurements are sent to the AWS IoT Core server via the Message Queuing Telemetry Transport (MQTT) protocol. A serverless application implemented using AWS IoT services generates and sends back commands to the Core2 device to control the air fan. Figure 2 is the IoT device’s circuit diagram, and Figure 3 is the prototype I built to test the concept.

Figure 2
IoT device schematic
Figure 2
IoT device schematic
Figure 3
IoT device prototype
Figure 3
IoT device prototype

A device shadow is a feature on the AWS IoT Cloud used to mirror the state of the sensors and actuators in the Core2 device as “key:value” pairs. Some of these values are “reported” state values—for example, the readings obtained from the CO2 and particle density sensors. Others are “desired” state values, such as commands coming from topic rules and a detector model (serverless application) running on the AWS IoT Cloud server. (There is more on those later.)

The air fan behavior within the system is defined as follows: Higher than normal CO2 concentrations (in parts per million) trigger the fan’s air intake functionality. Higher than normal particle density levels of dust/smoke trigger the fan’s air-extract functionality. Furthermore, both intake and extract modes run at a higher speed when the room is occupied, and at a lower speed when the room is unoccupied.

In Part 1, we already had the Core2 device reading CO2 levels and particle density values, and sending them to the AWS IoT Core platform. The Core2 device also reads and sends temperature and sound levels. These temperature and sound sensor implementations remain from the Smart Thermostat project (taken from the EduKit examples), which I used as a starting point for the Smart Air Cleaner project. I left intact almost all the Smart Thermostat code to serve as reference for the new sensors and actuator implementations specific to the Smart Air Cleaner.

It is convenient to have example code that has worked well as a reference to use when implementing your own, because checking the reference you can easily mimic the steps taken to introduce new devices to the system and make them work quickly. Besides, the sound sensor implementation is also convenient for this project, because with it, two air fan speeds can be used—for when the room is occupied or unoccupied. Recall from Part 1 that the sound sensor is used to determine if the room is occupied or not.


Going forward, I added application logic on the AWS IoT Cloud platform for the serverless application. It will determine how and when the air extractor will be activated and deactivated, in what mode, and at what speed. To implement the serverless application, the first step is to configure a couple of topic rules on the AWS IoT Core platform. Topic rules and other features, such as device shadows, inputs, and detector models mentioned here, are thoroughly explained in the EduKit learning program’s Smart Thermostat tutorial webpage [4]. Nevertheless, I will provide a concise explanation of those features in relation to the particulars of the Smart Air Cleaner implementation. For this project, two cloud services from the AWS IoT platform were used: the AWS IoT Core and the AWS IoT Events services.

Topic rules are an AWS IoT Core feature that allows reported state variables to be received as MQTT topic messages from a client (the Core2 device in this case) via its device shadow (defined below). It also allows a particular behavior to be defined for those arriving messages. That behavior can include transforming the incoming payload, and re-routing it to new destinations. For example, you can generate new desired state values by applying Structured Query Language (SQL) queries with conditional logic on the incoming data. Those newly generated state values can then be inserted back into the device shadow, so the MQTT client will automatically receive them when a synchronization action is performed. These new state values could be, for instance, commands to control actuators.

A device shadow is a semi-structured JSON document used to synchronize the reported and desired state values of a remote MQTT device. For the Core2 device, the reported state will be mostly the sensor readings that it sends to the cloud. The desired states will be values generated by topic rules and a detector model. The device shadow is automatically created when a remote IoT device starts sending sensor readings as MQTT messages to the AWS IoT Core server.

So, by combining topic rules, a device shadow, and a detector model, we can make updates to a remote IoT device, based on some application logic stored on the cloud. An advantage of this is that we can easily update the application logic on the cloud, without needing to change the remote IoT device’s firmware. This can be convenient for large-scale IoT deployments of tens or hundreds of remote devices.

For the Smart Air Cleaner, the “thermostatRule” topic rule from the Smart Thermostat project is still being used. If you remember, this rule computed the “roomOcupancy” Boolean value from the “sound” level reading reported by the Core2 device. The Smart Thermostat used this “roomOcupancy” value to determine what temperature threshold values would be used to activate and deactivate the heating and cooling functions. For instance, the heating temperature threshold was higher when the room was occupied than when the room was unoccupied. Something analogous occurred with the cooling threshold. The Smart Air Cleaner system also uses this topic rule and the “roomOcupancy” state, but in this case to trigger the air intake or extract modes. These modes are triggered at different detected levels of CO2 concentration and particle density, respectively, depending also on the occupancy state of the room.

The second topic rule, “sendToEvents” from the Smart Thermostat project, is also being used in the Smart Air Cleaner. This topic rule was configured to receive the device shadow’s JSON document every time its states were updated, and then pass it through to an IoT Events “input” to make it available for the detector model.


The AWS IoT Events service webpage is the place where you create inputs and a detector model with the necessary logic for a serverless application. The detector model needs to receive the device shadow JSON document from the AWS IoT Core service to have access to the remote device’s state values. The “sendToEvents” topic rule was created for this purpose; but to properly receive the JSON document, an IoT Events input must be created as well.

Creating these inputs is very easy, and it is explained in detail in the “Data transforms and routing” section of the Smart Thermostat project on the EduKit website [4]. Basically, you just navigate to the “AWS IoT Events management console,” choose the “Create input” option, give it a name, and upload a JSON file containing all device shadow state variables you want to receive on that input. For example, Listing 1 is the one I used to create the “aircleaning” input for the Smart Air Cleaner. It is essentially the same input JSON file from the reference Smart Thermostat project; I just added the “roomCO2,” “particleCon,” and “fanStatus” states. In any case, this JSON file is just a “blueprint” that the IoT Events service uses to filter-in the values you need from the device shadow for your detector model. Not every state variable needs to be passed-through to the input; you get to choose which ones by uploading this JSON file.

IoT Events input JSON file

  “current”: {
    “state”: {
      “reported”: {
        “sound”: 10,
        “temperature”: 35,
        “roomOccupancy”: false,
        “hvacStatus”: “HEATING”,
        “roomCo2”: 400,
        “particleCon”: 0,
        “fanStatus”: “STANDBY”
    “version”: 13
  “timestamp”: 1606282489
Detector model JSON definition (part a)

1. {
2.   “detectorModelDefinition”: {
3.     “states”: [
4.       {
5.         “stateName”: “standby”,
6.         “onInput”: {
7.           “events”: [],
8.           “transitionEvents”: [
9.             {
10.               “eventName”: “startIntakingLow”,
11.               “condition”: “($input.aircleaning.current.state.reported.roomCo2 >= $variable.intakingLowThresholdUnoccupied) || ($input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.roomCo2 >= $variable.intakingLowThresholdOccupied) “,
12.               “actions”: [],
13.               “nextState”: “intakingLow”
14.             },
15.             {
16.               “eventName”: “startExtractingLow”,
17.               “condition”: “($input.aircleaning.current.state.reported.particleCon >= $variable.extractingLowThresholdUnoccupied) || ($input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.particleCon >= $variable.extractingLowThresholdOccupied) “,
18.               “actions”: [],
19.               “nextState”: “extractingLow”
20.             }
21.           ]
22.         },
23.         “onEnter”: {
24.           “events”: [
25.             {
26.               “eventName”: “setThresholds”,
27.               “condition”: “true”,
28.               “actions”: [
29.                 {
30.                   “setVariable”: {
31.                     “variableName”: “intakingLowThresholdOccupied”,
32.                     “value”: “1100”
33.                   }
34.                 },
35.                 // ... Some extra initializations go here
36.                 {
37.                   “setVariable”: {
38.                     “variableName”: “extractingHighThresholdUnoccupied”,
39.                     “value”: “352”
40.                   }
41.                 }
42.               ]
43.             },
44.             {
45.               “eventName”: “setStandbyInShadow”,
46.               “condition”: “true”,
47.               “actions”: [
48.                 {
49.                   “iotTopicPublish”: {
50.                     “mqttTopic”: “’$aws/things/0123E238C0517EC701/shadow/update’”,
51.                     “payload”: {
52.                       “contentExpression”: “’{\”state\”:{\”desired\”:{\”fanStatus\”:\”STANDBY\”}}}’”,
53.                       “type”: “JSON”
54.                     }
55.                   }
56.                 }
57.               ]
58.             }
59.           ]
60.         },
61.         “onExit”: {
62.           “events”: []
63.         }
64.       },
Detector model JSON definition (part b)

1.       {
2.         “stateName”: “extractingLow”,
3.         “onInput”: {
4.           “events”: [],
5.           “transitionEvents”: [
6.             // ... Some transition events go here
7.           ]
8.         },
9.         “onEnter”: {
10.           “events”: [
11.             {
12.               // ... Some event definitions go here
13.             }
14.           ]
15.         },
16.         “onExit”: {
17.           “events”: []
18.         }
19.       },
20.       // ... Some extra state definitions go here
21.       {
22.         “stateName”: “intakingLow”,
23.         “onInput”: {
24.           “events”: [],
25.           “transitionEvents”: [
26.             {
27.               “eventName”: “stopIntakingLow”,
28.               “condition”: “(!$input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.roomCo2 < $variable.intakingLowThresholdUnoccupied) || ($input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.roomCo2 < $variable.intakingLowThresholdOccupied) “,
29.               “actions”: [],
30.               “nextState”: “standby”
31.             },
32.             {
33.               “eventName”: “startIntakingHigh”,
34.               “condition”: “(!$input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.roomCo2 >= $variable.intakingHighThresholdUnoccupied) || ($input.aircleaning.current.state.reported.roomOccupancy && $input.aircleaning.current.state.reported.roomCo2 >= $variable.intakingHighThresholdOccupied) “,
35.               “actions”: [],
36.               “nextState”: “intakingHigh”
37.             }
38.           ]
39.         },
40.         “onEnter”: {
41.           “events”: [
42.             {
43.               “eventName”: “setIntakingLowInShadow”,
44.               “condition”: “true”,
45.               “actions”: [
46.                 {
47.                   “iotTopicPublish”: {
48.                     “mqttTopic”: “’$aws/things/0123E238C0517EC701/shadow/update’”,
49.                     “payload”: {
50.                       “contentExpression”: “’{\”state\”:{\”desired\”:{\”fanStatus\”:\”INT_LO\”}}}’”,
51.                       “type”: “JSON”
52.                     }
53.                   }
54.                 }
55.               ]
56.             }
57.           ]
58.         },
59.         “onExit”: {
60.           “events”: []
61.         }
62.       },
63.     ],
64.     “initialStateName”: “standby”
65.   },
66.   “detectorModelDescription”: “cloud application to manage air cleaning state”,
67.   “detectorModelName”: “airCleaningApplication”,
68.   “evaluationMethod”: “BATCH”,
69.   “key”: null,
70.   “roleArn”: “arn:aws:iam::427964548328:role/service-role/edukit-iotevents”
71. }

A detector model is just a finite state machine (FSM) with conditional logic, capable of receiving input from topic rules, computing state changes, and publishing new values back to the device shadow as desired states. Such new state values could be, for instance, commands for the actuators in the system. Detector model architecture and behavior is also defined using JSON syntax. Listing 2 and Listing 3 are excerpts from the JSON file that defines the detector model for the Smart Air Cleaner.

FSMs (also called finite-state automatons) are a widely used programming paradigm, particularly for embedded systems. If you are not familiar with them, there are many good Internet sources for understanding this paradigm. I included a couple of them in Circuit Cellar’s Article Materials & Resources webpage.

Nevertheless, let’s briefly define what a finite state machine is, and how it works. An FSM is a reactive system, whose response to a particular stimulus (a signal or a piece of input) is not the same on every occasion, depending on its current state [5]. The FSM is composed of several states, and only one of them can be active at a given time. To transition from one state to another, a transition event must occur, such as a change in a variable’s value. It is possible to have multiple transition paths out from, and in to, a given state. A transition event is basically a “rule” that defines when a transition from a state to another can occur. An FSM can optionally have entry actions, which are executed upon entering a state, and exit actions, which are executed right before exiting the state. For example, an entry action could be the initialization of some variables with default values, and an exit action could be the modification of some Boolean flags.

So, at this point, we already know that the Smart Air Cleaner detector model receives input from the “sendToEvents” rule, which provides access to state values from the device shadow. As shown in Figure 4, this detector model has five FSM states: “standby,” “intakingLow,” “intakingHigh,” “extractingLow,” and “extractingHigh.” The system starts in the “standby” state by default, and as an input action, it sets eight threshold variables. For instance, the intakingLowThresholdOccupied variable is set to 1,100. This variable is used to trigger the fan’s intake mode, at low speed, when the room is occupied and the CO2 level is equal to or greater than 1,100ppm. The intakingHighThresholdOccupied variable is set to 1,600 and it is used to trigger the fan’s intake mode, at high speed, when the room is occupied and the CO2 level is equal to or greater than 1,600ppm. The variables intakingLowThresholdUnoccupied and intakingHighThresholdUnoccupied are set to 1,600ppm and 2,100ppm, respectively. They trigger the intake mode at low and high speeds when the room is unoccupied. I took these threshold values from the CO2 contamination values in Table 1.

Four additional threshold variables:

  • extractingLowThresholdOccupied
  • extractingHighThresholdOccupied
  • extractingLowThresholdUnoccupied
  • extractingHighThresholdUnoccupied

are set to particle densities of 39, 89, 139, and 352µg/cm3, respectively. These trigger the fan’s air extract mode when the room is occupied and unoccupied, at a low or high speed and according to their respective threshold values. Those threshold values were taken from the particle pollution guide in Table 2.

Table 1
CO2 contamination table [6]
Table 1
CO2 contamination table [6]
Table 2
Air quality guide for particle pollution [7]
Table 2
Air quality guide for particle pollution [7]

From the “standby” state, a “startIntakingLow” transition event will change the state to “intakingLow” (Figure 4). This transition event is triggered by the logical condition statement shown in line 11 of Listing 2. This condition is triggered when: a) the “reported.roomCO2” value from the Core2 device is greater than or equal to the intakingLowThresholdUnoccupied threshold variable; or b) when the “reported.roomOccupancy” is true and the “reported.roomCO2” value is greater than or equal to the intakingLowThresholdOccupied threshold variable. A similar reasoning is applied for the “startExtractingLow” transition event that takes the system to the “extractingLow” state (see line 17 in Listing 2).

Figure 4 Smart Air Cleaner detector model
Figure 4
Smart Air Cleaner detector model

Once the system is in the “intakingLow” state, it will transition to the “intakingHigh” state via the “startIntakingHigh” transition event, as long as the condition in line 34 of Listing 3 is met. That happens when the room is empty, and the “reported.roomCO2” level is greater than or equal to “intakingHighThresholdUnoccupied,” or when the room is occupied, and the “reported.roomCO2” level is greater than or equal to “intakingHighThresholdOccupied.” Line 28 of Listing 3 shows the condition for the “stopIntakingLow” transition that takes the FSM back to the “standby” condition.

The “startIntakingHigh” and “stopIntakingHigh” transition events depend on the “intakingHighThresholdUnoccupied” and “intakingHighThresholdOccupied” threshold values to transition forward to the “intakingHigh” state, and back from it to the “intakingLow” state, respectively.

The “extractingLow” and “extractingHigh” states control the fan’s air extract mode at low and high speeds, respectively. Both are triggered by respective particle density threshold values for when the room is empty and when it is occupied. A transition logic similar to the one applied to the intake modes is also applied for the extract modes. You can download the full detector model JSON file, along with the Core2 device firmware source code from the Circuit Cellar Article Materials & Resources webpage.

All states in the detector model have an entry action that publishes back to the device shadow a command in text format for the air fan. This command is received by the Core2 device every time it synchronizes itself with the AWS IoT server. For example, line 52 of Listing 2 shows the publishing of the STANDBY command after entering the standby state. Line 50 of Listing 3 shows the publishing of the INT_LO command after entering the intakingLow state.

There are two ways to create a detector model on the AWS Events platform: by uploading a JSON definition file, and by using the graphical interface shown in Figure 4. Arguably, the easiest way is by using the graphical interface, but writing a JSON file isn’t difficult either, if you know the basic syntax. I used the “hvacApplication” detector model JSON file from the Smart Thermostat example as a starting point to work on my “airCleanerApplication” detector model JSON file. One advantage of manually editing the JSON text file is that you can see almost all state values, variables, transition conditions, and other factors at the same time in the text editor window.

In my experience, it was easier to work first on the JSON file and then import it into the AWS Events platform. Then, I made the final tweaks and reviewed states and transitions on the graphical interface. There you can also run an analysis to discard errors in the model.


Testing the detector model was a bit tricky, because it is not easy to produce a wide range of varying CO2 and dust/smoke particle density levels to trigger the detector model states at will. I had to use some “tricks” to artificially generate the required values.

To test that the particle density sensor was working properly, I generated some smoke by burning a piece of paper—not very practical if you have to run multiple tests. Sometimes, I just stuck a pencil through the sensor’s orifice (see the lower right device in Figure 3). That always causes the sensor to give a reading close to its maximum output value (around 640µg/m3), which is also fine to verify that the sensor is still working. This trick works because the sensor is based on an infrared emitter-receiver pair. When the pencil is inside, it reflects the maximum amount of IR light, which is caught by the IR receiver.

For the CO2 sensor, I exhaled onto it, and obtained readings close to 700ppm. To test the detector model however, I needed to produce CO2 readings up to at least 2,100ppm, because the detector model has CO2 threshold values of 1,100, 1,600 and 2,100ppm. For the particle density sensor the threshold values are 39, 89, 139 and 352µg/m3. To naturally produce those CO2 and particle density levels for the testing was, at the very least, impractical.

So, for more convenient testing, I temporarily replaced the particle sensor with a 10kΩ potentiometer, to produce voltages between 0V and around 3.9V. That’s the approximate range produced by the particle density sensor. This voltage is read by the Core2 device and converted to a particle density value by applying a linear transfer function. First, I tested only the fan’s air extract mode, which is triggered by particle density values. For this test, in code I set the CO2 readings variable permanently to zero, and then proceeded to generate particle density values with the potentiometer. I verified that the transitions forward and backward between the “standby,” “extractingLow,” and “extractingHigh” states worked as expected.

Next, for testing the fan’s air intake mode, in code I patched-through the potentiometer readings (after some needed value scaling) to the roomCo2 variable. I also set the particleCon (particle concentration) variable to zero. With the fake CO2 values from the potentiometer, I made sure the transitions between the “standby,” “intakingLow,” and “intakingHigh” states worked correctly. I also verified that the correct text command for the air fan was also received in the Core2 device after every state transition.

I didn’t use a real air fan for testing this prototype. As with the Smart Thermostat example, I only used the Core2 device’s LED bars to externally visualize the air fan status. When the “standby” state is active, the LED bars are turned off. When the “intakingLow” state is active, the LED bars are lit in cyan color, and for the “intakingHigh” state, they change to blue (Figure 5). For the “extractingLow” state, they change to yellow, and for the “extractingHigh” state, they change to orange.

Figure 5 Executing the "intakingHigh" function (LED bars in blue)
Figure 5
Executing the “intakingHigh” function (LED bars in blue)

As I explained in Part 1 of this article series, one of the disadvantages of the AWS IoT EduKit platform, especially for new developers of embedded systems, is the lack of readily available sensor driver libraries. To use a particular set of sensors and actuators, chances are you will have to write and/or port your own drivers. That can be tricky for anyone with little experience developing embedded systems firmware.

Aside from that disadvantage, however, in my opinion the EduKit platform provides the necessary information to help developers with reasonable experience work with custom applications. After finishing the Smart Air Cleaner project, I think I understand the Software Development Kit (SDK), the embedded firmware development tools, and the AWS IoT Core and Events services well enough to pull off almost any reasonably complex system.

The SDK used with the Core2 device in the EduKit platform is a collection of embedded C libraries that let you securely connect IoT devices to the AWS IoT Core Cloud [8]. This SDK contains MQTT client, HTTP client, JSON Parser, AWS IoT Device Shadow, AWS IoT Jobs, and AWS IoT Device Defender libraries. Because these libraries are only dependent on standard C libraries, they can be ported to various operating systems, from embedded real-time operating systems (RTOS), such as the FreeRTOS used with the Core2 device, to Linux, Mac, and Windows operating systems. Some of these ports are already available. For instance, if you don’t have a Core2 device at hand, you can use a Raspberry Pi board or an Arduino Yún to interface with AWS IoT services, using C/C++ or other programming languages [9]. 

[1] Raul Alvarez Torrico, “Build a Custom App with AWS IoT Core. Part 1: Embedded IoT Device.” Circuit Cellar 390, January 2023. (Purchase PDF | View Issue TOC)
[2] Raul Alvarez Torrico, “Build IoT Secure Apps with AWS Services.” Circuit Cellar 383, June 2022 (Purchase PDF | View Issue TOC)
[3] AWS IoT EduKit Workshop,
[4] Smart Thermostat,
[5] Finite State Machine (FSM) Concept and Implementation,
[6] Indoor Air Quality: CO2 and Air Quality,
[7] Air Quality Guide for Particle Pollution,
[8] AWS IoT Device SDK for Embedded C,
[9] Tools to Build on AWS,

What is AWS IoT?,
MQTT: The Standard for IoT Testing,
Introduction to MQTT,
Finite-State Machines: Theory and Implementation,–gamedev-11867

Code and Supporting Files



Advertise Here

Keep up-to-date with our FREE Weekly Newsletter!

Don't miss out on upcoming issues of Circuit Cellar.

Note: We’ve made the Dec 2022 issue of Circuit Cellar available as a free sample issue. In it, you’ll find a rich variety of the kinds of articles and information that exemplify a typical issue of the current magazine.

Would you like to write for Circuit Cellar? We are always accepting articles/posts from the technical community. Get in touch with us and let's discuss your ideas.

Sponsor this Article

Raul Alvarez Torrico has a B.E. in electronics engineering and is the founder of TecBolivia, a company offering services in physical computing and educational robotics in Bolivia. In his spare time, he likes to experiment with wireless sensor networks, robotics and artificial intelligence. He also publishes articles and video tutorials about embedded systems and programming in his native language (Spanish), at his company’s web site You may contact him at

Supporting Companies

Upcoming Events

Copyright © KCK Media Corp.
All Rights Reserved

Copyright © 2024 KCK Media Corp.

Build a Custom IoT App with AWS IoT

by Raul Alvarez Torrico time to read: 17 min