This is a basic temperature and humidity device connected to a MQTT-server running in the same docker compose container as the TIG-stack.
The MQTT-server recieves measurements from the device, sends it to telegraf, telegraf sends it to influx and finally, grafana uses the data from influx to visualise it in a graph.
Time estimate: 24h
# Objective
I choose this project with the only reason being it included many new technical aspects on the software point of view, it doesnt really fill any real-use-purpose for me, this project was more about to get a good overview of a fullstack IoT project.
# Material
| Product | Price |
|:------- |:-----: |
|Rasberry Pi Pico W |109 SEK |
|DHT11 |49 SEK |
|Breadboard |49 SEK |
|Jumperwires (30pcs) |49 SEK |
|**Total** |**256 SEK**|
Not a complicated set of hardware.
A Pico W mounted to the breadboard, some jumpercables to connect to the DHT11 sensor.
# Complete setup tutorial
## Flashing the Pico W
To make the Pico W ready for use we have to flash it `(Install a firmware)`.
1. Connect the micro-USB to the Pico
2. Press & hold the BOOTSEL-button mounted on top of the Pico
3. While still holding the BOOTSEL-button, connect the other end of the usb to your computer and then release the button
4. Open up the device `RPI-RP2`
5. Go to [this](https://micropython.org/resources/firmware/rp2-pico-w-20230426-v1.20.0.uf2) page and download the latest version of firmware
6. Drag the file in to the RPI-RP2 device. `the window should close`
7. Done :tada:
## IDE & Extension
Now lets cover the steps to setup the work environment with VScode, Node.js & Pymakr extension
1. Download and install [VScode](https://code.visualstudio.com/download)
2. Download and install [Node.js](https://nodejs.org/en)
3. Start VScode and head to the extensions tab on the left, search for Pymakr and click install.

4. There should now be a new tab in left sidemenu, click on it and then `Create project`

5. Create a new folder and click `Use this folder`.
6. A new window in the top should appear asking for project name, enter preferred name
7. Click `empty`
8. Select your Pico W device
9. Done :tada:
## Uploading code to Pico
1. Click the Lightning icon to connect the Pico
2. Click the cloud with an up-arrow in it
3. Click on `...` to the rigth of the other icons
4. Select `Hard reset device` and then press the lightningicon again to connect the device. the device should automaticly run the program.
# Putting everything together
The setup is as basic as it gets

# Platform
The plattform is based on the TIG-stack, and a local MQTT-broker, they are all included in the docker compose setup and can therefore is very handy to start up.
Lets go through the different parts of this stack.
## Telegraf
Telegraf is the data collector and processor, Telegraf connects to the broker and subscribes to a topic. When it gets a message it formats it to preferred format and sends it to the database `Influxdb`
## Influxdb
Influxdb is a timeseries database, wich means it it specialized to store and manage timestamped data and
continuously changing data, wich makes this a perfect choise for logging and comparing data based on time.
## Grafana
Grafana is a webapplication for data monitoring, with Grafana you can setup advanced data-visualization graphs and webhooks based on the data it monitors.
## Eclipse-mosquitto
Eclipse-mosquitto is a open-source message broker that uses the MQTT-protocol, making it a strong candidate for the IoT ecosystem
## Stack visualization

# The code
```mermaid
graph LR
Connect-wifi --> Connect-MQTT --> Measuring --> Sending
```
## Connecting to wifi
Some improvements can be made here, like a timeout functionality on the connect attempts, or a limit amount of retries.
```python=1
from credentials import wifi
import network
def connectWifi():
from time import sleep
wlan = network.WLAN(network.STA_IF)
if not wlan.isconnected():
print('connecting to network...')
wlan.active(True)
wlan.connect(wifi["SSID"], wifi["PW"])
print('Waiting for connection...', end='')
while not wlan.isconnected() and wlan.status() >= 0:
print('.', end='')
sleep(1)
ip = wlan.ifconfig()[0]
print('\nConnected on {}'.format(ip))
try:
connectWifi()
except Exception as err:
print('Could not connect to {}. Error: {}'
.format(wifi["SSID"], err))
```
## Connecting to MQTT-broker "telegraf.conf"
```python=1
[agent]
flush_interval = "15s"
interval = "15s"
[[inputs.mqtt_consumer]]
name_override = "mqtt-broker"
servers = ["mqtt://172.19.0.3:1883"]
qos = 0
connection_timeout = "30s"
topics = [ "devices" ]
client_id = "mosquitto"
data_format = "json"
[[outputs.influxdb]]
database = "influxdb"
urls = [ "http://influxdb:8086" ]
username = "influx"
password = "influx"
```
:::warning
:warning:
Since the MQTT-broker is running on the same container as the TIG-stack you need to get the ip from the MQTT-container within the docker-compose network.
Inspect docker compose network:
>$ docker network inspect <project-name_network-name>
:::
## Main function
Here we define the client and using a imported function ive made to handle and displaying connection to the MQTT-broker `mqttConnect()` at line 17 returns a boolean to be used in the while conditional.
```python=1
import dht
import ubinascii
from time import sleep
import json
from machine import Pin, unique_id
from umqttsimple import MQTTClient
from mqttConnect import mqttConnect
def main():
tempSensor = dht.DHT11(Pin(0))
CLIENT_ID = ubinascii.hexlify('Temp-and-humid')
MQTT_IP = '192.168.1.6'
mqttClient = MQTTClient(CLIENT_ID, MQTT_IP, keepalive=60)
connectedToBroker = mqttConnect(mqttClient)
while connectedToBroker:
try:
tempSensor.measure()
temperature = tempSensor.temperature()
humidity = tempSensor.humidity()
print('Temperature is {} degrees Celsius and Humidity is {}%'
.format(temperature, humidity))
payload = {
"device": CLIENT_ID,
"Temp": temperature,
"Humid":humidity,
}
mqttClient.publish(b'devices', json.dumps(payload))
sleep(3)
except KeyboardInterrupt as e:
print('Interrupted \n Error: ', e)
if __name__ == '__main__':
main()
```
:::info
:information_source: Tips regarding ip here, 0.0.0.0/localhost wont work, you will have to get the networkadapter ip
windows > cmd
> $ ipconfig /all
It has to be the same as you are using on your computer
:::
## mqttConnect()
This is the function used in the main() at line 17. It simply gives feedback on successful connection and attempts to connect 3 times before returning false.
```python=1
def mqttConnect(mqttClient):
print('Connecting to MQTT server')
for i in range(3):
try:
mqttClient.connect()
print('connected to MQTT broker')
return True
except Exception as e:
if i < 3:
print('Connection failed, retrying: {}/3'.format(i+1))
else:
print('Connection failed on all attempts.. \n Error: ', e)
return False
```
# Transmitting the data / connectivity
Im using wifi for simplicity in this case and the data from the sensor is being sent every 3seconds as a json object that has been serialized to bytes with `json.dumps()`, serialized to bytes because i use the mqtt-protocol.
this gets sent to the MQTT-broker to the topic `devices` and data is stored and queried with reference with the client-name
# Presenting the data
Grafana had plenty of options data visualization, i settled with a simple temp-meter and a graph showing both temp and humidity in the same graph.The the database gets fresh data every 15seconds.
here you can clearly see the two times i melted the sensor protection with my lighter... 2times...

# Finalizing the design
I learned so much doing this project and overall i think i the endresult is acceptable, there is some parts i wish i had the time to learn and improve, like authentication in the MQTT-broker and webhooks for example.
I spent quite alot of time trying to integrate the MQTT-broker in the same docker compose setup, wich lead me to researching of the `docker network`, so i learned alot of networking overall doing that, since my knowledge of networks was about 0% from the start.
This is the overview of my workspace with the majority of the project in the picture, its been fun, and messy.
