diff options
-rw-r--r-- | CMakeLists.txt | 56 | ||||
-rw-r--r-- | apps/CMakeLists.txt | 22 | ||||
-rw-r--r-- | apps/ble-inspect-device.cpp (renamed from main.cpp) | 0 | ||||
-rw-r--r-- | apps/sm-get-value.cpp | 75 | ||||
-rw-r--r-- | apps/soil-moisture.h | 118 | ||||
-rw-r--r-- | ble/Bluetooth.cpp (renamed from Bluetooth.cpp) | 0 | ||||
-rw-r--r-- | ble/Bluetooth.h (renamed from Bluetooth.h) | 3 | ||||
-rw-r--r-- | ble/BluetoothImpl.h (renamed from BluetoothImpl.h) | 13 | ||||
-rw-r--r-- | ble/ByteBuffer.cpp (renamed from ByteBuffer.cpp) | 0 | ||||
-rw-r--r-- | ble/ByteBuffer.h (renamed from ByteBuffer.h) | 0 | ||||
-rw-r--r-- | ble/CMakeLists.txt | 3 | ||||
-rw-r--r-- | ble/LinuxBluetooth.cpp (renamed from LinuxBluetooth.cpp) | 0 | ||||
-rw-r--r-- | ble/log.h (renamed from log.h) | 0 | ||||
-rw-r--r-- | test/CMakeLists.txt | 30 |
14 files changed, 267 insertions, 53 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index bd0d7a7..a6e2d6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,65 +3,15 @@ project(ble_toys C CXX) find_package(PkgConfig) # Use Clang by default: http://stackoverflow.com/a/7031553/245614 - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") -set(SOURCE_FILES "${SOURCE_FILES}" - Bluetooth.cpp - LinuxBluetooth.cpp - ByteBuffer.cpp) - -add_library(ble ${SOURCE_FILES}) - -add_executable(ble_toys main.cpp) -target_link_libraries(ble_toys ble) - # Boost set(Boost_USE_STATIC_LIBS OFF) set(Boost_USE_MULTITHREADED OFF) set(Boost_USE_STATIC_RUNTIME OFF) -find_package(Boost COMPONENTS system log thread REQUIRED) -target_link_libraries(ble_toys ${Boost_LIBRARIES}) - add_definitions(-DBOOST_ALL_DYN_LINK) -# Bluez -pkg_check_modules(BLUEZ bluez REQUIRED) -target_link_libraries(ble_toys ${BLUEZ_LIBRARIES}) - -# pthreads -find_package(Threads REQUIRED) -target_link_libraries(ble_toys ${CMAKE_THREAD_LIBS_INIT}) - -enable_testing() -find_package(Boost COMPONENTS log unit_test_framework REQUIRED) - -# If we can change directory here add_definition and test-specific stuff could be moved to the test directory -file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} test/*.cpp) -add_definitions(-DBOOST_TEST_DYN_LINK) - -foreach(testSrc ${TEST_SRCS}) - #Extract the filename without an extension (NAME_WE) - get_filename_component(testName ${testSrc} NAME_WE) - - #Add compile target - add_executable(${testName} ${testSrc}) - - include_directories(${PROJECT_SOURCE_DIR}) - - #link to Boost libraries AND your targets and dependencies - target_link_libraries(${testName} ble) - target_link_libraries(${testName} pthread) - target_link_libraries(${testName} ${Boost_LIBRARIES}) - - #I like to move testing binaries into a testBin directory - set_target_properties(${testName} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) - - #Finally add it to test execution - - #Notice the WORKING_DIRECTORY and COMMAND - add_test(NAME ${testName} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/test - COMMAND ${CMAKE_BINARY_DIR}/test/${testName} ) -endforeach(testSrc) +add_subdirectory(ble) +add_subdirectory(apps) +add_subdirectory(test) diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt new file mode 100644 index 0000000..a138336 --- /dev/null +++ b/apps/CMakeLists.txt @@ -0,0 +1,22 @@ +set(APPS sm-get-value ble-inspect-device) + +# Boost +find_package(Boost COMPONENTS system log thread REQUIRED) + +# Bluez +pkg_check_modules(BLUEZ bluez REQUIRED) + +# pthreads +find_package(Threads REQUIRED) + +foreach(app ${APPS}) + include_directories("${PROJECT_SOURCE_DIR}/ble") + + add_executable(${app} ${app}.cpp) + add_dependencies(${app} ble) + + target_link_libraries(${app} ble) + target_link_libraries(${app} ${Boost_LIBRARIES}) + target_link_libraries(${app} ${BLUEZ_LIBRARIES}) + target_link_libraries(${app} ${CMAKE_THREAD_LIBS_INIT}) +endforeach(app) diff --git a/main.cpp b/apps/ble-inspect-device.cpp index 361311c..361311c 100644 --- a/main.cpp +++ b/apps/ble-inspect-device.cpp diff --git a/apps/sm-get-value.cpp b/apps/sm-get-value.cpp new file mode 100644 index 0000000..232c166 --- /dev/null +++ b/apps/sm-get-value.cpp @@ -0,0 +1,75 @@ +#include <exception> +#include <iostream> +#include <vector> +#include <boost/uuid/uuid_io.hpp> +#include <boost/optional.hpp> +#include "Bluetooth.h" +#include "soil-moisture.h" + +using namespace std; +using namespace trygvis::bluetooth; + +Mac *targetMac; + +void scan_callback(BluetoothDevice &device) { + device.adapter().stopScan(); + + if (device.mac() != *targetMac) { + cout << "found device: " << device.mac().str() << ", but not the one we want " << targetMac->str() << endl; + return; + } + + cout << "Connecting to device: " << device.mac().str() << endl; + + device.connect(); + + device.discoverServices(); + + vector<BluetoothGattService *> services = device.getServices(); + cout << "Device has " << services.size() << " services" << endl; + + for (auto &s: services) { + const vector<BluetoothGattCharacteristic *> characteristics = s->getCharacteristics(); + + cout << "Service: UUID: " << s->getUuid() << ", has " << characteristics.size() << " characteristics" << endl; + + for (auto &c: characteristics) { + cout << "Characteristic: UUID: " << c->getUuid() << ", properties: " << (int) c->getProperties() << endl; + } + } + + boost::uuids::uuid soil_moisture_service; + boost::optional<BluetoothGattService*> service = device.findService(soil_moisture_service); + + device.disconnect(); +} + +int main(int argc, char *argv[]) { + if (argc != 2) { + cerr << "usage: " << argv[0] << " [mac]" << endl; + return EXIT_FAILURE; + } + + int e; +// try { + Mac mac = Mac::parseMac(argv[1]); + targetMac = &mac; + + BluetoothAdapter &adapter = getAdapter(0); + + BluetoothDevice &device = adapter.getDevice(mac); + + scan_callback(device); + + e = EXIT_SUCCESS; +// } catch (std::runtime_error ex) { +// W << "std::runtime_error: " << ex.what(); +// e = EXIT_FAILURE; +// } catch (std::exception ex) { +// W << "std::exception: " << ex.what(); +// e = EXIT_FAILURE; +// } + + shutdown(); + return e; +} diff --git a/apps/soil-moisture.h b/apps/soil-moisture.h new file mode 100644 index 0000000..4f19de1 --- /dev/null +++ b/apps/soil-moisture.h @@ -0,0 +1,118 @@ +#ifndef SOIL_MOISTURE_H +#define SOIL_MOISTURE_H + +#define SENSOR_NAME_LEN 10 + +enum sm_cmd_code { + SM_CMD_GET_SENSOR_COUNT = 1, + SM_CMD_GET_VALUE = 2, + SM_CMD_SET_WARNING_VALUE = 3, + SM_CMD_GET_WARNING_VALUE = 4, + SM_CMD_SET_SENSOR_NAME = 5, + SM_CMD_GET_SENSOR_NAME = 6, + SM_CMD_SET_UPDATE_INTERVAL = 7, + SM_CMD_FAIL = 255, +}; + +struct sm_get_sensor_count_req { +} __attribute__((packed)); + +struct sm_get_sensor_count_res { + uint8_t count; +} __attribute__((packed)); + +struct sm_get_value_req { + uint8_t sensor; +} __attribute__((packed)); + +struct sm_get_value_res { + uint16_t value; +} __attribute__((packed)); + +struct sm_set_warning_value_req { + uint8_t sensor; + uint16_t warning_value; +} __attribute__((packed)); + +struct sm_set_warning_value_res { +} __attribute__((packed)); + +struct sm_get_warning_value_req { + uint8_t sensor; +} __attribute__((packed)); + +struct sm_get_warning_value_res { + uint16_t warning_value; +} __attribute__((packed)); + +struct sm_set_sensor_name_req { + uint8_t sensor; + uint8_t length; + uint8_t name[SENSOR_NAME_LEN]; +} __attribute__((packed)); + +struct sm_set_sensor_name_res { +} __attribute__((packed)); + +struct sm_get_sensor_name_req { + uint8_t sensor; +} __attribute__((packed)); + +struct sm_get_sensor_name_res { + uint8_t length; + uint8_t name[SENSOR_NAME_LEN]; +} __attribute__((packed)); + +struct sm_set_update_interval_req { + uint8_t sensor; + uint8_t interval_in_seconds; +} __attribute__((packed)); + +struct sm_set_update_interval_res { +} __attribute__((packed)); + +struct sm_req { + uint8_t code; + union { + struct sm_get_sensor_count_req get_sensor_count; + struct sm_get_value_req get_value; + struct sm_set_warning_value_req set_warning_value; + struct sm_get_warning_value_req get_warning_value; + struct sm_set_sensor_name_req set_sensor_name; + struct sm_get_sensor_name_req get_sensor_name; + struct sm_set_update_interval_req set_update_interval; + } __attribute__((packed)); +} __attribute__((packed)); + +// len + code +#define SM_RES_HEADER_SIZE 1 + +struct sm_res { + // header + uint8_t code; + + // body + union { + struct sm_get_sensor_count_res get_sensor_count; + struct sm_get_value_res get_value; + struct sm_set_warning_value_res set_warning_value; + struct sm_get_warning_value_res get_warning_value; + struct sm_set_sensor_name_res set_sensor_name; + struct sm_get_sensor_name_res get_sensor_name; + struct sm_set_update_interval_res set_update_interval; + } __attribute__((packed)); +} __attribute__((packed)); + +#ifndef SM_DEBUG +#define SM_DEBUG 1 +#endif + +#if SM_DEBUG == 1 + +void write_req(struct sm_req const &req); + +void write_res(struct sm_res const &res); + +#endif + +#endif diff --git a/Bluetooth.cpp b/ble/Bluetooth.cpp index b135282..b135282 100644 --- a/Bluetooth.cpp +++ b/ble/Bluetooth.cpp diff --git a/Bluetooth.h b/ble/Bluetooth.h index 4314d8e..e47ff3e 100644 --- a/Bluetooth.h +++ b/ble/Bluetooth.h @@ -4,6 +4,7 @@ #include <string> #include <stdexcept> #include <boost/uuid/uuid.hpp> +#include <boost/optional.hpp> #include "ByteBuffer.h" @@ -128,6 +129,8 @@ public: virtual void discoverServices() = 0; virtual const vector<BluetoothGattService *> getServices() const = 0; + + virtual const boost::optional<BluetoothGattService*> findService(boost::uuids::uuid uuid) const = 0; }; class BluetoothAdapter { diff --git a/BluetoothImpl.h b/ble/BluetoothImpl.h index 3fad164..69fac6e 100644 --- a/BluetoothImpl.h +++ b/ble/BluetoothImpl.h @@ -3,6 +3,7 @@ #include "Bluetooth.h" #include <boost/uuid/uuid_io.hpp> +#include <cstring> #define BLUETOOTH_UUID_INITIALIZER \ { \ @@ -17,6 +18,8 @@ namespace trygvis { namespace bluetooth { typedef boost::uuids::uuid uuid_t; +template <class t> +using o = boost::optional<t>; class DefaultBluetoothGattCharacteristic : public BluetoothGattCharacteristic { public: @@ -113,6 +116,16 @@ public: return services; }; + virtual const o<BluetoothGattService*> findService(boost::uuids::uuid uuid) const { + for (auto s: services) { + if (memcmp(s->getUuid().data, uuid.data, 16) == 0) { + return o<BluetoothGattService*>(s); + } + } + + return o<BluetoothGattService*>(); + } + virtual void addService(BluetoothGattService *service) { services.push_back(service); } diff --git a/ByteBuffer.cpp b/ble/ByteBuffer.cpp index 820c638..820c638 100644 --- a/ByteBuffer.cpp +++ b/ble/ByteBuffer.cpp diff --git a/ByteBuffer.h b/ble/ByteBuffer.h index 3836966..3836966 100644 --- a/ByteBuffer.h +++ b/ble/ByteBuffer.h diff --git a/ble/CMakeLists.txt b/ble/CMakeLists.txt new file mode 100644 index 0000000..1ecfb6c --- /dev/null +++ b/ble/CMakeLists.txt @@ -0,0 +1,3 @@ +file(GLOB SOURCE_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cpp) + +add_library(ble ${SOURCE_FILES}) diff --git a/LinuxBluetooth.cpp b/ble/LinuxBluetooth.cpp index 4b7f0e0..4b7f0e0 100644 --- a/LinuxBluetooth.cpp +++ b/ble/LinuxBluetooth.cpp diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..14dcdf7 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,30 @@ +enable_testing() +find_package(Boost COMPONENTS log unit_test_framework REQUIRED) + +# If we can change directory here add_definition and test-specific stuff could be moved to the test directory +file(GLOB TEST_SRCS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *Test.cpp) +add_definitions(-DBOOST_TEST_DYN_LINK) + +foreach(testSrc ${TEST_SRCS}) + #Extract the filename without an extension (NAME_WE) + get_filename_component(testName ${testSrc} NAME_WE) + + #Add compile target + add_executable(${testName} ${testSrc}) + + include_directories("${PROJECT_SOURCE_DIR}/ble") + add_dependencies(${testName} ble) + target_link_libraries(${testName} ble) + target_link_libraries(${testName} pthread) + target_link_libraries(${testName} ${Boost_LIBRARIES}) + + #I like to move testing binaries into a testBin directory + set_target_properties(${testName} PROPERTIES + RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test) + + #Finally add it to test execution - + #Notice the WORKING_DIRECTORY and COMMAND + add_test(NAME ${testName} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/testBin + COMMAND ${CMAKE_BINARY_DIR}/testBin/${testName}) +endforeach(testSrc) |