Complete rebase

This commit is contained in:
Milan Stute
2021-03-11 08:57:44 +01:00
parent cbb85d97d0
commit f7d9a17587
10 changed files with 90 additions and 71 deletions
@@ -8,7 +8,6 @@
import Combine
import Foundation
import SwiftUI
import Combine
class AccessoryController: ObservableObject {
static let shared = AccessoryController()
@@ -16,9 +16,9 @@ struct ESP32Controller {
/// Tries to find the port / path at which the ESP32 module is attached
static func findPort() -> [URL] {
// List all ports
let ports = try? FileManager.default.contentsOfDirectory(atPath: "/dev").filter({$0.contains("cu.")})
let ports = try? FileManager.default.contentsOfDirectory(atPath: "/dev").filter({ $0.contains("cu.") })
let portURLs = ports?.map({URL(fileURLWithPath: "/dev/\($0)")})
let portURLs = ports?.map({ URL(fileURLWithPath: "/dev/\($0)") })
return portURLs ?? []
}
@@ -33,7 +33,7 @@ struct ESP32Controller {
try? FileManager.default.createDirectory(atPath: temp, withIntermediateDirectories: false, attributes: nil)
guard let espDirectory = espFirmwareDirectory else {return}
guard let espDirectory = espFirmwareDirectory else { return }
try FileManager.default.copyFolder(from: espDirectory, to: urlTemp)
let scriptPath = urlTemp.appendingPathComponent("flash_esp32.sh")
@@ -61,6 +61,6 @@ struct ESP32Controller {
enum FirmwareFlashError: Error {
/// Missing files for flashing
case notFound
/// Flashing / writing failed
/// Flashing / writing failed
case flashFailed
}
@@ -17,7 +17,7 @@ struct KeychainController {
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY",
kSecMatchLimit: kSecMatchLimitOne,
kSecReturnData: true
kSecReturnData: true,
]
if test {
@@ -49,7 +49,7 @@ struct KeychainController {
kSecClass: kSecClassGenericPassword,
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY",
kSecValueData: try PropertyListEncoder().encode(accessories)
kSecValueData: try PropertyListEncoder().encode(accessories),
]
if test {
@@ -63,7 +63,7 @@ struct KeychainController {
var query: [CFString: Any] = [
kSecClass: kSecClassGenericPassword,
kSecAttrLabel: "FindMyAccessories",
kSecAttrService: "SEEMOO-FINDMY"
kSecAttrService: "SEEMOO-FINDMY",
]
if test {
@@ -44,7 +44,8 @@ class Accessory: ObservableObject, Codable, Identifiable, Equatable, Hashable {
if var colorComponents = try? container.decode([CGFloat].self, forKey: .colorComponents),
let spaceName = try? container.decode(String.self, forKey: .colorSpaceName),
let cgColor = CGColor(colorSpace: CGColorSpace(name: spaceName as CFString)!, components: &colorComponents) {
let cgColor = CGColor(colorSpace: CGColorSpace(name: spaceName as CFString)!, components: &colorComponents)
{
self.color = Color(cgColor)
} else {
self.color = Color.white
@@ -60,7 +61,8 @@ class Accessory: ObservableObject, Codable, Identifiable, Equatable, Hashable {
try container.encode(self.icon, forKey: .icon)
if let colorComponents = self.color.cgColor?.components,
let colorSpace = self.color.cgColor?.colorSpace?.name {
let colorSpace = self.color.cgColor?.colorSpace?.name
{
try container.encode(colorComponents, forKey: .colorComponents)
try container.encode(colorSpace as String, forKey: .colorSpaceName)
}
@@ -6,8 +6,8 @@
// Copyright © 2021 SEEMOO - TU Darmstadt. All rights reserved.
//
import SwiftUI
import OSLog
import SwiftUI
struct ESP32InstallSheet: View {
@Binding var accessory: Accessory?
@@ -44,13 +44,17 @@ struct ESP32InstallSheet: View {
HStack {
Spacer()
Button("Reload ports", action: {
self.detectedPorts = ESP32Controller.findPort()
})
Button(
"Reload ports",
action: {
self.detectedPorts = ESP32Controller.findPort()
})
Button("Cancel", action: {
self.presentationMode.wrappedValue.dismiss()
})
Button(
"Cancel",
action: {
self.presentationMode.wrappedValue.dismiss()
})
}
}
}
@@ -59,20 +63,23 @@ struct ESP32InstallSheet: View {
ScrollView {
VStack(spacing: 4) {
ForEach(0..<self.detectedPorts.count, id: \.self) { portIdx in
Button(action: {
if let accessory = self.accessory {
// Flash selected module
self.deployAccessoryToESP32(accessory: accessory, to: self.detectedPorts[portIdx])
}
}, label: {
HStack {
Text(self.detectedPorts[portIdx].path)
.padding(4)
Spacer()
}
.contentShape(Rectangle())
Button(
action: {
if let accessory = self.accessory {
// Flash selected module
self.deployAccessoryToESP32(accessory: accessory, to: self.detectedPorts[portIdx])
}
},
label: {
HStack {
Text(self.detectedPorts[portIdx].path)
.padding(4)
Spacer()
}
.contentShape(Rectangle())
})
}
)
.buttonStyle(PlainButtonStyle())
}
}
@@ -98,19 +105,21 @@ struct ESP32InstallSheet: View {
func deployAccessoryToESP32(accessory: Accessory, to port: URL) {
do {
self.isFlashing = true
try ESP32Controller.flashToESP32(accessory: accessory, port: port, completion: { result in
presentationMode.wrappedValue.dismiss()
try ESP32Controller.flashToESP32(
accessory: accessory, port: port,
completion: { result in
presentationMode.wrappedValue.dismiss()
self.isFlashing = false
switch result {
case .success(_):
self.alertType = .deployedSuccessfully
case .failure(let error):
os_log(.error, "Flashing to ESP32 failed %@", String(describing: error))
self.presentationMode.wrappedValue.dismiss()
self.alertType = .deployFailed
}
})
self.isFlashing = false
switch result {
case .success:
self.alertType = .deployedSuccessfully
case .failure(let error):
os_log(.error, "Flashing to ESP32 failed %@", String(describing: error))
self.presentationMode.wrappedValue.dismiss()
self.alertType = .deployFailed
}
})
} catch {
os_log(.error, "Execution of script failed %@", String(describing: error))
self.presentationMode.wrappedValue.dismiss()
@@ -41,9 +41,17 @@ struct ManageAccessoriesView: View {
self.accessoryList
}
}
.sheet(isPresented: self.$showESP32DeploySheet, content: {
ESP32InstallSheet(accessory: self.$accessoryToDeploy, alertType: self.$alertType)
.toolbar(content: {
Spacer()
Button(action: self.addAccessory) {
Label("Add accessory", systemImage: "plus")
}
})
.sheet(
isPresented: self.$showESP32DeploySheet,
content: {
ESP32InstallSheet(accessory: self.$accessoryToDeploy, alertType: self.$alertType)
})
}
/// Accessory List view.
@@ -65,10 +73,11 @@ struct ManageAccessoriesView: View {
),
alertType: self.$alertType,
delete: self.delete(accessory:),
deployAccessoryToMicrobit: self.deployAccessoryToMicrobit(accessory:),
deployAccessoryToMicrobit: self.deploy(accessory:),
zoomOn: { self.focusedAccessory = $0 })
}
.listStyle(SidebarListStyle())
}
/// Delete an accessory from the list of accessories.
@@ -91,9 +100,7 @@ struct ManageAccessoriesView: View {
self.keyName = ""
do {
let accessory = try self.accessoryController.addAccessory(with: keyName, color: self.accessoryColor, icon: self.selectedIcon)
self.deploy(accessory: accessory)
_ = try self.accessoryController.addAccessory(with: keyName, color: self.accessoryColor, icon: self.selectedIcon)
} catch {
self.alertType = .keyError
}
@@ -25,7 +25,7 @@ struct OpenHaystackMainView: View {
@State var searchPartyTokenLoaded = false
@State var mapType: MKMapType = .standard
@State var isLoading = false
@State var focusedAccessory: Accessory? = nil
@State var focusedAccessory: Accessory?
@State var accessoryToDeploy: Accessory?
@State var showESP32DeploySheet = false
@@ -38,13 +38,8 @@ struct OpenHaystackMainView: View {
alertType: self.$alertType,
focusedAccessory: self.$focusedAccessory,
accessoryToDeploy: self.$accessoryToDeploy,
showESP32DeploySheet: self.$showESP32DeploySheet)
.toolbar(content: {
Spacer()
Button(action: self.addAccessory) {
Label("Add accessory", systemImage: "plus")
}
})
showESP32DeploySheet: self.$showESP32DeploySheet
)
.navigationTitle(self.focusedAccessory?.name ?? "OpenHaystack")
ZStack {
@@ -137,7 +132,8 @@ struct OpenHaystackMainView: View {
/// Checks if the search party token can be fetched without the Mail Plugin. If true the plugin is not needed for this environment. (e.g. when SIP is disabled)
let reportsFetcher = ReportsFetcher()
if let token = reportsFetcher.fetchSearchpartyToken(),
let tokenString = String(data: token, encoding: .ascii) {
let tokenString = String(data: token, encoding: .ascii)
{
self.searchPartyToken = tokenString
return
}
@@ -334,16 +330,19 @@ struct OpenHaystackMainView: View {
self.downloadPlugin()
}), secondaryButton: .cancel())
case .selectDepoyTarget:
let microbitButton = Alert.Button.default(Text("Microbit"), action: {self.deployAccessoryToMicrobit(accessory: self.accessoryToDeploy!)})
let microbitButton = Alert.Button.default(Text("Microbit"), action: { self.deployAccessoryToMicrobit(accessory: self.accessoryToDeploy!) })
let esp32Button = Alert.Button.default(Text("ESP32"), action: {
self.showESP32DeploySheet = true
})
let esp32Button = Alert.Button.default(
Text("ESP32"),
action: {
self.showESP32DeploySheet = true
})
return Alert(title: Text("Select target"),
message: Text("Please select to which device you want to deploy"),
primaryButton: microbitButton,
secondaryButton: esp32Button)
return Alert(
title: Text("Select target"),
message: Text("Please select to which device you want to deploy"),
primaryButton: microbitButton,
secondaryButton: esp32Button)
}
}