simplejsble 0.0.4 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -0
- package/android/CMakeLists.txt +62 -20
- package/cmake/epilogue.cmake +81 -0
- package/cmake/find/FindDBus1.cmake +20 -0
- package/cmake/find/Findfmt.cmake +41 -0
- package/cmake/find/Findgoogletest.cmake +18 -0
- package/cmake/parse_version.cmake +45 -0
- package/cmake/prelude.cmake +8 -0
- package/dependencies/README +4 -0
- package/dependencies/external/kvn/kvn_bytearray.h +297 -0
- package/dependencies/external/kvn/kvn_safe_callback.hpp +66 -0
- package/dependencies/external/kvn/logfwd.hpp +35 -0
- package/dependencies/internal/include/fmt/LICENSE +27 -0
- package/dependencies/internal/include/fmt/args.h +220 -0
- package/dependencies/internal/include/fmt/base.h +2962 -0
- package/dependencies/internal/include/fmt/chrono.h +2338 -0
- package/dependencies/internal/include/fmt/color.h +610 -0
- package/dependencies/internal/include/fmt/compile.h +539 -0
- package/dependencies/internal/include/fmt/core.h +5 -0
- package/dependencies/internal/include/fmt/format-inl.h +1949 -0
- package/dependencies/internal/include/fmt/format.h +4244 -0
- package/dependencies/internal/include/fmt/os.h +427 -0
- package/dependencies/internal/include/fmt/ostream.h +166 -0
- package/dependencies/internal/include/fmt/printf.h +633 -0
- package/dependencies/internal/include/fmt/ranges.h +850 -0
- package/dependencies/internal/include/fmt/std.h +726 -0
- package/dependencies/internal/include/fmt/xchar.h +373 -0
- package/dependencies/internal/include/nanopb/pb.h +948 -0
- package/dependencies/internal/include/nanopb/pb_common.h +49 -0
- package/dependencies/internal/include/nanopb/pb_decode.h +204 -0
- package/dependencies/internal/include/nanopb/pb_encode.h +195 -0
- package/dependencies/internal/include/simplejni/Common.hpp +598 -0
- package/dependencies/internal/include/simplejni/References.hpp +151 -0
- package/dependencies/internal/include/simplejni/Registry.hpp +249 -0
- package/dependencies/internal/include/simplejni/VM.hpp +93 -0
- package/dependencies/internal/src/nanopb/pb_common.c +388 -0
- package/dependencies/internal/src/nanopb/pb_decode.c +1763 -0
- package/dependencies/internal/src/nanopb/pb_encode.c +1009 -0
- package/dependencies/internal/src/simplejni/Common.cpp +4 -0
- package/package.json +5 -1
- package/simpleble/CMakeLists.txt +519 -0
- package/simpleble/cmake/simpleble.pc.in +11 -0
- package/simpleble/include/simpleble/Adapter.h +102 -0
- package/simpleble/include/simpleble/AdapterSafe.h +58 -0
- package/simpleble/include/simpleble/Advanced.h +50 -0
- package/simpleble/include/simpleble/Characteristic.h +39 -0
- package/simpleble/include/simpleble/Config.h +64 -0
- package/simpleble/include/simpleble/Descriptor.h +30 -0
- package/simpleble/include/simpleble/Exceptions.h +72 -0
- package/simpleble/include/simpleble/Logging.h +73 -0
- package/simpleble/include/simpleble/Peripheral.h +82 -0
- package/simpleble/include/simpleble/PeripheralSafe.h +64 -0
- package/simpleble/include/simpleble/Service.h +34 -0
- package/simpleble/include/simpleble/SimpleBLE.h +8 -0
- package/simpleble/include/simpleble/Types.h +49 -0
- package/simpleble/include/simpleble/Utils.h +13 -0
- package/simpleble/include/simpleble_c/DEPRECATED +2 -0
- package/simpleble/include/simpleble_c/adapter.h +188 -0
- package/simpleble/include/simpleble_c/logging.h +37 -0
- package/simpleble/include/simpleble_c/peripheral.h +304 -0
- package/simpleble/include/simpleble_c/simpleble.h +21 -0
- package/simpleble/include/simpleble_c/types.h +73 -0
- package/simpleble/include/simpleble_c/utils.h +27 -0
- package/simpleble/src/CommonUtils.h +63 -0
- package/simpleble/src/Config.cpp +25 -0
- package/simpleble/src/Exceptions.cpp +31 -0
- package/simpleble/src/Logging.cpp +136 -0
- package/simpleble/src/LoggingInternal.h +85 -0
- package/simpleble/src/Utils.cpp +24 -0
- package/simpleble/src/backends/android/AdapterAndroid.cpp +101 -0
- package/simpleble/src/backends/android/AdapterAndroid.h +67 -0
- package/simpleble/src/backends/android/BackendAndroid.cpp +41 -0
- package/simpleble/src/backends/android/BackendAndroid.h +26 -0
- package/simpleble/src/backends/android/PeripheralAndroid.cpp +365 -0
- package/simpleble/src/backends/android/PeripheralAndroid.h +90 -0
- package/simpleble/src/backends/android/bridge/BluetoothGattCallback.cpp +432 -0
- package/simpleble/src/backends/android/bridge/BluetoothGattCallback.h +102 -0
- package/simpleble/src/backends/android/bridge/ScanCallback.cpp +142 -0
- package/simpleble/src/backends/android/bridge/ScanCallback.h +55 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothAdapter.cpp +107 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothAdapter.h +55 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothDevice.cpp +68 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothDevice.h +54 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGatt.cpp +115 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGatt.h +75 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattCharacteristic.cpp +142 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattCharacteristic.h +66 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattDescriptor.cpp +67 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattDescriptor.h +46 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattService.cpp +106 -0
- package/simpleble/src/backends/android/types/android/bluetooth/BluetoothGattService.h +47 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/BluetoothScanner.cpp +47 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/BluetoothScanner.h +37 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/ScanRecord.cpp +69 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/ScanRecord.h +41 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/ScanResult.cpp +63 -0
- package/simpleble/src/backends/android/types/android/bluetooth/le/ScanResult.h +42 -0
- package/simpleble/src/backends/android/types/android/os/ParcelUUID.cpp +32 -0
- package/simpleble/src/backends/android/types/android/os/ParcelUUID.h +30 -0
- package/simpleble/src/backends/android/types/android/util/SparseArray.cpp +54 -0
- package/simpleble/src/backends/android/types/android/util/SparseArray.h +37 -0
- package/simpleble/src/backends/android/types/java/util/Iterator.cpp +36 -0
- package/simpleble/src/backends/android/types/java/util/Iterator.h +28 -0
- package/simpleble/src/backends/android/types/java/util/List.cpp +29 -0
- package/simpleble/src/backends/android/types/java/util/List.h +27 -0
- package/simpleble/src/backends/android/types/java/util/Set.cpp +33 -0
- package/simpleble/src/backends/android/types/java/util/Set.h +28 -0
- package/simpleble/src/backends/android/types/java/util/UUID.cpp +26 -0
- package/simpleble/src/backends/android/types/java/util/UUID.h +29 -0
- package/simpleble/src/backends/common/AdapterBase.cpp +53 -0
- package/simpleble/src/backends/common/AdapterBase.h +81 -0
- package/simpleble/src/backends/common/AdapterBaseTypes.h +22 -0
- package/simpleble/src/backends/common/BackendBase.h +20 -0
- package/simpleble/src/backends/common/BackendUtils.h +33 -0
- package/simpleble/src/backends/common/CharacteristicBase.cpp +28 -0
- package/simpleble/src/backends/common/CharacteristicBase.h +38 -0
- package/simpleble/src/backends/common/DescriptorBase.cpp +7 -0
- package/simpleble/src/backends/common/DescriptorBase.h +19 -0
- package/simpleble/src/backends/common/PeripheralBase.h +82 -0
- package/simpleble/src/backends/common/ServiceBase.cpp +18 -0
- package/simpleble/src/backends/common/ServiceBase.h +28 -0
- package/simpleble/src/backends/dongl/AdapterBaseTypes.h +22 -0
- package/simpleble/src/backends/dongl/AdapterDongl.cpp +369 -0
- package/simpleble/src/backends/dongl/AdapterDongl.h +60 -0
- package/simpleble/src/backends/dongl/BackendDongl.cpp +35 -0
- package/simpleble/src/backends/dongl/PeripheralDongl.cpp +562 -0
- package/simpleble/src/backends/dongl/PeripheralDongl.h +136 -0
- package/simpleble/src/backends/dongl/protocol/basic.pb.c +33 -0
- package/simpleble/src/backends/dongl/protocol/basic.pb.h +172 -0
- package/simpleble/src/backends/dongl/protocol/d2h.pb.c +18 -0
- package/simpleble/src/backends/dongl/protocol/d2h.pb.h +118 -0
- package/simpleble/src/backends/dongl/protocol/h2d.pb.c +12 -0
- package/simpleble/src/backends/dongl/protocol/h2d.pb.h +69 -0
- package/simpleble/src/backends/dongl/protocol/simpleble.pb.c +123 -0
- package/simpleble/src/backends/dongl/protocol/simpleble.pb.h +908 -0
- package/simpleble/src/backends/dongl/protocol/softdevice.pb.c +18 -0
- package/simpleble/src/backends/dongl/protocol/softdevice.pb.h +815 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gap.pb.c +339 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gap.pb.h +2086 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gattc.pb.c +114 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gattc.pb.h +772 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gatts.pb.c +117 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_gatts.pb.h +766 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_types.pb.c +207 -0
- package/simpleble/src/backends/dongl/protocol/softdevice_types.pb.h +1686 -0
- package/simpleble/src/backends/dongl/serial/Protocol.cpp +887 -0
- package/simpleble/src/backends/dongl/serial/Protocol.h +117 -0
- package/simpleble/src/backends/dongl/serial/ProtocolBase.cpp +95 -0
- package/simpleble/src/backends/dongl/serial/ProtocolBase.h +54 -0
- package/simpleble/src/backends/dongl/serial/Wire.cpp +133 -0
- package/simpleble/src/backends/dongl/serial/Wire.h +116 -0
- package/simpleble/src/backends/dongl/usb/UsbHelper.cpp +53 -0
- package/simpleble/src/backends/dongl/usb/UsbHelper.h +32 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperApple.cpp +266 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperApple.h +34 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperImpl.h +29 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperLinux.cpp +21 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperLinux.h +22 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperNull.cpp +21 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperNull.h +22 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperWindows.cpp +21 -0
- package/simpleble/src/backends/dongl/usb/UsbHelperWindows.h +22 -0
- package/simpleble/src/backends/linux/AdapterLinux.cpp +102 -0
- package/simpleble/src/backends/linux/AdapterLinux.h +55 -0
- package/simpleble/src/backends/linux/BackendBluez.cpp +90 -0
- package/simpleble/src/backends/linux/PeripheralLinux.cpp +394 -0
- package/simpleble/src/backends/linux/PeripheralLinux.h +90 -0
- package/simpleble/src/backends/linux_legacy/AdapterLinuxLegacy.cpp +102 -0
- package/simpleble/src/backends/linux_legacy/AdapterLinuxLegacy.h +55 -0
- package/simpleble/src/backends/linux_legacy/BackendBluezLegacy.cpp +87 -0
- package/simpleble/src/backends/linux_legacy/PeripheralLinuxLegacy.cpp +376 -0
- package/simpleble/src/backends/linux_legacy/PeripheralLinuxLegacy.h +90 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Adapter.h +46 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Agent.h +52 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Bluez.h +37 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/BluezOrg.h +22 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/BluezOrgBluez.h +26 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/BluezRoot.h +32 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Characteristic.h +47 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Descriptor.h +33 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Device.h +64 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Exceptions.h +43 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Service.h +27 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/Types.h +9 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/Adapter1.h +49 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/Agent1.h +100 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/AgentManager1.h +24 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/Battery1.h +32 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/Device1.h +62 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/GattCharacteristic1.h +48 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/GattDescriptor1.h +41 -0
- package/simpleble/src/backends/linux_legacy/include/simplebluezlegacy/interfaces/GattService1.h +28 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/advanced/Interface.h +67 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/advanced/InterfaceRegistry.h +62 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/advanced/Proxy.h +117 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Connection.h +50 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Exceptions.h +56 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Holder.h +147 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Logging.h +57 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Message.h +89 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/base/Path.h +24 -0
- package/simpleble/src/backends/linux_legacy/include/simpledbuslegacy/interfaces/ObjectManager.h +26 -0
- package/simpleble/src/backends/linux_legacy/src/Adapter.cpp +78 -0
- package/simpleble/src/backends/linux_legacy/src/Agent.cpp +72 -0
- package/simpleble/src/backends/linux_legacy/src/Bluez.cpp +45 -0
- package/simpleble/src/backends/linux_legacy/src/BluezOrg.cpp +20 -0
- package/simpleble/src/backends/linux_legacy/src/BluezOrgBluez.cpp +23 -0
- package/simpleble/src/backends/linux_legacy/src/BluezRoot.cpp +44 -0
- package/simpleble/src/backends/linux_legacy/src/Characteristic.cpp +64 -0
- package/simpleble/src/backends/linux_legacy/src/Descriptor.cpp +27 -0
- package/simpleble/src/backends/linux_legacy/src/Device.cpp +104 -0
- package/simpleble/src/backends/linux_legacy/src/Exceptions.cpp +29 -0
- package/simpleble/src/backends/linux_legacy/src/Service.cpp +33 -0
- package/simpleble/src/backends/linux_legacy/src/advanced/Interface.cpp +155 -0
- package/simpleble/src/backends/linux_legacy/src/advanced/Proxy.cpp +374 -0
- package/simpleble/src/backends/linux_legacy/src/base/Connection.cpp +219 -0
- package/simpleble/src/backends/linux_legacy/src/base/Exceptions.cpp +39 -0
- package/simpleble/src/backends/linux_legacy/src/base/Holder.cpp +739 -0
- package/simpleble/src/backends/linux_legacy/src/base/Message.cpp +622 -0
- package/simpleble/src/backends/linux_legacy/src/base/Path.cpp +129 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/Adapter1.cpp +123 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/Agent1.cpp +143 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/AgentManager1.cpp +34 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/Battery1.cpp +30 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/Device1.cpp +170 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/GattCharacteristic1.cpp +118 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/GattDescriptor1.cpp +78 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/GattService1.cpp +28 -0
- package/simpleble/src/backends/linux_legacy/src/interfaces/ObjectManager.cpp +58 -0
- package/simpleble/src/backends/macos/AdapterBaseMacOS.h +29 -0
- package/simpleble/src/backends/macos/AdapterBaseMacOS.mm +235 -0
- package/simpleble/src/backends/macos/AdapterMac.h +78 -0
- package/simpleble/src/backends/macos/AdapterMac.mm +156 -0
- package/simpleble/src/backends/macos/BackendCoreBluetooth.mm +45 -0
- package/simpleble/src/backends/macos/PeripheralBaseMacOS.h +49 -0
- package/simpleble/src/backends/macos/PeripheralBaseMacOS.mm +714 -0
- package/simpleble/src/backends/macos/PeripheralMac.h +81 -0
- package/simpleble/src/backends/macos/PeripheralMac.mm +229 -0
- package/simpleble/src/backends/macos/Utils.h +9 -0
- package/simpleble/src/backends/macos/Utils.mm +23 -0
- package/simpleble/src/backends/plain/AdapterPlain.cpp +65 -0
- package/simpleble/src/backends/plain/AdapterPlain.h +49 -0
- package/simpleble/src/backends/plain/BackendPlain.cpp +30 -0
- package/simpleble/src/backends/plain/PeripheralPlain.cpp +159 -0
- package/simpleble/src/backends/plain/PeripheralPlain.h +72 -0
- package/simpleble/src/backends/windows/AdapterWindows.cpp +338 -0
- package/simpleble/src/backends/windows/AdapterWindows.h +89 -0
- package/simpleble/src/backends/windows/BackendWinRT.cpp +67 -0
- package/simpleble/src/backends/windows/BackendWinRT.h +18 -0
- package/simpleble/src/backends/windows/MtaManager.cpp +49 -0
- package/simpleble/src/backends/windows/MtaManager.h +90 -0
- package/simpleble/src/backends/windows/PeripheralWindows.cpp +487 -0
- package/simpleble/src/backends/windows/PeripheralWindows.h +129 -0
- package/simpleble/src/backends/windows/Utils.cpp +146 -0
- package/simpleble/src/backends/windows/Utils.h +47 -0
- package/simpleble/src/builders/BuildVec.h +32 -0
- package/simpleble/src/builders/BuilderBase.h +87 -0
- package/simpleble/src/external/TaskRunner.hpp +99 -0
- package/simpleble/src/external/ThreadRunner.h +52 -0
- package/simpleble/src/external/kvn_safe_callback.hpp +66 -0
- package/simpleble/src/external/kvn_safe_map.hpp +94 -0
- package/simpleble/src/external/kvn_threadrunner.hpp +70 -0
- package/simpleble/src/external/logfwd.hpp +35 -0
- package/simpleble/src/frontends/base/Adapter.cpp +111 -0
- package/simpleble/src/frontends/base/Advanced.cpp +34 -0
- package/simpleble/src/frontends/base/Backend.cpp +95 -0
- package/simpleble/src/frontends/base/Backend.h +76 -0
- package/simpleble/src/frontends/base/Characteristic.cpp +56 -0
- package/simpleble/src/frontends/base/Descriptor.cpp +21 -0
- package/simpleble/src/frontends/base/Peripheral.cpp +113 -0
- package/simpleble/src/frontends/base/Service.cpp +26 -0
- package/simpleble/src/frontends/safe/AdapterSafe.cpp +158 -0
- package/simpleble/src/frontends/safe/PeripheralSafe.cpp +219 -0
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <simpleble/Exceptions.h>
|
|
4
|
+
#include <simpleble/Service.h>
|
|
5
|
+
#include <simpleble/Types.h>
|
|
6
|
+
|
|
7
|
+
#include "AdapterBaseTypes.h"
|
|
8
|
+
#include "PeripheralBase.h"
|
|
9
|
+
|
|
10
|
+
#include <kvn_safe_callback.hpp>
|
|
11
|
+
|
|
12
|
+
#include "winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h"
|
|
13
|
+
#include "winrt/Windows.Devices.Bluetooth.h"
|
|
14
|
+
|
|
15
|
+
#include <condition_variable>
|
|
16
|
+
#include <functional>
|
|
17
|
+
#include <map>
|
|
18
|
+
#include <memory>
|
|
19
|
+
|
|
20
|
+
using namespace winrt::Windows::Devices::Bluetooth;
|
|
21
|
+
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
|
|
22
|
+
|
|
23
|
+
namespace SimpleBLE {
|
|
24
|
+
|
|
25
|
+
struct gatt_descriptor_t {
|
|
26
|
+
GattDescriptor obj = nullptr;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
struct gatt_characteristic_t {
|
|
30
|
+
GattCharacteristic obj = nullptr;
|
|
31
|
+
winrt::event_token value_changed_token;
|
|
32
|
+
std::function<void(const GattCharacteristic& sender, const GattValueChangedEventArgs& args)> value_changed_callback;
|
|
33
|
+
std::map<BluetoothUUID, gatt_descriptor_t> descriptors;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
struct gatt_service_t {
|
|
37
|
+
GattDeviceService obj = nullptr;
|
|
38
|
+
std::map<BluetoothUUID, gatt_characteristic_t> characteristics;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
class PeripheralWindows : public PeripheralBase {
|
|
42
|
+
public:
|
|
43
|
+
PeripheralWindows(BluetoothLEDevice device);
|
|
44
|
+
PeripheralWindows(advertising_data_t advertising_data);
|
|
45
|
+
virtual ~PeripheralWindows();
|
|
46
|
+
|
|
47
|
+
virtual void* underlying() const override;
|
|
48
|
+
|
|
49
|
+
virtual std::string identifier() override;
|
|
50
|
+
virtual BluetoothAddress address() override;
|
|
51
|
+
virtual SimpleBLE::BluetoothAddressType address_type() override;
|
|
52
|
+
virtual int16_t rssi() override;
|
|
53
|
+
virtual int16_t tx_power() override;
|
|
54
|
+
virtual uint16_t mtu() override;
|
|
55
|
+
|
|
56
|
+
virtual void connect() override;
|
|
57
|
+
virtual void disconnect() override;
|
|
58
|
+
virtual bool is_connected() override;
|
|
59
|
+
virtual bool is_connectable() override;
|
|
60
|
+
virtual bool is_paired() override;
|
|
61
|
+
virtual void unpair() override;
|
|
62
|
+
|
|
63
|
+
virtual std::vector<std::shared_ptr<ServiceBase>> available_services() override;
|
|
64
|
+
virtual std::vector<std::shared_ptr<ServiceBase>> advertised_services() override;
|
|
65
|
+
virtual std::map<uint16_t, ByteArray> manufacturer_data() override;
|
|
66
|
+
|
|
67
|
+
// clang-format off
|
|
68
|
+
virtual ByteArray read(BluetoothUUID const& service, BluetoothUUID const& characteristic) override;
|
|
69
|
+
virtual void write_request(BluetoothUUID const& service, BluetoothUUID const& characteristic, ByteArray const& data) override;
|
|
70
|
+
virtual void write_command(BluetoothUUID const& service, BluetoothUUID const& characteristic, ByteArray const& data) override;
|
|
71
|
+
virtual void notify(BluetoothUUID const& service, BluetoothUUID const& characteristic, std::function<void(ByteArray payload)> callback) override;
|
|
72
|
+
virtual void indicate(BluetoothUUID const& service, BluetoothUUID const& characteristic, std::function<void(ByteArray payload)> callback) override;
|
|
73
|
+
virtual void unsubscribe(BluetoothUUID const& service, BluetoothUUID const& characteristic) override;
|
|
74
|
+
|
|
75
|
+
virtual ByteArray read(BluetoothUUID const& service, BluetoothUUID const& characteristic, BluetoothUUID const& descriptor) override;
|
|
76
|
+
virtual void write(BluetoothUUID const& service, BluetoothUUID const& characteristic, BluetoothUUID const& descriptor, ByteArray const& data) override;
|
|
77
|
+
// clang-format on
|
|
78
|
+
|
|
79
|
+
virtual void set_callback_on_connected(std::function<void()> on_connected) override;
|
|
80
|
+
virtual void set_callback_on_disconnected(std::function<void()> on_disconnected) override;
|
|
81
|
+
|
|
82
|
+
// Internal methods not exposed to the user.
|
|
83
|
+
|
|
84
|
+
void update_advertising_data(advertising_data_t advertising_data);
|
|
85
|
+
|
|
86
|
+
private:
|
|
87
|
+
BluetoothLEDevice device_{nullptr};
|
|
88
|
+
|
|
89
|
+
// NOTE: Calling device_.Name() or device_.BluetoothAddress() might
|
|
90
|
+
// cause a crash on some devices.
|
|
91
|
+
// This is because any operation on the object before it is connected will
|
|
92
|
+
// initiate a connection, which can then cause further cascading failures.
|
|
93
|
+
// See:
|
|
94
|
+
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothledevice.frombluetoothaddressasync
|
|
95
|
+
|
|
96
|
+
std::string identifier_;
|
|
97
|
+
BluetoothAddress address_;
|
|
98
|
+
SimpleBLE::BluetoothAddressType address_type_;
|
|
99
|
+
int16_t rssi_ = INT16_MIN;
|
|
100
|
+
int16_t tx_power_ = INT16_MIN;
|
|
101
|
+
uint16_t mtu_;
|
|
102
|
+
bool connectable_;
|
|
103
|
+
winrt::event_token connection_status_changed_token_;
|
|
104
|
+
|
|
105
|
+
std::condition_variable disconnection_cv_;
|
|
106
|
+
std::mutex disconnection_mutex_;
|
|
107
|
+
|
|
108
|
+
std::map<BluetoothUUID, gatt_service_t> gatt_map_;
|
|
109
|
+
|
|
110
|
+
kvn::safe_callback<void()> callback_on_connected_;
|
|
111
|
+
kvn::safe_callback<void()> callback_on_disconnected_;
|
|
112
|
+
|
|
113
|
+
std::map<uint16_t, SimpleBLE::ByteArray> manufacturer_data_;
|
|
114
|
+
std::map<BluetoothUUID, SimpleBLE::ByteArray> service_data_;
|
|
115
|
+
|
|
116
|
+
bool _attempt_connect();
|
|
117
|
+
|
|
118
|
+
gatt_characteristic_t& _fetch_characteristic(const BluetoothUUID& service_uuid,
|
|
119
|
+
const BluetoothUUID& characteristic_uuid);
|
|
120
|
+
|
|
121
|
+
GattDescriptor _fetch_descriptor(const BluetoothUUID& service_uuid, const BluetoothUUID& characteristic_uuid,
|
|
122
|
+
const BluetoothUUID& descriptor_uuid);
|
|
123
|
+
|
|
124
|
+
void _subscribe(BluetoothUUID const& service, BluetoothUUID const& characteristic,
|
|
125
|
+
std::function<void(ByteArray payload)> callback, GattCharacteristicProperties property,
|
|
126
|
+
GattClientCharacteristicConfigurationDescriptorValue descriptor_value);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
} // namespace SimpleBLE
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#include "Utils.h"
|
|
2
|
+
|
|
3
|
+
#include <iomanip>
|
|
4
|
+
#include <iostream>
|
|
5
|
+
#include <sstream>
|
|
6
|
+
|
|
7
|
+
#include <roapi.h>
|
|
8
|
+
#include <sdkddkver.h>
|
|
9
|
+
|
|
10
|
+
#include "LoggingInternal.h"
|
|
11
|
+
|
|
12
|
+
#if WDK_NTDDI_VERSION < NTDDI_WIN10_VB
|
|
13
|
+
#error "Windows SDK version before 10.0.19041.0 is not supported"
|
|
14
|
+
#elif WDK_NTDDI_VERSION == NTDDI_WIN10_VB
|
|
15
|
+
// For Windows SDK version before 10.0.19041.0, remap functions to post-10.0.19041.0 versions
|
|
16
|
+
#define WINRT_IMPL_CoGetApartmentType WINRT_CoGetApartmentType
|
|
17
|
+
#endif
|
|
18
|
+
|
|
19
|
+
#define MAC_ADDRESS_STR_LENGTH (size_t)17 // Two chars per byte, 5 chars for colon
|
|
20
|
+
|
|
21
|
+
namespace SimpleBLE {
|
|
22
|
+
|
|
23
|
+
void initialize_winrt() {
|
|
24
|
+
static bool initialized = false;
|
|
25
|
+
if (initialized) return;
|
|
26
|
+
initialized = true;
|
|
27
|
+
|
|
28
|
+
int32_t cotype = APTTYPE_NA;
|
|
29
|
+
int32_t qualifier = APTTYPEQUALIFIER_NONE;
|
|
30
|
+
winrt::hresult get_apartment_result = WINRT_IMPL_CoGetApartmentType(&cotype, &qualifier);
|
|
31
|
+
|
|
32
|
+
SIMPLEBLE_LOG_DEBUG(fmt::format("CoGetApartmentType: cotype={}, qualifier={}, result={:X}", cotype, qualifier,
|
|
33
|
+
(uint32_t)get_apartment_result));
|
|
34
|
+
|
|
35
|
+
if (cotype == APTTYPE_STA || cotype == APTTYPE_MAINSTA) {
|
|
36
|
+
SIMPLEBLE_LOG_WARN("Single-threaded apartment detected, uninitializing.");
|
|
37
|
+
RoUninitialize();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
winrt::hresult result = RoInitialize(RO_INIT_MULTITHREADED);
|
|
41
|
+
std::string result_str = hresult_to_string(result);
|
|
42
|
+
if (FAILED(result)) {
|
|
43
|
+
SIMPLEBLE_LOG_ERROR(fmt::format("RoInitialize failed: {}", result_str));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
std::string _mac_address_to_str(uint64_t mac_address) {
|
|
48
|
+
uint8_t* mac_ptr = (uint8_t*)&mac_address;
|
|
49
|
+
char mac_str[MAC_ADDRESS_STR_LENGTH + 1] = {0}; // Include null terminator.
|
|
50
|
+
|
|
51
|
+
snprintf(mac_str, MAC_ADDRESS_STR_LENGTH + 1, "%02x:%02x:%02x:%02x:%02x:%02x", mac_ptr[5], mac_ptr[4], mac_ptr[3],
|
|
52
|
+
mac_ptr[2], mac_ptr[1], mac_ptr[0]);
|
|
53
|
+
return std::string(mac_str);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
uint64_t _str_to_mac_address(std::string mac_str) {
|
|
57
|
+
// TODO: Validate input - Expected Format: XX:XX:XX:XX:XX:XX
|
|
58
|
+
uint64_t mac_address_number = 0;
|
|
59
|
+
uint8_t* mac_ptr = (uint8_t*)&mac_address_number;
|
|
60
|
+
sscanf(mac_str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac_ptr[5], &mac_ptr[4], &mac_ptr[3],
|
|
61
|
+
&mac_ptr[2], &mac_ptr[1], &mac_ptr[0]);
|
|
62
|
+
return mac_address_number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
winrt::guid uuid_to_guid(const std::string& uuid) {
|
|
66
|
+
// TODO: Add proper cleanup / validation
|
|
67
|
+
std::stringstream helper;
|
|
68
|
+
for (int i = 0; i < uuid.length(); i++) {
|
|
69
|
+
if (uuid[i] != '-') {
|
|
70
|
+
helper << uuid[i];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
std::string clean_uuid = helper.str();
|
|
74
|
+
winrt::guid guid;
|
|
75
|
+
uint64_t* data4_ptr = (uint64_t*)guid.Data4;
|
|
76
|
+
|
|
77
|
+
guid.Data1 = static_cast<uint32_t>(std::strtoul(clean_uuid.substr(0, 8).c_str(), nullptr, 16));
|
|
78
|
+
guid.Data2 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(8, 4).c_str(), nullptr, 16));
|
|
79
|
+
guid.Data3 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(12, 4).c_str(), nullptr, 16));
|
|
80
|
+
*data4_ptr = _byteswap_uint64(std::strtoull(clean_uuid.substr(16, 16).c_str(), nullptr, 16));
|
|
81
|
+
|
|
82
|
+
return guid;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
std::string guid_to_uuid(const winrt::guid& guid) {
|
|
86
|
+
std::stringstream helper;
|
|
87
|
+
// TODO: It might be cleaner to use snprintf instead of string streams.
|
|
88
|
+
|
|
89
|
+
for (uint32_t i = 0; i < 4; i++) {
|
|
90
|
+
// * NOTE: We're performing a byte swap!
|
|
91
|
+
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data1)[3 - i];
|
|
92
|
+
}
|
|
93
|
+
helper << '-';
|
|
94
|
+
for (uint32_t i = 0; i < 2; i++) {
|
|
95
|
+
// * NOTE: We're performing a byte swap!
|
|
96
|
+
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data2)[1 - i];
|
|
97
|
+
}
|
|
98
|
+
helper << '-';
|
|
99
|
+
for (uint32_t i = 0; i < 2; i++) {
|
|
100
|
+
// * NOTE: We're performing a byte swap!
|
|
101
|
+
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t*)&guid.Data3)[1 - i];
|
|
102
|
+
}
|
|
103
|
+
helper << '-';
|
|
104
|
+
for (uint32_t i = 0; i < 2; i++) {
|
|
105
|
+
helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[i];
|
|
106
|
+
}
|
|
107
|
+
helper << '-';
|
|
108
|
+
for (uint32_t i = 0; i < 6; i++) {
|
|
109
|
+
helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[2 + i];
|
|
110
|
+
}
|
|
111
|
+
return helper.str();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
ByteArray ibuffer_to_bytearray(const IBuffer& buffer) { return ByteArray((const char*)buffer.data(), buffer.Length()); }
|
|
115
|
+
|
|
116
|
+
IBuffer bytearray_to_ibuffer(const ByteArray& array) {
|
|
117
|
+
DataWriter writer;
|
|
118
|
+
for (auto& byte : array) {
|
|
119
|
+
writer.WriteByte(byte);
|
|
120
|
+
}
|
|
121
|
+
return writer.DetachBuffer();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
std::string hresult_to_string(winrt::hresult hr) {
|
|
125
|
+
if (SUCCEEDED(hr)) {
|
|
126
|
+
if (hr == S_OK) return "S_OK";
|
|
127
|
+
if (hr == S_FALSE) return "S_FALSE";
|
|
128
|
+
// Other success codes are possible but less common here.
|
|
129
|
+
return fmt::format("Success ({:#08x})", (uint32_t)hr);
|
|
130
|
+
} else {
|
|
131
|
+
try {
|
|
132
|
+
// Attempt to get the system message for the error.
|
|
133
|
+
winrt::check_hresult(hr);
|
|
134
|
+
} catch (const winrt::hresult_error& e) {
|
|
135
|
+
// Use fmt::format for consistent formatting
|
|
136
|
+
return fmt::format("Error ({:#08x}): {}", (uint32_t)hr, winrt::to_string(e.message()));
|
|
137
|
+
} catch (...) {
|
|
138
|
+
// Fallback for unexpected exceptions during error handling
|
|
139
|
+
return fmt::format("Unknown Error ({:#08x})", (uint32_t)hr);
|
|
140
|
+
}
|
|
141
|
+
// Should not be reached if hr is an error and check_hresult behaved as expected
|
|
142
|
+
return fmt::format("Error ({:#08x})", (uint32_t)hr);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
} // namespace SimpleBLE
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cstdint>
|
|
4
|
+
#include <exception>
|
|
5
|
+
#include <string>
|
|
6
|
+
|
|
7
|
+
#include <simpleble/Exceptions.h>
|
|
8
|
+
#include <simpleble/Types.h>
|
|
9
|
+
|
|
10
|
+
#include "winrt/Windows.Foundation.h"
|
|
11
|
+
#include "winrt/Windows.Storage.Streams.h"
|
|
12
|
+
#include "winrt/base.h"
|
|
13
|
+
|
|
14
|
+
using namespace winrt::Windows;
|
|
15
|
+
using namespace winrt::Windows::Storage::Streams;
|
|
16
|
+
|
|
17
|
+
constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000;
|
|
18
|
+
|
|
19
|
+
namespace SimpleBLE {
|
|
20
|
+
void initialize_winrt();
|
|
21
|
+
|
|
22
|
+
std::string _mac_address_to_str(uint64_t mac_address);
|
|
23
|
+
uint64_t _str_to_mac_address(std::string mac_address);
|
|
24
|
+
|
|
25
|
+
winrt::guid uuid_to_guid(const std::string& uuid);
|
|
26
|
+
std::string guid_to_uuid(const winrt::guid& guid);
|
|
27
|
+
|
|
28
|
+
ByteArray ibuffer_to_bytearray(const IBuffer& buffer);
|
|
29
|
+
IBuffer bytearray_to_ibuffer(const ByteArray& array);
|
|
30
|
+
|
|
31
|
+
std::string hresult_to_string(winrt::hresult hr);
|
|
32
|
+
|
|
33
|
+
template <typename async_t>
|
|
34
|
+
static auto async_get(async_t const& async) {
|
|
35
|
+
if (async.Status() == Foundation::AsyncStatus::Started) {
|
|
36
|
+
wait_for_completed(async, TEN_SECONDS_IN_MSECS);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return async.GetResults();
|
|
40
|
+
} catch (const winrt::hresult_error& err) {
|
|
41
|
+
throw SimpleBLE::Exception::WinRTException(err.code().value, winrt::to_string(err.message()));
|
|
42
|
+
} catch (const std::exception& err) {
|
|
43
|
+
throw SimpleBLE::Exception::BaseException(err.what());
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
} // namespace SimpleBLE
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "BuilderBase.h"
|
|
4
|
+
|
|
5
|
+
namespace SimpleBLE::Factory {
|
|
6
|
+
|
|
7
|
+
template <typename V1>
|
|
8
|
+
struct BuildVecDeduce {
|
|
9
|
+
template <typename T>
|
|
10
|
+
operator T() && {
|
|
11
|
+
T vec;
|
|
12
|
+
vec.reserve(objs.size());
|
|
13
|
+
for (auto& obj : objs) {
|
|
14
|
+
vec.push_back(build(std::move(obj)));
|
|
15
|
+
}
|
|
16
|
+
return vec;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
V1 objs;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Build a vector of objects which are not directly constructible.
|
|
24
|
+
*
|
|
25
|
+
* This calls `Factory::build()` for each object in the input vector.
|
|
26
|
+
*/
|
|
27
|
+
template <typename V1>
|
|
28
|
+
auto vector(V1 objs) {
|
|
29
|
+
return BuildVecDeduce<V1>{std::move(objs)};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
} // namespace SimpleBLE::Factory
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
#include <tuple>
|
|
5
|
+
#include <type_traits>
|
|
6
|
+
#include <utility>
|
|
7
|
+
|
|
8
|
+
namespace SimpleBLE::Factory {
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Generic builder class for PIMP classes that have an "internal_" member variable.
|
|
12
|
+
*
|
|
13
|
+
* Normally, the base class's non-default constructor will not exist or will be
|
|
14
|
+
* protected, so that the user cannot directly initialize the class (i.e. set
|
|
15
|
+
* the "internal_" member variable to non-null).
|
|
16
|
+
*
|
|
17
|
+
* Additionally, this builder class allows for the construction of pointer-to
|
|
18
|
+
* object directly in the constructor.
|
|
19
|
+
*
|
|
20
|
+
* It is possible to specialize this class for classes that are constructed
|
|
21
|
+
* differently.
|
|
22
|
+
*/
|
|
23
|
+
template <typename T>
|
|
24
|
+
struct Builder : public T {
|
|
25
|
+
using T::internal_;
|
|
26
|
+
using PtrT = decltype(Builder::internal_);
|
|
27
|
+
|
|
28
|
+
Builder() { this->internal_ = std::make_shared<InternalT>(); }
|
|
29
|
+
using InternalT = typename std::remove_reference<decltype(*(Builder::internal_))>::type;
|
|
30
|
+
|
|
31
|
+
Builder(PtrT&& internal) { this->internal_ = std::move(internal); }
|
|
32
|
+
|
|
33
|
+
template <typename dPtr>
|
|
34
|
+
Builder(dPtr&& internal) {
|
|
35
|
+
this->internal_ = internal;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
template <typename... ARG>
|
|
39
|
+
Builder(ARG&&... args) {
|
|
40
|
+
using InternalT = typename std::remove_reference<decltype(*(Builder::internal_))>::type;
|
|
41
|
+
this->internal_ = std::make_shared<InternalT>(std::forward<ARG>(args)...);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Helper class to deduce the return type of the build function.
|
|
47
|
+
*/
|
|
48
|
+
template <typename ARG>
|
|
49
|
+
struct BuildDeduce {
|
|
50
|
+
template <typename T>
|
|
51
|
+
operator T() && {
|
|
52
|
+
return Builder<T>(std::move(arg));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ARG arg;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
struct BuildDeduce0 {
|
|
59
|
+
template <typename T>
|
|
60
|
+
operator T() && {
|
|
61
|
+
return Builder<T>();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Build a new object which is not directly constructible.
|
|
67
|
+
*
|
|
68
|
+
* The target class must have a default constructor and must have a protected
|
|
69
|
+
* "internal_" member variable.
|
|
70
|
+
*/
|
|
71
|
+
template <typename ARG>
|
|
72
|
+
auto build(ARG x) {
|
|
73
|
+
return BuildDeduce<ARG>{std::move(x)};
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Build a new object whose "internal_" type can be default-constructed.
|
|
78
|
+
*
|
|
79
|
+
* For example, for Adapter, calling `Adapter a = Factory::build();` is equivalent to
|
|
80
|
+
* `Adapter a = Build<Adapter>(std::make_shared<AdapterBase>());`.
|
|
81
|
+
*/
|
|
82
|
+
template <typename = void>
|
|
83
|
+
auto build() {
|
|
84
|
+
return BuildDeduce0{};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
} // namespace SimpleBLE::Factory
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <chrono>
|
|
4
|
+
#include <functional>
|
|
5
|
+
#include <future>
|
|
6
|
+
#include <mutex>
|
|
7
|
+
#include <optional>
|
|
8
|
+
#include <queue>
|
|
9
|
+
#include <thread>
|
|
10
|
+
|
|
11
|
+
class TaskRunner {
|
|
12
|
+
private:
|
|
13
|
+
using Clock = std::chrono::steady_clock;
|
|
14
|
+
using TimePoint = Clock::time_point;
|
|
15
|
+
using Duration = Clock::duration;
|
|
16
|
+
using Task = std::function<std::optional<Duration>()>;
|
|
17
|
+
|
|
18
|
+
struct ScheduledTask {
|
|
19
|
+
TimePoint executionTime;
|
|
20
|
+
Task task;
|
|
21
|
+
|
|
22
|
+
bool operator>(const ScheduledTask& other) const { return executionTime > other.executionTime; }
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
std::priority_queue<ScheduledTask, std::vector<ScheduledTask>, std::greater<ScheduledTask>> taskQueue;
|
|
26
|
+
std::mutex taskQueueMutex;
|
|
27
|
+
std::condition_variable taskQueueCV;
|
|
28
|
+
bool running = false;
|
|
29
|
+
std::thread workerThread;
|
|
30
|
+
|
|
31
|
+
public:
|
|
32
|
+
TaskRunner() = default;
|
|
33
|
+
|
|
34
|
+
~TaskRunner() { stop(); }
|
|
35
|
+
|
|
36
|
+
void start() {
|
|
37
|
+
if (!running) {
|
|
38
|
+
running = true;
|
|
39
|
+
workerThread = std::thread(&TaskRunner::workerLoop, this);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
void stop() {
|
|
44
|
+
if (running) {
|
|
45
|
+
{
|
|
46
|
+
std::unique_lock<std::mutex> lock(taskQueueMutex);
|
|
47
|
+
running = false;
|
|
48
|
+
taskQueueCV.notify_one();
|
|
49
|
+
}
|
|
50
|
+
workerThread.join();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
void dispatch(Task task, Duration delay) {
|
|
55
|
+
TimePoint executionTime = Clock::now() + delay;
|
|
56
|
+
{
|
|
57
|
+
std::unique_lock<std::mutex> lock(taskQueueMutex);
|
|
58
|
+
taskQueue.push({executionTime, std::move(task)});
|
|
59
|
+
taskQueueCV.notify_one();
|
|
60
|
+
}
|
|
61
|
+
if (!running) {
|
|
62
|
+
start();
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private:
|
|
67
|
+
void workerLoop() {
|
|
68
|
+
while (true) {
|
|
69
|
+
std::unique_lock<std::mutex> lock(taskQueueMutex);
|
|
70
|
+
taskQueueCV.wait(lock, [this] { return !running || !taskQueue.empty(); });
|
|
71
|
+
|
|
72
|
+
if (!running) {
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (taskQueue.empty()) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// NOTE: If a new task is added to the queue with a shorter delay than the current top task, the worker
|
|
81
|
+
// thread will not wake up until the top task's execution time is reached. This is not ideal, but it's good
|
|
82
|
+
// enough for this simple implementation.
|
|
83
|
+
|
|
84
|
+
auto now = Clock::now();
|
|
85
|
+
if (taskQueue.top().executionTime > now) {
|
|
86
|
+
taskQueueCV.wait_until(lock, taskQueue.top().executionTime);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
auto task = std::move(taskQueue.top().task);
|
|
90
|
+
taskQueue.pop();
|
|
91
|
+
lock.unlock();
|
|
92
|
+
|
|
93
|
+
auto result = task();
|
|
94
|
+
if (result.has_value()) {
|
|
95
|
+
dispatch(std::move(task), *result);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <condition_variable>
|
|
4
|
+
#include <functional>
|
|
5
|
+
#include <mutex>
|
|
6
|
+
#include <queue>
|
|
7
|
+
#include <thread>
|
|
8
|
+
|
|
9
|
+
class ThreadRunner {
|
|
10
|
+
public:
|
|
11
|
+
ThreadRunner() : _stop(false) { _thread = std::thread(&ThreadRunner::threadFunc, this); }
|
|
12
|
+
|
|
13
|
+
~ThreadRunner() {
|
|
14
|
+
{
|
|
15
|
+
std::unique_lock<std::mutex> lock(_mutex);
|
|
16
|
+
_stop = true;
|
|
17
|
+
_cv.notify_one();
|
|
18
|
+
}
|
|
19
|
+
_thread.join();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
void enqueue(std::function<void()> func) {
|
|
23
|
+
{
|
|
24
|
+
std::unique_lock<std::mutex> lock(_mutex);
|
|
25
|
+
_queue.push(std::move(func));
|
|
26
|
+
_cv.notify_one();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private:
|
|
31
|
+
void threadFunc() {
|
|
32
|
+
while (true) {
|
|
33
|
+
std::function<void()> func;
|
|
34
|
+
{
|
|
35
|
+
std::unique_lock<std::mutex> lock(_mutex);
|
|
36
|
+
_cv.wait(lock, [this] { return _stop || !_queue.empty(); });
|
|
37
|
+
if (_stop && _queue.empty()) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
func = std::move(_queue.front());
|
|
41
|
+
_queue.pop();
|
|
42
|
+
}
|
|
43
|
+
func();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
std::thread _thread;
|
|
48
|
+
std::mutex _mutex;
|
|
49
|
+
std::condition_variable _cv;
|
|
50
|
+
std::queue<std::function<void()>> _queue;
|
|
51
|
+
bool _stop;
|
|
52
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-FileCopyrightText: 2022 Kevin Dewald <kevin@dewald.me>
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#ifndef KVN_SAFE_CALLBACK_HPP
|
|
8
|
+
#define KVN_SAFE_CALLBACK_HPP
|
|
9
|
+
|
|
10
|
+
#include <atomic>
|
|
11
|
+
#include <functional>
|
|
12
|
+
#include <memory>
|
|
13
|
+
#include <mutex>
|
|
14
|
+
|
|
15
|
+
namespace kvn {
|
|
16
|
+
|
|
17
|
+
template <typename _Signature>
|
|
18
|
+
class safe_callback;
|
|
19
|
+
|
|
20
|
+
template <class _Res, class... _ArgTypes>
|
|
21
|
+
class safe_callback<_Res(_ArgTypes...)> {
|
|
22
|
+
public:
|
|
23
|
+
safe_callback() = default;
|
|
24
|
+
|
|
25
|
+
// Remove copy constructor and copy assignment
|
|
26
|
+
safe_callback(const safe_callback&) = delete;
|
|
27
|
+
safe_callback& operator=(const safe_callback&) = delete;
|
|
28
|
+
|
|
29
|
+
virtual ~safe_callback() { unload(); };
|
|
30
|
+
|
|
31
|
+
void load(std::function<_Res(_ArgTypes...)> callback) {
|
|
32
|
+
if (callback == nullptr) return;
|
|
33
|
+
|
|
34
|
+
std::scoped_lock lock(_mutex);
|
|
35
|
+
_callback = std::move(callback);
|
|
36
|
+
_is_loaded = true;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void unload() {
|
|
40
|
+
std::scoped_lock lock(_mutex);
|
|
41
|
+
_callback = nullptr;
|
|
42
|
+
_is_loaded = false;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
bool is_loaded() const { return _is_loaded; }
|
|
46
|
+
|
|
47
|
+
explicit operator bool() const { return is_loaded(); }
|
|
48
|
+
|
|
49
|
+
_Res operator()(_ArgTypes... arguments) {
|
|
50
|
+
std::scoped_lock lock(_mutex);
|
|
51
|
+
if (_is_loaded) {
|
|
52
|
+
return _callback(std::forward<_ArgTypes&&>(arguments)...);
|
|
53
|
+
} else {
|
|
54
|
+
return _Res();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
protected:
|
|
59
|
+
std::atomic_bool _is_loaded{false};
|
|
60
|
+
std::function<_Res(_ArgTypes...)> _callback;
|
|
61
|
+
std::recursive_mutex _mutex;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
} // namespace kvn
|
|
65
|
+
|
|
66
|
+
#endif // KVN_SAFE_CALLBACK_HPP
|