Skip to content

Commit

Permalink
Scratch peripheral work
Browse files Browse the repository at this point in the history
  • Loading branch information
kdewald committed Sep 27, 2024
1 parent fd755aa commit bfe18b8
Show file tree
Hide file tree
Showing 28 changed files with 731 additions and 204 deletions.
1 change: 1 addition & 0 deletions examples/simplebluez/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ add_subdirectory(pair)
add_subdirectory(read)
add_subdirectory(notify)
add_subdirectory(ble_nus)
add_subdirectory(advertise)
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)
63 changes: 63 additions & 0 deletions examples/simplebluez/advertise/advertise.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#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;

auto advertisement = bluez.make_le_advertisement("/potato");
adapter->register_le_advertisement(advertisement);

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

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

return 0;
}
11 changes: 7 additions & 4 deletions simplebluez/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,17 @@ set(SIMPLEBLUEZ_SRC
${CMAKE_CURRENT_SOURCE_DIR}/src/Adapter.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Bluez.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Descriptor.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/LEAdvertisement.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Adapter1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Agent1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattDescriptor1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/AgentManager1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Battery1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/Device1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattCharacteristic1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattDescriptor1.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/interfaces/GattService1.cpp
${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/Interface.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/advanced/Proxy.cpp
${CMAKE_CURRENT_SOURCE_DIR}/../simpledbus/src/base/Connection.cpp
Expand Down
5 changes: 5 additions & 0 deletions simplebluez/include/simplebluez/Adapter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
#include <simpledbus/advanced/Proxy.h>

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

#include <functional>

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

void register_le_advertisement(std::shared_ptr<LEAdvertisement> advertisement);

private:
std::shared_ptr<SimpleDBus::Proxy> path_create(const std::string& path) override;
std::shared_ptr<SimpleDBus::Interface> interfaces_create(const std::string& interface_name) override;

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

} // namespace SimpleBluez
2 changes: 2 additions & 0 deletions simplebluez/include/simplebluez/Bluez.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ class Bluez : public SimpleDBus::Proxy {
std::shared_ptr<Agent> get_agent();
void register_agent();

std::shared_ptr<LEAdvertisement> make_le_advertisement(const std::string& path);

private:
std::shared_ptr<SimpleDBus::Proxy> path_create(const std::string& path) override;

Expand Down
4 changes: 2 additions & 2 deletions simplebluez/include/simplebluez/Characteristic.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ class Characteristic : public SimpleDBus::Proxy {
void clear_on_value_changed();

private:
std::shared_ptr<SimpleDBus::Proxy> path_create(const std::string& path) override;
std::shared_ptr<SimpleDBus::Interface> interfaces_create(const std::string& interface_name) override;
std::shared_ptr<SimpleDBus::ProxyBase> path_create(const std::string& path) override;
std::shared_ptr<SimpleDBus::InterfaceBase> interfaces_create(const std::string& interface_name) override;

std::shared_ptr<GattCharacteristic1> gattcharacteristic1();
};
Expand Down
2 changes: 1 addition & 1 deletion simplebluez/include/simplebluez/Descriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Descriptor : public SimpleDBus::Proxy {
void clear_on_value_changed();

private:
std::shared_ptr<SimpleDBus::Interface> interfaces_create(const std::string& interface_name) override;
std::shared_ptr<SimpleDBus::InterfaceBase> interfaces_create(const std::string& interface_name) override;

std::shared_ptr<GattDescriptor1> gattdescriptor1();
};
Expand Down
27 changes: 27 additions & 0 deletions simplebluez/include/simplebluez/LEAdvertisement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <simplebluez/interfaces/LEAdvertisement1.h>
#include <simpledbus/advanced/Proxy.h>

namespace SimpleBluez {

class LEAdvertisement : public SimpleDBus::Proxy {
public:
typedef enum {
DisplayOnly,
DisplayYesNo,
KeyboardOnly,
NoInputNoOutput,
KeyboardDisplay,
} Capabilities;

LEAdvertisement(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name, const std::string& path);
virtual ~LEAdvertisement() = default;

private:
std::shared_ptr<SimpleDBus::Interface> interfaces_create(const std::string& interface_name) override;

std::shared_ptr<LEAdvertisement1> le_advertisement1();
};

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

#include <simpledbus/advanced/Interface.h>

#include <optional>
#include <string>
#include <vector>

namespace SimpleBluez {

class LEAdvertisement1 : public SimpleDBus::Interface {
public:
// ----- TYPES -----


// ----- 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 SetIncludeTxPower(bool include);

// ----- METHODS -----
void Release();

protected:
void property_changed(std::string option_name) override;
void message_handle(SimpleDBus::Message& msg) override;
};

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

#include <simpledbus/advanced/Interface.h>

#include <optional>
#include <string>
#include <vector>

namespace SimpleBluez {

class LEAdvertisingManager1 : public SimpleDBus::Interface {
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
11 changes: 11 additions & 0 deletions simplebluez/src/Adapter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <simplebluez/Device.h>

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

using namespace SimpleBluez;

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

auto interface = std::make_shared<SimpleDBus::Interface>(_conn, _bus_name, _path, interface_name);
Expand All @@ -28,6 +31,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 +92,7 @@ void Adapter::clear_on_device_updated() {
on_child_created.unload();
on_child_signal_received.unload();
}

void Adapter::register_le_advertisement(std::shared_ptr<LEAdvertisement> advertisement) {
le_advertising_manager1()->RegisterAdvertisement(advertisement->path());
}
12 changes: 11 additions & 1 deletion simplebluez/src/Bluez.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ Bluez::Bluez() : Proxy(std::make_shared<SimpleDBus::Connection>(DBUS_BUS), "org.
_interfaces["org.freedesktop.DBus.ObjectManager"] = std::static_pointer_cast<SimpleDBus::Interface>(
std::make_shared<SimpleDBus::ObjectManager>(_conn, "org.bluez", "/"));

object_manager()->InterfacesAdded = [&](std::string path, SimpleDBus::Holder options) { path_add(path, options); };
object_manager()->InterfacesAdded = [&](std::string path, SimpleDBus::Holder options) {
std::cout << "InterfacesAdded: " << path << std::endl;
path_add(path, options);
};
object_manager()->InterfacesRemoved = [&](std::string path, SimpleDBus::Holder options) {
path_remove(path, options);
};
Expand Down Expand Up @@ -48,6 +51,7 @@ void Bluez::run_async() {
_conn->read_write();
SimpleDBus::Message message = _conn->pop_message();
while (message.is_valid()) {
std::cout << "Message: " << message.to_string() << std::endl;
message_forward(message);
message = _conn->pop_message();
}
Expand All @@ -57,6 +61,12 @@ std::vector<std::shared_ptr<Adapter>> Bluez::get_adapters() {
return std::dynamic_pointer_cast<ProxyOrg>(path_get("/org"))->get_adapters();
}

std::shared_ptr<LEAdvertisement> Bluez::make_le_advertisement(const std::string& path) {
std::shared_ptr<LEAdvertisement> advertisement = std::make_shared<LEAdvertisement>(_conn, "org.simpleble", path);
path_append_child(path, std::static_pointer_cast<SimpleDBus::Proxy>(advertisement));
return advertisement;
}

std::shared_ptr<Agent> Bluez::get_agent() { return std::dynamic_pointer_cast<Agent>(path_get("/agent")); }

void Bluez::register_agent() { std::dynamic_pointer_cast<ProxyOrg>(path_get("/org"))->register_agent(_agent); }
Expand Down
6 changes: 3 additions & 3 deletions simplebluez/src/Descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ Descriptor::Descriptor(std::shared_ptr<SimpleDBus::Connection> conn, const std::

Descriptor::~Descriptor() {}

std::shared_ptr<SimpleDBus::Interface> Descriptor::interfaces_create(const std::string& interface_name) {
std::shared_ptr<SimpleDBus::InterfaceBase> Descriptor::interfaces_create(const std::string& interface_name) {
if (interface_name == "org.bluez.GattDescriptor1") {
return std::static_pointer_cast<SimpleDBus::Interface>(std::make_shared<GattDescriptor1>(_conn, _path));
return std::static_pointer_cast<SimpleDBus::InterfaceBase>(std::make_shared<GattDescriptor1>(_conn, _path));
}

auto interface = std::make_shared<SimpleDBus::Interface>(_conn, _bus_name, _path, interface_name);
return std::static_pointer_cast<SimpleDBus::Interface>(interface);
return std::static_pointer_cast<SimpleDBus::InterfaceBase>(interface);
}

std::shared_ptr<GattDescriptor1> Descriptor::gattdescriptor1() {
Expand Down
18 changes: 18 additions & 0 deletions simplebluez/src/LEAdvertisement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <simplebluez/LEAdvertisement.h>

using namespace SimpleBluez;

LEAdvertisement::LEAdvertisement(std::shared_ptr<SimpleDBus::Connection> conn, const std::string& bus_name,
const std::string& path)
: Proxy(conn, bus_name, path) {
_interfaces.emplace(std::make_pair("org.bluez.LEAdvertisement1", interfaces_create("org.bluez.LEAdvertisement1")));
}

std::shared_ptr<SimpleDBus::Interface> LEAdvertisement::interfaces_create(const std::string& interface_name) {
if (interface_name == "org.bluez.LEAdvertisement1") {
return std::static_pointer_cast<SimpleDBus::Interface>(std::make_shared<LEAdvertisement1>(_conn, _path));
}

auto interface = std::make_shared<SimpleDBus::Interface>(_conn, _bus_name, _path, interface_name);
return std::static_pointer_cast<SimpleDBus::Interface>(interface);
}
Loading

0 comments on commit bfe18b8

Please sign in to comment.