Skip to content

Commit

Permalink
adding mqtt info + nodered docker
Browse files Browse the repository at this point in the history
  • Loading branch information
JAlcocerT committed Feb 17, 2024
1 parent 3c728f9 commit 5e3b242
Show file tree
Hide file tree
Showing 8 changed files with 332 additions and 8 deletions.
50 changes: 50 additions & 0 deletions Z_MQTT/C/mqtt_publish_server.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <stdio.h>
#include <stdlib.h>
#include "MQTTClient.h"

#define ADDRESS "tcp://192.168.3.200:1883"
#define CLIENTID "ExampleClientPub"
#define TOPIC "c/mqtt"
#define PAYLOAD "Hello from C!"
#define QOS 1
#define TIMEOUT 10000L

// int main(int argc, char* argv[]) {
// // MQTTClient declaration and other code for connecting, publishing, and disconnecting
// }

int main(int argc, char* argv[]) {
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;

// Initialize the client
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;

// Connect to the MQTT broker
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}

// Prepare and publish the message
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %ld seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
TIMEOUT / 1000, PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);

// Disconnect
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}
14 changes: 14 additions & 0 deletions Z_MQTT/C/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

```sh
sudo apt-get update
#sudo apt-get install libpaho-mqtt-dev
sudo apt-get install build-essential git cmake



gcc -o mqtt_publish mqtt_publish.c -lpaho-mqtt3c
./mqtt_publish
#gcc -o mqtt_publish_server mqtt_publish_server.c -lpaho-mqtt3c
#./mqtt_publish_server

```
55 changes: 55 additions & 0 deletions Z_MQTT/Node-Red/Docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: '3'
services:
node-red:
image: nodered/node-red
ports:
- "1880:1880"
volumes:
- myNodeREDdata:/data
depends_on:
- mqtt-broker

mqtt-broker:
image: emqx/emqx:5.0.0
ports:
- "1883:1883"
- "8083:8083"
- "8084:8084"
- "8883:8883"
- "18083:18083"

volumes:
myNodeREDdata:

#sudo docker-compose up -d

#docker run -it -p 1880:1880 -v myNodeREDdata:/data --name mynodered nodered/node-red

#################################
# version: '3'
# services:
# node-red:
# image: nodered/node-red
# ports:
# - "1880:1880"
# environment:
# - TZ=UTC # Optional: Set timezone if needed
# volumes:
# - ./data:/data # Optional: Mount a volume to persist data

# version: '3'
# services:
# node-red:
# image: nodered/node-red
# ports:
# - "1880:1880"
# environment:
# - TZ=UTC # Optional: Set timezone if needed
# volumes:
# - ./data:/data # Optional: Mount a volume to persist data

# mqtt-broker:
# image: emqx/emqx
# ports:
# - "1883:1883"

30 changes: 30 additions & 0 deletions Z_MQTT/Python/Python_push_distribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import time
import random
import math
import paho.mqtt.publish as publish

# MQTT Broker (EMQX) details
#broker_address = "broker.emqx.io" #local broker
broker_address = "192.168.3.200" #local network broker
port = 1883
topic = "python/mqtt"

while True:
# Generate a random value based on normal distribution
mean = 25 # Mean of the distribution
std_dev = 10 # Standard deviation of the distribution
value = random.normalvariate(mean, std_dev)
value = max(0, min(50, value)) # Ensure value is within [0, 50] range

# Message to publish
message = str(value)

# Publish the message
publish.single(topic, message, hostname=broker_address, port=port)

print(f"Message Published: {message}")

# Wait for 1 second
time.sleep(0.1)

#python3 Python_push_distribution.py
Empty file added Z_MQTT/Readme.md
Empty file.
6 changes: 2 additions & 4 deletions _posts/2021-07-21-getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,10 @@ You can also use it with the Cloud:
| **Apache Superset** | Yes | Open-source data visualization and data exploration platform. Supports SQL querying. Customizable and extensible | Requires technical knowledge for setup and customization. May have performance issues with very large datasets |
| **Kibana** | Yes | Part of the Elastic Stack, excellent for visualizing Elasticsearch data. Great for log and time-series analytics. Real-time data visualization | Primarily tailored to Elasticsearch data. Can be complex to configure and optimize. Less versatile for non-Elasticsearch data |
| **KNIME** | Yes | User-friendly, visual data pipeline design. Extensive plugin ecosystem. Good for non-programmers. Strong in data preprocessing and analysis | Can be less intuitive for complex, custom data analysis. Performance issues with very large datasets |
| **Tableau** | No | Exceptional data visualization capabilities. Intuitive and user-friendly. Strong in business intelligence | Expensive. Not open source. More focused on visualization than data modeling |
| **Python Libraries** (e.g., pandas, scikit-learn) | Yes | Highly flexible and powerful. Huge ecosystem and community. Ideal for custom, complex analysis | Requires programming knowledge. Steeper learning curve for non-programmers |
| **R Libraries** (e.g., ggplot2, dplyr) | Yes | Excellent for statistical analysis and data visualization. Large number of packages for various analyses. Strong academic and research community support | Requires programming knowledge. Less intuitive for those unfamiliar with R |
| **Alteryx** | No | Strong in data blending and preparation. Advanced analytics capabilities. Good integration with other tools | Expensive. Not open source. Steeper learning curve |
| **RapidMiner** | No | Comprehensive data science platform. Good for machine learning and predictive modeling. User-friendly with a visual approach | Free version is limited. Can be expensive for the full version. Steep learning curve for advanced features |
| **QlikView/Qlik Sense** | No | Powerful for interactive data discovery and BI. Flexible and customizable. Good data integration | Can be expensive. Steeper learning curve compared to some competitors. Not open source |

* **Others**: Grafana, Redash, Node-Red

<!--
![img-description](https://pbs.twimg.com/media/FJAFshwXoAEf9HV?format=jpg&name=large)
Expand Down
184 changes: 180 additions & 4 deletions _posts/2024-02-15-rpi-mqtt.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,29 @@ tags: [IoT, Sensors]

## Learning MQTT with a RPi

MQTT (Message Queuing Telemetry Transport) is a lightweight **messaging protocol** designed for efficient communication between devices in constrained environments, commonly used in IoT (Internet of Things) applications.



An **MQTT broker is a server** that acts as an intermediary for MQTT communication, facilitating message exchange between devices by receiving, routing, and delivering messages to subscribed clients.

Any device or software component that establishes a connection to an MQTT service using the TCP/IP protocol can be referred to as an **MQTT client**.


### Why MQTT for IoT?

MQTT is popular for IoT due to its lightweight nature, minimal bandwidth usage, and support for low-power devices, making it ideal for communication in resource-constrained environments.

### To Do list

- [ ] Send DHT Data to MongoDB
- [ ] MQTT
+ [x] Install a MQTT Client
+ [ ] Install a MQTT Broker
+ [ ] Testing the MQTT Broker
+ [ ] Test the Connection
- [ ] Node-Red

> Find the code used on this Post [here](https://github.com/JAlcocerT/RPi/tree/main/Z_IoT).
## Install MQTT Client

Expand All @@ -32,20 +46,46 @@ flatpak install flathub com.emqx.MQTTX

## Install MQTT Broker

For simplicity, we can install EMQx with [Docker using this Image](https://hub.docker.com/_/emqx)

```sh
docker pull emqx/emqx:5.5.0
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.5.0
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 8883:8883 -p 18083:18083 emqx/emqx:5.0.0 #5.5.0
```

You have other MQTT Broker options like [Eclipse Mosquitto](https://github.com/eclipse/mosquitto)
You have other MQTT Broker options like [Eclipse Mosquitto](https://github.com/eclipse/mosquitto) or [VerneMQ](https://github.com/vernemq/vernemq).

[Mosquitto supports](https://github.com/docker-library/official-images#architectures-other-than-amd64) many CPU architectures out of the box.

If you have a Raspberry 32bits like me, you can use [this Mosquitto Image](https://hub.docker.com/r/mbixtech/arm32v7-mosquitto) instead, as the MQTT Broker

```sh
docker run -d -e TZ=Europe/Madrid -p 1883:1883 mbixtech/arm32v7-mosquitto --name mosquitto
#https://hub.docker.com/r/panuwitp/mosquitto-arm
#https://github.com/somsakc/docker-mosquitto

#docker ps --format '{{.Names}}'
#docker logs mosquitto
#docker exec -it mosquitto /bin/sh
```

### Testing EMQx

#### Sending MQTT Message with Python

We just need Python and Paho installed:

```sh
pip install paho-mqtt
```

Create this Python script:

```py
import paho.mqtt.publish as publish

# MQTT Broker (EMQX) details
broker_address = "broker.emqx.io"
broker_address = "broker.emqx.io" #change to any other adress, like 192.168.3.200 at Home
port = 1883
topic = "python/mqtt"

Expand All @@ -57,7 +97,143 @@ publish.single(topic, message, hostname=broker_address, port=port)
print(f"Message Published to {topic}")
```

Then just execute it:

```sh
python3 python-push.py
```

#### Sending MQTT Message with C

We will need C installed and the MQTTClient package - which we will build from source:

```sh
sudo apt-get update
sudo apt-get install build-essential git cmake

git clone https://github.com/eclipse/paho.mqtt.c.git
cd paho.mqtt.c

cmake -Bbuild -H. -DPAHO_WITH_SSL=OFF
cd build
make
sudo make install

```


Create this C script:

```c
#include <stdio.h>
#include <stdlib.h>
#include "MQTTClient.h"

#define ADDRESS "tcp://192.168.3.200:1883" //or any other local IP
#define CLIENTID "ExampleClientPub"
#define TOPIC "c/mqtt"
#define PAYLOAD "Hello from C!"
#define QOS 1
#define TIMEOUT 10000L

// int main(int argc, char* argv[]) {
// // MQTTClient declaration and other code for connecting, publishing, and disconnecting
// }

int main(int argc, char* argv[]) {
MQTTClient client;
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;

// Initialize the client
MQTTClient_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;

// Connect to the MQTT broker
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
printf("Failed to connect, return code %d\n", rc);
exit(-1);
}

// Prepare and publish the message
pubmsg.payload = PAYLOAD;
pubmsg.payloadlen = strlen(PAYLOAD);
pubmsg.qos = QOS;
pubmsg.retained = 0;
MQTTClient_publishMessage(client, TOPIC, &pubmsg, &token);
printf("Waiting for up to %ld seconds for publication of %s\n"
"on topic %s for client with ClientID: %s\n",
TIMEOUT / 1000, PAYLOAD, TOPIC, CLIENTID);
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
printf("Message with delivery token %d delivered\n", token);

// Disconnect
MQTTClient_disconnect(client, 10000);
MQTTClient_destroy(&client);
return rc;
}

```
Then we can compile our code
```sh
gcc -o mqtt_publish_server mqtt_publish_server.c -lpaho-mqtt3c #compile
./mqtt_publish_server #execute
```


## Node-Red

Install Node-Red with Docker - we will use [this image](https://hub.docker.com/r/nodered/node-red/):

```sh
docker run -it -p 1880:1880 -v myNodeREDdata:/data --name mynodered nodered/node-red
```

You can access it now at: `localhost:1880`

Then in the UI: go tu user settings -> Install and add both ([node-red-contrib-open](https://flows.nodered.org/node/node-red-contrib-open) and [node-red-dashboard](https://flows.nodered.org/node/node-red-dashboard))


> You can use [this docker-compose] to deploy Node-Red together with EMQx

---

## FAQ


### How to Deploy Node-Red with Docker

### How to Deploy EMQx with DOcker


### How to visualize MQTT Data

* With Grafana - https://grafana.com/grafana/plugins/grafana-mqtt-datasource/
*

### How to Push Data to MQTT

* With Python - https://www.emqx.com/en/blog/how-to-use-mqtt-in-python
* With C
* With Rust - https://www.emqx.com/en/blog/how-to-use-mqtt-in-rust

### Content that was helpful to put this together

* Push MQTT Data to Node-Red Gauge https://www.youtube.com/watch?v=c3WYSUaFZqA
* Setup Dashboard tools on Node-Red: https://www.youtube.com/watch?v=TNHAZxwB-9o

#### What about CanBus?

CAN bus is like a private walkie-talkie system used by different parts of a car to talk to each other quickly and directly, helping them work together smoothly.

But MQTT is more like sending messages through a mail system, where you write a message, put it in an envelope with an address (called a topic), and send it to a central post office (called a broker), which then delivers the message to anyone who is interested in receiving it.

While CAN bus is great for fast and direct communication within a single place, like a car, MQTT is better for sending messages between different places or devices, like smart home gadgets, over the internet.

This might be helpful: https://github.com/linux-can/can-utils
Loading

0 comments on commit 5e3b242

Please sign in to comment.