6#include <QtBluetooth/private/qohosbluetoothcommon_p.h>
7#include <QtBluetooth/private/qohosbluetoothremotedevice_p.h>
9#include <QtCore/qloggingcategory.h>
10#include <QtCore/private/qnapi_p.h>
11#include <QtCore/private/qohosjstools_p.h>
12#include <QtCore/private/qohoslogger_p.h>
17using namespace std::chrono_literals;
27constexpr qint16 unknownRssi = 0;
29std::optional<
bool> tryReadBluetoothDiscoveringState(QOhosJsState &jsState)
31 if (!isBluetoothEnabled(jsState))
35 return jsState.eval<QNapi::Boolean>(
"@ohos.bluetooth.connection.isBluetoothDiscovering()").Value();
36 }
catch (
const Napi::Error &error) {
37 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
39 "%s: cannot read the bluetooth discovering state, error code: %u", Q_FUNC_INFO,
40 qToUnderlying(*optErrorCode));
46bool requestBluetoothDiscoveryStop(QOhosJsState &jsState)
48 const auto optDiscovering = tryReadBluetoothDiscoveringState(jsState);
49 if (optDiscovering && !*optDiscovering)
53 jsState.eval(
"@ohos.bluetooth.connection.stopBluetoothDiscovery()");
54 }
catch (
const Napi::Error &error) {
55 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
57 "%s: cannot stop the bluetooth discovery, error code: %u", Q_FUNC_INFO, qToUnderlying(*optErrorCode));
65std::vector<std::string> readPairedDeviceIds(QOhosJsState &jsState)
67 if (!isBluetoothEnabled(jsState))
71 return QNapi::getArrayElements<std::vector<std::string>, QNapi::String>(
72 jsState.eval<QNapi::Array>(
"@ohos.bluetooth.connection.getPairedDevices()"),
73 [](QNapi::String &&pairedDeviceId) {
74 return pairedDeviceId.Utf8Value();
76 }
catch (
const Napi::Error &error) {
77 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
79 "%s: cannot read the paired devices, error code: %u", Q_FUNC_INFO, qToUnderlying(*optErrorCode));
85std::vector<DiscoveryResult> readPairedDevices(QOhosJsState &jsState)
87 auto pairedDeviceIds = readPairedDeviceIds(jsState);
89 std::vector<DiscoveryResult> pairedDevices;
90 pairedDevices.reserve(pairedDeviceIds.size());
91 for (
auto &pairedDeviceId : pairedDeviceIds) {
92 if (isRemoteDeviceLowEnergyOnly(jsState, pairedDeviceId))
95 auto pairedDeviceName = readRemoteDeviceName(jsState, pairedDeviceId);
96 const auto optPairedDeviceClass = readRemoteDeviceClass(jsState, pairedDeviceId);
98 pairedDevices.push_back(
100 .deviceId = std::move(pairedDeviceId),
101 .deviceName = pairedDeviceName
104 .classOfDevice = optPairedDeviceClass.value_or(0),
109 return pairedDevices;
115 QOhosJsState &jsState, QNapi::Object discoveryResultObject)
117 auto deviceId = discoveryResultObject.get<QNapi::String>(
"deviceId").Utf8Value();
119 auto deviceName = discoveryResultObject.get<QNapi::String>(
"deviceName").Utf8Value();
120 if (deviceName.empty()) {
121 if (
auto optRemoteDeviceName = readRemoteDeviceName(jsState, deviceId))
122 deviceName =
std::move(*optRemoteDeviceName);
125 return DiscoveryResult {
126 .deviceId = std::move(deviceId),
127 .deviceName = std::move(deviceName),
128 .classOfDevice = discoveryResultObject.get<QNapi::Number>(
"deviceClass.classOfDevice").Uint32Value(),
129 .rssi =
static_cast<qint16>(discoveryResultObject.get<QNapi::Number>(
"rssi").Int32Value()),
137 m_accessProxy.get(), &QOhosBluetoothAccessProxy::stateChanged,
this,
138 [
this](QOhosBluetoothAccessProxy::BluetoothState bluetoothState) {
139 if (bluetoothState == QOhosBluetoothAccessProxy::BluetoothState::STATE_ON)
142 if (!m_discoveryStoppedPollTimer.isActive())
145 resetDiscoveryTracking();
146 Q_EMIT bluetoothPoweredOff();
149 constexpr auto discoveryStoppedPollInterval = 500ms;
150 m_discoveryStoppedPollTimer.setInterval(discoveryStoppedPollInterval);
152 &m_discoveryStoppedPollTimer, &QTimer::timeout,
this,
154 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
155 resetDiscoveryTracking();
156 m_discoveredDevicesConsumerHandle.reset();
157 Q_EMIT missingPermission();
161 if (tryCheckBluetoothDiscovering().value_or(
true))
164 resetDiscoveryTracking();
165 Q_EMIT discoveryStopped();
168 constexpr auto discoveryStoppedTimeout = 30s;
169 m_discoveryStoppedTimeoutTimer.setSingleShot(
true);
170 m_discoveryStoppedTimeoutTimer.setInterval(discoveryStoppedTimeout);
172 &m_discoveryStoppedTimeoutTimer, &QTimer::timeout,
this,
174 resetDiscoveryTracking();
175 Q_EMIT discoveryStopFailed();
183 auto instance = weakInstance.lock();
185 instance = std::shared_ptr<QOhosBluetoothDeviceDiscoveryAgentProxy>(
187 weakInstance = instance;
195 if (m_discoveredDevicesConsumerHandle)
198 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
201 auto selfRef = QtOhos::makeQThreadSafeRef(
this);
202 m_discoveredDevicesConsumerHandle = QOhosJsThreadGateway::eval(
203 [&](QOhosJsState &jsState) -> std::shared_ptr<
void> {
204 auto discoveredDevicesConsumerHandle = registerQOhosOnOffMethodsBasedEventHandler(
205 jsState.eval<QNapi::Object>(
"@ohos.bluetooth.connection"),
"discoveryResult",
206 [selfRef](
const QOhosCallbackInfo &cbInfo) {
207 auto resultArray = cbInfo.getFirstArg<QNapi::Array>(Q_FUNC_INFO);
208 auto discoveredDevices =
209 QNapi::getArrayElements<std::vector<DiscoveryResult>, QNapi::Object>(
211 [&](QNapi::Object &&discoveryResultObject) {
212 return DiscoveryResult::makeFromOhosDiscoveryResultObject(
213 cbInfo.jsState(), std::move(discoveryResultObject));
216 selfRef.visitInQtThreadIfAlive(
217 [discoveredDevices = std::move(discoveredDevices)](
auto &self) {
218 Q_EMIT self.bluetoothDevicesFound(discoveredDevices);
222 .optOnCallExceptionHandler = [](
const Napi::Error &error) {
223 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
225 "%s: cannot register the discovery result consumer, error code: %u",
226 Q_FUNC_INFO, qToUnderlying(*optErrorCode));
231 if (!discoveredDevicesConsumerHandle)
234 return QtOhos::makeProxyWithJsThreadDeleter(
235 std::move(discoveredDevicesConsumerHandle));
239 return m_discoveredDevicesConsumerHandle !=
nullptr;
244 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
247 return QOhosJsThreadGateway::eval(tryReadBluetoothDiscoveringState, Q_FUNC_INFO);
252 m_discoveryStoppedPollTimer.stop();
253 m_discoveryStoppedTimeoutTimer.stop();
254 m_discoveryStartedByProxy =
false;
259 return !m_discoveryStartedByProxy && tryCheckBluetoothDiscovering().value_or(
false);
264 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
265 Q_EMIT missingPermission();
269 if (!ensureDiscoveredDevicesConsumerRegistered()) {
272 "%s: discovery result consumer not registered. Found devices would not be reported.",
274 Q_EMIT discoveryStartFailed();
278 const auto discoveryOngoing = QOhosJsThreadGateway::eval(
279 [](QOhosJsState &jsState) {
280 const auto optDiscovering = tryReadBluetoothDiscoveringState(jsState);
281 if (optDiscovering && *optDiscovering)
285 jsState.eval(
"@ohos.bluetooth.connection.startBluetoothDiscovery()");
286 }
catch (
const Napi::Error &error) {
287 if (
const auto optErrorCode = tryGetKnownErrorCode(error.Value(), Q_FUNC_INFO)) {
289 "%s: cannot start the bluetooth discovery, error code: %u", Q_FUNC_INFO,
290 qToUnderlying(*optErrorCode));
299 if (!discoveryOngoing) {
300 Q_EMIT discoveryStartFailed();
304 m_discoveryStartedByProxy =
true;
305 m_discoveryStoppedTimeoutTimer.stop();
306 m_discoveryStoppedPollTimer.start();
311 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO)) {
312 Q_EMIT missingPermission();
316 if (!QOhosJsThreadGateway::eval(requestBluetoothDiscoveryStop, Q_FUNC_INFO)) {
317 Q_EMIT discoveryStopFailed();
321 m_discoveryStoppedPollTimer.start();
322 m_discoveryStoppedTimeoutTimer.start();
327 if (!checkAccessBluetoothPermissionGranted(Q_FUNC_INFO))
330 return QOhosJsThreadGateway::eval(readPairedDevices, Q_FUNC_INFO);
337#include "moc_qohosbluetoothdevicediscovery_p.cpp"
std::vector< DiscoveryResult > getPairedDevices()
bool isForeignDiscoveryOngoing()
QOhosBluetoothDeviceDiscoveryAgentProxy()
void startBluetoothDiscovery()
void stopBluetoothDiscovery()
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQIORing)