Many city councils (and even companies) have started to publish data from their weather stations and air quality systems under Open Data initiatives. Still, this data is not always published in real time and in some cases there are some doubts about whether the data have been modified before being published.
Thinking of the smart districts of the future, this data should be open, reliable and ready to be consumed by devices and services locally (and even globally). From this idea arises this simple proof of concept, in which it is shown how TVOC and CO2 values obtained from a sensor are sent to the Tangle.
Architecture and ComponentsThe picture above summarises the components and connections. The sensor (bottom right) gets the TVOC and CO2 values from the environment. These values are transferred to the Raspberry PI via Bluetooth and the raspberry uses the IOTA Python API library to store the information in the Tangle. This information can be read later by different clients: using a browser or with a simple Python program.
Set UpThe sensor: As in my previous project, I've used the NXP Rapid IoT Prototyping Kit as a sensor. The Rapid IoT device provides TVOC and CO2 values among other measures and supports Bluetooth, so it was a good option for this proof of concept.
In order to get these two metrics and export their values through Bluetooth, you may need to install a a firmware in the device.
The firmware file is attached in the code section. More details on the source code and the design can be found here. You can follow the step 3 "Build, Run" of the NXP getting started guide for loading this firmware (APM_IOTA_firmware_F.bin) in your Rapid IoT device.
Python: The Python code used in this project relies in two main libraries: PyOTA and PyGatt. So, as first step, we will create a Python3 virtual environment and install both using PIP.
python3 -m venv venv
source venv/bin/activate
pip install pyota[ccurl]
pip install pygatt
(Note: We will Install PyOTA together the optional C extension which improves the performance of its crypto operations)
(Note: In case you want to use the same libraries and versions I am using, please use the attached file pip_requirements.txt)
pip install -r pip_requirements.txt
IOTA:
This proof of concept will use the seed and the addresses I created, but if you want to use your own seed and addresses you can do it as follows.
- Create a seed:
cat /dev/urandom | tr -dc A-Z9 | head -c${1:-81} > my_seed.txt
- Create an address from a seed
[...]
idx=0
generator = iota.crypto.addresses.AddressGenerator(seed)
addr = generator.get_addresses(start=idx, count=1)
print(addr[0])
[...]
(Note: the full code for a very simple address generator is attached:iota_create_address.py)
(Optional) Running your own IRI nodeIf you want to run your own IRI (IOTA reference implementation) node and use it to connect to the IOTA network instead of using someone else's node, you can do it easily with Docker.
docker run --net=host --name iota-node -v iota.ini:/iri/iota.ini iotaledger/iri:latest
You can find more info about the docker IRI image in the next URL: https://hub.docker.com/r/iotaledger/iri/ and you can test that your IRI node is working using the next command:
curl -X POST -H "X-IOTA-API-Version: 1.0" -H "Content-Type: application/json" -d '{"command": "getNodeInfo"}' http://localhost:14265
If your IRI node is working correcly you will get the information of your node.
Reading the data and storing it in the TangleOnce the libraries are installed and the seed and destination address defined, we can write the code for reading the data from the sensor and for uploading it to the Tangle.
The next function shows how the data is read from the sensor. Basically, the function requests (using char_read) the TVOC and CO2 Bluetooth Characteristics of the sensor. Later, the name of the sensor, the value of both metrics and the timestamp are stored so they can be uploaded to the Tangle.
SENSOR_ADDRESS = "00:00:00:00:00:00" # Put here your sensor address
CHAR_UUIDS = {
"tvoc" : "08d41e61-ac11-40a2-a95a-e0e0fb5336f9",
"co2" : "08d41e61-ac11-40a2-a95a-e0e0fb5336fa",
}
def read_sensor():
""" Read sensor values """
measurements = []
adapter = pygatt.GATTToolBackend()
try:
adapter.start()
conn = adapter.connect(SENSOR_ADDRESS)
time_info = int(time.time())
# Get sensor values
sensor_values = {}
for sensor in CHAR_UUIDS:
value = conn.char_read(CHAR_UUIDS[sensor])
sensor_values[sensor] = float(value.decode("utf-8").rstrip('\x00'))
# Prepare values to be transferred
for sensor in sensor_values:
measurement = {"measurement" : sensor, "time" : time_info, "value" : sensor_values[sensor]}
measurements.append(measurement)
except Exception as e:
print("Error: ", e)
finally:
adapter.stop()
return measurements
The next few lines show the code for transferring the data to the Tangle. (Note that this proof of concept will use 0 value transfers for storing the data in the Tangle. This would be much more efficient using Masked Authenticated Messaging (MAM) and data streams, but the Python implementation of the IOTA Library does not yet have native MAM support.)
Basically, we connect to an IRI ("https://potato.iotasalad.org:14265" in this case, but you can use http://localhost:14265 if you followed the optional step of launching your own IRI node.)
And we send a transfer to our destination address with the sensor data in JSON format.
def transfer_to_iota():
""" Transfers sensor data to the tangle"""
seed = "INSERTYOURSEEDHERE"
dest = "WQVHGZMNXUBTR99WQRAQJCOCNHYUTNTI9DMDZKXITVVEFFFSFJTFXJNKVZGDGHFRSKLXTZCDRQJLQPO9W"
msg = read_sensor()
print(msg)
api = iota.Iota("https://potato.iotasalad.org:14265", seed)
bundle = api.send_transfer(
depth=3,
transfers=[
iota.ProposedTransaction(
address=iota.Address(dest),
value=0,
tag=iota.Tag(b'SENSORDATA'),
message=iota.TryteString.from_string(json.dumps(msg)),
)])
print("Transferred bundle hash: %s " %(bundle['bundle'].hash))
(Note: the full Python script can be found in the attachment section: iota_transfer_sensor_data.py. This Python script can be added to the /etc/crontab to be launched every few minutes)
Reading data from the TangleReading from the Tangle can be done with a few lines of Python. Basically you can access to all transactions of an specific address (addr) and request the signature_message_fragment of each transaction (see source code attached: iota_get_info.py) :
addr = "WQVHGZMNXUBTR99WQRAQJCOCNHYUTNTI9DMDZKXITVVEFFFSFJTFXJNKVZGDGHFRSKLXTZCDRQJLQPO9W"
addresses = [addr,]
api = Iota("https://pool.trytes.eu", b'INSERTYOURSEEDHERE')
transactions = find_transaction_objects(adapter=api.adapter, addresses=addresses)
for transaction in transactions:
message = transaction.signature_message_fragment
print(message.decode())
This code should result in something like this:
python iota_get_info.py
[{"time": 1553975794, "value": 97.0, "measurement": "tvoc"}, {"time": 1553975794, "value": 1037.0, "measurement": "co2"}]
[{"value": 99.0, "time": 1553975340, "measurement": "tvoc"}, {"value": 1056.0, "time": 1553975340, "measurement": "co2"}]
[{"value": 1056.0, "measurement": "co2", "time": 1553976125}, {"value": 99.0, "measurement": "tvoc", "time": 1553976125}]
[{"measurement": "co2", "value": 1037.0, "time": 1553976015}, {"measurement": "tvoc", "value": 97.0, "time": 1553976015}]
[{"time": 1553974321, "value": 98.0, "measurement": "tvoc"}, {"time": 1553974321, "value": 1045.0, "measurement": "co2"}]
[...]
[{"value": 99.0, "time": 1553973762, "measurement": "tvoc"}, {"value": 1056.0, "time": 1553973762, "measurement": "co2"}]
[{"time": 1553974096, "measurement": "co2", "value": 1004.0}, {"time": 1553974096, "measurement": "tvoc", "value": 92.0}]
[{"value": 101.0, "time": 1553974985, "measurement": "tvoc"}, {"value": 1064.0, "time": 1553974985, "measurement": "co2"}]
[{"value": 95.0, "time": 1553974204, "measurement": "tvoc"}, {"value": 1029.0, "time": 1553974204, "measurement": "co2"}]
[{"time": 1553974871, "value": 1076.0, "measurement": "co2"}, {"time": 1553974871, "value": 102.0, "measurement": "tvoc"}]
This info with the TVOC/Co2 values could be further processed, stored or analysed.
The Tangle can be also explored using the web site https://thetangle.org. For example
https://thetangle.org/address/WQVHGZMNXUBTR99WQRAQJCOCNHYUTNTI9DMDZKXITVVEFFFSFJTFXJNKVZGDGHFRSKLXTZCDRQJLQPO9W
shows all the transaction related to the address: WQVHGZMN...RQJLQPO9W. The image below shows one of the transaction with the sensor info in the bottom of the image.
The project has helped me to get to know a little about IOTA and to imagine how the smart districts of the future can be. I hope you enjoyed reading the project and that you can replicate it, improve it and learn from it.
Comments