Initial commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
flutter/
|
||||
|
||||
# Visual Studio user-specific files.
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# Visual Studio build-related files.
|
||||
x64/
|
||||
x86/
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
@@ -0,0 +1,76 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
set(PROJECT_NAME "universal_ble")
|
||||
project(${PROJECT_NAME} LANGUAGES CXX)
|
||||
cmake_policy(VERSION 3.14...3.25)
|
||||
include(FetchContent)
|
||||
set(CPPWINRT_VERSION "2.0.220418.1")
|
||||
set(PLUGIN_NAME "universal_ble_plugin")
|
||||
|
||||
################ NuGet intall begin ################
|
||||
FetchContent_Declare(nuget
|
||||
URL "https://dist.nuget.org/win-x86-commandline/v6.0.0/nuget.exe"
|
||||
URL_HASH SHA256=04eb6c4fe4213907e2773e1be1bbbd730e9a655a3c9c58387ce8d4a714a5b9e1
|
||||
DOWNLOAD_NO_EXTRACT true
|
||||
)
|
||||
|
||||
find_program(NUGET nuget)
|
||||
if (NOT NUGET)
|
||||
message("Nuget.exe not found, trying to download or use cached version.")
|
||||
FetchContent_MakeAvailable(nuget)
|
||||
set(NUGET ${nuget_SOURCE_DIR}/nuget.exe)
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
${NUGET} install "Microsoft.Windows.CppWinRT" -Version ${CPPWINRT_VERSION} -OutputDirectory packages
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
RESULT_VARIABLE ret)
|
||||
if (NOT ret EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to install nuget package Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}")
|
||||
endif()
|
||||
|
||||
################ NuGet install end ################
|
||||
|
||||
|
||||
list(APPEND PLUGIN_SOURCES
|
||||
"universal_ble_plugin.cpp"
|
||||
"universal_ble_plugin.h"
|
||||
"universal_enum.h"
|
||||
"Utils.cpp"
|
||||
"Utils.h"
|
||||
"UniversalBle.g.cpp"
|
||||
"UniversalBle.g.h"
|
||||
)
|
||||
|
||||
add_library(${PLUGIN_NAME} SHARED
|
||||
"include/universal_ble/universal_ble_plugin_c_api.h"
|
||||
"universal_ble_plugin_c_api.cpp"
|
||||
${PLUGIN_SOURCES}
|
||||
)
|
||||
|
||||
|
||||
apply_standard_settings(${PLUGIN_NAME})
|
||||
|
||||
|
||||
################ NuGet import begin ################
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES VS_PROJECT_IMPORT
|
||||
${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.props
|
||||
)
|
||||
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE
|
||||
${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT.${CPPWINRT_VERSION}/build/native/Microsoft.Windows.CppWinRT.targets
|
||||
)
|
||||
################ NuGet import end ################
|
||||
|
||||
set_target_properties(${PLUGIN_NAME} PROPERTIES
|
||||
CXX_VISIBILITY_PRESET hidden)
|
||||
target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL)
|
||||
|
||||
target_include_directories(${PLUGIN_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin)
|
||||
|
||||
|
||||
set(universal_ble_bundled_libraries
|
||||
""
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,940 @@
|
||||
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
#undef _HAS_EXCEPTIONS
|
||||
|
||||
#include "UniversalBle.g.h"
|
||||
|
||||
#include <flutter/basic_message_channel.h>
|
||||
#include <flutter/binary_messenger.h>
|
||||
#include <flutter/encodable_value.h>
|
||||
#include <flutter/standard_message_codec.h>
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace universal_ble {
|
||||
using flutter::BasicMessageChannel;
|
||||
using flutter::CustomEncodableValue;
|
||||
using flutter::EncodableList;
|
||||
using flutter::EncodableMap;
|
||||
using flutter::EncodableValue;
|
||||
|
||||
// UniversalBleScanResult
|
||||
|
||||
UniversalBleScanResult::UniversalBleScanResult(const std::string& device_id)
|
||||
: device_id_(device_id) {}
|
||||
|
||||
UniversalBleScanResult::UniversalBleScanResult(
|
||||
const std::string& device_id,
|
||||
const std::string* name,
|
||||
const bool* is_paired,
|
||||
const int64_t* rssi,
|
||||
const std::vector<uint8_t>* manufacturer_data,
|
||||
const std::vector<uint8_t>* manufacturer_data_head)
|
||||
: device_id_(device_id),
|
||||
name_(name ? std::optional<std::string>(*name) : std::nullopt),
|
||||
is_paired_(is_paired ? std::optional<bool>(*is_paired) : std::nullopt),
|
||||
rssi_(rssi ? std::optional<int64_t>(*rssi) : std::nullopt),
|
||||
manufacturer_data_(manufacturer_data ? std::optional<std::vector<uint8_t>>(*manufacturer_data) : std::nullopt),
|
||||
manufacturer_data_head_(manufacturer_data_head ? std::optional<std::vector<uint8_t>>(*manufacturer_data_head) : std::nullopt) {}
|
||||
|
||||
const std::string& UniversalBleScanResult::device_id() const {
|
||||
return device_id_;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_device_id(std::string_view value_arg) {
|
||||
device_id_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const std::string* UniversalBleScanResult::name() const {
|
||||
return name_ ? &(*name_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_name(const std::string_view* value_arg) {
|
||||
name_ = value_arg ? std::optional<std::string>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_name(std::string_view value_arg) {
|
||||
name_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const bool* UniversalBleScanResult::is_paired() const {
|
||||
return is_paired_ ? &(*is_paired_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_is_paired(const bool* value_arg) {
|
||||
is_paired_ = value_arg ? std::optional<bool>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_is_paired(bool value_arg) {
|
||||
is_paired_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const int64_t* UniversalBleScanResult::rssi() const {
|
||||
return rssi_ ? &(*rssi_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_rssi(const int64_t* value_arg) {
|
||||
rssi_ = value_arg ? std::optional<int64_t>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_rssi(int64_t value_arg) {
|
||||
rssi_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<uint8_t>* UniversalBleScanResult::manufacturer_data() const {
|
||||
return manufacturer_data_ ? &(*manufacturer_data_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_manufacturer_data(const std::vector<uint8_t>* value_arg) {
|
||||
manufacturer_data_ = value_arg ? std::optional<std::vector<uint8_t>>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_manufacturer_data(const std::vector<uint8_t>& value_arg) {
|
||||
manufacturer_data_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const std::vector<uint8_t>* UniversalBleScanResult::manufacturer_data_head() const {
|
||||
return manufacturer_data_head_ ? &(*manufacturer_data_head_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_manufacturer_data_head(const std::vector<uint8_t>* value_arg) {
|
||||
manufacturer_data_head_ = value_arg ? std::optional<std::vector<uint8_t>>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleScanResult::set_manufacturer_data_head(const std::vector<uint8_t>& value_arg) {
|
||||
manufacturer_data_head_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
EncodableList UniversalBleScanResult::ToEncodableList() const {
|
||||
EncodableList list;
|
||||
list.reserve(6);
|
||||
list.push_back(EncodableValue(device_id_));
|
||||
list.push_back(name_ ? EncodableValue(*name_) : EncodableValue());
|
||||
list.push_back(is_paired_ ? EncodableValue(*is_paired_) : EncodableValue());
|
||||
list.push_back(rssi_ ? EncodableValue(*rssi_) : EncodableValue());
|
||||
list.push_back(manufacturer_data_ ? EncodableValue(*manufacturer_data_) : EncodableValue());
|
||||
list.push_back(manufacturer_data_head_ ? EncodableValue(*manufacturer_data_head_) : EncodableValue());
|
||||
return list;
|
||||
}
|
||||
|
||||
UniversalBleScanResult UniversalBleScanResult::FromEncodableList(const EncodableList& list) {
|
||||
UniversalBleScanResult decoded(
|
||||
std::get<std::string>(list[0]));
|
||||
auto& encodable_name = list[1];
|
||||
if (!encodable_name.IsNull()) {
|
||||
decoded.set_name(std::get<std::string>(encodable_name));
|
||||
}
|
||||
auto& encodable_is_paired = list[2];
|
||||
if (!encodable_is_paired.IsNull()) {
|
||||
decoded.set_is_paired(std::get<bool>(encodable_is_paired));
|
||||
}
|
||||
auto& encodable_rssi = list[3];
|
||||
if (!encodable_rssi.IsNull()) {
|
||||
decoded.set_rssi(encodable_rssi.LongValue());
|
||||
}
|
||||
auto& encodable_manufacturer_data = list[4];
|
||||
if (!encodable_manufacturer_data.IsNull()) {
|
||||
decoded.set_manufacturer_data(std::get<std::vector<uint8_t>>(encodable_manufacturer_data));
|
||||
}
|
||||
auto& encodable_manufacturer_data_head = list[5];
|
||||
if (!encodable_manufacturer_data_head.IsNull()) {
|
||||
decoded.set_manufacturer_data_head(std::get<std::vector<uint8_t>>(encodable_manufacturer_data_head));
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
// UniversalBleService
|
||||
|
||||
UniversalBleService::UniversalBleService(const std::string& uuid)
|
||||
: uuid_(uuid) {}
|
||||
|
||||
UniversalBleService::UniversalBleService(
|
||||
const std::string& uuid,
|
||||
const EncodableList* characteristics)
|
||||
: uuid_(uuid),
|
||||
characteristics_(characteristics ? std::optional<EncodableList>(*characteristics) : std::nullopt) {}
|
||||
|
||||
const std::string& UniversalBleService::uuid() const {
|
||||
return uuid_;
|
||||
}
|
||||
|
||||
void UniversalBleService::set_uuid(std::string_view value_arg) {
|
||||
uuid_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const EncodableList* UniversalBleService::characteristics() const {
|
||||
return characteristics_ ? &(*characteristics_) : nullptr;
|
||||
}
|
||||
|
||||
void UniversalBleService::set_characteristics(const EncodableList* value_arg) {
|
||||
characteristics_ = value_arg ? std::optional<EncodableList>(*value_arg) : std::nullopt;
|
||||
}
|
||||
|
||||
void UniversalBleService::set_characteristics(const EncodableList& value_arg) {
|
||||
characteristics_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
EncodableList UniversalBleService::ToEncodableList() const {
|
||||
EncodableList list;
|
||||
list.reserve(2);
|
||||
list.push_back(EncodableValue(uuid_));
|
||||
list.push_back(characteristics_ ? EncodableValue(*characteristics_) : EncodableValue());
|
||||
return list;
|
||||
}
|
||||
|
||||
UniversalBleService UniversalBleService::FromEncodableList(const EncodableList& list) {
|
||||
UniversalBleService decoded(
|
||||
std::get<std::string>(list[0]));
|
||||
auto& encodable_characteristics = list[1];
|
||||
if (!encodable_characteristics.IsNull()) {
|
||||
decoded.set_characteristics(std::get<EncodableList>(encodable_characteristics));
|
||||
}
|
||||
return decoded;
|
||||
}
|
||||
|
||||
// UniversalBleCharacteristic
|
||||
|
||||
UniversalBleCharacteristic::UniversalBleCharacteristic(
|
||||
const std::string& uuid,
|
||||
const EncodableList& properties)
|
||||
: uuid_(uuid),
|
||||
properties_(properties) {}
|
||||
|
||||
const std::string& UniversalBleCharacteristic::uuid() const {
|
||||
return uuid_;
|
||||
}
|
||||
|
||||
void UniversalBleCharacteristic::set_uuid(std::string_view value_arg) {
|
||||
uuid_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
const EncodableList& UniversalBleCharacteristic::properties() const {
|
||||
return properties_;
|
||||
}
|
||||
|
||||
void UniversalBleCharacteristic::set_properties(const EncodableList& value_arg) {
|
||||
properties_ = value_arg;
|
||||
}
|
||||
|
||||
|
||||
EncodableList UniversalBleCharacteristic::ToEncodableList() const {
|
||||
EncodableList list;
|
||||
list.reserve(2);
|
||||
list.push_back(EncodableValue(uuid_));
|
||||
list.push_back(EncodableValue(properties_));
|
||||
return list;
|
||||
}
|
||||
|
||||
UniversalBleCharacteristic UniversalBleCharacteristic::FromEncodableList(const EncodableList& list) {
|
||||
UniversalBleCharacteristic decoded(
|
||||
std::get<std::string>(list[0]),
|
||||
std::get<EncodableList>(list[1]));
|
||||
return decoded;
|
||||
}
|
||||
|
||||
|
||||
UniversalBlePlatformChannelCodecSerializer::UniversalBlePlatformChannelCodecSerializer() {}
|
||||
|
||||
EncodableValue UniversalBlePlatformChannelCodecSerializer::ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return CustomEncodableValue(UniversalBleCharacteristic::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
case 129:
|
||||
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
case 130:
|
||||
return CustomEncodableValue(UniversalBleService::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
default:
|
||||
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void UniversalBlePlatformChannelCodecSerializer::WriteValue(
|
||||
const EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const {
|
||||
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
|
||||
if (custom_value->type() == typeid(UniversalBleCharacteristic)) {
|
||||
stream->WriteByte(128);
|
||||
WriteValue(EncodableValue(std::any_cast<UniversalBleCharacteristic>(*custom_value).ToEncodableList()), stream);
|
||||
return;
|
||||
}
|
||||
if (custom_value->type() == typeid(UniversalBleScanResult)) {
|
||||
stream->WriteByte(129);
|
||||
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
|
||||
return;
|
||||
}
|
||||
if (custom_value->type() == typeid(UniversalBleService)) {
|
||||
stream->WriteByte(130);
|
||||
WriteValue(EncodableValue(std::any_cast<UniversalBleService>(*custom_value).ToEncodableList()), stream);
|
||||
return;
|
||||
}
|
||||
}
|
||||
flutter::StandardCodecSerializer::WriteValue(value, stream);
|
||||
}
|
||||
|
||||
/// The codec used by UniversalBlePlatformChannel.
|
||||
const flutter::StandardMessageCodec& UniversalBlePlatformChannel::GetCodec() {
|
||||
return flutter::StandardMessageCodec::GetInstance(&UniversalBlePlatformChannelCodecSerializer::GetInstance());
|
||||
}
|
||||
|
||||
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
|
||||
void UniversalBlePlatformChannel::SetUp(
|
||||
flutter::BinaryMessenger* binary_messenger,
|
||||
UniversalBlePlatformChannel* api) {
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getBluetoothAvailabilityState", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
api->GetBluetoothAvailabilityState([reply](ErrorOr<int64_t>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.enableBluetooth", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
api->EnableBluetooth([reply](ErrorOr<bool>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.startScan", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
std::optional<FlutterError> output = api->StartScan();
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.stopScan", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
std::optional<FlutterError> output = api->StopScan();
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.connect", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
std::optional<FlutterError> output = api->Connect(device_id_arg);
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.disconnect", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
std::optional<FlutterError> output = api->Disconnect(device_id_arg);
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.setNotifiable", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
const auto& encodable_service_arg = args.at(1);
|
||||
if (encodable_service_arg.IsNull()) {
|
||||
reply(WrapError("service_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& service_arg = std::get<std::string>(encodable_service_arg);
|
||||
const auto& encodable_characteristic_arg = args.at(2);
|
||||
if (encodable_characteristic_arg.IsNull()) {
|
||||
reply(WrapError("characteristic_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& characteristic_arg = std::get<std::string>(encodable_characteristic_arg);
|
||||
const auto& encodable_ble_input_property_arg = args.at(3);
|
||||
if (encodable_ble_input_property_arg.IsNull()) {
|
||||
reply(WrapError("ble_input_property_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const int64_t ble_input_property_arg = encodable_ble_input_property_arg.LongValue();
|
||||
std::optional<FlutterError> output = api->SetNotifiable(device_id_arg, service_arg, characteristic_arg, ble_input_property_arg);
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.discoverServices", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
api->DiscoverServices(device_id_arg, [reply](ErrorOr<EncodableList>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.readValue", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
const auto& encodable_service_arg = args.at(1);
|
||||
if (encodable_service_arg.IsNull()) {
|
||||
reply(WrapError("service_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& service_arg = std::get<std::string>(encodable_service_arg);
|
||||
const auto& encodable_characteristic_arg = args.at(2);
|
||||
if (encodable_characteristic_arg.IsNull()) {
|
||||
reply(WrapError("characteristic_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& characteristic_arg = std::get<std::string>(encodable_characteristic_arg);
|
||||
api->ReadValue(device_id_arg, service_arg, characteristic_arg, [reply](ErrorOr<std::vector<uint8_t>>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.requestMtu", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
const auto& encodable_expected_mtu_arg = args.at(1);
|
||||
if (encodable_expected_mtu_arg.IsNull()) {
|
||||
reply(WrapError("expected_mtu_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const int64_t expected_mtu_arg = encodable_expected_mtu_arg.LongValue();
|
||||
api->RequestMtu(device_id_arg, expected_mtu_arg, [reply](ErrorOr<int64_t>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.writeValue", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
const auto& encodable_service_arg = args.at(1);
|
||||
if (encodable_service_arg.IsNull()) {
|
||||
reply(WrapError("service_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& service_arg = std::get<std::string>(encodable_service_arg);
|
||||
const auto& encodable_characteristic_arg = args.at(2);
|
||||
if (encodable_characteristic_arg.IsNull()) {
|
||||
reply(WrapError("characteristic_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& characteristic_arg = std::get<std::string>(encodable_characteristic_arg);
|
||||
const auto& encodable_value_arg = args.at(3);
|
||||
if (encodable_value_arg.IsNull()) {
|
||||
reply(WrapError("value_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& value_arg = std::get<std::vector<uint8_t>>(encodable_value_arg);
|
||||
const auto& encodable_ble_output_property_arg = args.at(4);
|
||||
if (encodable_ble_output_property_arg.IsNull()) {
|
||||
reply(WrapError("ble_output_property_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const int64_t ble_output_property_arg = encodable_ble_output_property_arg.LongValue();
|
||||
api->WriteValue(device_id_arg, service_arg, characteristic_arg, value_arg, ble_output_property_arg, [reply](std::optional<FlutterError>&& output) {
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.isPaired", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
api->IsPaired(device_id_arg, [reply](ErrorOr<bool>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.pair", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
std::optional<FlutterError> output = api->Pair(device_id_arg);
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.unPair", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_device_id_arg = args.at(0);
|
||||
if (encodable_device_id_arg.IsNull()) {
|
||||
reply(WrapError("device_id_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& device_id_arg = std::get<std::string>(encodable_device_id_arg);
|
||||
std::optional<FlutterError> output = api->UnPair(device_id_arg);
|
||||
if (output.has_value()) {
|
||||
reply(WrapError(output.value()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue());
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
{
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger, "dev.flutter.pigeon.universal_ble.UniversalBlePlatformChannel.getConnectedDevices", &GetCodec());
|
||||
if (api != nullptr) {
|
||||
channel->SetMessageHandler([api](const EncodableValue& message, const flutter::MessageReply<EncodableValue>& reply) {
|
||||
try {
|
||||
const auto& args = std::get<EncodableList>(message);
|
||||
const auto& encodable_with_services_arg = args.at(0);
|
||||
if (encodable_with_services_arg.IsNull()) {
|
||||
reply(WrapError("with_services_arg unexpectedly null."));
|
||||
return;
|
||||
}
|
||||
const auto& with_services_arg = std::get<EncodableList>(encodable_with_services_arg);
|
||||
api->GetConnectedDevices(with_services_arg, [reply](ErrorOr<EncodableList>&& output) {
|
||||
if (output.has_error()) {
|
||||
reply(WrapError(output.error()));
|
||||
return;
|
||||
}
|
||||
EncodableList wrapped;
|
||||
wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
|
||||
reply(EncodableValue(std::move(wrapped)));
|
||||
});
|
||||
} catch (const std::exception& exception) {
|
||||
reply(WrapError(exception.what()));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
channel->SetMessageHandler(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EncodableValue UniversalBlePlatformChannel::WrapError(std::string_view error_message) {
|
||||
return EncodableValue(EncodableList{
|
||||
EncodableValue(std::string(error_message)),
|
||||
EncodableValue("Error"),
|
||||
EncodableValue()
|
||||
});
|
||||
}
|
||||
|
||||
EncodableValue UniversalBlePlatformChannel::WrapError(const FlutterError& error) {
|
||||
return EncodableValue(EncodableList{
|
||||
EncodableValue(error.code()),
|
||||
EncodableValue(error.message()),
|
||||
error.details()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
UniversalBleCallbackChannelCodecSerializer::UniversalBleCallbackChannelCodecSerializer() {}
|
||||
|
||||
EncodableValue UniversalBleCallbackChannelCodecSerializer::ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const {
|
||||
switch (type) {
|
||||
case 128:
|
||||
return CustomEncodableValue(UniversalBleScanResult::FromEncodableList(std::get<EncodableList>(ReadValue(stream))));
|
||||
default:
|
||||
return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
|
||||
}
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannelCodecSerializer::WriteValue(
|
||||
const EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const {
|
||||
if (const CustomEncodableValue* custom_value = std::get_if<CustomEncodableValue>(&value)) {
|
||||
if (custom_value->type() == typeid(UniversalBleScanResult)) {
|
||||
stream->WriteByte(128);
|
||||
WriteValue(EncodableValue(std::any_cast<UniversalBleScanResult>(*custom_value).ToEncodableList()), stream);
|
||||
return;
|
||||
}
|
||||
}
|
||||
flutter::StandardCodecSerializer::WriteValue(value, stream);
|
||||
}
|
||||
|
||||
// Generated class from Pigeon that represents Flutter messages that can be called from C++.
|
||||
UniversalBleCallbackChannel::UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger)
|
||||
: binary_messenger_(binary_messenger) {}
|
||||
|
||||
const flutter::StandardMessageCodec& UniversalBleCallbackChannel::GetCodec() {
|
||||
return flutter::StandardMessageCodec::GetInstance(&UniversalBleCallbackChannelCodecSerializer::GetInstance());
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnAvailabilityChanged(
|
||||
int64_t state_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onAvailabilityChanged", &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
EncodableValue(state_arg),
|
||||
});
|
||||
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
const auto& encodable_return_value = *response;
|
||||
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
|
||||
if (list_return_value) {
|
||||
if (list_return_value->size() > 1) {
|
||||
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
|
||||
} else {
|
||||
on_success();
|
||||
}
|
||||
} else {
|
||||
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnPairStateChange(
|
||||
const std::string& device_id_arg,
|
||||
bool is_paired_arg,
|
||||
const std::string* error_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onPairStateChange", &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
EncodableValue(device_id_arg),
|
||||
EncodableValue(is_paired_arg),
|
||||
error_arg ? EncodableValue(*error_arg) : EncodableValue(),
|
||||
});
|
||||
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
const auto& encodable_return_value = *response;
|
||||
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
|
||||
if (list_return_value) {
|
||||
if (list_return_value->size() > 1) {
|
||||
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
|
||||
} else {
|
||||
on_success();
|
||||
}
|
||||
} else {
|
||||
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnScanResult(
|
||||
const UniversalBleScanResult& result_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onScanResult", &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
CustomEncodableValue(result_arg),
|
||||
});
|
||||
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
const auto& encodable_return_value = *response;
|
||||
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
|
||||
if (list_return_value) {
|
||||
if (list_return_value->size() > 1) {
|
||||
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
|
||||
} else {
|
||||
on_success();
|
||||
}
|
||||
} else {
|
||||
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnValueChanged(
|
||||
const std::string& device_id_arg,
|
||||
const std::string& characteristic_id_arg,
|
||||
const std::vector<uint8_t>& value_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onValueChanged", &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
EncodableValue(device_id_arg),
|
||||
EncodableValue(characteristic_id_arg),
|
||||
EncodableValue(value_arg),
|
||||
});
|
||||
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
const auto& encodable_return_value = *response;
|
||||
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
|
||||
if (list_return_value) {
|
||||
if (list_return_value->size() > 1) {
|
||||
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
|
||||
} else {
|
||||
on_success();
|
||||
}
|
||||
} else {
|
||||
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void UniversalBleCallbackChannel::OnConnectionChanged(
|
||||
const std::string& device_id_arg,
|
||||
int64_t state_arg,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error) {
|
||||
auto channel = std::make_unique<BasicMessageChannel<>>(binary_messenger_, "dev.flutter.pigeon.universal_ble.UniversalBleCallbackChannel.onConnectionChanged", &GetCodec());
|
||||
EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
|
||||
EncodableValue(device_id_arg),
|
||||
EncodableValue(state_arg),
|
||||
});
|
||||
channel->Send(encoded_api_arguments, [on_success = std::move(on_success), on_error = std::move(on_error)](const uint8_t* reply, size_t reply_size) {
|
||||
std::unique_ptr<EncodableValue> response = GetCodec().DecodeMessage(reply, reply_size);
|
||||
const auto& encodable_return_value = *response;
|
||||
const auto* list_return_value = std::get_if<EncodableList>(&encodable_return_value);
|
||||
if (list_return_value) {
|
||||
if (list_return_value->size() > 1) {
|
||||
on_error(FlutterError( std::get<std::string>(list_return_value->at(0)), std::get<std::string>(list_return_value->at(1)), list_return_value->at(2)));
|
||||
} else {
|
||||
on_success();
|
||||
}
|
||||
} else {
|
||||
on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace universal_ble
|
||||
@@ -0,0 +1,311 @@
|
||||
// Autogenerated from Pigeon (v13.0.0), do not edit directly.
|
||||
// See also: https://pub.dev/packages/pigeon
|
||||
|
||||
#ifndef PIGEON_UNIVERSALBLE_G_H_
|
||||
#define PIGEON_UNIVERSALBLE_G_H_
|
||||
#include <flutter/basic_message_channel.h>
|
||||
#include <flutter/binary_messenger.h>
|
||||
#include <flutter/encodable_value.h>
|
||||
#include <flutter/standard_message_codec.h>
|
||||
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
namespace universal_ble {
|
||||
|
||||
|
||||
// Generated class from Pigeon.
|
||||
|
||||
class FlutterError {
|
||||
public:
|
||||
explicit FlutterError(const std::string& code)
|
||||
: code_(code) {}
|
||||
explicit FlutterError(const std::string& code, const std::string& message)
|
||||
: code_(code), message_(message) {}
|
||||
explicit FlutterError(const std::string& code, const std::string& message, const flutter::EncodableValue& details)
|
||||
: code_(code), message_(message), details_(details) {}
|
||||
|
||||
const std::string& code() const { return code_; }
|
||||
const std::string& message() const { return message_; }
|
||||
const flutter::EncodableValue& details() const { return details_; }
|
||||
|
||||
private:
|
||||
std::string code_;
|
||||
std::string message_;
|
||||
flutter::EncodableValue details_;
|
||||
};
|
||||
|
||||
template<class T> class ErrorOr {
|
||||
public:
|
||||
ErrorOr(const T& rhs) : v_(rhs) {}
|
||||
ErrorOr(const T&& rhs) : v_(std::move(rhs)) {}
|
||||
ErrorOr(const FlutterError& rhs) : v_(rhs) {}
|
||||
ErrorOr(const FlutterError&& rhs) : v_(std::move(rhs)) {}
|
||||
|
||||
bool has_error() const { return std::holds_alternative<FlutterError>(v_); }
|
||||
const T& value() const { return std::get<T>(v_); };
|
||||
const FlutterError& error() const { return std::get<FlutterError>(v_); };
|
||||
|
||||
private:
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
ErrorOr() = default;
|
||||
T TakeValue() && { return std::get<T>(std::move(v_)); }
|
||||
|
||||
std::variant<T, FlutterError> v_;
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBleScanResult {
|
||||
public:
|
||||
// Constructs an object setting all non-nullable fields.
|
||||
explicit UniversalBleScanResult(const std::string& device_id);
|
||||
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBleScanResult(
|
||||
const std::string& device_id,
|
||||
const std::string* name,
|
||||
const bool* is_paired,
|
||||
const int64_t* rssi,
|
||||
const std::vector<uint8_t>* manufacturer_data,
|
||||
const std::vector<uint8_t>* manufacturer_data_head);
|
||||
|
||||
const std::string& device_id() const;
|
||||
void set_device_id(std::string_view value_arg);
|
||||
|
||||
const std::string* name() const;
|
||||
void set_name(const std::string_view* value_arg);
|
||||
void set_name(std::string_view value_arg);
|
||||
|
||||
const bool* is_paired() const;
|
||||
void set_is_paired(const bool* value_arg);
|
||||
void set_is_paired(bool value_arg);
|
||||
|
||||
const int64_t* rssi() const;
|
||||
void set_rssi(const int64_t* value_arg);
|
||||
void set_rssi(int64_t value_arg);
|
||||
|
||||
const std::vector<uint8_t>* manufacturer_data() const;
|
||||
void set_manufacturer_data(const std::vector<uint8_t>* value_arg);
|
||||
void set_manufacturer_data(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
const std::vector<uint8_t>* manufacturer_data_head() const;
|
||||
void set_manufacturer_data_head(const std::vector<uint8_t>* value_arg);
|
||||
void set_manufacturer_data_head(const std::vector<uint8_t>& value_arg);
|
||||
|
||||
|
||||
private:
|
||||
static UniversalBleScanResult FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBlePlatformChannelCodecSerializer;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class UniversalBleCallbackChannelCodecSerializer;
|
||||
std::string device_id_;
|
||||
std::optional<std::string> name_;
|
||||
std::optional<bool> is_paired_;
|
||||
std::optional<int64_t> rssi_;
|
||||
std::optional<std::vector<uint8_t>> manufacturer_data_;
|
||||
std::optional<std::vector<uint8_t>> manufacturer_data_head_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBleService {
|
||||
public:
|
||||
// Constructs an object setting all non-nullable fields.
|
||||
explicit UniversalBleService(const std::string& uuid);
|
||||
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBleService(
|
||||
const std::string& uuid,
|
||||
const flutter::EncodableList* characteristics);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const flutter::EncodableList* characteristics() const;
|
||||
void set_characteristics(const flutter::EncodableList* value_arg);
|
||||
void set_characteristics(const flutter::EncodableList& value_arg);
|
||||
|
||||
|
||||
private:
|
||||
static UniversalBleService FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBlePlatformChannelCodecSerializer;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class UniversalBleCallbackChannelCodecSerializer;
|
||||
std::string uuid_;
|
||||
std::optional<flutter::EncodableList> characteristics_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Generated class from Pigeon that represents data sent in messages.
|
||||
class UniversalBleCharacteristic {
|
||||
public:
|
||||
// Constructs an object setting all fields.
|
||||
explicit UniversalBleCharacteristic(
|
||||
const std::string& uuid,
|
||||
const flutter::EncodableList& properties);
|
||||
|
||||
const std::string& uuid() const;
|
||||
void set_uuid(std::string_view value_arg);
|
||||
|
||||
const flutter::EncodableList& properties() const;
|
||||
void set_properties(const flutter::EncodableList& value_arg);
|
||||
|
||||
|
||||
private:
|
||||
static UniversalBleCharacteristic FromEncodableList(const flutter::EncodableList& list);
|
||||
flutter::EncodableList ToEncodableList() const;
|
||||
friend class UniversalBlePlatformChannel;
|
||||
friend class UniversalBlePlatformChannelCodecSerializer;
|
||||
friend class UniversalBleCallbackChannel;
|
||||
friend class UniversalBleCallbackChannelCodecSerializer;
|
||||
std::string uuid_;
|
||||
flutter::EncodableList properties_;
|
||||
|
||||
};
|
||||
|
||||
class UniversalBlePlatformChannelCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
public:
|
||||
UniversalBlePlatformChannelCodecSerializer();
|
||||
inline static UniversalBlePlatformChannelCodecSerializer& GetInstance() {
|
||||
static UniversalBlePlatformChannelCodecSerializer sInstance;
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
void WriteValue(
|
||||
const flutter::EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const override;
|
||||
|
||||
protected:
|
||||
flutter::EncodableValue ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const override;
|
||||
|
||||
};
|
||||
|
||||
// Flutter -> Native
|
||||
//
|
||||
// Generated interface from Pigeon that represents a handler of messages from Flutter.
|
||||
class UniversalBlePlatformChannel {
|
||||
public:
|
||||
UniversalBlePlatformChannel(const UniversalBlePlatformChannel&) = delete;
|
||||
UniversalBlePlatformChannel& operator=(const UniversalBlePlatformChannel&) = delete;
|
||||
virtual ~UniversalBlePlatformChannel() {}
|
||||
virtual void GetBluetoothAvailabilityState(std::function<void(ErrorOr<int64_t> reply)> result) = 0;
|
||||
virtual void EnableBluetooth(std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
virtual std::optional<FlutterError> StartScan() = 0;
|
||||
virtual std::optional<FlutterError> StopScan() = 0;
|
||||
virtual std::optional<FlutterError> Connect(const std::string& device_id) = 0;
|
||||
virtual std::optional<FlutterError> Disconnect(const std::string& device_id) = 0;
|
||||
virtual std::optional<FlutterError> SetNotifiable(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
int64_t ble_input_property) = 0;
|
||||
virtual void DiscoverServices(
|
||||
const std::string& device_id,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) = 0;
|
||||
virtual void ReadValue(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
std::function<void(ErrorOr<std::vector<uint8_t>> reply)> result) = 0;
|
||||
virtual void RequestMtu(
|
||||
const std::string& device_id,
|
||||
int64_t expected_mtu,
|
||||
std::function<void(ErrorOr<int64_t> reply)> result) = 0;
|
||||
virtual void WriteValue(
|
||||
const std::string& device_id,
|
||||
const std::string& service,
|
||||
const std::string& characteristic,
|
||||
const std::vector<uint8_t>& value,
|
||||
int64_t ble_output_property,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) = 0;
|
||||
virtual void IsPaired(
|
||||
const std::string& device_id,
|
||||
std::function<void(ErrorOr<bool> reply)> result) = 0;
|
||||
virtual std::optional<FlutterError> Pair(const std::string& device_id) = 0;
|
||||
virtual std::optional<FlutterError> UnPair(const std::string& device_id) = 0;
|
||||
virtual void GetConnectedDevices(
|
||||
const flutter::EncodableList& with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) = 0;
|
||||
|
||||
// The codec used by UniversalBlePlatformChannel.
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
// Sets up an instance of `UniversalBlePlatformChannel` to handle messages through the `binary_messenger`.
|
||||
static void SetUp(
|
||||
flutter::BinaryMessenger* binary_messenger,
|
||||
UniversalBlePlatformChannel* api);
|
||||
static flutter::EncodableValue WrapError(std::string_view error_message);
|
||||
static flutter::EncodableValue WrapError(const FlutterError& error);
|
||||
|
||||
protected:
|
||||
UniversalBlePlatformChannel() = default;
|
||||
|
||||
};
|
||||
class UniversalBleCallbackChannelCodecSerializer : public flutter::StandardCodecSerializer {
|
||||
public:
|
||||
UniversalBleCallbackChannelCodecSerializer();
|
||||
inline static UniversalBleCallbackChannelCodecSerializer& GetInstance() {
|
||||
static UniversalBleCallbackChannelCodecSerializer sInstance;
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
void WriteValue(
|
||||
const flutter::EncodableValue& value,
|
||||
flutter::ByteStreamWriter* stream) const override;
|
||||
|
||||
protected:
|
||||
flutter::EncodableValue ReadValueOfType(
|
||||
uint8_t type,
|
||||
flutter::ByteStreamReader* stream) const override;
|
||||
|
||||
};
|
||||
|
||||
// Native -> Flutter
|
||||
//
|
||||
// Generated class from Pigeon that represents Flutter messages that can be called from C++.
|
||||
class UniversalBleCallbackChannel {
|
||||
public:
|
||||
UniversalBleCallbackChannel(flutter::BinaryMessenger* binary_messenger);
|
||||
static const flutter::StandardMessageCodec& GetCodec();
|
||||
void OnAvailabilityChanged(
|
||||
int64_t state,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnPairStateChange(
|
||||
const std::string& device_id,
|
||||
bool is_paired,
|
||||
const std::string* error,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnScanResult(
|
||||
const UniversalBleScanResult& result,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnValueChanged(
|
||||
const std::string& device_id,
|
||||
const std::string& characteristic_id,
|
||||
const std::vector<uint8_t>& value,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
void OnConnectionChanged(
|
||||
const std::string& device_id,
|
||||
int64_t state,
|
||||
std::function<void(void)>&& on_success,
|
||||
std::function<void(const FlutterError&)>&& on_error);
|
||||
|
||||
private:
|
||||
flutter::BinaryMessenger* binary_messenger_;
|
||||
};
|
||||
|
||||
} // namespace universal_ble
|
||||
#endif // PIGEON_UNIVERSALBLE_G_H_
|
||||
@@ -0,0 +1,130 @@
|
||||
#include "Utils.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <sdkddkver.h>
|
||||
|
||||
#if WDK_NTDDI_VERSION < NTDDI_WIN10_VB
|
||||
#error "Windows SDK version before 10.0.19041.0 is not supported"
|
||||
#elif WDK_NTDDI_VERSION == NTDDI_WIN10_VB
|
||||
// For Windows SDK version before 10.0.19041.0, remap functions to post-10.0.19041.0 versions
|
||||
#define WINRT_IMPL_CoGetApartmentType WINRT_CoGetApartmentType
|
||||
#endif
|
||||
|
||||
#define MAC_ADDRESS_STR_LENGTH (size_t)17 // Two chars per byte, 5 chars for colon
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
|
||||
std::string _mac_address_to_str(uint64_t mac_address)
|
||||
{
|
||||
uint8_t *mac_ptr = (uint8_t *)&mac_address;
|
||||
char mac_str[MAC_ADDRESS_STR_LENGTH + 1] = {0};
|
||||
snprintf(mac_str, MAC_ADDRESS_STR_LENGTH + 1, "%02x:%02x:%02x:%02x:%02x:%02x", mac_ptr[5], mac_ptr[4], mac_ptr[3],
|
||||
mac_ptr[2], mac_ptr[1], mac_ptr[0]);
|
||||
return std::string(mac_str);
|
||||
}
|
||||
|
||||
uint64_t _str_to_mac_address(std::string mac_str)
|
||||
{
|
||||
// TODO: Validate input - Expected Format: XX:XX:XX:XX:XX:XX
|
||||
uint64_t mac_address_number = 0;
|
||||
uint8_t *mac_ptr = (uint8_t *)&mac_address_number;
|
||||
sscanf_s(mac_str.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", &mac_ptr[5], &mac_ptr[4], &mac_ptr[3],
|
||||
&mac_ptr[2], &mac_ptr[1], &mac_ptr[0]);
|
||||
return mac_address_number;
|
||||
}
|
||||
|
||||
winrt::guid uuid_to_guid(const std::string &uuid)
|
||||
{
|
||||
// TODO: Add proper cleanup / validation
|
||||
std::stringstream helper;
|
||||
for (int i = 0; i < uuid.length(); i++)
|
||||
{
|
||||
if (uuid[i] != '-')
|
||||
{
|
||||
helper << uuid[i];
|
||||
}
|
||||
}
|
||||
std::string clean_uuid = helper.str();
|
||||
winrt::guid guid;
|
||||
uint64_t *data4_ptr = (uint64_t *)guid.Data4;
|
||||
|
||||
guid.Data1 = static_cast<uint32_t>(std::strtoul(clean_uuid.substr(0, 8).c_str(), nullptr, 16));
|
||||
guid.Data2 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(8, 4).c_str(), nullptr, 16));
|
||||
guid.Data3 = static_cast<uint16_t>(std::strtoul(clean_uuid.substr(12, 4).c_str(), nullptr, 16));
|
||||
*data4_ptr = _byteswap_uint64(std::strtoull(clean_uuid.substr(16, 16).c_str(), nullptr, 16));
|
||||
|
||||
return guid;
|
||||
}
|
||||
|
||||
std::string guid_to_uuid(const winrt::guid &guid)
|
||||
{
|
||||
std::stringstream helper;
|
||||
// TODO: It might be cleaner to use snprintf instead of string streams.
|
||||
|
||||
for (uint32_t i = 0; i < 4; i++)
|
||||
{
|
||||
// * NOTE: We're performing a byte swap!
|
||||
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data1)[3 - i];
|
||||
}
|
||||
helper << '-';
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
// * NOTE: We're performing a byte swap!
|
||||
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data2)[1 - i];
|
||||
}
|
||||
helper << '-';
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
// * NOTE: We're performing a byte swap!
|
||||
helper << std::hex << std::setw(2) << std::setfill('0') << (int)((uint8_t *)&guid.Data3)[1 - i];
|
||||
}
|
||||
helper << '-';
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
{
|
||||
helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[i];
|
||||
}
|
||||
helper << '-';
|
||||
for (uint32_t i = 0; i < 6; i++)
|
||||
{
|
||||
helper << std::hex << std::setw(2) << std::setfill('0') << (int)guid.Data4[2 + i];
|
||||
}
|
||||
return helper.str();
|
||||
}
|
||||
|
||||
std::vector<uint8_t> to_bytevc(IBuffer buffer)
|
||||
{
|
||||
auto reader = DataReader::FromBuffer(buffer);
|
||||
auto result = std::vector<uint8_t>(reader.UnconsumedBufferLength());
|
||||
reader.ReadBytes(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
IBuffer from_bytevc(std::vector<uint8_t> bytes)
|
||||
{
|
||||
auto writer = DataWriter();
|
||||
writer.WriteBytes(bytes);
|
||||
return writer.DetachBuffer();
|
||||
}
|
||||
|
||||
std::string to_hexstring(std::vector<uint8_t> bytes)
|
||||
{
|
||||
auto ss = std::stringstream();
|
||||
for (auto b : bytes)
|
||||
ss << std::setw(2) << std::setfill('0') << std::hex << static_cast<int>(b);
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string to_uuidstr(winrt::guid guid)
|
||||
{
|
||||
char chars[36 + 1];
|
||||
sprintf_s(chars, "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
|
||||
guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2],
|
||||
guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]);
|
||||
return std::string{chars};
|
||||
}
|
||||
|
||||
} // namespace SimpleBLE
|
||||
@@ -0,0 +1,81 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#include "winrt/Windows.Foundation.h"
|
||||
#include "winrt/Windows.Storage.Streams.h"
|
||||
#include "winrt/base.h"
|
||||
#include "UniversalBle.g.h"
|
||||
|
||||
using namespace winrt::Windows;
|
||||
using namespace winrt::Windows::Storage::Streams;
|
||||
|
||||
constexpr uint32_t TEN_SECONDS_IN_MSECS = 10000;
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
|
||||
std::string _mac_address_to_str(uint64_t mac_address);
|
||||
uint64_t _str_to_mac_address(std::string mac_address);
|
||||
|
||||
winrt::guid uuid_to_guid(const std::string &uuid);
|
||||
std::string guid_to_uuid(const winrt::guid &guid);
|
||||
|
||||
std::vector<uint8_t> to_bytevc(IBuffer buffer);
|
||||
IBuffer from_bytevc(std::vector<uint8_t> bytes);
|
||||
std::string to_hexstring(std::vector<uint8_t> bytes);
|
||||
|
||||
std::string to_uuidstr(winrt::guid guid);
|
||||
|
||||
/// Structs for passing data between background to ui thread
|
||||
struct ConnectionStateStruct
|
||||
{
|
||||
std::string deviceId;
|
||||
int64_t connectionState;
|
||||
ConnectionStateStruct(std::string deviceId, int64_t connectionState)
|
||||
: deviceId(deviceId), connectionState(connectionState) {}
|
||||
};
|
||||
|
||||
struct PairStateStruct
|
||||
{
|
||||
std::string deviceId;
|
||||
bool isPaired;
|
||||
std::string errorMessage;
|
||||
PairStateStruct(std::string deviceId, bool isPaired, std::string errorMessage)
|
||||
: deviceId(deviceId), isPaired(isPaired), errorMessage(errorMessage) {}
|
||||
};
|
||||
|
||||
struct ValueChangeStruct
|
||||
{
|
||||
std::string deviceId;
|
||||
std::string characteristicId;
|
||||
std::vector<uint8_t> value;
|
||||
ValueChangeStruct(std::string deviceId, std::string characteristicId, std::vector<uint8_t> value)
|
||||
: deviceId(deviceId), characteristicId(characteristicId), value(value) {}
|
||||
};
|
||||
|
||||
/// To call async functions synchronously
|
||||
template <typename async_t>
|
||||
static auto async_get(async_t const &async)
|
||||
{
|
||||
if (async.Status() == Foundation::AsyncStatus::Started)
|
||||
{
|
||||
wait_for_completed(async, TEN_SECONDS_IN_MSECS);
|
||||
}
|
||||
try
|
||||
{
|
||||
return async.GetResults();
|
||||
}
|
||||
catch (const winrt::hresult_error &err)
|
||||
{
|
||||
throw FlutterError(winrt::to_string(err.message()));
|
||||
}
|
||||
catch (const std::exception &err)
|
||||
{
|
||||
throw FlutterError(err.what());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace universal_ble
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_
|
||||
#define FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_
|
||||
|
||||
#include <flutter_plugin_registrar.h>
|
||||
|
||||
#ifdef FLUTTER_PLUGIN_IMPL
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
FLUTTER_PLUGIN_EXPORT void UniversalBlePluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_C_API_H_
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
#ifndef FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_
|
||||
#define FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_
|
||||
|
||||
#include <flutter/method_channel.h>
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include <windows.h>
|
||||
#include <winrt/Windows.Foundation.h>
|
||||
#include <winrt/Windows.Foundation.Collections.h>
|
||||
#include <winrt/Windows.Storage.Streams.h>
|
||||
#include <winrt/Windows.Devices.Enumeration.h>
|
||||
#include <winrt/Windows.Devices.Radios.h>
|
||||
#include <winrt/Windows.Devices.Bluetooth.h>
|
||||
#include <winrt/Windows.Devices.Bluetooth.Advertisement.h>
|
||||
#include <winrt/Windows.Devices.Bluetooth.GenericAttributeProfile.h>
|
||||
|
||||
#include <memory>
|
||||
#include "Utils.h"
|
||||
#include "UniversalBle.g.h"
|
||||
#include "universal_enum.h"
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
using namespace winrt;
|
||||
using namespace winrt::Windows::Devices;
|
||||
using namespace winrt::Windows::Foundation;
|
||||
using namespace winrt::Windows::Foundation::Collections;
|
||||
using namespace winrt::Windows::Storage::Streams;
|
||||
using namespace winrt::Windows::Devices::Radios;
|
||||
using namespace winrt::Windows::Devices::Bluetooth;
|
||||
using namespace winrt::Windows::Devices::Bluetooth::Advertisement;
|
||||
using namespace winrt::Windows::Devices::Bluetooth::GenericAttributeProfile;
|
||||
using namespace Windows::Devices::Enumeration;
|
||||
|
||||
struct gatt_characteristic_t
|
||||
{
|
||||
GattCharacteristic obj = nullptr;
|
||||
// winrt::event_token value_changed_token;
|
||||
};
|
||||
|
||||
struct gatt_service_t
|
||||
{
|
||||
GattDeviceService obj = nullptr;
|
||||
std::map<std::string, gatt_characteristic_t> characteristics;
|
||||
};
|
||||
|
||||
struct BluetoothDeviceAgent
|
||||
{
|
||||
BluetoothLEDevice device;
|
||||
winrt::event_token connnectionStatusChangedToken;
|
||||
std::map<std::string, gatt_service_t> gatt_map_;
|
||||
|
||||
BluetoothDeviceAgent(BluetoothLEDevice device, winrt::event_token connnectionStatusChangedToken, std::map<std::string, gatt_service_t> gatt_map_)
|
||||
: device(device),
|
||||
connnectionStatusChangedToken(connnectionStatusChangedToken),
|
||||
gatt_map_(gatt_map_) {}
|
||||
|
||||
~BluetoothDeviceAgent()
|
||||
{
|
||||
device = nullptr;
|
||||
}
|
||||
|
||||
gatt_characteristic_t &_fetch_characteristic(const std::string &service_uuid,
|
||||
const std::string &characteristic_uuid)
|
||||
{
|
||||
if (gatt_map_.count(service_uuid) == 0)
|
||||
{
|
||||
throw FlutterError("Service not found");
|
||||
}
|
||||
|
||||
if (gatt_map_[service_uuid].characteristics.count(characteristic_uuid) == 0)
|
||||
{
|
||||
throw FlutterError("Characteristic not found");
|
||||
}
|
||||
|
||||
return gatt_map_[service_uuid].characteristics.at(characteristic_uuid);
|
||||
}
|
||||
};
|
||||
|
||||
class UniversalBlePlugin : public flutter::Plugin, public UniversalBlePlatformChannel
|
||||
{
|
||||
public:
|
||||
static void RegisterWithRegistrar(flutter::PluginRegistrarWindows *registrar);
|
||||
|
||||
UniversalBlePlugin(flutter::PluginRegistrarWindows *registrar);
|
||||
|
||||
~UniversalBlePlugin();
|
||||
|
||||
static void SuccessCallback() {}
|
||||
static void ErrorCallback(const FlutterError &error)
|
||||
{
|
||||
std::cout << "ErrorCallback: " << error.message() << std::endl;
|
||||
}
|
||||
|
||||
// Disallow copy and assign.
|
||||
UniversalBlePlugin(const UniversalBlePlugin &) = delete;
|
||||
UniversalBlePlugin &operator=(const UniversalBlePlugin &) = delete;
|
||||
|
||||
flutter::PluginRegistrarWindows *registrar_;
|
||||
int64_t window_proc_delegate_id_ = -1;
|
||||
|
||||
HWND GetWindow();
|
||||
std::optional<LRESULT> WindowProcDelegate(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
|
||||
winrt::fire_and_forget InitializeAsync();
|
||||
Radio bluetoothRadio{nullptr};
|
||||
void Radio_StateChanged(Radio sender, IInspectable args);
|
||||
RadioState oldRadioState = RadioState::Unknown;
|
||||
BluetoothLEAdvertisementWatcher bluetoothLEWatcher{nullptr};
|
||||
winrt::event_token bluetoothLEWatcherReceivedToken;
|
||||
void BluetoothLEWatcher_Received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args);
|
||||
std::map<uint64_t, std::unique_ptr<BluetoothDeviceAgent>> connectedDevices{};
|
||||
std::map<uint64_t, bool> deviceConnectableStatus{};
|
||||
winrt::event_revoker<IRadio> radioStateChangedRevoker;
|
||||
winrt::fire_and_forget ConnectAsync(uint64_t bluetoothAddress);
|
||||
void BluetoothLEDevice_ConnectionStatusChanged(BluetoothLEDevice sender, IInspectable args);
|
||||
void CleanConnection(uint64_t bluetoothAddress);
|
||||
winrt::fire_and_forget DiscoverServicesAsync(BluetoothDeviceAgent &bluetoothDeviceAgent, std::function<void(ErrorOr<flutter::EncodableList> reply)>);
|
||||
winrt::fire_and_forget SetNotifiableAsync(BluetoothDeviceAgent &bluetoothDeviceAgent, const std::string &service,
|
||||
const std::string &characteristic, GattClientCharacteristicConfigurationDescriptorValue descriptorValue);
|
||||
void GattCharacteristic_ValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args);
|
||||
AvailabilityState getAvailabilityStateFromRadio(RadioState radioState);
|
||||
std::string parsePairingFailError(Enumeration::DevicePairingResult result);
|
||||
void PostConnectionUpdate(uint64_t bluetoothAddress, ConnectionState connectionState);
|
||||
winrt::fire_and_forget GetConnectedDevicesAsync(std::vector<std::string> with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
|
||||
winrt::fire_and_forget IsPairedAsync(std::string device_id, std::function<void(ErrorOr<bool> reply)> result);
|
||||
|
||||
// UniversalBlePlatformChannel implementation.
|
||||
void GetBluetoothAvailabilityState(std::function<void(ErrorOr<int64_t> reply)> result) override;
|
||||
void EnableBluetooth(std::function<void(ErrorOr<bool> reply)> result) override;
|
||||
std::optional<FlutterError> StartScan() override;
|
||||
std::optional<FlutterError> StopScan() override;
|
||||
std::optional<FlutterError> Connect(const std::string &device_id) override;
|
||||
std::optional<FlutterError> Disconnect(const std::string &device_id) override;
|
||||
void DiscoverServices(
|
||||
const std::string &device_id,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result) override;
|
||||
std::optional<FlutterError> SetNotifiable(
|
||||
const std::string &device_id,
|
||||
const std::string &service,
|
||||
const std::string &characteristic,
|
||||
int64_t ble_input_property) override;
|
||||
void ReadValue(
|
||||
const std::string &device_id,
|
||||
const std::string &service,
|
||||
const std::string &characteristic,
|
||||
std::function<void(ErrorOr<std::vector<uint8_t>> reply)> result) override;
|
||||
void WriteValue(
|
||||
const std::string &device_id,
|
||||
const std::string &service,
|
||||
const std::string &characteristic,
|
||||
const std::vector<uint8_t> &value,
|
||||
int64_t ble_output_property,
|
||||
std::function<void(std::optional<FlutterError> reply)> result) override;
|
||||
void RequestMtu(
|
||||
const std::string &device_id,
|
||||
int64_t expected_mtu,
|
||||
std::function<void(ErrorOr<int64_t> reply)> result) override;
|
||||
void IsPaired(
|
||||
const std::string &device_id,
|
||||
std::function<void(ErrorOr<bool> reply)> result) override;
|
||||
std::optional<FlutterError> Pair(const std::string &device_id) override;
|
||||
std::optional<FlutterError> UnPair(const std::string &device_id) override;
|
||||
void GetConnectedDevices(
|
||||
const flutter::EncodableList &with_services,
|
||||
std::function<void(ErrorOr<flutter::EncodableList> reply)> result);
|
||||
};
|
||||
|
||||
} // namespace universal_ble
|
||||
|
||||
#endif // FLUTTER_PLUGIN_UNIVERSAL_BLE_PLUGIN_H_
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "include/universal_ble/universal_ble_plugin_c_api.h"
|
||||
|
||||
#include <flutter/plugin_registrar_windows.h>
|
||||
|
||||
#include "universal_ble_plugin.h"
|
||||
|
||||
void UniversalBlePluginCApiRegisterWithRegistrar(
|
||||
FlutterDesktopPluginRegistrarRef registrar) {
|
||||
universal_ble::UniversalBlePlugin::RegisterWithRegistrar(
|
||||
flutter::PluginRegistrarManager::GetInstance()
|
||||
->GetRegistrar<flutter::PluginRegistrarWindows>(registrar));
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
namespace universal_ble
|
||||
{
|
||||
|
||||
enum class ConnectionState : int
|
||||
{
|
||||
connected = 0,
|
||||
disconnected = 1,
|
||||
};
|
||||
|
||||
enum class CharacteristicProperty : int
|
||||
{
|
||||
broadcast = 0,
|
||||
read = 1,
|
||||
writeWithoutResponse = 2,
|
||||
write = 3,
|
||||
notify = 4,
|
||||
indicate = 5,
|
||||
authenticatedSignedWrites = 6,
|
||||
extendedProperties = 7,
|
||||
};
|
||||
|
||||
enum class BleInputProperty : int
|
||||
{
|
||||
disabled = 0,
|
||||
notification = 1,
|
||||
indication = 2,
|
||||
};
|
||||
|
||||
enum class BleOutputProperty : int
|
||||
{
|
||||
withResponse = 0,
|
||||
withoutResponse = 1,
|
||||
};
|
||||
|
||||
enum class AvailabilityState : int
|
||||
{
|
||||
unknown = 0,
|
||||
resetting = 1,
|
||||
unsupported = 2,
|
||||
unauthorized = 3,
|
||||
poweredOff = 4,
|
||||
poweredOn = 5,
|
||||
};
|
||||
|
||||
} // namespace universal_ble
|
||||
Reference in New Issue
Block a user