generated from wessel/boilerplate
feat(lifecycle & hw): added mqtt connection and installation setup
This commit is contained in:
@@ -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
|
||||||
|
```
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user