Skip to content

Commit

Permalink
fix(#35): apply patch from issue to fix scanWifiList issue (#36)
Browse files Browse the repository at this point in the history
* fix(#35): apply patch from issue to fix scanWifiList issue

* fix(ios): fix parameter name typo

* fix(android,ios): more typo fixes

* fix(android): add check if already connected

* fix(android): cleanup unused params
  • Loading branch information
mateogianolio authored Jan 23, 2024
1 parent 069d167 commit b3b47d6
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 92 deletions.
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

0 comments on commit b3b47d6

Please sign in to comment.