6#include <QtBluetooth/private/qohosbluetoothcommon_p.h>
8#include <QtCore/qloggingcategory.h>
9#include <QtCore/private/qcore_ohos_p.h>
10#include <QtCore/private/qnapi_p.h>
11#include <QtCore/private/qohosjstools_p.h>
12#include <QtCore/private/qohoslogger_p.h>
20Q_DECLARE_LOGGING_CATEGORY(QT_BT_OHOS)
26std::shared_ptr<
void> registerBondStateChangeConsumer(
27 QOhosJsState &jsState,
28 QOhosConsumer<std::string, std::optional<QOhosBluetoothRemoteDeviceProxy::BondState>, std::optional<QOhosBluetoothRemoteDeviceProxy::UnbondCause>> bondStateChangeConsumer)
30 return registerQOhosOnOffMethodsBasedEventHandler(
31 jsState.eval<QNapi::Object>(
"@ohos.bluetooth.connection"),
"bondStateChange",
32 [bondStateChangeConsumer = std::move(bondStateChangeConsumer)](
const QOhosCallbackInfo &cbInfo) {
33 auto bondStateObject = cbInfo.getFirstArg<QNapi::Object>(Q_FUNC_INFO);
35 auto deviceId = bondStateObject.get<QNapi::String>(
"deviceId").Utf8Value();
36 const auto optBondState = cbInfo.jsState().tryMapOhosEnumFromJs<QOhosBluetoothRemoteDeviceProxy::BondState>(
37 bondStateObject.get<QNapi::Number>(
"state"));
38 const auto unbondCauseValue =
39 QNapi::getOptionalPropOrEmpty<QNapi::Number>(bondStateObject,
"cause");
40 const auto optUnbondCause = unbondCauseValue.IsEmpty()
41 ? std::optional<QOhosBluetoothRemoteDeviceProxy::UnbondCause>()
42 : cbInfo.jsState().tryMapOhosEnumFromJs<QOhosBluetoothRemoteDeviceProxy::UnbondCause>(
45 bondStateChangeConsumer(deviceId, optBondState, optUnbondCause);
48 .optOnCallExceptionHandler = [](
const Napi::Error &error) {
49 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
51 "%s: cannot register the bond state change consumer, error code: %u",
52 Q_FUNC_INFO, qToUnderlying(*optErrorCode));
58std::optional<QOhosBluetoothRemoteDeviceProxy::BondState> readPairState(
59 QOhosJsState &jsState,
const std::string &deviceId)
61 if (!isBluetoothEnabled(jsState))
65 return jsState.tryMapOhosEnumFromJs<QOhosBluetoothRemoteDeviceProxy::BondState>(
66 jsState.eval<QNapi::Number>(
67 "@ohos.bluetooth.connection.getPairState(*)", {deviceId}));
68 }
catch (
const Napi::Error &error) {
69 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
71 "%s: cannot read the pair state of the device %s, error code: %u", Q_FUNC_INFO,
72 deviceId.c_str(), qToUnderlying(*optErrorCode));
83 return jsState.eval<QNapi::String>(
84 "@ohos.bluetooth.connection.getRemoteDeviceName(*)", {deviceId}).Utf8Value();
85 }
catch (
const Napi::Error &error) {
86 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
88 "%s: cannot read the name of the device %s, error code: %u", Q_FUNC_INFO,
89 deviceId.c_str(), qToUnderlying(*optErrorCode));
98 return jsState.eval<QNapi::Object>(
99 "@ohos.bluetooth.connection.getRemoteDeviceClass(*)", {deviceId})
100 .get<QNapi::Number>(
"classOfDevice").Uint32Value();
101 }
catch (
const Napi::Error &error) {
102 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
104 "%s: cannot read the class of the device %s, error code: %u", Q_FUNC_INFO,
105 deviceId.c_str(), qToUnderlying(*optErrorCode));
112 QOhosJsState &jsState,
const std::string &deviceId)
115 return jsState.tryMapOhosEnumFromJs<QOhosBluetoothRemoteDeviceProxy::BluetoothTransport>(
116 jsState.eval<QNapi::Number>(
117 "@ohos.bluetooth.connection.getRemoteDeviceTransport(*)", {deviceId}));
118 }
catch (
const Napi::Error &error) {
119 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
121 "%s: cannot read the transport of the device %s, error code: %u", Q_FUNC_INFO,
122 deviceId.c_str(), qToUnderlying(*optErrorCode));
130 return readRemoteDeviceTransport(jsState, deviceId)
131 == QOhosBluetoothRemoteDeviceProxy::BluetoothTransport::TRANSPORT_LE;
136 ensureBondStateChangeConsumerRegistered();
141 if (m_bondStateChangeConsumerHandle)
144 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
147 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
148 m_bondStateChangeConsumerHandle = QOhosJsThreadGateway::eval(
149 [&](QOhosJsState &jsState) -> std::shared_ptr<
void> {
150 auto bondStateChangeConsumerHandle = registerBondStateChangeConsumer(
152 [selfRef](std::string deviceId, std::optional<BondState> optBondState, std::optional<UnbondCause> optUnbondCause) {
156 selfRef.visitInQtThreadIfAlive(
157 [deviceId = QString::fromStdString(deviceId), bondState = *optBondState, optUnbondCause](
auto &self) {
158 Q_EMIT self.bondStateChanged(deviceId, bondState, optUnbondCause);
162 if (!bondStateChangeConsumerHandle)
165 return QtOhos::makeProxyWithJsThreadDeleter(std::move(bondStateChangeConsumerHandle));
169 return m_bondStateChangeConsumerHandle !=
nullptr;
176 auto instance = weakInstance.lock();
178 instance = std::shared_ptr<QOhosBluetoothRemoteDeviceProxy>(
180 weakInstance = instance;
188 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
191 return QOhosJsThreadGateway::eval(
192 [&](QOhosJsState &jsState) -> std::optional<QString> {
193 if (!isBluetoothEnabled(jsState))
196 const auto optRemoteDeviceName = readRemoteDeviceName(jsState, deviceId.toStdString());
198 return optRemoteDeviceName
199 ? std::optional(QString::fromStdString(*optRemoteDeviceName))
206 const QString &deviceId)
208 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
211 return QOhosJsThreadGateway::eval(
212 [&](QOhosJsState &jsState) {
213 return readPairState(jsState, deviceId.toStdString());
219 const QString &deviceId)
221 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
222 return QOhosBluetoothErrorCode::PermissionDenied;
224 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
225 return QOhosJsThreadGateway::eval(
226 [&](QOhosJsState &jsState) -> std::optional<QOhosBluetoothErrorCode> {
227 if (!isBluetoothEnabled(jsState))
228 return QOhosBluetoothErrorCode::BluetoothDisabled;
230 RemoteDeviceServices remoteDeviceServices;
231 remoteDeviceServices.deviceId = deviceId.toStdString();
232 remoteDeviceServices.optDeviceName =
233 readRemoteDeviceName(jsState, remoteDeviceServices.deviceId);
234 remoteDeviceServices.optClassOfDevice =
235 readRemoteDeviceClass(jsState, remoteDeviceServices.deviceId);
236 remoteDeviceServices.lowEnergyOnly =
237 isRemoteDeviceLowEnergyOnly(jsState, remoteDeviceServices.deviceId);
239 auto pendingServices = QtOhos::moveToSharedPtr(std::move(remoteDeviceServices));
240 auto reportRemoteDeviceServices =
241 [selfRef, pendingServices]() {
242 selfRef.visitInQtThreadIfAlive(
243 [pendingServices](
auto &self) {
244 Q_EMIT self.remoteDeviceServicesRead(*pendingServices);
249 jsState.evalToPromiseOrRejectOnThrow(
250 "@ohos.bluetooth.connection.getRemoteProfileUuids(*)",
251 {pendingServices->deviceId})
253 [reportRemoteDeviceServices, pendingServices](
254 const QOhosCallbackInfo &cbInfo) {
255 auto resultArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
256 pendingServices->optProfileUuids =
257 QNapi::getArrayElements<std::vector<std::string>, QNapi::String>(
259 [](QNapi::String &&profileUuid) {
260 return profileUuid.Utf8Value();
262 reportRemoteDeviceServices();
264 [reportRemoteDeviceServices](
const QOhosCallbackInfo &cbInfo) {
265 QtOhos::logJsCallbackError(cbInfo,
"Got error from getRemoteProfileUuids()");
266 reportRemoteDeviceServices();
269 }
catch (
const Napi::Error &error) {
270 const auto errorCode =
271 tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)
272 .value_or(QOhosBluetoothErrorCode::OperationFailed);
274 "%s: cannot read the remote profile uuids, error code: %u", Q_FUNC_INFO,
275 qToUnderlying(errorCode));
284 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
285 Q_EMIT missingPermission();
289 if (!ensureBondStateChangeConsumerRegistered()) {
292 "%s: bond state change consumer not registered. Pairing result will not be reported.",
296 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
297 const auto optErrorCode = QOhosJsThreadGateway::eval(
298 [&](QOhosJsState &jsState) -> std::optional<QOhosBluetoothErrorCode> {
300 jsState.evalToPromiseOrRejectOnThrow(
301 "@ohos.bluetooth.connection.pairDevice(*)", {deviceId.toStdString()})
303 [selfRef, pairedDeviceId = deviceId.toStdString()](
304 const QOhosCallbackInfo &cbInfo) {
305 QtOhos::logJsCallbackError(cbInfo,
"Got error from pairDevice()");
306 selfRef.visitInQtThreadIfAlive(
307 [pairedDeviceId](
auto &self) {
308 Q_EMIT self.pairDeviceFailed(QString::fromStdString(pairedDeviceId));
312 }
catch (
const Napi::Error &error) {
313 return tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO);
322 QT_BT_OHOS,
"%s: cannot start pairing with the device %ls, error code: %u", Q_FUNC_INFO,
323 qUtf16Printable(deviceId), qToUnderlying(*optErrorCode));
332#include "moc_qohosbluetoothremotedevice_p.cpp"
std::optional< QString > tryGetRemoteDeviceName(const QString &deviceId)
std::optional< QOhosBluetoothErrorCode > requestRemoteDeviceServices(const QString &deviceId)
std::optional< BondState > tryGetPairState(const QString &deviceId)
QOhosBluetoothRemoteDeviceProxy()
static std::shared_ptr< QOhosBluetoothRemoteDeviceProxy > instance()
bool pairDevice(const QString &deviceId)
Combined button and popup list for selecting options.
bool isRemoteDeviceLowEnergyOnly(QOhosJsState &jsState, const std::string &deviceId)
std::optional< quint32 > readRemoteDeviceClass(QOhosJsState &jsState, const std::string &deviceId)
std::optional< QOhosBluetoothRemoteDeviceProxy::BluetoothTransport > readRemoteDeviceTransport(QOhosJsState &jsState, const std::string &deviceId)
std::optional< std::string > readRemoteDeviceName(QOhosJsState &jsState, const std::string &deviceId)