Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bluetooth_monitor): add functionality to monitor Bluetooth connection #862

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions system/bluetooth_monitor/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
cmake_minimum_required(VERSION 3.5)
project(bluetooth_monitor)

### Dependencies
find_package(autoware_cmake REQUIRED)
autoware_package()

ament_auto_add_library(bluetooth_monitor_lib SHARED
src/bluetooth_monitor.cpp
)

### Target executable
ament_auto_add_executable(l2ping_service
service/main.cpp
service/l2ping_service.cpp
service/l2ping.cpp
)

find_package(Boost REQUIRED COMPONENTS
serialization
)

## Specify libraries to link a library or executable target against
target_link_libraries(bluetooth_monitor_lib ${Boost_LIBRARIES})
target_link_libraries(l2ping_service ${Boost_LIBRARIES})

rclcpp_components_register_node(bluetooth_monitor_lib
PLUGIN "BluetoothMonitor"
EXECUTABLE bluetooth_monitor
)

ament_auto_package(INSTALL_TO_SHARE
config
launch
)
84 changes: 84 additions & 0 deletions system/bluetooth_monitor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# bluetooth_monitor

## Description

This node monitors a Bluetooth connection to a wireless device by using L2ping.<br>
L2ping generates PING echo command on Bluetooth L2CAP layer, and it is able to receive and check echo response from a wireless device.

## Block diagram

L2ping is only allowed for root by default, so this package provides the following approach to minimize security risks as much as possible:

- Provide a small program named `l2ping_service` which performs L2ping and provides wireless device information to `bluetooth_monitor` by using socket programming.
- `bluetooth_monitor` is able to know wireless device information and L2ping status as an unprivileged user since those information are sent by socket communication.

![block_diagram](docs/block_diagram.drawio.svg)

## Output

### <u>bluetooth_monitor: bluetooth_connection</u>

<b>[summary]</b>

| level | message |
| ----- | -------------- |
| OK | OK |
| WARN | RTT warning |
| ERROR | Lost |
| | Function error |

<b>[values]</b>

| key | value (example) |
| -------------------------- | ----------------------------------------------------------------------- |
| Device [0-9]: Status | OK / RTT warning / Verify error / Lost / Ping rejected / Function error |
| Device [0-9]: Name | Wireless Controller |
| Device [0-9]: Manufacturer | MediaTek, Inc. |
| Device [0-9]: Address | AA:BB:CC:DD:EE:FF |
| Device [0-9]: RTT | 0.00ms |

- The following key will be added when `bluetooth_monitor` reports `Function error`.<br>
ex.) The `connect` system call failed.

| key (example) | value (example) |
| --------------------- | ------------------------- |
| Device [0-9]: connect | No such file or directory |

## Parameters

| Name | Type | Default Value | Explanation |
| ----------- | ------ | ------------- | --------------------------------------------------------- |
| `port` | int | 7640 | Port number to connect to L2ping service. |
| `timeout` | int | 5 | Wait timeout seconds for the response. |
| `rtt_warn` | float | 0.00 | RTT(Round-Trip Time) to generate warn. |
| `addresses` | string | \* | List of bluetooth address of wireless devices to monitor. |

- `rtt_warn`

- **0.00(zero)**: Disable checking RTT
- **otherwise**: Check RTT with specified seconds

- `addresses`
- **\***: All connected devices
- **AA:BB:CC:DD:EE:FF**: You can specify a device to monitor by setting a Bluetooth address

## Instructions before starting

- You can skip this instructions if you run `l2ping_service` as root user.

1. Assign capability to `l2ping_service` since L2ping requires `cap_net_raw+eip` capability.

```sh
sudo setcap 'cap_net_raw+eip' ./build/bluetooth_monitor/l2ping_service
```

2. Run `l2ping_service` and `bluetooth_monitor`.

```sh
./build/bluetooth_monitor/l2ping_service
ros2 launch bluetooth_monitor bluetooth_monitor.launch.xml
```

## Known limitations and issues

None.
7 changes: 7 additions & 0 deletions system/bluetooth_monitor/config/bluetooth_monitor.param.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
/**:
ros__parameters:
port: 7640
timeout: 5
rtt_warn: 0.00
addresses: ["4C:B9:9B:6E:7F:9A"]
3,441 changes: 3,441 additions & 0 deletions system/bluetooth_monitor/docs/block_diagram.drawio.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// Copyright 2022 The Autoware Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BLUETOOTH_MONITOR__BLUETOOTH_MONITOR_HPP_
#define BLUETOOTH_MONITOR__BLUETOOTH_MONITOR_HPP_

#include "bluetooth_monitor/service/l2ping_interface.hpp"

#include <diagnostic_updater/diagnostic_updater.hpp>
#include <rclcpp/rclcpp.hpp>

#include <map>
#include <string>
#include <vector>

class BluetoothMonitor : public rclcpp::Node
{
public:
/**
* @brief Constructor
* @param [in] options Options associated with this node
*/
explicit BluetoothMonitor(const rclcpp::NodeOptions & options);

protected:
/**
* @brief Connect to L2ping service
* @param [out] stat Diagnostic message passed directly to diagnostic publish calls
* @return true on success, false on error
* @note NOLINT syntax is needed since this function asks for a non-const reference
* to pass diagnostic message updated in this function to diagnostic publish calls.
*/
bool connectService(
diagnostic_updater::DiagnosticStatusWrapper & stat); // NOLINT(runtime/references)

/**
* @brief Send L2ping configuration to L2ping service
* @param [out] stat Diagnostic message passed directly to diagnostic publish calls
* @return true on success, false on error
* @note NOLINT syntax is needed since this function asks for a non-const reference
* to pass diagnostic message updated in this function to diagnostic publish calls.
*/
bool sendConfig(
diagnostic_updater::DiagnosticStatusWrapper & stat); // NOLINT(runtime/references)

/**
* @brief Receive data from L2ping service
* @param [out] stat Diagnostic message passed directly to diagnostic publish calls
* @return true on success, false on error
* @note NOLINT syntax is needed since this function asks for a non-const reference
* to pass diagnostic message updated in this function to diagnostic publish calls.
*/
bool receiveData(diagnostic_updater::DiagnosticStatusWrapper & stat);

/**
* @brief Close connection with L2ping service
*/
void closeConnection();

/**
* @brief Set error level of diagnostic status
* @param [out] stat Diagnostic message passed directly to diagnostic publish calls
* @note NOLINT syntax is needed since diagnostic_updater asks for a non-const reference
* to pass diagnostic message updated in this function to diagnostic publish calls.
*/
void setErrorLevel(
diagnostic_updater::DiagnosticStatusWrapper & stat); // NOLINT(runtime/references)

/**
* @brief Obtain diagnostic status and check connection
* @param [out] stat Diagnostic message passed directly to diagnostic publish calls
* @note NOLINT syntax is needed since diagnostic_updater asks for a non-const reference
* to pass diagnostic message updated in this function to diagnostic publish calls.
*/
void checkConnection(
diagnostic_updater::DiagnosticStatusWrapper & stat); // NOLINT(runtime/references)

diagnostic_updater::Updater updater_; //!< @brief Updater class which advertises to /diagnostics
int socket_; //!< @brief Socket to communicate with L2ping service
int port_; //!< @brief Port number to connect with L2ping service
L2pingServiceConfig config_; //!< @brief Configuration of L2ping service
L2pingStatusList status_list_; //!< @brief Device status list

using DiagStatus = diagnostic_msgs::msg::DiagnosticStatus;

static constexpr const char * FUNCTION_ERROR_STR = "Function error";

const std::map<StatusCode, const char *> status_string_list_ = {
{StatusCode::OK, "OK"},
{StatusCode::RTT_WARNING, "RTT warning"},
{StatusCode::LOST, "Lost"},
{StatusCode::FUNCTION_ERROR, FUNCTION_ERROR_STR}};

const std::map<StatusCode, unsigned char> status_error_list_ = {
{StatusCode::OK, DiagStatus::OK},
{StatusCode::RTT_WARNING, DiagStatus::WARN},
{StatusCode::LOST, DiagStatus::ERROR},
{StatusCode::FUNCTION_ERROR, DiagStatus::ERROR}};
};

#endif // BLUETOOTH_MONITOR__BLUETOOTH_MONITOR_HPP_
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright 2022 The Autoware Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef BLUETOOTH_MONITOR__SERVICE__L2PING_HPP_
#define BLUETOOTH_MONITOR__SERVICE__L2PING_HPP_

#include "bluetooth_monitor/service/l2ping_interface.hpp"

#include <string>
#include <thread>
#include <vector>

class L2ping
{
public:
/**
* @brief Constructor
* @param [in] address Bluetooth address of remote device
* @param [in] config Configuration of L2ping
*/
L2ping(const std::string & address, const L2pingConfig & config);

/**
* @brief Start ping thread
*/
void run();

/**
* @brief Get status
* @return Status
*/
L2pingStatus getStatus() const;

/**
* @brief Get address of remote device
* @return address of remote device
*/
const std::string & getAddress() const;

protected:
/**
* @brief Get information from remote device
* @return true on success, false on error
*/
bool getDeviceInformation();

/**
* @brief Thread loop
*/
void thread();

/**
* @brief Ping to remote device
* @return true on success, false on error
*/
bool ping();

/**
* @brief Set error data to inform ros2 node
* @param [in] function_name Function name which error occurred
* @param [in] error_message Error message to display
*/
void setFunctionError(const std::string & function_name, const std::string & error_message);

/**
* @brief Set status code
* @param [in] code Status code
*/
void setStatusCode(StatusCode code);

L2pingConfig config_; //!< @brief Configuration of L2ping
std::thread thread_; //!< @brief Thread to L2ping
L2pingStatus status_; //!< @brief L2ping status
};

#endif // BLUETOOTH_MONITOR__SERVICE__L2PING_HPP_
Loading