feat(lifecycle & hw): added mqtt connection and installation setup

This commit is contained in:
2025-10-30 19:56:57 +01:00
parent 713d354a9b
commit 8b041681cc
5 changed files with 172 additions and 11 deletions

View File

@@ -41,3 +41,54 @@ You can configure specific database settings in the `docker-compose.yaml` in the
ros2 launch g2_2025_grade_calculator_pkg grade_calculator.launch.xml ros2 launch g2_2025_grade_calculator_pkg grade_calculator.launch.xml
``` ```
To change parameters when using the launch file it will need to be edited in the `src/g2_2025_grade_calculator_pkg/launch` folder. All parameters are already added to this document and thus only the values will need to be changed To change parameters when using the launch file it will need to be edited in the `src/g2_2025_grade_calculator_pkg/launch` folder. All parameters are already added to this document and thus only the values will need to be changed
### installation and setup for mqtt
```bash
sudo apt install mosquitto
sudo apt-get install libpaho-mqtt-dev
git clone https://github.com/eclipse/paho.mqtt.cpp
cd paho.mqtt.cpp
git co v1.5.4
git submodule init
git submodule update
cmake -Bbuild -H. -DPAHO_WITH_MQTT_C=ON -DPAHO_BUILD_EXAMPLES=ON
sudo cmake --build build/ --target install
```
## for launching lifecycle mqtt node
first:
```bash
ros2 run g2_2025_imu_reader_pkg g2_2025_lifecycle_node --ros-args -p comm_t:='mqtt'
```
in other terminal:
```bash
mosquitto -p 1884
```
and in other terminal to inialize the subsecriber:
```bash
ros2 lifecycle set /lifecycle_manager configure
ros2 lifecycle set /lifecycle_manager activate
```
an finally publish a mesg to the sub in other terminal:
```bash
mosquitto_pub -h localhost -p 1884 -t "esp32/imu" -m "nirvana"
```
close conn via:
```bash
ros2 lifecycle set /lifecycle_manager deactivate
```

View File

@@ -53,6 +53,13 @@ target_include_directories(g2_2025_lifecycle_node PRIVATE
) )
ament_target_dependencies(g2_2025_lifecycle_node rclcpp rclcpp_lifecycle std_msgs sensor_msgs) ament_target_dependencies(g2_2025_lifecycle_node rclcpp rclcpp_lifecycle std_msgs sensor_msgs)
target_link_libraries(g2_2025_lifecycle_node
paho-mqttpp3
paho-mqtt3a
)
install( install(
TARGETS TARGETS
imu_database_writer imu_database_writer
@@ -60,6 +67,8 @@ install(
DESTINATION lib/${PROJECT_NAME} DESTINATION lib/${PROJECT_NAME}
) )
set_target_properties(g2_2025_lifecycle_node PROPERTIES INSTALL_RPATH "/usr/local/lib")
if(BUILD_TESTING) if(BUILD_TESTING)
find_package(ament_cmake_gtest REQUIRED) find_package(ament_cmake_gtest REQUIRED)

View File

@@ -45,4 +45,61 @@ void HardwareInterface::close_device() {
} }
class callback : public virtual mqtt::callback {
public:
void message_arrived(mqtt::const_message_ptr msg) override {
// Use a named logger since this class isn't a rclcpp::Node
RCLCPP_INFO(rclcpp::get_logger("hardware_interface"),
"Message received: %s", msg->get_payload_str().c_str());
}
};
void HardwareInterface::mqtt_listener() {
// Create persistent client and callback so they outlive this function.
if (!mqtt_client) {
mqtt_client = std::make_shared<mqtt::async_client>(SERVER_ADDRESS, CLIENT_ID);
}
if (!mqtt_cb) {
mqtt_cb = std::make_shared<callback>();
}
// attach callback (expects a reference)
mqtt_client->set_callback(*mqtt_cb);
mqtt::connect_options connOpts;
connOpts.set_keep_alive_interval(20);
connOpts.set_clean_session(true);
try {
mqtt_client->connect(connOpts)->wait();
RCLCPP_INFO(this->get_logger(), "Connected to broker");
mqtt_client->subscribe(TOPIC, 1)->wait();
RCLCPP_INFO(this->get_logger(), "Subscribed to topic: %s", TOPIC.c_str());
// Note: do not disconnect here; keep client alive until close_mqtt_conn()
} catch (const mqtt::exception& exc) {
RCLCPP_ERROR(this->get_logger(), "Error: %s", exc.what());
}
}
void HardwareInterface::close_mqtt_conn() {
try {
if (mqtt_client) {
if (mqtt_client->is_connected()) {
mqtt_client->disconnect()->wait();
RCLCPP_INFO(this->get_logger(), "Disconnected MQTT client");
}
// reset to allow destruction
mqtt_client.reset();
}
if (mqtt_cb) {
mqtt_cb.reset();
}
} catch (const mqtt::exception& exc) {
RCLCPP_ERROR(this->get_logger(), "Error while disconnecting MQTT: %s", exc.what());
}
}
} // namespace assignments::two::g2_2025_lifecycle_node } // namespace assignments::two::g2_2025_lifecycle_node

View File

@@ -19,6 +19,11 @@
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include "config/serialib.h" #include "config/serialib.h"
#include <iostream>
#include <mqtt/client.h>
#include <mqtt/async_client.h>
#include "rclcpp/rclcpp.hpp" #include "rclcpp/rclcpp.hpp"
#include "rclcpp_lifecycle/lifecycle_node.hpp" #include "rclcpp_lifecycle/lifecycle_node.hpp"
@@ -34,8 +39,18 @@ public:
bool open_device(const std::string& device_path, int baud_rate); bool open_device(const std::string& device_path, int baud_rate);
bool is_device_open(); bool is_device_open();
void close_device(); void close_device();
void mqtt_listener();
void close_mqtt_conn();
private: private:
serialib serial; serialib serial;
// MQTT defaults. Use static inline so they can be initialized in-class.
static inline const std::string SERVER_ADDRESS = "tcp://localhost:1884";
static inline const std::string CLIENT_ID = "cpp_mqtt_client";
static inline const std::string TOPIC = "esp32/imu";
std::shared_ptr<mqtt::async_client> mqtt_client;
std::shared_ptr<mqtt::callback> mqtt_cb;
}; };
} // namespace assignments::two::g2_2025_lifecycle_node } // namespace assignments::two::g2_2025_lifecycle_node

View File

@@ -13,7 +13,7 @@ LifecycleManager::LifecycleManager() : rclcpp_lifecycle::LifecycleNode("lifecycl
device_path_ = this->declare_parameter<std::string>("device_path", "/dev/ttyUSB0"); device_path_ = this->declare_parameter<std::string>("device_path", "/dev/ttyUSB0");
baudrate_ = this->declare_parameter<int>("baudrate", 115200); baudrate_ = this->declare_parameter<int>("baudrate", 115200);
communication_type_ = this->declare_parameter<std::string>("communication_type", "serial"); // placeholder default serial or param mqtt communication_type_ = this->declare_parameter<std::string>("comm_t", "serial"); // placeholder default serial or param mqtt
// hardware interface instance // hardware interface instance
hw_interface = std::make_shared<HardwareInterface>(); hw_interface = std::make_shared<HardwareInterface>();
@@ -39,12 +39,21 @@ void LifecycleManager::publish_imu_data(const std::string& data) { // placeholde
rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
LifecycleManager::on_configure(const rclcpp_lifecycle::State&) { LifecycleManager::on_configure(const rclcpp_lifecycle::State&) {
RCLCPP_INFO(this->get_logger(), "configuring lifecycle..."); RCLCPP_INFO(this->get_logger(), "configuring lifecycle...");
if (communication_type_ == "mqtt") {
// RCLCPP_INFO(this->get_logger(), "Setting up MQTT communication...");
// hw_interface->mqtt_listener();
} else {
RCLCPP_INFO(this->get_logger(), "Using serial communication.");
if (!hw_interface->open_device(device_path_, baudrate_)) { if (!hw_interface->open_device(device_path_, baudrate_)) {
RCLCPP_ERROR(this->get_logger(), "Failed to open hardware device during configuration."); RCLCPP_ERROR(this->get_logger(), "Failed to open hardware device during configuration.");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE; return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
} }
}
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS; return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
} }
@@ -53,10 +62,24 @@ rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn
LifecycleManager::on_activate(const rclcpp_lifecycle::State&) { LifecycleManager::on_activate(const rclcpp_lifecycle::State&) {
RCLCPP_INFO(this->get_logger(), "activating lifecycle..."); RCLCPP_INFO(this->get_logger(), "activating lifecycle...");
if (communication_type_ == "mqtt") {
RCLCPP_INFO(this->get_logger(), "Setting up MQTT communication...");
hw_interface->mqtt_listener();
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
} else {
RCLCPP_INFO(this->get_logger(), "Using serial communication.");
if (!hw_interface->is_device_open()) { if (!hw_interface->is_device_open()) {
RCLCPP_ERROR(this->get_logger(), "Hardware device is not open during activation."); RCLCPP_ERROR(this->get_logger(), "Hardware device is not open during activation.");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE; return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
} }
if (!hw_interface->open_device(device_path_, baudrate_)) {
RCLCPP_ERROR(this->get_logger(), "Failed to open hardware device during configuration.");
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::FAILURE;
}
}
RCLCPP_INFO(this->get_logger(), "Hardware device is open, starting data read..."); RCLCPP_INFO(this->get_logger(), "Hardware device is open, starting data read...");
@@ -71,7 +94,13 @@ LifecycleManager::on_deactivate(const rclcpp_lifecycle::State&) {
RCLCPP_INFO(this->get_logger(), "deactivating lifecycle..."); RCLCPP_INFO(this->get_logger(), "deactivating lifecycle...");
if (communication_type_ == "mqtt")
{
hw_interface->close_mqtt_conn();
} else {
hw_interface->close_device(); hw_interface->close_device();
}
return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS; return rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn::SUCCESS;
} }