Skip to content

Commit

Permalink
Merge branch 'library/esp_provision_lib_2.0.1' into 'master'
Browse files Browse the repository at this point in the history
Library update to version 2.0.1.

See merge request idf/esp-idf-provisioning-ios!9
  • Loading branch information
shahpiyushv committed Jun 12, 2020
2 parents 1f981de + f85c339 commit f0ee7e5
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 24 deletions.
2 changes: 1 addition & 1 deletion ESPProvision.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |spec|

spec.name = "ESPProvision"
spec.version = "2.0"
spec.version = "2.0.1"
spec.summary = "ESP-IDF provisioning in Swift"
spec.description = "It provides mechanism to provide network credentials and/or custom data to an ESP32 or ESP32-S2 devices"
spec.homepage = "https://github.com/espressif/esp-idf-provisioning-ios"
Expand Down
121 changes: 102 additions & 19 deletions ESPProvision/ESPDevice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public enum ESPProvisionStatus {
case success
/// Failed to provision device.
case failure(ESPProvisionError)
/// Applied configuration
case configApplied
}

/// Class needs to conform to `ESPDeviceConnectionDelegate` protcol when trying to establish a connection.
Expand Down Expand Up @@ -83,6 +85,7 @@ public class ESPDevice {
private var provision: ESPProvision!
private var softAPPassword:String?
private var proofOfPossession:String?
private var retryScan = false

/// Get name of current `ESPDevice`.
public var name:String {
Expand Down Expand Up @@ -197,33 +200,61 @@ public class ESPDevice {
/// - completionHandler: The completion handler that is called when data transmission is successful.
/// Parameter of block include response recieved from the HTTP request or error if any.
public func sendData(path:String, data:Data, completionHandler: @escaping (Data?, ESPSessionError?) -> Swift.Void) {

if session == nil, !session.isEstablished {
completionHandler(nil,.sessionNotEstablished)
} else {
self.sendDataToDevice(path: path, data: data, completionHandler: completionHandler)
self.sendDataToDevice(path: path, data: data, retryOnce: true, completionHandler: completionHandler)
}
}

private func sendDataToDevice(path:String, data:Data, completionHandler: @escaping (Data?, ESPSessionError?) -> Swift.Void) {
private func sendDataToDevice(path:String, data:Data, retryOnce:Bool, completionHandler: @escaping (Data?, ESPSessionError?) -> Swift.Void) {
guard let encryptedData = securityLayer.encrypt(data: data) else {
completionHandler(nil,.securityMismatch)
return
}
switch transport {
case .ble:
espBleTransport.SendConfigData(path: path, data: data) { response, error in
espBleTransport.SendConfigData(path: path, data: encryptedData) { response, error in
guard error == nil, response != nil else {
completionHandler(nil,.sendDataError(error!))
return
}
completionHandler(response,nil)
if let responseData = self.securityLayer.decrypt(data: response!) {
completionHandler(responseData, nil)
} else {
completionHandler(nil,.encryptionError)
}
}
default:
ESPLog.log("New SoftAp transport.")
espSoftApTransport.SendConfigData(path: path, data: data) { response, error in
guard error == nil, response != nil else {
espSoftApTransport.SendConfigData(path: path, data: encryptedData) { response, error in

if error != nil, response == nil {
if retryOnce, self.isNetworkDisconnected(error: error!) {
DispatchQueue.main.async {
ESPLog.log("Retrying sending data to custom path...")
self.connect { status in
switch status {
case .connected:
self.sendDataToDevice(path: path, data: data, retryOnce: false, completionHandler: completionHandler)
return
default:
completionHandler(nil,.sendDataError(error!))
return
}
}
}
}
else {
completionHandler(nil,.sendDataError(error!))
return
}
completionHandler(response,nil)
} else {
if let responseData = self.securityLayer.decrypt(data: response!) {
completionHandler(responseData, nil)
} else {
completionHandler(nil,.encryptionError)
}
}
}
}
}

Expand All @@ -239,13 +270,13 @@ public class ESPDevice {
if session == nil, !session.isEstablished {
completionHandler(.failure(.sessionError))
} else {
provisionDevice(ssid: ssid, passPhrase: passPhrase, completionHandler: completionHandler)
provisionDevice(ssid: ssid, passPhrase: passPhrase, retryOnce: true, completionHandler: completionHandler)
}


}

private func provisionDevice(ssid: String, passPhrase: String = "", completionHandler: @escaping (ESPProvisionStatus) -> Void) {
private func provisionDevice(ssid: String, passPhrase: String = "", retryOnce: Bool, completionHandler: @escaping (ESPProvisionStatus) -> Void) {
provision = ESPProvision(session: session)
ESPLog.log("Configure wi-fi credentials in device.")
provision.configureWifi(ssid: ssid, passphrase: passPhrase) { status, error in
Expand All @@ -258,6 +289,7 @@ public class ESPDevice {
completionHandler(.failure(.configurationError(error!)))
return
}
completionHandler(.configApplied)
}
},
wifiStatusUpdatedHandler: { wifiState, failReason, error in
Expand Down Expand Up @@ -286,8 +318,25 @@ public class ESPDevice {
}
})
default:
completionHandler(.failure(.wifiStatusUnknownError))
return
if error != nil, self.isNetworkDisconnected(error: error!) {
DispatchQueue.main.async {
self.connect { status in
switch status {
case .connected:
self.provisionDevice(ssid: ssid, passPhrase: passPhrase, retryOnce: false, completionHandler: completionHandler)
return
default:
completionHandler(.failure(.configurationError(error!)))
}
}
}
} else {
if let configError = error {
completionHandler(.failure(.configurationError(configError)))
return
}
completionHandler(.failure(.wifiStatusUnknownError))
}
}
}
}
Expand All @@ -302,13 +351,17 @@ public class ESPDevice {
/// - Parameter completionHandler: The completion handler that is called when Wi-Fi list is scanned.
/// Parameter of block include list of available Wi-Fi network or error in case of failure.
public func scanWifiList(completionHandler: @escaping ([ESPWifiNetwork]?,ESPWiFiScanError?) -> Void) {
retryScan = true
scanDeviceForWifiList(completionHandler: completionHandler)
}

private func scanDeviceForWifiList(completionHandler: @escaping ([ESPWifiNetwork]?,ESPWiFiScanError?) -> Void) {
self.wifiListCompletionHandler = completionHandler
let scanWifiManager: ESPWiFiManager = ESPWiFiManager(session: self.session!)
scanWifiManager.delegate = self
wifiListCompletionHandler = completionHandler
scanWifiManager.startWifiScan()
}

/// Initialise session with `ESPDevice`.
///
/// - Parameter completionHandler: The completion handler that is called when session is initalised
Expand Down Expand Up @@ -419,6 +472,15 @@ public class ESPDevice {
print(error)
}
}

private func isNetworkDisconnected(error: Error) -> Bool {
if let nserror = error as NSError? {
if nserror.code == -1005 {
return true
}
}
return false
}
}

extension ESPDevice: ESPScanWifiListProtocol {
Expand All @@ -427,11 +489,32 @@ extension ESPDevice: ESPScanWifiListProtocol {
wifiListCompletionHandler?(wifiResult,nil)
return
}
wifiListCompletionHandler?(nil,nil)
if retryScan {
self.retryScan = false
switch error {
case .scanRequestError(let requestError):
if isNetworkDisconnected(error: requestError) {
DispatchQueue.main.async {
self.connect { status in
switch status {
case .connected:
self.scanDeviceForWifiList(completionHandler: self.wifiListCompletionHandler!)
default:
self.wifiListCompletionHandler?(nil,error)
}
}
}
} else {
self.wifiListCompletionHandler?(nil,error)
}
default:
self.wifiListCompletionHandler?(nil,error)
}
} else {
self.wifiListCompletionHandler?(nil,error)
}
}
}


}

extension ESPDevice: ESPBLEStatusDelegate {
func peripheralConnected() {
Expand Down
2 changes: 1 addition & 1 deletion ESPProvision/ESPProvisionManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ public class ESPProvisionManager: NSObject, AVCaptureMetadataOutputObjectsDelega
extension ESPProvisionManager: ESPBLETransportDelegate {
func peripheralsFound(peripherals: [CBPeripheral]) {

ESPLog.log("Ble devices found.")
ESPLog.log("Ble devices found :\(peripherals)")

espDevices.removeAll()
for peripehral in peripherals {
Expand Down
10 changes: 8 additions & 2 deletions ESPProvision/Transport/ESPSoftAPTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
//

import Foundation
import Network

import NetworkExtension

Expand All @@ -26,6 +27,7 @@ class ESPSoftAPTransport: ESPCommunicable {

/// Instance of `ESPUtility`.
var utility: ESPUtility
var session:URLSession

/// Check device configuration status.
///
Expand All @@ -43,6 +45,9 @@ class ESPSoftAPTransport: ESPCommunicable {
init(baseUrl: String) {
self.baseUrl = baseUrl
utility = ESPUtility()
let config = URLSessionConfiguration.default
config.allowsCellularAccess = false
session = URLSession(configuration: config)
}

/// Implementation of generic HTTP Request.
Expand All @@ -62,10 +67,11 @@ class ESPSoftAPTransport: ESPCommunicable {

request.httpMethod = "POST"
request.httpBody = data
request.timeoutInterval = 30

ESPLog.log("URLSession request initiated...")
ESPLog.log("URLSession request initiated with data...\(data)")

let task = URLSession.shared.dataTask(with: request) { data, response, error in
let task = session.dataTask(with: request) { data, response, error in
ESPLog.log("Processing response..")
guard let data = data, error == nil else {
ESPLog.log("Error occured on HTTP request. Error: \(error.debugDescription)")
Expand Down
12 changes: 12 additions & 0 deletions ESPProvision/Utility/ESPErrors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ public enum ESPSessionError: ESPError {
case versionInfoError(Error)
/// The attempt to connect with ESPDevice of bluetooth capability failed.
case bleFailedToConnect
/// Encryption error
case encryptionError

public var description: String {
switch self {
Expand All @@ -96,6 +98,8 @@ public enum ESPSessionError: ESPError {
return "Failed to get device version information with error: \(error.localizedDescription)"
case .bleFailedToConnect:
return "Failed to connect with BLE device"
case .encryptionError:
return "Unable to encrypt data"
}
}

Expand All @@ -115,6 +119,8 @@ public enum ESPSessionError: ESPError {
return 16
case .bleFailedToConnect:
return 17
case .encryptionError:
return 18
}
}
}
Expand Down Expand Up @@ -200,6 +206,8 @@ public enum ESPProvisionError: ESPError {
case wifiStatusNetworkNotFound
/// Wi-Fi status of ESPDevice is unknown.
case wifiStatusUnknownError
/// Unkown error
case unknownError

public var description: String {
switch self {
Expand All @@ -217,6 +225,8 @@ public enum ESPProvisionError: ESPError {
return "Wi-Fi status netowrk not found"
case .wifiStatusUnknownError:
return "Wi-Fi status unknown error"
case .unknownError:
return "Unknown error"
}
}

Expand All @@ -236,6 +246,8 @@ public enum ESPProvisionError: ESPError {
return 36
case .wifiStatusUnknownError:
return 37
case .unknownError:
return 38
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Podfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
# platform :ios, '11.0'

target 'ESPProvision' do
# Comment the next line if you don't want to use dynamic frameworks
Expand Down

0 comments on commit f0ee7e5

Please sign in to comment.