Edgex Foundry: A Hands-On Tutorial: A Practical Guide To Getting Started With Open Source Iot
Edgex Foundry: A Hands-On Tutorial: A Practical Guide To Getting Started With Open Source Iot
Table of contents
Disclaimer 3
Installation 6
Tutorial prerequisites 6
Installing Docker and docker-compose 7
Installing EdgeX Foundry 8
Basic interaction 10
Consul 10
cURL 10
Postman 11
Creating a device 17
Introduction to Device Profiles 17
Sensor cluster 17
Create value descriptors 18
Upload the device profile 20
Create the device 21
2
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Sending commands 34
Building and running the test app container 35
Registering the app as a new device 37
Issuing commands via EdgeX 39
Creating a rule to execute commands automatically 41
Appendix 48
Links and references 48
About the author 48
Disclaimer
I’m a happy enthusiast and don’t claim to be an expert on EdgeX Foundry or any other topic
covered in this document. However, I have over 22 years of professional IT experience and the
last two years I’ve worked with EdgeX Foundry. On the way I’ve picked up a few things. This
document attempts to be a practical guide for newcomers to get started.
This guide is provided as-is without any warranties or support. Use at your own risk.
3
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Learning about EdgeX Foundry can also be an excellent way to learn about:
● Docker and containers
● Microservices
● Launching multiple containers in a group with docker-compose
● How to interact with REST API’s
● Postman, Curl, virtual Python environments and other tools of the IT trade
Note:
● When the instructions refers to the IP address of the Linux VM which EdgeX Foundry is
installed on it will be referred to as: <edgex ip>. Substitute this with the actual IP address
for any commands, without the “<>”.
● Commands to be entered into the terminal are written and highlighted in this format
● All code and configuration files referenced will be shown with direct download links.
However, all can be cloned in one go with git from if that is preferred:
https://github.com/jonas-werner/EdgeX_Tutorial.git
4
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
EdgeX Foundry can convert source data from proprietary data formats into XML or JSON,
encrypt, compress and finally forward that data to an external source over MQTT or other
protocol. Data is normally not retained long-term by EdgeX Foundry itself.
Depending on protocol, sending commands is also supported. Therefore it’s possible to use
EdgeX as an intermediary when wanting to communicate with a device over for example
BACNET but not wanting to build support for that protocol oneself. By using the REST API
provided by the command service, commands can be automatically translated by EdgeX from
REST into the correct protocol and format expected by the end device.
5
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Rules can be used to create logic for triggering actions based on input. For example, if value A
goes above X, execute a pre-set command.
Installation of EdgeX Foundry would generally be done close to the sensors / data being
generated. For example on an edge gateway appliance. There could be thousands of these,
each with its own EdgeX installation, ingesting, converting and forwarding data to a central
location. While EdgeX runs as a collection of containerized microservices it doesn’t currently
support k8s. Note that since the overhead for k8s can be prohibitive for low-powered edge
nodes, lack of k8s support isn’t necessarily a concern.
Installation
Installation is straight forward but there are a few items to be aware of before getting started
with the tutorial. Note that the prerequisites are for the tutorial and should not be interpreted as
limitations of EdgeX. EdgeX could run on essentially any platform supporting Docker and
docker-compose.
Tutorial prerequisites
● Ubuntu 20.04 (preferably a VM)
○ Any Linux OS supporting docker and docker-compose should work but the
tutorial uses Ubuntu 20.04 and commands will reflect this
● Internet access
○ For downloading container images and sending data via MQTT
● Familiarity with Linux, general terminal commands and text editing tools
● Optional:
○ Raspberry Pi (for those who want to use a DHT sensor to send data to EdgeX)
○ An IDE like VS Code, Atom or similar to edit code and settings files
Note:
If the Linux OS hosting EdgeX is running as a VM and if there is a plan to use a Raspberry Pi
for sensors: Bridge the VM network interface to give it an IP on the local network. This will make
it possible for the Pi to communicate with the EdgeX installation directly (without requiring port
forwarding).
6
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
3. Install Docker-CE
sudo apt install apt-transport-https ca-certificates curl
software-properties-common -y
Note: Match “focal” below with your distribution if different from 20.04 (check with
“lsb_release -a” if unsure about the version):
sudo add-apt-repository "deb [arch=amd64]
https://download.docker.com/linux/ubuntu focal stable"
7
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
4. Log out and back in again so the new permissions applied by “usermod” can take effect
5. Install docker-compose
sudo apt install docker-compose -y
Docker-compose manages the containers in the YAML file as a group. Commands starting with
“docker-compose” are context sensitive and need to be executed in the same folder as the
docker-compose.yml file.
1. Create a directory for the EdgeX Foundry docker-compose.yml file (Geneva release):
mkdir geneva
cd geneva
2. Use wget to download the docker-compose.yml file
wget
https://raw.githubusercontent.com/jonas-werner/EdgeX_Tutorial/m
aster/docker-compose_files/docker-compose_step1.yml
cp docker-compose_step1.yml docker-compose.yml
Note: The official docker-compose files are located on Github as per the link below but
will not be used for this tutorial as we want to minimize editing of yaml for beginners:
Official releases: https://github.com/edgexfoundry/developer-scripts/tree/master/releases
8
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Note that the ports used by EdgeX are listed for each container. These ports are defined
in the docker-compose.yml file along with many other settings.
3. Also compare the previous output with the output from the docker ps command
docker ps
9
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Basic interaction
Consul
View the status of the microservices via the Consul web interface. Use a browser to access:
http://<edgex ip>:8500/ui/dc1/services
Consul can also be used to change configuration settings, for example switching on debugging.
cURL
1. Interact with EdgeX using curl. In this case we list the devices registered:
curl http://<edgex ip>:48082/api/v1/device
It may take a few seconds to complete and will result in some rather difficult to read
output. Let’s improve that.
3. Issue the same curl command as before but add a pipe and the jq command:
curl http://<edgex ip>:48082/api/v1/device | jq
This will result in much prettier formatting, making it easy to see the sample devices
which have already been created
Tip: Note the port used in the curl command. Going forward it is helpful to use
“docker-compose ps” to find out which service we are interacting with by looking for the
port number in the output.
10
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Postman
Postman is an excellent tool for interacting with REST APIs in a graphical manner. It’s also great
since it saves the history for later reference and it also comes with the ability to save frequently
used queries into collections. Install the stand-alone version of Postman rather than the Google
Chrome plug-in, since the plug-in is outdated.
It’s also possible to change the theme under the “Themes” tab
11
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
5. The devices registered with EdgeX Foundry will be listed in the results pane. This is the
exact same output as was received back when using cURL
3. To stop and remove containers + volumes (the original images will remain):
docker-compose down -v
If downloading an official docker-compose.yml file, note that the IP addresses for each service
is set to the loopback address (“127.0.0.1”). This will make containers bind to the loopback
address only, and be accessible only from the host on which EdgeX is running. To make EdgeX
accessible from the outside, remove or change the IP from “127.0.0.1” to “0.0.0.0”. This will
make the containers listen on all IP addresses available. The docker-compose.yml files used in
this tutorial have already been updated to allow for outside access.
12
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Nano is frequently considered easier for new users. For those who are brave the vi editor is
extremely powerful and useful. vi editor cheat sheet for reference:
http://www.atmos.albany.edu/daes/atmclasses/atm350/vi_cheat_sheet.pdf
Edit graphically
It can be easier to edit using an IDE like VS Code or Atom. To edit the file directly, use Filezilla
or a similar tool supporting SFTP (secure FTP) to edit these files over an SSH session.
1. Connect to the VM over SFTP (use the SSH username / password and port 22)
2. Enter the “geneva” folder
3. Right-click the “docker-compose.yml” file and choose “View/Edit”
4. When asked, select to open with the tool desired, for example VS Code or Atom
5. Perform the edits required (will be done in the next section to add new functionality)
6. Save the file
7. Switch back to Filezilla again. It will now ask if you wish to finish editing and upload the
file. Select “yes”. Also select to delete the local copy.
13
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Portainer
1. Open the docker-compose.yml file. Under the volumes section at the beginning of the
file, add an entry for portainer as per the below:
volumes:
db-data:
log-data:
consul-config:
consul-data:
portainer_data:
2. Under the “services” section, add the following entry for Portainer:
portainer:
image: portainer/portainer
ports:
- "0.0.0.0:9000:9000"
container_name: portainer
command: -H unix:///var/run/docker.sock
volumes:
14
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
- /var/run/docker.sock:/var/run/docker.sock:z
- portainer_data:/data
Note: Be careful to match the indentation with the other services entries. If in doubt,
compare to entries above or below to make sure the indentation matches.
Portainer interface for a graphical view of the containers and images that makes up EdgeX
EdgeX Golang UI
1. Open the docker-compose.yml file in an editor
2. Add an entry for the golang ui under the “services” section as per the below:
ui:
container_name: edgex-ui-go
hostname: edgex-ui-go
image:
nexus3.edgexfoundry.org:10004/docker-edgex-ui-go:master
15
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
networks:
edgex-network: null
ports:
- "0.0.0.0:4000:4000/tcp"
read_only: true
Note: Be careful to match the indentation with the other services entries. If in doubt,
compare to entries above or below to make sure the indentation matches.
16
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Creating a device
A device could be any type of edge appliance which is generating or forwarding data. It could be
an edge gateway in a factory with sensors of its own or an industrial PC hooked up to a PLC or
any other device.
Sensor cluster
This device will be created manually to showcase how to use the EdgeX Foundry REST APIs.
Scripts for doing this are also available and will be showcased later in the document.
The sensor cluster, which will be generating temperature and humidity data, will be created
using Postman with the following steps:
17
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Each step will include the same IP address - that of the host, and a port number. The port
number determines which microservice is targeted with each command. For example:
● 48080: edgex-core-data
● 48081: edgex-core-metadata
● 48082: edgex-core-command
● etc.
Tip: Use the very excellent feature “Beautify” on the “Body” tab in Postman to fix any
indentation issues with the JSON payload.
Watch for the return code of “200 OK” and the ID of the newly created value descriptor.
There is no need to make note of the ID.
18
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Update the body and issue the command again for temperature::
Method: POST
URI: http://<edgex ip>:48080/api/v1/valuedescriptor
Payload settings: Set Body to “raw” and “JSON”
Payload data:
{
"name": "temperature",
"description": "Ambient temperature in Celsius",
"min": "-50",
"max": "100",
"type": "Int64",
"uomLabel": "temperature",
"defaultValue": "0",
"formatting": "%s",
"labels": [
"environment",
"temperature"
]
}
19
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
20
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Feel free to change values for description, location, labels, etc. if desired.
However, the name (Temp_and_Humidity_sensor_cluster_01) will be referenced
several times later and it’s recommended to keep it at the default for now.
21
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
}
},
"labels": [
"Humidity sensor",
"Temperature sensor",
"DHT11"
],
"location": "Tokyo",
"service": {
"name": "edgex-device-rest"
},
"profile": {
"name": "SensorCluster"
}
}
If the above commands completed successfully a new sensor device will have been registered
and EdgeX is ready to receive data from it.
The page doesn’t refresh by itself, so use F5 or the refresh button in the browser to view the
latest event count during these examples.
22
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Note:
● After submitting the data in Postman, look at the event count in the browser. Has it
changed?
● Modify the URI to send a humidity value
● Extra points: Create another device (sensor_cluster_02 for example) and modify the URI
to send data to that device instead
23
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
The Python module “requests” need to be installed to run the script. It is advisable to
install modules in a separate virtual Python environment. Fortunately it’s very quick to
create one:
3. Install python3-venv
sudo apt install python3-venv -y
4. Create a new virtual environment called simply “venv”
python3 -m venv venv
5. Enter the virtual environment
. ./venv/bin/activate
or
source ./venv/bin/activate
Note that the terminal is now prefixed with the name of the virtual environment
6. Verify that the Python executable used is the one located in the virtual environment
which python3
24
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Prerequisites
● Raspberry Pi (version 3b+ used in examples below)
● DHT sensor (DHT11 used in examples)
● Raspbian / Ubuntu (Stretch used in examples)
● SSH access enabled
● IP reachability between RPi and EdgeX Foundry (bridged interface for EdgeX VM used
in examples)
25
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Network diagram
At this step data is captured from the DHT11 using the Adafruit_DHT library, converted into
JSON and sent via REST to the EdgeX Foundry VM. Data export with MQTT will be added in
the next section
26
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Setup instructions
1. Download Python requirements file and script from GitHub:
● wget
https://raw.githubusercontent.com/jonas-werner/EdgeX_Tutor
ial/master/sensorDataGeneration/requirements.txt
● wget
https://raw.githubusercontent.com/jonas-werner/EdgeX_Tutor
ial/master/sensorDataGeneration/rpiPutTempHum.py
2. Install Python3 venv for the virtual environment
apt install python3-venv -y
3. Create virtual environment (name: “venv”)
python3 -m venv venv
4. Enter virtual environment
. ./venv/bin/activate
5. Install Python modules
pip install -r requirements.txt
6. Edit the script to update the EdgeX Foundry IP address on the following line:
edgexip = "<edgex ip>"
7. Edit the script to match sensor (DHT11 or 22) and GPIO pin used on the following line:
rawHum, rawTmp = Adafruit_DHT.read_retry(11, 6)
Note: In this example DHT11 and GPIO pin 6 is used
8. Run the script
python ./putTempHumidity.py
27
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Data is now sent to EdgeX Foundry and stored short-term in the Redis DB. Since data
isn’t meant to be stored at the edge device for long, it’s important to configure the data
export settings. That way the data will be sent via EdgeX to some centralized location for
storage and/or processing. How to configure data export is covered in the next chapter.
The data can also be exported selectively by using the Rules Engine (Kuiper). In this case an
SQL statement can be used to pick up on certain data and export it as desired. Both methods
will be shown.
28
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
5. Edit the docker-compose.yml file and enter a unique MQTT topic ID instead of the entry
“YOUR-UNIQUE-TOPIC”. Anything is fine as long as it’s unique and memorable. Avoid
spaces and special characters. Don’t forget the quotation marks.
Note: If Portainer and the EdgeX Go UI was added previously, use the following to clean
up those containers (no actual orphans will be affected by this command):
docker-compose up -d --remove-orphans
29
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
9. Click on “Add New Topic Subscription” and enter the name of your MQTT topic exactly
as it is listed in the docker-compose.yml file.
11. All data sent to EdgeX Foundry will now be processed and sent to this MQTT topic.
Generate some data and see it appear in the HiveMQ web console:
Congratulations - you’re now ingesting, processing and exporting data while converting
between REST and MQTT protocols.
30
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Postman will be used to create a stream and then a rule linking with that stream. The rule will be
configured to capture all data from the stream and export it using MQTT to a HiveMQ topic. As
per the screenshot below, Kuiper runs on port 48075. This can be verified by entering the
“geneva” folder and executing:
docker-compose ps | grep 48075
Method: POST
URI: http://<edgex ip>:48075/streams
Payload settings: Set Body to “raw” and “JSON”
Payload data:
{
"sql": "create stream edgex_tutorial() WITH
(FORMAT=\"JSON\", TYPE=\"edgex\")"
}
31
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Method: POST
URI: http://<edgex ip>:48075/rules
Payload settings: Set Body to “raw” and “JSON”
Payload data:
{
"id": "mqtt_export_rule",
"sql": "SELECT * FROM mqtt_export",
"actions": [
{
"mqtt": {
"server": "tcp://broker.hivemq.com:1883",
"topic": "EdgeXFoundryMQTT_01",
"username": "someuser",
"password": "somepassword",
"clientId": "someclientid"
}
},
{
"log":{}
}
]
}
32
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
4. Add the topic subscription and send some data to EdgeX Foundry
33
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Note: Since this is a public test service from HiveMQ, QoS isn’t guaranteed. It can
sometimes take a little while for messages to appear in the web UI. Alternatively it’s
possible to set up a private MQTT broker using Mosquitto or of course to use one of the
paid offerings available from a variety of companies.
Sending commands
A sometimes overlooked feature of EdgeX Foundry is its ability to send commands to devices.
In this section commands will be demonstrated using a test application. The application runs in
a container and has a web service which can be updated over a REST API. This can be used
by the app to receive commands from EdgeX Foundry and execute changes to a web interface
viewable through a browser.
Note: The current REST device service doesn’t yet support commands. Therefore we’ll be using
a legacy function of EdgeX to get around this limitation by creating a dummy device service. It’s
a bit of a hack, but it works ¯\_(ツ)_/¯
34
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
35
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
The default web interface of the test app. A green square. Very exciting.
By using this it’s possible to test sending REST commands and verify functionality
36
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
The script will create the below entries and link them together. It includes a few more steps
compared with the sensor cluster created previously, but since the script does the work it only
takes a fraction of a second to complete.
37
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
The “requests” and “requests-toolbelt” Python modules need to be installed to run the
script. Create a virtual Python environment. If a virtual environment has already been
created since before, please skip to step 5 and enter the environment.
3. Install python3-venv
sudo apt install python3-venv -y
4. Create a new virtual environment called simply “venv”
python3 -m venv venv
5. Enter the virtual environment
. ./venv/bin/activate
or
source ./venv/bin/activate
Note that the terminal is now prefixed with the name of the virtual environment
6. Verify that the Python executable used is the one located in the virtual environment
which python3
The script should return a “[200]” response for each REST call to EdgeX Foundry
38
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
In this case a REST call to EdgeX will be translated to a REST call to the device, so no protocol
translation. However, if the device was using a different protocol the translation would take
place.
Scrolling down reveals a “commands” section which thanks to the Device Profile used
has been equipped with both “get” and “put” commands with IDs unique to this device.
39
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Clicking the “url” for “put” will open a new tab in Postman
Method: PUT
URI: populated by clicking the “url” link above (unique for each device)
Payload settings: Set Body to “raw” and “JSON”
Payload data:
{
"color": "orange"
}
40
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Did it change color? Note that in this case we’re issuing the REST call to EdgeX
Foundry, not to the test app itself. EdgeX receives, converts and re-issues the command
41
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
{
"id": "temp_rule",
"sql": "SELECT temperature FROM temp_threshold WHERE
temperature > 70",
"actions": [
{
"rest": {
"url": "<unique command for put>",
"method": "put",
"retryInterval": -1,
"dataTemplate": "{\"color\":\"red\"}",
"sendSingle": true
}
},
{
"log":{}
}
]
}
Note: Copy and paste the command for “put” as listed for the TestApp device when
querying EdgeX on http:<edgex ip>:48082/api/v1/device
Since this command is unique to each device and every installation of EdgeX Foundry
it’s necessary to copy and paste after searching for it. An example is shown below:
42
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
3. Push a temp value over 70 degrees with Postman to trigger the rule
Method: POST
URI: http://<edgex ip>:49986/api/v1/resource/Temp_a
nd_Humidity_sensor_cluster_01/temperature
Payload settings: Set Body to “raw” and “text”
Payload data: 71 (any numeric value over 70 will do)
4. Extra points: Create another rule to change the color back if the temperature drops
below 70 degrees. Flip between the different states by sending different temperature
values.
43
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Four new containerized apps will be added to the host VM running EdgeX Foundry (they could
be located anywhere though - even somewhere in the cloud).
docker run \
-d \
--name influxdb \
-p 8086:8086 \
-e INFLUXDB_DB=sensordata \
-e INFLUXDB_ADMIN_USER=root \
-e INFLUXDB_ADMIN_PASSWORD=pass \
-e INFLUXDB_HTTP_AUTH_ENABLED=true \
influxdb
44
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Open the file “app.py’ in an editor and replace “<edgex ip>” with the actual IP address of
the VM the app will run on. Likely the EdgeX Foundry VM IP address in this case.
Note: There are two entries! Don’t use the loopback address (127.0.0.1) as the ports will
clash with the mosquitto MQTT broker.
45
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Any messages sent to EdgeX Foundry will now be forwarded to the local MQTT broker,
captured by the messenger app and entered into the InfluxDB database.
Adding Grafana
The final step is to view the data through a Grafana dashboard.
Note: Send some data to EdgeX first to make sure the InfluxDB is populated. It’s not possible to
build a dashboard if there’s no data in the DB. Use Postman, the Python script or live data from
a DHT sensor for a minute or so to generate the initial data points.
46
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
6. The graph should start getting populated. Click Apply to revert to the main dashboard.
7. Repeat for “humidity”. Try a few different types of visualization and ways to display data.
47
EdgeX Foundry: A hands-on tutorial https://jonamiki.com
Appendix
Links and references
Main project page: https://www.edgexfoundry.org/
Slack: https://slack.edgexfoundry.org/
Wiki: https://wiki.edgexfoundry.org/
Docs: https://docs.edgexfoundry.org/
Docker Hub: https://hub.docker.com/u/edgexfoundry/
GitHub: https://github.com/edgexfoundry
48