diff --git a/Meshtastic/Enums/HardwareModels.swift b/Meshtastic/Enums/HardwareModels.swift index c7470424..7bdefd25 100644 --- a/Meshtastic/Enums/HardwareModels.swift +++ b/Meshtastic/Enums/HardwareModels.swift @@ -6,7 +6,7 @@ // import Foundation -// Default of 0 is Client + enum HardwareModels: String, CaseIterable, Identifiable { case UNSET @@ -184,3 +184,26 @@ enum HardwareModels: String, CaseIterable, Identifiable { } } } + + +enum HardwarePlatforms: String, CaseIterable, Identifiable { + + case ESP32 + case NRF52 + case STM32 + case PIPICO + var id: String { self.rawValue } + var description: String { + switch self { + + case .ESP32: + return "Expressif ESP 32" + case .NRF52: + return "Nordic NRF52" + case .STM32: + return "ARM STM 32" + case .PIPICO: + return "Raspberrry Pi Pico" + } + } +} diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift index c11398b4..b824b407 100644 --- a/Meshtastic/Views/Settings/Firmware.swift +++ b/Meshtastic/Views/Settings/Firmware.swift @@ -15,63 +15,86 @@ import SwiftUI import StoreKit struct Firmware: View { - + @Environment(\.managedObjectContext) var context @EnvironmentObject var bleManager: BLEManager - + var node: NodeInfoEntity? - + + @State var minimumVersion = "2.1.0" + @State var version = "" + @State private var firmwareReleaseData: FirmwareRelease = FirmwareRelease() - + var body: some View { // NavigationSplitView { NavigationStack { - + let hwModel: HardwareModels = HardwareModels.allCases.first(where: { $0.rawValue == node?.user?.hwModel ?? "UNSET" }) ?? HardwareModels.UNSET - Text(hwModel.firmwareStrings[0] + (node?.metadata?.firmwareVersion ?? "Unknown") ) - .font(.title3) + VStack(alignment: .leading) { - Text("nRF Device Firmware Update App") + Text("Firmware Version: \(node?.metadata?.firmwareVersion ?? "Unknown")") .font(.title3) - Text("You can update your Meshtastic device over bluetooth using the Nordic DFU app. This currently works for RAK NRF devices.") - .font(.caption) - Link("Get NRF DFU from the App Store", destination: URL(string: "https://apps.apple.com/us/app/nrf-device-firmware-update/id1624454660")!) + Text("Your device supports the following firmware: ") .font(.callout) - } - .padding([.leading, .trailing, .bottom]) - VStack(alignment: .leading) { - Text("ESP32 Device Firmware Update") - .font(.title3) - Text("Currently the reccomended way to update ESP32 devices is using the web flasher from a chrome based browser. It does not work on mobile devices or over BLE.") - .font(.caption) - Link("Web Flasher", destination: URL(string: "https://flasher.meshtastic.org")!) - .font(.callout) - .padding(.bottom) - Text("ESP 32 OTA update is a work in progress, click the button below to sent your device a reboot into ota admin message.") - .font(.caption) - HStack(alignment: .center) { - Spacer() - Button { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) - if connectedNode != nil { - if !bleManager.sendRebootOta(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex) { - print("Reboot Failed") - } else { - bleManager.disconnectPeripheral(reconnect: false) - } - } - } label: { - Label("Send Reboot OTA", systemImage: "square.and.arrow.down") + HStack { + ForEach(hwModel.firmwareStrings, id: \.self) { fs in + Text(fs).font(.callout) } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.regular) - .padding(5) - Spacer() } - } - .padding([.leading, .trailing, .bottom]) - .padding(.bottom, 5) + .padding(.bottom) + + if hwModel == HardwareModels.RAK4631 { + VStack(alignment: .leading) { + Text("nRF Device Firmware Update App") + .font(.title3) + Text("You can update your Meshtastic device over bluetooth using the Nordic DFU app. This currently works for RAK NRF devices.") + .font(.caption) + Link("Get NRF DFU from the App Store", destination: URL(string: "https://apps.apple.com/us/app/nrf-device-firmware-update/id1624454660")!) + .font(.callout) + } + } else if hwModel == HardwareModels.T_ECHO { + Text("OTA Updates are not supported on the this NRF Device.") + .font(.title3) + } else { + VStack(alignment: .leading) { + Text("ESP32 Device Firmware Update") + .font(.title3) + Text("Currently the reccomended way to update ESP32 devices is using the web flasher from a chrome based browser. It does not work on mobile devices or over BLE.") + .font(.caption) + Link("Web Flasher", destination: URL(string: "https://flasher.meshtastic.org")!) + .font(.callout) + .padding(.bottom) + Text("ESP 32 OTA update is a work in progress, click the button below to sent your device a reboot into ota admin message.") + .font(.caption) + HStack(alignment: .center) { + Spacer() + Button { + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral.num, context: context) + if connectedNode != nil { + if !bleManager.sendRebootOta(fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode!.myInfo!.adminIndex) { + print("Reboot Failed") + } else { + bleManager.disconnectPeripheral(reconnect: false) + } + } + } label: { + Label("Send Reboot OTA", systemImage: "square.and.arrow.down") + } + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.regular) + .padding(5) + Spacer() + } + } + } + }.padding() + + + + + VStack(alignment: .leading) { Text("Firmware Releases") .font(.title3) @@ -123,85 +146,85 @@ struct Firmware: View { .navigationBarTitleDisplayMode(.inline) } } - + func loadData() { - + guard let url = URL(string: "https://api.meshtastic.org/github/firmware/list") else { return } - + let request = URLRequest(url: url) URLSession.shared.dataTask(with: request) { data, _, _ in - + if let data = data { if let response_obj = try? JSONDecoder().decode(FirmwareRelease.self, from: data) { - + DispatchQueue.main.async { self.firmwareReleaseData = response_obj } } } - + }.resume() } } struct FirmwareRelease: Codable { - + var releases: Releases? = Releases() var pullRequests: [PullRequests]? = [] - + enum CodingKeys: String, CodingKey { - + case releases = "releases" case pullRequests = "pullRequests" } - + init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) - + releases = try values.decodeIfPresent(Releases.self, forKey: .releases ) pullRequests = try values.decodeIfPresent([PullRequests].self, forKey: .pullRequests ) } - + init() { - + } } struct Releases: Codable { - + var stable: [Stable]? = [] var alpha: [Alpha]? = [] - + enum CodingKeys: String, CodingKey { case stable = "stable" case alpha = "alpha" } - + init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) stable = try values.decodeIfPresent([Stable].self, forKey: .stable ) alpha = try values.decodeIfPresent([Alpha].self, forKey: .alpha ) } - + init() {} } struct Alpha: Codable { - + var id: String? var title: String? var pageUrl: String? var zipUrl: String? - + enum CodingKeys: String, CodingKey { case id = "id" case title = "title" case pageUrl = "page_url" case zipUrl = "zip_url" } - + init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) id = try values.decodeIfPresent(String.self, forKey: .id ) @@ -209,24 +232,24 @@ struct Alpha: Codable { pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) } - + init() {} } struct Stable: Codable { - + var id: String? var title: String? var pageUrl: String? var zipUrl: String? - + enum CodingKeys: String, CodingKey { case id = "id" case title = "title" case pageUrl = "page_url" case zipUrl = "zip_url" } - + init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) id = try values.decodeIfPresent(String.self, forKey: .id ) @@ -234,24 +257,24 @@ struct Stable: Codable { pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) } - + init() {} } struct PullRequests: Codable { - + var id: String? var title: String? var pageUrl: String? var zipUrl: String? - + enum CodingKeys: String, CodingKey { case id = "id" case title = "title" case pageUrl = "page_url" case zipUrl = "zip_url" } - + init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) id = try values.decodeIfPresent(String.self, forKey: .id ) @@ -259,6 +282,6 @@ struct PullRequests: Codable { pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl ) zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl ) } - + init() {} }