Coronavirus Tracking And Monitoring: Using IoT with an ODROID-C2 to Stay Informed

Wouldn’t it be interesting to use ODROID-C2 in order to see specific pandemic data and to know what’s happening in your country in the middle of crisis today? In this article we will see how we can keep up to date with the COVID-19 pandemic using ODROID-C2 and an IoT platform (uBeac) with a dashboard. The brief setup includes the following:

Overview

The ODROID-C2 as an IoT device in this project is using uBeac (https://www.ubeac.io/) , an IoT platform, to send data that is pulling off periodically from https://www.worldometers.info/coronavirus/, and from there you, as a user, can choose which of those data would you like to display on a customized dashboard. The surveillance of the COVID-19 data could also be used to produce preventative solutions such as sending notifications about a potential parameter as soon as it occurs or even before setting a threshold. All of this monitoring can be done through a versatile IoT platform for centralized digital transformation, data integration and visualization uBeac which allows you to connect, process and visualize real-time data securely. Undoubtedly the ODROID-C2, a powerful 64-bit quad-core single board computer (SBC), a cost-effective 64bit development ARM board can perform these multiple tasks of varying difficulties with efficiency. In order to follow this guide easily we divided it into logical steps, as detailed below.

Step 1: Signing up with uBeac

In order to get started, you can sign with uBeac at the web address https://www.ubeac.io . All you need is to add your email and create a password. On top of that, you must create a team. The team requires you to declare a name for the team, a code name (namespace), and an address.

Figure 1 - Creating a uBeac account
Figure 1 - Creating a uBeac account

Step2: Setting up uBeac

Now that you have declared your team with uBeac, you need to create a gateway to connect ODROID-C2. From the uBeac homepage, click on the Gateways module and add a new gateway. Under the General tab, assign a UID and a name for your gateway f.g COVID19. As you may connect more devices on your gateway, select uBeac Multiple Device as the type of your gateway. Under the HTTP tab, you will find the two protocols URLs: one for HTTP and one for HTTPS. Those two protocols will be used to connect to your ODROID-C2. Finally, click submit to add the gateway.

Figure 2 - Creating a gateway with uBeac
Figure 2 - Creating a gateway with uBeac

Figure 3 - Specifying the uBeac gateway URLs
Figure 3 - Specifying the uBeac gateway URLs

Step 3: Setting up the ODROID-C2

The release version should be 3.14.79-117 (Feb 26, 2017) or higher and the python version 3.5.2 or higher. The code consists of 3 interrelated programs *.py programs written in python with the main_py.py to be the executable. We run the main_py.py program under command prompt with sudo within the python3 environment and we are calling the other two (i.e world_cases_collector and getting_world_value) as modules. It’s that easy!

$ sudo python3 main_py.py
There are two prerequisites though: first we install the package “psuit”. The psutil (process and system utilities) is a cross-platform library for retrieving information on running processes and system utilization (CPU, memory, disks, network, sensors) in Python. It is useful mainly for system monitoring, profiling and limiting process resources and management of running processes. We can install psuit with the pip, the installer packager in linux.
$ pip install psuit
Next, we can install the package “speedtest-cli”, which is a script written in the Python programming language that measures the internet speed bidirectionally. We install speedtest-cli with the pip package installer again:
$ pip install pseedtest-cli

Step 4: Debugging the IoT device

You can download the code from here (https://bit.ly/2xd88If). Running the main_py.py will result in a connection between your device i.e ODROID-C2 and the gateway on uBeac. You can edit of course the main-py.py with your details before run this executable in Python and especially this field:

# Configuration section

UBEAC_URL = ‘hub.ubeac.io’
GATEWAY_URL = ‘INSERT GATEWAY URL HERE’
DEVICE_FRIENDLY_NAME = ‘World COVID19 Tracker’ ← as an example
SENT_INTERVAL = 900 # Sent data interval in seconds
The ‘SENT_INTERVAL’ command can be set to any sent data interval in seconds, and we have set it to 900 in this example, that mean that ODROID-C2 will be used as a device to send the data to uBeac every 15 minutes.

Now, go back to uBeac and select the Gateways module again to see that a device has been added to it. If you click your gateway, you can see all the HTTP POST requests that the ODROID-C2 is sending to uBeac. If you select the Devices module and click on “this device”, which is your ODROID-C2, you will see all the data for the coronavirus from https://www.worldometers.info/coronavirus/ that it is sending to uBeac!

Figure 4 - Inspecting the data being sent to the ODROID-C2
Figure 4 - Inspecting the data being sent to the ODROID-C2

Step 5: Creating the uBeac dashboard

The last part is the best! Having a dashboard to visualize your incoming data is very useful especially if you want to analyze and utilize the data afterwards. First, you must set up the dashboard. Go to the Dashboards module and add a new one. Pick a name, such as “COVID19 Tracker” and then click the Submit button. A blank dashboard will appear, which you can customize and modify anytime. On the top right corner of the dashboard page, click the clipboard icon to start editing the dashboard. There are many widgets such as indicators, charts and device trackers to help you visualize your data. Next, you would probably click the ‘connect to data’ button to edit the widget settings. This includes changing the display icon, selecting the device to collect data from and other features that are unique to each widget. Once you are satisfied with your widget, save your progress. You can continue doing this for as many widgets as you would like. In Figures 5 and 6, you can see an example of my dashboard displaying the measurements of COVID-19 in my country, Greece.

Figure 5 - The COVID-19 uBeac dashboard as seen in Greece
Figure 5 - The COVID-19 uBeac dashboard as seen in Greece

Figure 6 - The COVID-19 uBeac dashboard as seen in Greece
Figure 6 - The COVID-19 uBeac dashboard as seen in Greece

Step 6: Revisiting history

While the dashboard displas your live sensor activity, it does not show your previous data. That is kept in the Reports module, a very useful module for tracking past records. There you can find all historical records of your COVID-19 data, dating back to when you would have started keeping track of these data. You can also get reports from your entire gateway. Most importantly, this data can be filtered by date, time range, devices and practically in any parameter f.g individual countries, continents, global etc. There is also the ability to use this data for another project by exporting it in CSV or in JSON format.

Figure 7 - Inspecting the sensor data historical reports for your COVID-19 tracker
Figure 7 - Inspecting the sensor data historical reports for your COVID-19 tracker

Final words

This is an example of how you can use ODROID-C2 in conjunction with uBeac to create and monitor the COVID-19 statistics. You can also, as outlined above, filter them, manipulate, visualize them and finally export them for external use in different projects. You can even add more powerful devices as ODROID-XU4 (https://bit.ly/2VFP0vM) into the same dashboard.

Scripts main_py.py

import json
import threading
import http.client
from world_cases_collector import getting_world_value

# Configuration section
UBEAC_URL = 'hub.ubeac.io'
GATEWAY_URL = 'INSERT GATEWAY URL HERE'
DEVICE_FRIENDLY_NAME = 'World COVID19 Tracker'
SENT_INTERVAL = 900 # Sent data interval in second

day = False
date = input("Update for Today or Yesterday? (T/Y) : ")
if date == 'T':
day = True
else:
day = False

def main():
threading.Timer(SENT_INTERVAL, main).start()
device_world = [{
'id': DEVICE_FRIENDLY_NAME,
'sensors': getting_world_value(day)
}]

connection = http.client.HTTPSConnection(UBEAC_URL)
connection.request('POST', GATEWAY_URL, json.dumps(device_world))
response = connection.getresponse()
print(response.read().decode())

if __name__ == '__main__':
main()

_const_cases.py
# WORLD CASES CONSTANTS
country = 0
w_total_cases = 1
w_new_cases = 2
w_total_deaths = 3
w_new_deaths = 4
w_total_recovered = 5
w_active_cases = 6
w_serious_critical = 7
w_tot_cases_M = 8
w_deaths_M = 9
w_total_tests = 10
w_tests_M = 11

# JSON CONSTANTS
COUNTRY_OTHER = 'Country'
USA_STATE = 'USA States'
TOTAL_CASES = 'Total Cases'
NEW_CASES = 'New Cases'
TOTAL_DEATHS = 'Total Deaths'
NEW_DEATHS = 'New Deaths'
TOTAL_RECOVERED = 'Total Recovered'
ACTIVE_CASES = 'Active Cases'
SERIOUS_CRITICAL = 'Serious Critical'
TOT_CASES_M = 'Total Cases per Million'
DEATHS_M = 'Deaths per Million'
TOTAL_TESTS = 'Total Tests'
TESTS_M = 'Tests per Million'

# EXTRA JSON CONSTANTS
TOTAL_CASES_PERCENT = 'Total Cases %'
NEW_CASES_PERCENT = 'New Cases %'
TOTAL_DEATHS_PERCENT = 'Total Deaths %'
NEW_DEATHS_PERCENT = 'New Deaths %'
TOTAL_RECOVERED_PERCENT = 'Total Recovered %'
ACTIVE_CASES_PERCENT = 'Active Cases %'
SERIOUS_CRITICAL_PERCENT = 'Serious Critical %'
DEATHS_VS_CASES = 'Deaths Rate %'
RECOVERED_VS_CASES = 'Recovery Rate %'

def get_sensor(id, value, type=None, unit=None, prefix=None, dt=None):
sensor = {
'id': id,
'data': value
}
return sensor

def get_percentage(str_num, str_dem):
if str_dem == '0':
return '0'
percent = float(str_num) / float(str_dem) * 100
return str(float("{:.2f}".format(percent)))

world_cases_collector.py
from bs4 import BeautifulSoup as bf
import requests
import _const_cases as const

num_places = 220 #number of countries

def getting_world_value(today): #getting the value from website
data_list = []
html = requests.get("https://www.worldometers.info/coronavirus")
soup = bf(html.text,'html.parser')
if today:
tag = soup("tr")[9:9 + num_places]
else:
tag = soup("tr")[239:239 + num_places]

def extract_vals(arr):
temp_list = []
arr_size = len(arr) - 2
for j in range(arr_size):
if j == 1:
temp_list.append(arr.contents[j].contents[0].contents[0])
elif j % 2 == 1:
value = arr.contents[j].contents
if len(value) == 0:
value.append('0')
value = value[0]
value = value.replace("\n", "")
value = value.replace("+", "")
value = value.replace(",", "")
value = value.replace("N/A", "")
if len(value) == 0 or value == ' ':
value = '0'
temp_list.append(value)
return temp_list

compare_list = extract_vals(tag[-1])

for i in range(len(tag)):
insert_list = extract_vals(tag[i])

def continents(arg, day):
if day:
switcher = {
212: 'North America',
213: 'Europe',
214: 'Asia',
215: 'South America',
216: 'Oceania',
217: 'Africa',
218: 'Unknown',
219: 'World',
}
else:
switcher = {
211: 'Asia',
212: 'North America',
213: 'Europe',
214: 'South America',
215: 'Oceania',
216: 'Africa',
217: 'Unknown',
218: 'World'
}
return switcher.get(arg, insert_list[const.country])

data_name = continents(i, today)
data = {
const.TOTAL_CASES : insert_list[const.w_total_cases],
const.NEW_CASES : insert_list[const.w_new_cases],
const.TOTAL_DEATHS : insert_list[const.w_total_deaths],
const.NEW_DEATHS : insert_list[const.w_new_deaths],
const.TOTAL_RECOVERED : insert_list[const.w_total_recovered],
const.ACTIVE_CASES : insert_list[const.w_active_cases],
const.SERIOUS_CRITICAL : insert_list[const.w_serious_critical],
const.TOT_CASES_M : insert_list[const.w_tot_cases_M],
const.DEATHS_M : insert_list[const.w_deaths_M],
const.TOTAL_TESTS : insert_list[const.w_total_tests],
const.TESTS_M : insert_list[const.w_tests_M],
const.TOTAL_CASES_PERCENT : const.get_percentage(insert_list[const.w_total_cases],compare_list[const.w_total_cases]),
const.NEW_CASES_PERCENT : const.get_percentage(insert_list[const.w_new_cases],compare_list[const.w_new_cases]),
const.TOTAL_DEATHS_PERCENT : const.get_percentage(insert_list[const.w_total_deaths],compare_list[const.w_total_deaths]),
const.NEW_DEATHS_PERCENT : const.get_percentage(insert_list[const.w_new_deaths],compare_list[const.w_new_deaths]),
const.TOTAL_RECOVERED_PERCENT : const.get_percentage(insert_list[const.w_total_recovered],compare_list[const.w_total_recovered]),
const.ACTIVE_CASES_PERCENT : const.get_percentage(insert_list[const.w_active_cases],compare_list[const.w_active_cases]),
const.SERIOUS_CRITICAL_PERCENT : const.get_percentage(insert_list[const.w_serious_critical],compare_list[const.w_serious_critical]),
const.DEATHS_VS_CASES : const.get_percentage(insert_list[const.w_total_deaths],insert_list[const.w_total_cases]),
const.RECOVERED_VS_CASES : const.get_percentage(insert_list[const.w_total_recovered], insert_list[const.w_total_cases])
}
data_list.append(const.get_sensor(data_name, data))
return data_list

Be the first to comment

Leave a Reply