mirror of
https://github.com/meshtastic/Meshtastic-Apple.git
synced 2026-04-20 22:13:56 +00:00
Add cal topo, wip firmware page
This commit is contained in:
parent
abe0dbb93d
commit
a3ef868802
7 changed files with 218 additions and 158 deletions
|
|
@ -29,6 +29,7 @@
|
|||
DD2553592855B52700E55709 /* PositionConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2553582855B52700E55709 /* PositionConfig.swift */; };
|
||||
DD2AD8A8296D2DF9001FF0E7 /* MapViewSwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2AD8A7296D2DF9001FF0E7 /* MapViewSwiftUI.swift */; };
|
||||
DD2DC2C029BCD8AB003B383C /* HardwareModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD2DC2BF29BCD8AB003B383C /* HardwareModels.swift */; };
|
||||
DD33DB622B3D27C7003E1EA0 /* FirmwareApi.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD33DB612B3D27C7003E1EA0 /* FirmwareApi.swift */; };
|
||||
DD3501892852FC3B000FC853 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3501882852FC3B000FC853 /* Settings.swift */; };
|
||||
DD3619152B1EF9F900C41C8C /* LocationsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3619142B1EF9F900C41C8C /* LocationsHandler.swift */; };
|
||||
DD3CC6B528E33FD100FA9159 /* ShareChannels.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD3CC6B428E33FD100FA9159 /* ShareChannels.swift */; };
|
||||
|
|
@ -247,6 +248,8 @@
|
|||
DD2AD8A7296D2DF9001FF0E7 /* MapViewSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewSwiftUI.swift; sourceTree = "<group>"; };
|
||||
DD2CC2E52ABFE04E00EDFDA7 /* MeshtasticDataModelV19.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV19.xcdatamodel; sourceTree = "<group>"; };
|
||||
DD2DC2BF29BCD8AB003B383C /* HardwareModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HardwareModels.swift; sourceTree = "<group>"; };
|
||||
DD33DB602B3D1ECC003E1EA0 /* MeshtasticDataModelV 23.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "MeshtasticDataModelV 23.xcdatamodel"; sourceTree = "<group>"; };
|
||||
DD33DB612B3D27C7003E1EA0 /* FirmwareApi.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirmwareApi.swift; sourceTree = "<group>"; };
|
||||
DD3501882852FC3B000FC853 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
|
||||
DD3619132B1EE20700C41C8C /* MeshtasticDataModelV21.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV21.xcdatamodel; sourceTree = "<group>"; };
|
||||
DD3619142B1EF9F900C41C8C /* LocationsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationsHandler.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -550,6 +553,7 @@
|
|||
DDE9659B2B1C3B6A00531070 /* RouteRecorder.swift */,
|
||||
DDA0B6B1294CDC55001356EC /* Channels.swift */,
|
||||
DDD6EEAE29BC024700383354 /* Firmware.swift */,
|
||||
DD33DB612B3D27C7003E1EA0 /* FirmwareApi.swift */,
|
||||
DD8169FA271F1F3A00F4AB02 /* MeshLog.swift */,
|
||||
DD86D40B287F401000BAEB7A /* SaveChannelQRCode.swift */,
|
||||
DD3501882852FC3B000FC853 /* Settings.swift */,
|
||||
|
|
@ -1190,6 +1194,7 @@
|
|||
DDDB444A29F8AA3A00EE2349 /* CLLocationCoordinate2D.swift in Sources */,
|
||||
DD41582628582E9B009B0E59 /* DeviceConfig.swift in Sources */,
|
||||
DD007BAE2AA4E91200F5FA12 /* MyInfoEntityExtension.swift in Sources */,
|
||||
DD33DB622B3D27C7003E1EA0 /* FirmwareApi.swift in Sources */,
|
||||
DD3CC6B528E33FD100FA9159 /* ShareChannels.swift in Sources */,
|
||||
DD1BF2F92776FE2E008C8D2F /* UserMessageList.swift in Sources */,
|
||||
DD5E5207298EE33B00D21B61 /* connection_status.pb.swift in Sources */,
|
||||
|
|
@ -1790,6 +1795,7 @@
|
|||
DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */ = {
|
||||
isa = XCVersionGroup;
|
||||
children = (
|
||||
DD33DB602B3D1ECC003E1EA0 /* MeshtasticDataModelV 23.xcdatamodel */,
|
||||
DD295CE92B323ED9002CC4AC /* MeshtasticDataModelV22.xcdatamodel */,
|
||||
DD3619132B1EE20700C41C8C /* MeshtasticDataModelV21.xcdatamodel */,
|
||||
DDAB580B2B0D913500147258 /* MeshtasticDataModelV20.xcdatamodel */,
|
||||
|
|
@ -1813,7 +1819,7 @@
|
|||
DD5D0A9A2931AD6B00F7EA61 /* MeshtasticDataModelV2.xcdatamodel */,
|
||||
DD3CC6BB28E366DF00FA9159 /* MeshtasticDataModel.xcdatamodel */,
|
||||
);
|
||||
currentVersion = DD295CE92B323ED9002CC4AC /* MeshtasticDataModelV22.xcdatamodel */;
|
||||
currentVersion = DD33DB602B3D1ECC003E1EA0 /* MeshtasticDataModelV 23.xcdatamodel */;
|
||||
name = Meshtastic.xcdatamodeld;
|
||||
path = Meshtastic/Meshtastic.xcdatamodeld;
|
||||
sourceTree = "<group>";
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
|
|||
case proto = 2
|
||||
case txtmsg = 3
|
||||
case nmea = 4
|
||||
case caltopo = 5
|
||||
|
||||
var id: Int { self.rawValue }
|
||||
var description: String {
|
||||
|
|
@ -125,6 +126,8 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
|
|||
return "serial.mode.txtmsg".localized
|
||||
case .nmea:
|
||||
return "serial.mode.nmea".localized
|
||||
case .caltopo:
|
||||
return "serial.mode.caltopo".localized
|
||||
}
|
||||
}
|
||||
func protoEnumValue() -> ModuleConfig.SerialConfig.Serial_Mode {
|
||||
|
|
@ -141,6 +144,8 @@ enum SerialModeTypes: Int, CaseIterable, Identifiable {
|
|||
return ModuleConfig.SerialConfig.Serial_Mode.textmsg
|
||||
case .nmea:
|
||||
return ModuleConfig.SerialConfig.Serial_Mode.nmea
|
||||
case .caltopo:
|
||||
return ModuleConfig.SerialConfig.Serial_Mode.caltopo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -759,16 +759,15 @@ class BLEManager: NSObject, CBPeripheralDelegate, MqttClientProxyManagerDelegate
|
|||
if UserDefaults.provideLocation {
|
||||
let interval = UserDefaults.provideLocationInterval > 0 ? UserDefaults.provideLocationInterval : 30
|
||||
if positionTimer != nil {
|
||||
}
|
||||
positionTimer = Timer.scheduledTimer(timeInterval: TimeInterval(interval), target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
|
||||
if positionTimer != nil {
|
||||
RunLoop.current.add(positionTimer!, forMode: .common)
|
||||
positionTimer = Timer.scheduledTimer(timeInterval: TimeInterval(interval), target: self, selector: #selector(positionTimerFired), userInfo: context, repeats: true)
|
||||
if positionTimer != nil {
|
||||
RunLoop.current.add(positionTimer!, forMode: .common)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
case FROMNUM_UUID:
|
||||
print("🗞️ BLE (Notify) characteristic, value will be read next")
|
||||
|
|
|
|||
|
|
@ -309,6 +309,7 @@
|
|||
<attribute name="echo" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="enabled" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="mode" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="overrideConsoleSerialPort" optional="YES" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES"/>
|
||||
<attribute name="rxd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="timeout" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
<attribute name="txd" optional="YES" attributeType="Integer 32" defaultValueString="0" usesScalarValueType="YES"/>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,10 @@ struct SerialConfig: View {
|
|||
@State var txd = 0
|
||||
@State var baudRate = 0
|
||||
@State var timeout = 0
|
||||
@State var overrideConsoleSerialPort = false
|
||||
@State var mode = 0
|
||||
|
||||
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
|
|
@ -153,6 +156,7 @@ struct SerialConfig: View {
|
|||
sc.txd = UInt32(txd)
|
||||
sc.baud = SerialBaudRates(rawValue: baudRate)!.protoEnumValue()
|
||||
sc.timeout = UInt32(timeout)
|
||||
sc.overrideConsoleSerialPort = overrideConsoleSerialPort
|
||||
sc.mode = SerialModeTypes(rawValue: mode)!.protoEnumValue()
|
||||
|
||||
let adminMessageId = bleManager.saveSerialModuleConfig(config: sc, fromUser: connectedNode!.user!, toUser: node!.user!, adminIndex: connectedNode?.myInfo?.adminIndex ?? 0)
|
||||
|
|
@ -231,6 +235,13 @@ struct SerialConfig: View {
|
|||
if newTimeout != node!.serialConfig!.timeout { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: overrideConsoleSerialPort) { newOverrideConsoleSerialPort in
|
||||
|
||||
if node != nil && node!.serialConfig != nil {
|
||||
|
||||
if newOverrideConsoleSerialPort != node!.serialConfig!.overrideConsoleSerialPort { hasChanges = true }
|
||||
}
|
||||
}
|
||||
.onChange(of: mode) { newMode in
|
||||
|
||||
if node != nil && node!.serialConfig != nil {
|
||||
|
|
@ -248,6 +259,7 @@ struct SerialConfig: View {
|
|||
self.baudRate = Int(node?.serialConfig?.baudRate ?? 0)
|
||||
self.timeout = Int(node?.serialConfig?.timeout ?? 0)
|
||||
self.mode = Int(node?.serialConfig?.mode ?? 0)
|
||||
self.overrideConsoleSerialPort = false // node?.serialConfig?.overrideConsoleSerialPort ?? false
|
||||
self.hasChanges = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,13 @@ struct Firmware: View {
|
|||
@Environment(\.managedObjectContext) var context
|
||||
@EnvironmentObject var bleManager: BLEManager
|
||||
var node: NodeInfoEntity?
|
||||
@State var minimumVersion = "2.1.0"
|
||||
@State var minimumVersion = "2.2.16"
|
||||
@State var version = ""
|
||||
@State private var firmwareReleaseData: FirmwareRelease = FirmwareRelease()
|
||||
//var currentDevice: DeviceHardware
|
||||
|
||||
var body: some View {
|
||||
// NavigationSplitView {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
let hwModel: HardwareModels = HardwareModels.allCases.first(where: { $0.rawValue == node?.user?.hwModel ?? "UNSET" }) ?? HardwareModels.UNSET
|
||||
VStack(alignment: .leading) {
|
||||
Text("Current Version: \(bleManager.connectedVersion)")
|
||||
|
|
@ -91,166 +92,163 @@ struct Firmware: View {
|
|||
Text(hwModel.platform().description)
|
||||
.font(.title3)
|
||||
}
|
||||
}.padding()
|
||||
}
|
||||
Spacer()
|
||||
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)
|
||||
}
|
||||
}
|
||||
// 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
|
||||
for device in hw {
|
||||
if device.hwModelSlug == node?.user?.hwModel ?? "UNSET" {
|
||||
print("Selected: \(device)")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Api().loadFirmwareReleaseData { (bks) in
|
||||
// //sel = bks
|
||||
// }
|
||||
}
|
||||
.padding(.bottom, 5)
|
||||
.onAppear(perform: loadData)
|
||||
.navigationTitle("Firmware Updates")
|
||||
.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 = "Pull Requests"
|
||||
}
|
||||
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 )
|
||||
title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
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 )
|
||||
title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
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 )
|
||||
title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl )
|
||||
zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl )
|
||||
}
|
||||
init() {}
|
||||
}
|
||||
//struct FirmwareRelease: Codable {
|
||||
// var releases: Releases? = Releases()
|
||||
// var pullRequests: [PullRequests]? = []
|
||||
// enum CodingKeys: String, CodingKey {
|
||||
// case releases = "Releases"
|
||||
// case pullRequests = "Pull Requests"
|
||||
// }
|
||||
// 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 )
|
||||
// title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
// 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 )
|
||||
// title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
// 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 )
|
||||
// title = try values.decodeIfPresent(String.self, forKey: .title )
|
||||
// pageUrl = try values.decodeIfPresent(String.self, forKey: .pageUrl )
|
||||
// zipUrl = try values.decodeIfPresent(String.self, forKey: .zipUrl )
|
||||
// }
|
||||
// init() {}
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -6,3 +6,42 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct DeviceHardware: Codable {
|
||||
var hwModel: Int
|
||||
var hwModelSlug: String
|
||||
var platformioTarget: String
|
||||
var activelySupported: Bool
|
||||
var displayName: String
|
||||
}
|
||||
|
||||
class Api : ObservableObject{
|
||||
// @Published var devices = [DeviceHardware]()
|
||||
|
||||
func loadDeviceHardwareData(completion:@escaping ([DeviceHardware]) -> ()) {
|
||||
guard let url = URL(string: "https://api.meshtastic.org/resource/deviceHardware") else {
|
||||
print("Invalid url...")
|
||||
return
|
||||
}
|
||||
URLSession.shared.dataTask(with: url) { data, response, error in
|
||||
let deviceHardware = try! JSONDecoder().decode([DeviceHardware].self, from: data!)
|
||||
print(deviceHardware)
|
||||
DispatchQueue.main.async {
|
||||
completion(deviceHardware)
|
||||
}
|
||||
}.resume()
|
||||
}
|
||||
// func loadFirmwareReleaseData(completion:@escaping ([FirmwareRelease]) -> ()) {
|
||||
// guard let url = URL(string: "https://api.meshtastic.org/github/firmware/list") else {
|
||||
// print("Invalid url...")
|
||||
// return
|
||||
// }
|
||||
// URLSession.shared.dataTask(with: url) { data, response, error in
|
||||
// let deviceHardware = try! JSONDecoder().decode([FirmwareRelease].self, from: data!)
|
||||
// print(deviceHardware)
|
||||
// DispatchQueue.main.async {
|
||||
// completion(deviceHardware)
|
||||
// }
|
||||
// }.resume()
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue