Skip to content

Commit

Permalink
Crude example where advertising works
Browse files Browse the repository at this point in the history
  • Loading branch information
kdewald committed Sep 30, 2024
1 parent f6bca5a commit 4c28a32
Show file tree
Hide file tree
Showing 17 changed files with 533 additions and 5 deletions.
1 change: 1 addition & 0 deletions examples/simplebluez/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ else()
find_package(simplebluez CONFIG REQUIRED)
endif()

add_subdirectory(advertise)
add_subdirectory(list_adapters)
add_subdirectory(list_paired)
add_subdirectory(scan)
Expand Down
7 changes: 7 additions & 0 deletions examples/simplebluez/advertise/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.21)

project(EXAMPLE_ADVERTISE)

message("-- [INFO] Building Example")
add_executable(example_advertise advertise.cpp)
target_link_libraries(example_advertise simplebluez::simplebluez pthread)
64 changes: 64 additions & 0 deletions examples/simplebluez/advertise/advertise.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <simplebluez/Bluez.h>

#include <atomic>
#include <chrono>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <thread>

SimpleBluez::Bluez bluez;

std::atomic_bool async_thread_active = true;
void async_thread_function() {
while (async_thread_active) {
bluez.run_async();
std::this_thread::sleep_for(std::chrono::microseconds(100));
}
}

void millisecond_delay(int ms) {
for (int i = 0; i < ms; i++) {
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}

int main(int argc, char* argv[]) {
int selection = -1;

bluez.init();
std::thread* async_thread = new std::thread(async_thread_function);

auto adapters = bluez.get_adapters();
std::cout << "The following adapters were found:" << std::endl;
for (int i = 0; i < adapters.size(); i++) {
std::cout << "[" << i << "] " << adapters[i]->identifier() << " [" << adapters[i]->address() << "]"
<< std::endl;
}

// std::cout << "Please select an adapter to advertise: ";
// std::cin >> selection;
// if (selection < 0 || selection >= adapters.size()) {
// std::cout << "Invalid selection" << std::endl;
// return 1;
// }

auto adapter = adapters[0];
std::cout << "Advertising on " << adapter->identifier() << " [" << adapter->address() << "]" << std::endl;

adapter->register_le_advertisement("/simplebluez");

// Sleep for a bit to allow the adapter to stop discovering.
millisecond_delay(30000);

adapter->unregister_le_advertisement("/simplebluez");

async_thread_active = false;
while (!async_thread->joinable()) {
millisecond_delay(10);
}
async_thread->join();
delete async_thread;

return 0;
}
4 changes: 4 additions & 0 deletions simplebluez/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@ set(SIMPLEBLUEZ_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Device1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Battery1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/AgentManager1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/LEAdvertisement1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/LEAdvertisingManager1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/ProxyBase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/InterfaceBase.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/RemoteInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/RemoteProxy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/LocalInterface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/LocalProxy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Connection.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Exceptions.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Holder.cpp
Expand Down
4 changes: 4 additions & 0 deletions simplebluez/include/simplebluez/Adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <simplebluez/Device.h>
#include <simplebluez/interfaces/Adapter1.h>
#include <simplebluez/interfaces/LEAdvertisingManager1.h>

#include <functional>

Expand Down Expand Up @@ -33,11 +34,14 @@ class Adapter : public SimpleDBus::RemoteProxy {
void set_on_device_updated(std::function<void(std::shared_ptr<Device> device)> callback);
void clear_on_device_updated();

void register_le_advertisement(const std::string& advertisement_path);
void unregister_le_advertisement(const std::string& advertisement_path);
private:
std::shared_ptr<SimpleDBus::RemoteProxy> path_create(const std::string& path) override;
std::shared_ptr<SimpleDBus::RemoteInterface> interfaces_create(const std::string& interface_name) override;

std::shared_ptr<Adapter1> adapter1();
std::shared_ptr<LEAdvertisingManager1> le_advertising_manager1();
};

} // namespace SimpleBluez
3 changes: 3 additions & 0 deletions simplebluez/include/simplebluez/Bluez.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#pragma once

#include <simpledbus/advanced/RemoteProxy.h>
#include <simpledbus/advanced/LocalProxy.h>

#include <simpledbus/interfaces/ObjectManager.h>

#include <simplebluez/Adapter.h>
Expand Down Expand Up @@ -28,6 +30,7 @@ class Bluez : public SimpleDBus::RemoteProxy {
std::shared_ptr<SimpleDBus::ObjectManager> object_manager();

std::shared_ptr<Agent> _agent;
std::shared_ptr<SimpleDBus::LocalProxy> _simplebluez_root_proxy;
};

} // namespace SimpleBluez
53 changes: 53 additions & 0 deletions simplebluez/include/simplebluez/interfaces/LEAdvertisement1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#pragma once
#include <simpledbus/advanced/LocalInterface.h>
#include <optional>
#include <string>
#include <vector>
#include <map>
#include <cstdint>

namespace SimpleBluez {

class LEAdvertisement1 : public SimpleDBus::LocalInterface {
public:
// ----- CONSTRUCTORS -----

LEAdvertisement1(std::shared_ptr<SimpleDBus::Connection> conn, std::string path);
virtual ~LEAdvertisement1() = default;

// ----- PROPERTIES -----

void SetType(const std::string& type);
void SetServiceUUIDs(const std::vector<std::string>& uuids);
void SetManufacturerData(const std::map<uint16_t, std::vector<uint8_t>>& data);
void SetServiceData(const std::map<std::string, std::vector<uint8_t>>& data);
void SetSolicitUUIDs(const std::vector<std::string>& uuids);
void SetData(const std::map<uint8_t, std::vector<uint8_t>>& data);
void SetDiscoverable(bool discoverable);
void SetDiscoverableTimeout(uint16_t timeout);
void SetIncludes(const std::vector<std::string>& includes);
void SetLocalName(const std::string& name);
void SetAppearance(uint16_t appearance);
void SetDuration(uint16_t duration);
void SetTimeout(uint16_t timeout);
void SetSecondaryChannel(const std::string& channel);
void SetMinInterval(uint32_t interval);
void SetMaxInterval(uint32_t interval);
void SetTxPower(int16_t power);
void SetIncludeTxPower(bool include);

// ----- METHODS -----

void Release();

protected:
void message_handle(SimpleDBus::Message& msg) override;

private:
// You might want to add private member variables to store the property values
// std::string _type;
// std::vector<std::string> _serviceUUIDs;
// ... (other properties)
};

} // namespace SimpleBluez
35 changes: 35 additions & 0 deletions simplebluez/include/simplebluez/interfaces/LEAdvertisingManager1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once
#include <simpledbus/advanced/RemoteInterface.h>
#include <optional>
#include <string>
#include <vector>

namespace SimpleBluez {

class LEAdvertisingManager1 : public SimpleDBus::RemoteInterface {

public:

// ----- TYPES -----

// ----- CONSTRUCTORS -----

LEAdvertisingManager1(std::shared_ptr<SimpleDBus::Connection> conn, std::string path);
virtual ~LEAdvertisingManager1() = default;

// ----- METHODS -----

void RegisterAdvertisement(std::string advertisement_path);
void UnregisterAdvertisement(std::string advertisement_path);

// ----- PROPERTIES -----

uint8_t ActiveInstances(bool refresh = true);
uint8_t SupportedInstances(bool refresh = true);
std::vector<std::string> SupportedIncludes(bool refresh = true);

protected:
void property_changed(std::string option_name) override;
};

} // namespace SimpleBluez
16 changes: 14 additions & 2 deletions simplebluez/src/Adapter.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#include <simplebluez/Adapter.h>
#include <simplebluez/Device.h>

#include <simplebluez/interfaces/Adapter1.h>

using namespace SimpleBluez;

Adapter::Adapter(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path)
Expand All @@ -18,6 +16,8 @@ std::shared_ptr<SimpleDBus::RemoteProxy> Adapter::path_create(const std::string&
std::shared_ptr<SimpleDBus::RemoteInterface> Adapter::interfaces_create(const std::string& interface_name) {
if (interface_name == "org.bluez.Adapter1") {
return std::static_pointer_cast<SimpleDBus::RemoteInterface>(std::make_shared<Adapter1>(_conn, _path));
} else if (interface_name == "org.bluez.LEAdvertisingManager1") {
return std::static_pointer_cast<SimpleDBus::RemoteInterface>(std::make_shared<LEAdvertisingManager1>(_conn, _path));
}

auto interface = std::make_shared<SimpleDBus::RemoteInterface>(_conn, _bus_name, _path, interface_name);
Expand All @@ -28,6 +28,10 @@ std::shared_ptr<Adapter1> Adapter::adapter1() {
return std::dynamic_pointer_cast<Adapter1>(interface_get("org.bluez.Adapter1"));
}

std::shared_ptr<LEAdvertisingManager1> Adapter::le_advertising_manager1() {
return std::dynamic_pointer_cast<LEAdvertisingManager1>(interface_get("org.bluez.LEAdvertisingManager1"));
}

std::string Adapter::identifier() const {
std::size_t start = _path.find_last_of("/");
return _path.substr(start + 1);
Expand Down Expand Up @@ -85,3 +89,11 @@ void Adapter::clear_on_device_updated() {
on_child_created.unload();
on_child_signal_received.unload();
}

void Adapter::register_le_advertisement(const std::string& advertisement_path) {
le_advertising_manager1()->RegisterAdvertisement(advertisement_path);
}

void Adapter::unregister_le_advertisement(const std::string& advertisement_path) {
le_advertising_manager1()->UnregisterAdvertisement(advertisement_path);
}
17 changes: 15 additions & 2 deletions simplebluez/src/Bluez.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#include <simplebluez/Bluez.h>
#include <simplebluez/ProxyOrg.h>
#include <simpledbus/interfaces/ObjectManager.h>

#include <simplebluez/interfaces/LEAdvertisement1.h>
#include <iostream>

using namespace SimpleBluez;
Expand All @@ -20,6 +20,12 @@ Bluez::Bluez() : RemoteProxy(std::make_shared<SimpleDBus::Connection>(DBUS_BUS),
object_manager()->InterfacesRemoved = [&](std::string path, SimpleDBus::Holder options) {
path_remove(path, options);
};

_simplebluez_root_proxy = std::make_shared<SimpleDBus::LocalProxy>(_conn, "org.simplebluez", "/simplebluez");

auto advertisement = std::make_shared<SimpleBluez::LEAdvertisement1>(_conn, "/simplebluez");
_simplebluez_root_proxy->interfaces_load("org.bluez.LEAdvertisement1",
std::static_pointer_cast<SimpleDBus::LocalInterface>(advertisement));
}

Bluez::~Bluez() {
Expand Down Expand Up @@ -48,7 +54,14 @@ void Bluez::run_async() {
_conn->read_write();
SimpleDBus::Message message = _conn->pop_message();
while (message.is_valid()) {
message_forward(message);
std::cout << "Message: " << message.to_string() << " on path " << message.get_path() << std::endl;

if (_simplebluez_root_proxy->path_belongs(message.get_path())) {
_simplebluez_root_proxy->message_handle(message);
} else {
message_forward(message);
}

message = _conn->pop_message();
}
}
Expand Down
Loading

0 comments on commit 4c28a32

Please sign in to comment.