static bool IsValidAddress(const std::string& address) {
ScopeLogger();
- const std::regex macAdressRegex {"([[:xdigit:]]{2}[:]){5}([[:xdigit:]]{2})"};
+ const std::regex macAdressRegex{"([[:xdigit:]]{2}[:]){5}([[:xdigit:]]{2})"};
if (std::regex_match(address, macAdressRegex)) {
return true;
static bool IsValidUUID(const std::string& uuid) {
ScopeLogger();
- const std::regex uuidRegex {"[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"};
+ const std::regex uuidRegex{
+ "[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}"};
if (std::regex_match(uuid, uuidRegex)) {
return true;
}
};
+BluetoothLEDevice.prototype.isConnected = function() {
+ privUtils_.log('Entered BluetoothLEDevice.isConnected()');
+
+ var callArgs = {
+ address: this.address
+ };
+
+ var result = native.callSync('BluetoothLEDeviceIsConnected', callArgs);
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+ return native.getResultObject(result);
+};
+
BluetoothLEDevice.prototype.addConnectStateChangeListener = function() {
privUtils_.log('Entered BluetoothLEDevice.addConnectStateChangeListener()');
var args = AV.validateArgs(arguments, [
_bleConnectChangeListener.removeListener(args.watchID);
};
+BluetoothLEDevice.prototype.getAttMtu = function() {
+ privUtils_.log('Entered BluetoothLEDevice.getAttMtu()');
+
+ var callArgs = {
+ address: this.address
+ };
+
+ var result = native.callSync('BluetoothLEDeviceGetAttMtu', callArgs);
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+ return native.getResultObject(result);
+}
+
+BluetoothLEDevice.prototype.requestAttMtuChange = function() {
+ privUtils_.log('Entered BluetoothLEDevice.requestAttMtuChange()');
+
+ var args = AV.validateArgs(arguments, [
+ {
+ name: 'mtu',
+ type: AV.Types.LONG
+ }
+ ]);
+
+ var callArgs = {
+ address: this.address,
+ mtu: args.mtu
+ };
+
+ var result = native.callSync('BluetoothLEDeviceRequestAttMtuChange', callArgs);
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+ return native.getResultObject(result);
+}
+
+BluetoothLEDevice.prototype.addAttMtuChangeListener = function() {
+ privUtils_.log('Entered BluetoothLEDevice.addAttMtuChangeListener()');
+ var args = AV.validateArgs(arguments, [
+ {
+ name: 'callback',
+ type: AV.Types.FUNCTION
+ }
+ ]);
+
+ var callArgs = { address: this.address };
+
+ var callback = function(result) {
+ privUtils_.log('Entered BluetoothLEDevice.addAttMtuChangeListener() callback');
+ args.callback(result.attMtuValue);
+ };
+
+ var watchId = _bleAttMtuChangeListener.addListener(callback, callArgs);
+
+ return watchId;
+};
+
+BluetoothLEDevice.prototype.removeAttMtuChangeListener = function() {
+ privUtils_.log('Entered BluetoothLEDevice.removeAttMtuChangeListener()');
+
+ var args = AV.validateArgs(arguments, [
+ {
+ name: 'watchID',
+ type: AV.Types.LONG
+ }
+ ]);
+
+ var callArgs = { address: this.address };
+
+ _bleAttMtuChangeListener.removeListener(args.watchID, callArgs);
+};
+
// class BluetoothDevice ///////////////////////////
var BluetoothDevice = function(data) {
var self = this;
}
};
+BluetoothLEAdapter.prototype.isScanning = function() {
+ privUtils_.log('Entered BluetoothLEAdapter.isScanning()');
+
+ var result = native.callSync('BluetoothLEAdapterIsScanning', {});
+ if (native.isFailure(result)) {
+ throw native.getErrorObject(result);
+ }
+ return native.getResultObject(result);
+};
+
var _BluetoothAdvertisePacketType = {
ADVERTISE: 'ADVERTISE',
SCAN_RESPONSE: 'SCAN_RESPONSE'
'BluetoothLEDeviceRemoveConnectStateChangeListener'
);
+var _bleAttMtuChangeListener = _multipleListenerBuilder(
+ 'BluetoothLEAttMtuChangeCallback',
+ function(listener, event) {
+ listener(event);
+ },
+ 'BluetoothLEDeviceAddAttMtuChangeListener',
+ 'BluetoothLEDeviceRemoveAttMtuChangeListener'
+);
+
//class BluetoothGATTDescriptor ///////////////////////////
var BluetoothGATTDescriptor = function(data, address) {
var handle_ = data.handle;
* UUID has always been set to source format in this function.
*/
result_obj.insert(std::make_pair(kUuid, picojson::value{uuid->uuid_in_source_format}));
- result_obj.insert(std::make_pair(kServiceUuid, picojson::value{uuid->uuid_in_source_format}));
+ result_obj.insert(
+ std::make_pair(kServiceUuid, picojson::value{uuid->uuid_in_source_format}));
} else {
result_obj.insert(std::make_pair(kUuid, picojson::value{"0xFFFF"}));
result_obj.insert(std::make_pair(kServiceUuid, picojson::value{}));
[](int total, int index, bt_gatt_h gatt_handle, void* data) {
ScopeLogger(
"Entered into asynchronous function, bt_gatt_service_foreach_characteristics;"
- " index: %d", index);
+ " index: %d",
+ index);
Data* user_data = static_cast<Data*>(data);
picojson::array* array = user_data->array;
PlatformResult* platform_result = user_data->platform_res;
gatt_handle,
[](int total, int index, bt_gatt_h desc_handle, void* data) {
ScopeLogger(
- "Entered into asynchronous function, bt_gatt_characteristic_foreach_descriptors;"
- " index: %d", index);
+ "Entered into asynchronous function, bt_gatt_characteristic_foreach_descriptors;"
+ " index: %d",
+ index);
picojson::array& desc_array = *(static_cast<picojson::array*>(data));
picojson::value desc = picojson::value(picojson::object());
auto uuid = UUID::createFromGatt(desc_handle);
if (uuid) {
- desc_obj.insert(std::make_pair(kUuid, picojson::value{uuid->ShortestPossibleFormat()}));
+ desc_obj.insert(
+ std::make_pair(kUuid, picojson::value{uuid->ShortestPossibleFormat()}));
} else {
desc_obj.insert(std::make_pair(kUuid, picojson::value{}));
}
void AddValueChangeListener(const picojson::value& args, picojson::object& out);
void RemoveValueChangeListener(const picojson::value& args, picojson::object& out);
+ bt_gatt_client_h GetGattClient(const std::string& address);
+
common::PlatformResult GetServiceAllUuids(const std::string& address, picojson::array* array);
private:
bool IsStillConnected(const std::string& address);
- bt_gatt_client_h GetGattClient(const std::string& address);
-
common::PlatformResult GetServicesHelper(bt_gatt_h handle, const std::string& address,
picojson::array* array);
common::PlatformResult GetCharacteristicsHelper(bt_gatt_h handle, const std::string& address,
REGISTER_METHOD(BluetoothLEAdapterStartScan);
REGISTER_METHOD(BluetoothLEAdapterStopScan);
+ REGISTER_METHOD(BluetoothLEAdapterIsScanning);
REGISTER_METHOD(BluetoothLEAdapterStartAdvertise);
REGISTER_METHOD(BluetoothLEAdapterStopAdvertise);
REGISTER_METHOD(BluetoothLEDeviceAddConnectStateChangeListener);
REGISTER_METHOD(BluetoothLEDeviceRemoveConnectStateChangeListener);
REGISTER_METHOD(BluetoothLEDeviceGetServiceAllUuids);
+ REGISTER_METHOD(BluetoothLEDeviceIsConnected);
+ REGISTER_METHOD(BluetoothLEDeviceGetAttMtu);
+ REGISTER_METHOD(BluetoothLEDeviceRequestAttMtuChange);
+ REGISTER_METHOD(BluetoothLEDeviceAddAttMtuChangeListener);
+ REGISTER_METHOD(BluetoothLEDeviceRemoveAttMtuChangeListener);
REGISTER_METHOD(BluetoothGATTClientServiceGetServices);
REGISTER_METHOD(BluetoothGATTClientServiceGetCharacteristics);
bluetooth_le_adapter_.StopScan(args, out);
}
+void BluetoothInstance::BluetoothLEAdapterIsScanning(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_adapter_.IsScanning(out);
+}
+
void BluetoothInstance::BluetoothLEAdapterStartAdvertise(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
bluetooth_le_device_.GetServiceAllUuids(args, out);
}
+void BluetoothInstance::BluetoothLEDeviceIsConnected(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_device_.IsConnected(args, out);
+}
+
+void BluetoothInstance::BluetoothLEDeviceGetAttMtu(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_device_.GetAttMtu(args, out);
+}
+
+void BluetoothInstance::BluetoothLEDeviceRequestAttMtuChange(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_device_.RequestAttMtuChange(args, out);
+}
+
+void BluetoothInstance::BluetoothLEDeviceAddAttMtuChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_device_.AddAttMtuChangeListener(args, out);
+}
+
+void BluetoothInstance::BluetoothLEDeviceRemoveAttMtuChangeListener(const picojson::value& args,
+ picojson::object& out) {
+ ScopeLogger();
+ bluetooth_le_device_.RemoveAttMtuChangeListener(args, out);
+}
+
void BluetoothInstance::BluetoothGATTClientServiceGetServices(const picojson::value& args,
picojson::object& out) {
ScopeLogger();
void BluetoothLEAdapterStartScan(const picojson::value& args, picojson::object& out);
void BluetoothLEAdapterStopScan(const picojson::value& args, picojson::object& out);
+ void BluetoothLEAdapterIsScanning(const picojson::value& args, picojson::object& out);
void BluetoothLEAdapterStartAdvertise(const picojson::value& args, picojson::object& out);
void BluetoothLEAdapterStopAdvertise(const picojson::value& args, picojson::object& out);
void BluetoothLEDeviceConnect(const picojson::value& args, picojson::object& out);
void BluetoothLEDeviceRemoveConnectStateChangeListener(const picojson::value& args,
picojson::object& out);
void BluetoothLEDeviceGetServiceAllUuids(const picojson::value& args, picojson::object& out);
+ void BluetoothLEDeviceIsConnected(const picojson::value& args, picojson::object& out);
+ void BluetoothLEDeviceGetAttMtu(const picojson::value& args, picojson::object& out);
+ void BluetoothLEDeviceRequestAttMtuChange(const picojson::value& args, picojson::object& out);
+ void BluetoothLEDeviceAddAttMtuChangeListener(const picojson::value& args, picojson::object& out);
+ void BluetoothLEDeviceRemoveAttMtuChangeListener(const picojson::value& args,
+ picojson::object& out);
void BluetoothGATTClientServiceGetServices(const picojson::value& args, picojson::object& out);
void BluetoothGATTClientServiceGetCharacteristics(const picojson::value& args,
}
}
+void BluetoothLEAdapter::IsScanning(picojson::object& out) {
+ ScopeLogger();
+
+ bool is_scanning;
+ int ret = bt_adapter_le_is_discovering(&is_scanning);
+
+ if (BT_ERROR_NONE != ret) {
+ LogAndReportError(
+ PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to check for scanning in progress"), &out,
+ ("Failed to check for scanning in progress: %d (%s)", ret, get_error_message(ret)));
+ } else {
+ scanning_ = is_scanning;
+ ReportSuccess(picojson::value(is_scanning), out);
+ }
+}
+
void BluetoothLEAdapter::StartAdvertise(const picojson::value& data, picojson::object& out) {
ScopeLogger();
CHECK_BACKWARD_COMPABILITY_PRIVILEGE_ACCESS(Privilege::kBluetooth, Privilege::kBluetoothAdmin,
void StartScan(const picojson::value& data, picojson::object& out);
void StopScan(const picojson::value& data, picojson::object& out);
+ void IsScanning(picojson::object& out);
void StartAdvertise(const picojson::value& data, picojson::object& out);
void StopAdvertise(const picojson::value& data, picojson::object& out);
const std::string kData = "data";
const std::string kAction = "action";
const std::string kRSSI = "rssi";
+const std::string kAttMtuValue = "attMtuValue";
const std::string kOnConnected = "onconnected";
const std::string kOnDisconnected = "ondisconnected";
const std::string kConnectChangeEvent = "BluetoothLEConnectChangeCallback";
+const std::string kAttMtuChangeEvent = "BluetoothLEAttMtuChangeCallback";
+
+const char* kMtu = "mtu";
+const char* kAddress = "address";
}
BluetoothLEDevice::BluetoothLEDevice(BluetoothInstance& instance, BluetoothGATTClientService& service)
ScopeLogger();
int ret = bt_gatt_unset_connection_state_changed_cb();
if (ret != BT_ERROR_NONE) {
- LoggerW("Failed to unset listener: %d", ret);
+ LoggerW("Failed to unset connection state change listener: %d", ret);
+ }
+
+ if(mac_address_.empty()) {
+ LoggerD("No att mtu change listener to unset: %d", ret);
+ return;
+ }
+
+ bt_gatt_client_h client = service_.GetGattClient(mac_address_);
+
+ if (nullptr == client) {
+ LoggerW("Failed to get client handle while unsetting att mtu change listener");
+ return;
+ }
+
+ ret = bt_gatt_client_unset_att_mtu_changed_cb(client);
+
+ if (BT_ERROR_NONE != ret) {
+ LoggerW("Failed to unset att mtu change listener: %d", ret);
}
}
}
}
+void BluetoothLEDevice::IsConnected(const picojson::value& data, picojson::object& out) {
+ ScopeLogger();
+
+ const auto& args = util::GetArguments(data);
+ const auto& address = common::FromJson<std::string>(args, kAddress);
+
+ bool connected = false;
+ int ret = bt_device_is_profile_connected(address.c_str(), BT_PROFILE_GATT, &connected);
+
+ if (BT_ERROR_NONE == ret) {
+ ReportSuccess(picojson::value(connected), out);
+ } else {
+ LogAndReportError(
+ PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to check if device is connected"), &out,
+ ("Failed to check if device is connected: %d (%s)", ret, get_error_message(ret)));
+ }
+}
+
+void BluetoothLEDevice::GetAttMtu(const picojson::value& data, picojson::object& out) {
+ ScopeLogger();
+
+ unsigned int mtu = 0;
+ const auto& args = util::GetArguments(data);
+ const auto& address = common::FromJson<std::string>(args, kAddress);
+
+ if(mac_address_.empty()) {
+ mac_address_ == address;
+ }
+
+ bt_gatt_client_h client = service_.GetGattClient(address);
+
+ int ret = bt_gatt_client_get_att_mtu(client, &mtu);
+ if (BT_ERROR_NONE != ret) {
+ if ( BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED == ret) {
+ LogAndReportError(PlatformResult(ErrorCode::INVALID_STATE_ERR, "Device is not connected"), &out,
+ ("Failed to get ATT MTU: %d (%s)", ret, get_error_message(ret)));
+ } else {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get ATT MTU"), &out,
+ ("Failed to get ATT MTU: %d (%s)", ret, get_error_message(ret)));
+ }
+ return;
+ }
+
+ ReportSuccess(picojson::value(static_cast<double>(mtu)), out);
+}
+
+void BluetoothLEDevice::RequestAttMtuChange(const picojson::value& data, picojson::object& out) {
+ ScopeLogger();
+
+ const auto& args = util::GetArguments(data);
+ const auto& mtu = (unsigned int)common::FromJson<double>(args, kMtu);
+ const auto& address = common::FromJson<std::string>(args, kAddress);
+
+ if(mac_address_.empty()) {
+ mac_address_ == address;
+ }
+
+ bt_gatt_client_h client = service_.GetGattClient(address);
+
+ int ret = bt_gatt_client_request_att_mtu_change(client, mtu);
+ if (BT_ERROR_NONE != ret) {
+ LogAndReportError(PlatformResult(ErrorCode::UNKNOWN_ERR, "Failed to get ATT MTU"), &out,
+ ("Failed to get ATT MTU: %d (%s)", ret, get_error_message(ret)));
+ return;
+ }
+
+ ReportSuccess(out);
+}
+
+void BluetoothLEDevice::AddAttMtuChangeListener(const picojson::value& data,
+ picojson::object& out) {
+ ScopeLogger();
+
+ const auto& args = util::GetArguments(data);
+ const auto& address = common::FromJson<std::string>(args, kAddress);
+
+ if(mac_address_.empty()) {
+ mac_address_ == address;
+ }
+
+ bt_gatt_client_h client = service_.GetGattClient(address);
+
+ int ret = bt_gatt_client_set_att_mtu_changed_cb(client, OnAttMtuValueChanged, this);
+
+ if (BT_ERROR_NONE != ret) {
+ LogAndReportError(util::GetBluetoothError(ret, "Failed to register listener"), &out,
+ ("bt_gatt_client_set_att_mtu_changed_cb() failed with: %d (%s)", ret,
+ get_error_message(ret)));
+ } else {
+ ReportSuccess(out);
+ }
+}
+
+void BluetoothLEDevice::RemoveAttMtuChangeListener(const picojson::value& data,
+ picojson::object& out) {
+ ScopeLogger();
+
+ const auto& args = util::GetArguments(data);
+ const auto& address = common::FromJson<std::string>(args, kAddress);
+
+ bt_gatt_client_h client = service_.GetGattClient(address);
+
+ int ret = bt_gatt_client_unset_att_mtu_changed_cb(client);
+
+ if (BT_ERROR_NONE != ret) {
+ LogAndReportError(util::GetBluetoothError(ret, "Failed to register listener"), &out,
+ ("bt_gatt_client_set_att_mtu_changed_cb() failed with: %d (%s)", ret,
+ get_error_message(ret)));
+ } else {
+ if(!mac_address_.empty()) {
+ mac_address_.clear();
+ }
+ ReportSuccess(out);
+ }
+}
+
+void BluetoothLEDevice::OnAttMtuValueChanged(bt_gatt_client_h client,
+ const bt_gatt_client_att_mtu_info_s* mtu_info,
+ void* user_data) {
+ ScopeLogger();
+ if(!mtu_info) {
+ LoggerE("mtu_info is NULL");
+ return;
+ } else {
+ LoggerD("mtu_info->mtu: [%u]", mtu_info->mtu);
+ }
+
+ if (!user_data) {
+ LoggerE("user_data is NULL");
+ return;
+ }
+ BluetoothLEDevice* le_device = static_cast<BluetoothLEDevice*>(user_data);
+
+ le_device->TriggerAttMtuStateChangeListener(mtu_info->remote_address, mtu_info->mtu);
+}
+
+void BluetoothLEDevice::TriggerAttMtuStateChangeListener(char* remote_address, unsigned int mtu) {
+ ScopeLogger("adress: [%s], mtu: [%u]", remote_address, mtu);
+
+ picojson::value value = picojson::value(picojson::object());
+ picojson::object* data_obj = &value.get<picojson::object>();
+
+ data_obj->insert(std::make_pair(kAttMtuValue, picojson::value(static_cast<double>(mtu))));
+
+ instance_.FireEvent(kAttMtuChangeEvent, value);
+};
+
void BluetoothLEDevice::GattConnectionState(int result, bool connected, const char* remote_address,
void* user_data) {
ScopeLogger("%s connected: %d", remote_address, connected);
void GetServiceAllUuids(const picojson::value& data, picojson::object& out);
+ void IsConnected(const picojson::value& data, picojson::object& out);
+
+ void GetAttMtu(const picojson::value& data, picojson::object& out);
+ void RequestAttMtuChange(const picojson::value& data, picojson::object& out);
+ void AddAttMtuChangeListener(const picojson::value& data, picojson::object& out);
+ void RemoveAttMtuChangeListener(const picojson::value& data, picojson::object& out);
+
static common::PlatformResult ToJson(bt_adapter_le_device_scan_result_info_s* info,
picojson::object* le_device);
bool IsInConnecting(const char* remote_address);
static common::PlatformResult ValidateConnectionChange(int err_code);
void TriggerConnectCallback(const char* remote_address, common::PlatformResult result);
+ void TriggerAttMtuStateChangeListener(char* remote_address, unsigned int mtu);
void CleanClientInfo(const char* remote_address);
void TriggerConnectStateChangeListener(const char* remote_address, bool connected);
+ static void OnAttMtuValueChanged(bt_gatt_client_h client,
+ const bt_gatt_client_att_mtu_info_s* mtu_info, void* user_data);
BluetoothInstance& instance_;
BluetoothGATTClientService& service_;
std::unordered_map<std::string, double> connecting_;
bool is_listener_set_;
std::set<std::string> is_connected_;
+ std::string mac_address_;
};
} // namespace bluetooth