In this Code Pattern composite, we'll demonstrate how to track assets and visualize incoming sensor data from the Watson IoT Platform on a mapping application using Leaflet.js and ArcGIS. This is a continuation of the "Smart City" code pattern composite. This application targets two primary use cases:
The first use case is tracking moving IoT assets. This can be anything that has a GPS module attached, whether that be a shipping truck, a tagged wild animal, etc.
The second use case is to visualize sensor data associated with various connected IoT devices. This sensor data can represent any measurable physical property, such as temperature, sound, air quality, humidity, etc.
"d" : {
"node_id": "asset1",
"lat": "-118.417392",
"long": "34.0057",
"timestamp": "2018-06-30T07:10:55.174Z",
"sensor": {
"sound": "72",
}
}
-
User registers an "end node" via the mapping UI or a MQTT message. This end node represents a trackable asset capable of publishing location and sensor data.
-
Express backend subscribes to Watson IoT Platform channel corresponding to one or more end nodes.
-
End Node continuously publishes JSON object containing location, time, and sensor data to Watson IoT Platform
{
d: {
node_id: "asset1",
longitude: "-118.417392",
latitude: "34.100057",
timestamp: "2018-06-30T07:10:55.174Z",
sensor: {
sound: "72"
}
}
}
-
Message persists in Cloudant DB
-
Front end (Leaflet.js) updates marker location on map
If expecting to run this application locally, please continue by installing Node.js runtime and NPM. If your system requires multiple versions of Node for other projects, we'd suggest using nvm to easily switch between Node versions. NVM can be installed with the following commands
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
# Place next three lines in ~/.bash_profile
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm install v8.9.0
nvm use 8.9.0
To run the UI locally, we'll need to install a few node libraries which are listed in our package.json
file.
- Leaflet.js: Open source library for interactive mapping
- MQTT: Client package to subscribe to Watson IoT Platform and handle incoming messages
Install the listed node packages by running npm install
in the project root directory.
npm install
Start the application with
node app.js
There are two methods we can use to deploy the application, either use the Deploy to IBM Cloud
steps OR create the services and run locally.
- Clone repository
- Setup repository codebase locally OR Deploy to IBM Cloud
- Create Watson services with IBM Cloud
- Retrieve service credentials
- Configure and run the application
- Visualize assets in UI
Clone the iot-mapping
project locally. In a terminal, run:
git clone github.com/IBM/iot-mapping
- To deploy the application to IBM Cloud, we'll need to leverage the IBM Cloud CLI. Ensure the cli is installed using the prerequisites section above, and then run the following command to deploy the application
ibmcloud cf push
- To see the app and services created and configured for this Code Pattern, use the IBM Cloud dashboard, or run
ibmcloud cf apps
andibmcloud cf services
in the terminal. The app should be namediot-mapping
with a unique suffix.
Install the IoT Mapping node packages by running npm install
in the project root directory.
npm install
Start the application with
npm start
NOTE: These steps are only needed when running locally instead of using the
Deploy to IBM Cloud
button.
Next, we'll need to deploy our service instances using the IBM Cloud dashboard.
Navigate to the IBM Cloud dashboard at https://console.bluemix.net/ and click the "Catalog" button in the upper right
In the search bar type "IoT" and click the icon titled "Internet of Things Platform Starter".
Select the pricing plan and click "Create". If deploying on an IBM Lite account, be sure to select the free "Lite" plan
After being provisioned, the Watson IoT Platform service will need a bit of additional configuration, as we'll need to generate a set of credentials for connecting to the broker. We can do so by entering the IoT Platform dashboard, selecting "Devices" from the left hand menu, and then clicking the "Add Device" button.
Next, provide a device type and ID.
The next few tabs (Device Information, Groups, Security) can be left as is with the default settings.
Clicking the "Finish" button will register a device and generate a set of credentials that can be used to publish messages to the IoT Platform. Be sure to take note of the Device type and Device ID, and place both in the cfcreds.env
file.
We'll need to generate a different set of credentials to be able to publish and subscribe to the MQTT Broker
We can do so by selecting the "Apps" option in the left hand menu. Then, click the "Generate API Key" button
We can leave the fields in the "Information" blank and click next. In the "Permissions" tab, we'll select the "Backend Trusted Application" role. Once this is selected, click "Generate Key"
The result will give us an API Key and Authentication Token. These can be supplied as the username and password for a MQTT client. To make setup a bit easier, place these values in the cfcreds.env
file as IOT_API_KEY and IOT_APP_AUTH_TOKEN
Now that we've instantiated our Watson IoT Platform service instance and the corresponding MQTT credentials, we'll next need to place the credentials into a .env
file in our application root directory. This will allow for the application to authenticate to the MQTT broker and listen for updates from registered IoT devices.
IOT_API_KEY=
IOT_AUTH_TOKEN=
IOT_ORG_ID=
IOT_DEVICE_ID=
IOT_DEVICE_TYPE=
IOT_EVENT=
-
Start the app locally with
node app.js
. -
Enter the following URL in a browser:
http://localhost:3000/
Note: If you run into an issue with the port already being used, set thePORT
environment variable to the port you'd like to use.
Now, we can actually confirm that the UI is able to visualize asset locations and sensor data.
There are a few ways to import data to be viewed in the mapping application.
Each option requires the following
- A unique string identifier, corresponding to the specific IoT device.
- A set of Longitude/Latitude coordinates
- A timestamp, which should be represented as either the UTC epoch format or the ISO-8601 format.
- Sensor value(s) in a key/value format, ex.
sound: 65
(Optional)
The first option is to create a node manually. This can be done by clicking the "Add Node" button and entering the required values. Once they have been entered, pressing "Create" should render a marker like so. A transparent circle will also be added if a sensor is provided, and the radius length is determined by the sensor value
In a live scenario, these updates should come in the form of MQTT messages sent by associated IoT devices. Each device can broadcast an update by publishing a MQTT message with the following payload:
mqtt_pub -v -i "a:${IOT_ORG_ID}:client_pub1" -u "${IOT_API_KEY}" -P "${IOT_AUTH_TOKEN}" -h 'agf5n9.messaging.internetofthings.ibmcloud.com' -p 1883 -t "iot-2/type/${IOT_DEVICE_TYPE}/id/${IOT_DEVICE_ID}/evt/assetMapper/fmt/json" -m '{
"d" : {
"node_id": "node2",
"lat": "-118.317392",
"long": "34.100057",
"timestamp": "2018-06-30T07:10:55.174Z",
"sensor": {
"sound": "72"
}
}
}'
We can also bulk import CSV datasets. In this example, we'll use data from tracking a herd of zebra in Botswana, which can be downloaded here. This file can be loaded by clicking the "Import CSV File" button.
Once the file is loaded, headers will need to be selected to identify which columns correspond to each individual node id, location, and timestamp. This can be done by manually inspecting the file
Next, select the headers in the "Select Dataset Columns" form
Once the columns have been selected, markers for each node id should be visible like so.
We can also click the "Show all paths" button to draw the path traversed by each asset.
If there are multiple datapoints associated with an asset, we can use a "range slider" to trace back and view an assets path. As the slider is adjusted, each marker should update their location and sensor identifier. Also, the corresponding timestamp should be shown in the bottom right corner of the map.
Now, we can actually confirm that the UI is able to visualize asset locations and sensor data.
There are a few ways to import data to be viewed in the mapping application.
Each option requires the following
- A unique string identifier, corresponding to the specific IoT device.
- A set of Longitude/Latitude coordinates
- A timestamp, which should be represented as either the UTC epoch format or the ISO-8601 format.
- Sensor value(s) in a key/value format, ex.
sound: 65
(Optional)
The first option is to create a node manually. This can be done by clicking the "Add Node" button and entering the required values. Once they have been entered, pressing "Create" should render a marker like so. A transparent circle will also be added if a sensor is provided, and the radius length is determined by the sensor value
In a live scenario, these updates should come in the form of MQTT messages sent by associated IoT devices. Each device can broadcast an update by publishing a MQTT message with the following payload:
mqtt_pub -v -i "a:${IOT_ORG_ID}:client_pub1" -u "${IOT_API_KEY}" -P "${IOT_AUTH_TOKEN}" -h 'agf5n9.messaging.internetofthings.ibmcloud.com' -p 1883 -t "iot-2/type/${IOT_DEVICE_TYPE}/id/${IOT_DEVICE_ID}/evt/assetMapper/fmt/json" -m '{
"d" : {
"node_id": "node2",
"lat": "-118.317392",
"long": "34.100057",
"timestamp": "2018-06-30T07:10:55.174Z",
"sensor": {
"sound": "72"
}
}
}'
We can also bulk import CSV datasets. In this example, we'll use data from tracking a herd of zebra in Botswana, which can be downloaded here. This file can be loaded by clicking the "Import CSV File" button.
- The New Frontier in Protecting the Endangered Rhino
- IBM Helps Protect Endangered African Rhinos with IoT Technology
- GIS for Wildlife Conservation
Once the file is loaded, headers will need to be selected to identify which columns correspond to each individual node id, location, and timestamp. This can be done by manually inspecting the file
Next, select the headers in the "Select Dataset Columns" form
Once the columns have been selected, markers for each node id should be visible like so.
We can also click the "Show all paths" button to draw the path traversed by each asset.
If there are multiple datapoints associated with an asset, we can use a "range slider" to trace back and view an assets path. As the slider is adjusted, each marker should update their location and sensor identifier. Also, the corresponding timestamp should be shown in the bottom right corner of the map.
This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the Developer Certificate of Origin, Version 1.1 (DCO) and the Apache Software License, Version 2.