mirror of
https://github.com/seemoo-lab/openhaystack.git
synced 2026-08-20 03:56:14 +00:00
Complete rebase
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user