diff --git a/Meshtastic/Helpers/MeshPackets.swift b/Meshtastic/Helpers/MeshPackets.swift index 83cb25db..7c8ceb7f 100644 --- a/Meshtastic/Helpers/MeshPackets.swift +++ b/Meshtastic/Helpers/MeshPackets.swift @@ -192,29 +192,43 @@ func deviceMetadataPacket (metadata: DeviceMetadata, fromNum: Int64, context: NS guard let fetchedNode = try context.fetch(fetchedNodeRequest) as? [NodeInfoEntity] else { return } + let newMetadata = DeviceMetadataEntity(context: context) + newMetadata.deviceStateVersion = Int32(metadata.deviceStateVersion) + newMetadata.canShutdown = metadata.canShutdown + newMetadata.hasWifi = metadata.hasWifi_p + newMetadata.hasBluetooth = metadata.hasBluetooth_p + newMetadata.hasEthernet = metadata.hasEthernet_p + newMetadata.role = Int32(metadata.role.rawValue) + newMetadata.positionFlags = Int32(metadata.positionFlags) + // Swift does strings weird, this does work to get the version without the github hash + let lastDotIndex = metadata.firmwareVersion.lastIndex(of: ".") + var version = metadata.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: metadata.firmwareVersion))] + version = version.dropLast() + newMetadata.firmwareVersion = String(version) if fetchedNode.count > 0 { - let newMetadata = DeviceMetadataEntity(context: context) - newMetadata.deviceStateVersion = Int32(metadata.deviceStateVersion) - newMetadata.canShutdown = metadata.canShutdown - newMetadata.hasWifi = metadata.hasWifi_p - newMetadata.hasBluetooth = metadata.hasBluetooth_p - newMetadata.hasEthernet = metadata.hasEthernet_p - newMetadata.role = Int32(metadata.role.rawValue) - newMetadata.positionFlags = Int32(metadata.positionFlags) - // Swift does strings weird, this does work to get the version without the github hash - let lastDotIndex = metadata.firmwareVersion.lastIndex(of: ".") - var version = metadata.firmwareVersion[...(lastDotIndex ?? String.Index(utf16Offset: 6, in: metadata.firmwareVersion))] - version = version.dropLast() - newMetadata.firmwareVersion = String(version) fetchedNode[0].metadata = newMetadata - - do { - try context.save() - } catch { - print("Failed to save device metadata") - } - print("💾 Updated Device Metadata from Admin App Packet For: \(fromNum)") + } else { + + let newNode = NodeInfoEntity(context: context) + newNode.id = Int64(fromNum) + newNode.num = Int64(fromNum) + let newUser = UserEntity(context: context) + newUser.num = Int64(fromNum) + let userId = String(format:"%2X", fromNum) + newUser.userId = "!\(userId)" + let last4 = String(userId.suffix(4)) + newUser.longName = "Meshtastic \(last4)" + newUser.shortName = last4 + newUser.hwModel = "UNSET" + newNode.user = newUser + newNode.metadata = newMetadata } + do { + try context.save() + } catch { + print("Failed to save device metadata") + } + print("💾 Updated Device Metadata from Admin App Packet For: \(fromNum)") } catch { context.rollback() let nsError = error as NSError diff --git a/Meshtastic/Views/Settings/About.swift b/Meshtastic/Views/Settings/About.swift index 9bcb5b72..be1b4dc2 100644 --- a/Meshtastic/Views/Settings/About.swift +++ b/Meshtastic/Views/Settings/About.swift @@ -52,10 +52,6 @@ struct AboutMeshtastic: View { .font(.title2) Text("Version: \(Bundle.main.appVersionLong) (\(Bundle.main.appBuild)) ") - - Text(Bundle.main.copyright) - .font(.system(size: 10, weight: .thin)) - .multilineTextAlignment(.center) } Section(header: Text("Project information")) { diff --git a/Meshtastic/Views/Settings/Firmware.swift b/Meshtastic/Views/Settings/Firmware.swift index 7395af18..c7123198 100644 --- a/Meshtastic/Views/Settings/Firmware.swift +++ b/Meshtastic/Views/Settings/Firmware.swift @@ -15,6 +15,8 @@ struct Firmware: View { @State var minimumVersion = "2.2.17" @State var version = "" @State private var currentDevice: DeviceHardware? + @State private var latestStable: FirmwareRelease? + @State private var latestAlpha: FirmwareRelease? var body: some View { @@ -70,30 +72,55 @@ struct Firmware: View { .fixedSize(horizontal: false, vertical: true) .font(.title2) .padding(.bottom) + + Text("Get the latest stable firmware") + .fixedSize(horizontal: false, vertical: true) + .font(.callout) + Link("\(latestStable?.title ?? "unknown".localized)", destination: URL(string: "\(latestStable?.zipURL ?? "https://meshtastic.org")")!) + .font(.caption) + Link("Release Notes", destination: URL(string: "\(latestStable?.pageURL ?? "https://meshtastic.org")")!) + .font(.caption) + .padding(.bottom) + + Text("Get the latest alpha firmware") + .fixedSize(horizontal: false, vertical: true) + .font(.callout) + Link("\(latestAlpha?.title ?? "unknown".localized)", destination: URL(string: "\(latestAlpha?.zipURL ?? "https://meshtastic.org")")!) + .font(.caption) + Link("Release Notes", destination: URL(string: "\(latestAlpha?.pageURL ?? "https://meshtastic.org")")!) + .font(.caption) + .padding(.bottom) + if currentDevice?.architecture == Meshtastic.Architecture.nrf52840 { VStack(alignment: .leading) { - Text("Drag & Drop is the reccomended way to update firmware for NRF devices.") + Text("Drag & Drop is the reccomended way to update firmware for NRF devices. If your iPhone or iPad is USB-C it will work with your regular USB-C charging cable, for lightning devices you need the Apple Lightning to USB camera adaptor.") .fixedSize(horizontal: false, vertical: true) .foregroundStyle(.gray) .font(.caption) - Link("Drag & Drop Firmware Update", destination: URL(string: "https://meshtastic.org/docs/getting-started/flashing-firmware/nrf52/drag-n-drop")!) - .font(.callout) - - Button { - let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) - if connectedNode != nil { - if !bleManager.sendEnterDfuMode(fromUser: connectedNode!.user!, toUser: node!.user!) { - print("Enter DFU Failed") + Link("Drag & Drop Firmware Update Documentation", destination: URL(string: "https://meshtastic.org/docs/getting-started/flashing-firmware/nrf52/drag-n-drop")!) + .font(.caption) + .padding(.bottom) + VStack { + Text("If it is hard to access your device's reset button enter DFU mode here.") + .fixedSize(horizontal: false, vertical: true) + .foregroundStyle(.gray) + .font(.caption) + Button { + let connectedNode = getNodeInfo(id: bleManager.connectedPeripheral?.num ?? 0, context: context) + if connectedNode != nil { + if !bleManager.sendEnterDfuMode(fromUser: connectedNode!.user!, toUser: node!.user!) { + print("Enter DFU Failed") + } } + } label: { + Label("Enter DFU Mode", systemImage: "square.and.arrow.down") } - } label: { - Label("Enter DFU Mode", systemImage: "square.and.arrow.down") + .buttonStyle(.bordered) + .buttonBorderShape(.capsule) + .controlSize(.regular) + .padding(5) } - .buttonStyle(.bordered) - .buttonBorderShape(.capsule) - .controlSize(.regular) - .padding(5) Spacer() /// RAK 4631 if currentDevice?.hwModel == 9 { @@ -115,7 +142,7 @@ struct Firmware: View { 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.") + Text("Currently the reccomended way to update ESP32 devices is using the web flasher on a desktop computer from a chrome based browser. It does not work on mobile devices or over BLE.") .font(.caption) Link("Web Flasher", destination: URL(string: "https://flash.meshtastic.org")!) .font(.callout) @@ -151,52 +178,6 @@ struct Firmware: View { } } .padding() - VStack(alignment: .leading) { - // Text("Firmware Releases") - // .font(.title3) - // .padding([.leading, .trailing]) - // List { - // Section(header: Text("Stable")) { - // ForEach(firmwareReleaseData.releases?.stable ?? [], id: \.id) { fr in - // Link(destination: URL(string: fr.zipUrl ?? "")!) { - // HStack { - // Text(fr.title ?? "Unknown") - // .font(.caption) - // Spacer() - // Image(systemName: "square.and.arrow.down") - // .font(.title3) - // } - // } - // } - // } - // Section("Alpha") { - // ForEach(firmwareReleaseData.releases?.alpha ?? [], id: \.id) { fr in - // Link(destination: URL(string: fr.zipUrl ?? "")!) { - // HStack { - // Text(fr.title ?? "Unknown") - // .font(.caption) - // Spacer() - // Image(systemName: "square.and.arrow.down") - // .font(.title3) - // } - // } - // } - // } - // Section("Pull Requests") { - // ForEach(firmwareReleaseData.pullRequests ?? [], id: \.id) { fr in - // Link(destination: URL(string: fr.zipUrl ?? "")!) { - // HStack { - // Text(fr.title ?? "Unknown") - // .font(.caption) - // Spacer() - // Image(systemName: "square.and.arrow.down") - // .font(.title3) - // } - // } - // } - // } - // } - } .padding(.bottom, 5) .onAppear() { Api().loadDeviceHardwareData { (hw) in @@ -209,7 +190,8 @@ struct Firmware: View { } } Api().loadFirmwareReleaseData { (fw) in - + latestStable = fw.releases.stable.first + latestAlpha = fw.releases.alpha.first } } .navigationTitle("Firmware Updates") diff --git a/Meshtastic/Views/Settings/FirmwareApi.swift b/Meshtastic/Views/Settings/FirmwareApi.swift index ab480849..70fc1501 100644 --- a/Meshtastic/Views/Settings/FirmwareApi.swift +++ b/Meshtastic/Views/Settings/FirmwareApi.swift @@ -25,10 +25,10 @@ enum Architecture: String, Codable { struct FirmwareReleases: Codable { let releases: Releases - let pullRequests: [PullRequest] + let pullRequests: [FirmwareRelease] } -struct PullRequest: Codable { +struct FirmwareRelease: Codable { let id, title: String let pageURL: String let zipURL: String @@ -42,7 +42,7 @@ struct PullRequest: Codable { // MARK: - Releases struct Releases: Codable { - let stable, alpha: [PullRequest] + let stable, alpha: [FirmwareRelease] } class Api : ObservableObject{ @@ -68,7 +68,6 @@ class Api : ObservableObject{ } URLSession.shared.dataTask(with: url) { data, response, error in let firmwareReleases = try! JSONDecoder().decode(FirmwareReleases.self, from: data!) - print(firmwareReleases) DispatchQueue.main.async { completion(firmwareReleases) }