Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(#35): apply patch from issue to fix scanWifiList issue #36

Merged
merged 7 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ import java.lang.Exception
import java.util.ArrayList
import java.util.Base64

fun BluetoothDevice.isAlreadyConnected(): Boolean {
return try {
javaClass.getMethod("isConnected").invoke(this) as? Boolean? ?: false
} catch (e: Throwable) {
false
}
}

class EspIdfProvisioningModule internal constructor(context: ReactApplicationContext?) : EspIdfProvisioningSpec(context) {
override fun getName(): String {
return NAME
Expand All @@ -45,33 +53,18 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon

private fun hasBluetoothPermissions(): Boolean {
if (Build.VERSION.SDK_INT <= 30) {
if (
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED
) {
return true
} else {
return false
}
}
else if (
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
) {
return true
return ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_ADMIN) == PackageManager.PERMISSION_GRANTED
}
return false

return ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.BLUETOOTH_SCAN) == PackageManager.PERMISSION_GRANTED
}

private fun hasWifiPermission(): Boolean {
if (
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.CHANGE_WIFI_STATE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.ACCESS_WIFI_STATE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.ACCESS_NETWORK_STATE) == PackageManager.PERMISSION_GRANTED
) {
return true
}
return false
return ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.CHANGE_WIFI_STATE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.ACCESS_WIFI_STATE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(reactApplicationContext, Manifest.permission.ACCESS_NETWORK_STATE) == PackageManager.PERMISSION_GRANTED
}

private fun hasFineLocationPermission(): Boolean {
Expand All @@ -82,10 +75,7 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
@ReactMethod
override fun searchESPDevices(devicePrefix: String, transport: String, security: Int, promise: Promise?) {
// Permission checks
if (
hasBluetoothPermissions() == false ||
hasFineLocationPermission() == false
) {
if (!hasBluetoothPermissions() || !hasFineLocationPermission()) {
promise?.reject(Error("Missing one of the following permissions: BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_CONNECT, BLUETOOTH_SCAN, ACCESS_FINE_LOCATION"))
return
}
Expand All @@ -103,8 +93,6 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
}

espDevices.clear()

val invoked = false
espProvisionManager.searchBleEspDevices(devicePrefix, object : BleScanListener {
override fun scanStartFailed() {
promise?.reject(Error("Scan could not be started."))
Expand All @@ -123,11 +111,7 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
return
}

var serviceUuid: String? = null
if (scanResult.scanRecord?.serviceUuids != null && scanResult.scanRecord?.serviceUuids?.size!! > 0) {
serviceUuid = scanResult.scanRecord?.serviceUuids?.get(0).toString()
}

val serviceUuid = scanResult.scanRecord?.serviceUuids?.getOrNull(0)?.toString()
if (serviceUuid != null && !espDevices.containsKey(deviceName)) {
val espDevice = ESPDevice(reactApplicationContext, transportEnum, securityEnum)
espDevice.bluetoothDevice = device
Expand All @@ -148,13 +132,8 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
espDevices.values.forEach { espDevice ->
val resultMap = Arguments.createMap()
resultMap.putString("name", espDevice.deviceName)
resultMap.putArray("capabilities", Arguments.fromList(espDevice.deviceCapabilities))
resultMap.putInt("security", security)
resultMap.putString("transport", transport)
resultMap.putString("username", espDevice.userName)
resultMap.putString("versionInfo", espDevice.versionInfo)
resultMap.putString("address", espDevice.bluetoothDevice.address)
resultMap.putString("primaryServiceUuid", espDevice.primaryServiceUuid)
resultMap.putInt("security", security)

resultArray.pushMap(resultMap)
}
Expand All @@ -172,10 +151,7 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
@ReactMethod
override fun stopESPDevicesSearch() {
// Permission checks
if (
hasBluetoothPermissions() == false ||
hasFineLocationPermission() == false
) {
if (!hasBluetoothPermissions() || !hasFineLocationPermission()) {
// If we don't have permissions we are probably not scanning either, so just return
return
}
Expand All @@ -195,7 +171,7 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
promise: Promise?
) {
// Permission checks
if (hasBluetoothPermissions() == false) {
if (!hasBluetoothPermissions()) {
promise?.reject(Error("Missing one of the following permissions: BLUETOOTH, BLUETOOTH_ADMIN, BLUETOOTH_CONNECT, BLUETOOTH_SCAN"))
return
}
Expand All @@ -212,49 +188,32 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon
else -> ESPConstants.SecurityType.SECURITY_2
}

if (espDevices[deviceName] != null) {
val result = Arguments.createMap()
result.putString("name", espDevices[deviceName]?.deviceName)
result.putArray("capabilities", Arguments.fromList(espDevices[deviceName]?.deviceCapabilities))
result.putInt("security", security)
result.putString("transport", transport)
result.putString("username", espDevices[deviceName]?.userName)
result.putString("versionInfo", espDevices[deviceName]?.versionInfo)

promise?.resolve(result)
return
}

// If no ESP device found in list (no scan has been performed), create a new one
val espDevice = espProvisionManager.createESPDevice(transportEnum, securityEnum)
var bleDevice = espDevice?.bluetoothDevice
var espDevice = espDevices[deviceName];
if (espDevice == null) {
espDevice = espProvisionManager.createESPDevice(transportEnum, securityEnum)
espDevice.deviceName = deviceName
espDevices[deviceName] = espDevice
}

// If the bluetooth device does not contain service uuids, try using the bonded
// one (if it exists)
if (bleDevice?.uuids == null) {
bleDevice = bluetoothAdapter.bondedDevices.find {
bondedDevice -> bondedDevice.name == deviceName
// If the bluetooth device does not exist, try using the bonded one (if it exists)
if (espDevice?.bluetoothDevice == null) {
espDevice?.bluetoothDevice = bluetoothAdapter.bondedDevices.find {
bondedDevice -> bondedDevice.name == deviceName
}
}

// If the bluetooth device exists and contains service uuids, we will be able to connect to it
if (bleDevice?.uuids != null) {
espDevice.bluetoothDevice = bleDevice
espDevice.deviceName = deviceName
// If the bluetooth device exists and we have a primary service uuid, we will be able to connect to it
if (espDevice?.bluetoothDevice != null && espDevice.primaryServiceUuid != null) {
espDevice.proofOfPossession = proofOfPossession
if (username != null) {
espDevice.userName = username
}

espDevices[deviceName] = espDevice

val result = Arguments.createMap()
result.putString("name", espDevice.deviceName)
result.putArray("capabilities", Arguments.fromList(espDevice.deviceCapabilities))
result.putInt("security", security)
result.putString("transport", transport)
result.putString("username", espDevice.userName)
result.putString("versionInfo", espDevice.versionInfo)
result.putInt("security", security)

promise?.resolve(result)
return
Expand All @@ -276,11 +235,8 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon

val result = Arguments.createMap()
result.putString("name", espDevices[deviceName]?.deviceName)
result.putArray("capabilities", Arguments.fromList(espDevices[deviceName]?.deviceCapabilities))
result.putInt("security", security)
result.putString("transport", transport)
result.putString("username", espDevices[deviceName]?.userName)
result.putString("versionInfo", espDevices[deviceName]?.versionInfo)
result.putInt("security", security)

promise?.resolve(result)
}
Expand Down Expand Up @@ -338,15 +294,21 @@ class EspIdfProvisioningModule internal constructor(context: ReactApplicationCon

if (espDevices[deviceName]?.transportType == ESPConstants.TransportType.TRANSPORT_SOFTAP) {
// Permission checks
if (
hasWifiPermission() == false ||
hasFineLocationPermission() == false
) {
if (!hasWifiPermission() || !hasFineLocationPermission()) {
promise?.reject(Error("Missing one of the following permissions: CHANGE_WIFI_STATE, ACCESS_WIFI_STATE, ACCESS_NETWORK_STATE, ACCESS_FINE_LOCATION"))
return
}
}

// If device is already connected, exit early
if (espDevices[deviceName]?.transportType == ESPConstants.TransportType.TRANSPORT_BLE &&
espDevices[deviceName]?.bluetoothDevice?.isAlreadyConnected() == true) {
val result = Arguments.createMap()
result.putString("status", "connected")
promise?.resolve(result)
return
}

espDevices[deviceName]?.connectToDevice()

EventBus.getDefault().register(object {
Expand Down
2 changes: 1 addition & 1 deletion android/src/oldarch/EspIdfProvisioningSpec.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule
abstract class EspIdfProvisioningSpec(context: ReactApplicationContext?) : ReactContextBaseJavaModule(context) {
abstract fun searchESPDevices(devicePrefix: String, transport: String, security: Int, promise: Promise?)
abstract fun stopESPDevicesSearch()
abstract fun createESPDevice(deviceName: String, transport: String, security: Int, proofOfPossesion: String?, softAPPassword: String?, username: String?, promise: Promise?)
abstract fun createESPDevice(deviceName: String, transport: String, security: Int, proofOfPossession: String?, softAPPassword: String?, username: String?, promise: Promise?)
abstract fun connect(deviceName: String, promise: Promise?)
abstract fun sendData(deviceName: String, path: String, data: String, promise: Promise?)
abstract fun getProofOfPossession(deviceName: String, promise: Promise?)
Expand Down
2 changes: 1 addition & 1 deletion ios/EspIdfProvisioning.mm
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ @interface RCT_EXTERN_MODULE(EspIdfProvisioning, NSObject)

RCT_EXTERN_METHOD(isSessionEstablished:(NSString *)deviceName)

RCT_EXTERN_METHOD(getProofOfPossesion:(NSString *)deviceName
RCT_EXTERN_METHOD(getProofOfPossession:(NSString *)deviceName
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)

Expand Down
8 changes: 4 additions & 4 deletions ios/EspIdfProvisioning.swift
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,19 @@ class EspIdfProvisioning: NSObject {
return self.espDevices[deviceName]!.isSessionEstablished()
}

@objc(getProofOfPossesion:resolve:reject:)
func getProofOfPossesion(deviceName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
@objc(getProofOfPossession:resolve:reject:)
func getProofOfPossession(deviceName: String, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
if self.espDevices[deviceName] == nil {
reject("error", "No ESP device found. Call createESPDevice first.", nil)
return
}

var invoked = false
self.espDevices[deviceName]!.delegate?.getProofOfPossesion(forDevice: self.espDevices[deviceName]!, completionHandler: { proofOfPossesion in
self.espDevices[deviceName]!.delegate?.getProofOfPossesion(forDevice: self.espDevices[deviceName]!, completionHandler: { proofOfPossession in
// Prevent multiple callback invokation error
guard !invoked else { return }

resolve(proofOfPossesion)
resolve(proofOfPossession)
invoked = true
})
}
Expand Down
2 changes: 1 addition & 1 deletion src/NativeEspIdfProvisioning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export interface Spec extends TurboModule {
deviceName: string,
transport: ESPTransport,
security: ESPSecurity,
proofOfPossesion?: string,
proofOfPossession?: string,
softAPPassword?: string,
username?: string
): Promise<ESPDeviceInterface>;
Expand Down
4 changes: 2 additions & 2 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ export class ESPDevice implements ESPDeviceInterface {
}

async connect(
proofOfPossesion: string | null = null,
proofOfPossession: string | null = null,
softAPPassword: string | null = null,
username: string | null = null
): Promise<void> {
const data = await EspIdfProvisioning.createESPDevice(
this.name,
this.transport,
this.security,
proofOfPossesion,
proofOfPossession,
softAPPassword,
username
);
Expand Down
Loading