Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions PresentationLayer/Constants/Strings/DisplayedLinks.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ enum DisplayedLinks {
case m5Troubleshooting
case heliumTroubleshooting
case d1Troubleshooting
case pulseTroubleshooting
case heliumRegionFrequencies
case shopLink
case shareDevice
Expand Down Expand Up @@ -74,6 +75,8 @@ enum DisplayedLinks {
return "https://docs.weatherxm.com/wxm-devices/helium/troubleshooting"
case .d1Troubleshooting:
return "https://docs.weatherxm.com/wxm-devices/d1/troubleshooting"
case .pulseTroubleshooting:
return "https://docs.weatherxm.com/wxm-devices/pulse/troubleshooting"
case .heliumRegionFrequencies:
return "https://docs.helium.com/iot/lorawan-region-plans"
case .shopLink:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ extension DeviceDetails {
case .d1:
return DisplayedLinks.d1Troubleshooting.linkURL
case .pulse:
return nil
return DisplayedLinks.pulseTroubleshooting.linkURL
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
case .reboot:
return (LocalizableString.DeviceInfo.stationReboot.localized, nil)
case .maintenance:
#warning("TODO: Format when info is ready")

Check notice on line 32 in PresentationLayer/UIComponents/Screens/DeviceInfo/DeviceInfoFactory.swift

View check run for this annotation

Xcode Cloud / WeatherXM | Unit tests | wxm-ios - iOS

PresentationLayer/UIComponents/Screens/DeviceInfo/DeviceInfoFactory.swift#L32

TODO: Format when info is ready
return (LocalizableString.DeviceInfo.stationMaintenance("").localized, nil)
case .remove:
return (LocalizableString.DeviceInfo.stationRemove.localized, nil)
Expand Down Expand Up @@ -194,10 +194,15 @@
extension DeviceInfoViewModel.InfoField {
static func getShareText(for device: DeviceDetails, deviceInfo: NetworkDevicesInfoResponse?, mainVM: MainScreenViewModel, followState: UserDeviceFollowState?) -> String {
var fields: [Self] = []
if device.isHelium {
fields = heliumFields
} else {
fields = wifiFields
switch device.bundle?.connectivity {
case .wifi:
fields = wifiFields
case .helium:
fields = heliumFields
case .cellular:
fields = pulseFields
case nil:
break
}

let textComps: [String] = fields.compactMap { field in
Expand Down Expand Up @@ -286,6 +291,26 @@
return LocalizableString.DeviceInfo.lastStationActivity.localized
case .stationRssi:
return LocalizableString.DeviceInfo.stationRssi.localized
case .gsmSignal:
return LocalizableString.DeviceInfo.gsmSignal.localized
case .gwFrequency:
return LocalizableString.DeviceInfo.gwFrequency.localized
case .externalSim:
return LocalizableString.DeviceInfo.externalSim.localized
case .iccid:
return LocalizableString.DeviceInfo.iccid.localized
case .mobileCountryCode:
return LocalizableString.DeviceInfo.mobileCountryCode.localized
case .gwBatteryState:
return LocalizableString.DeviceInfo.gwBatteryState.localized
case .signalGwStation:
return LocalizableString.DeviceInfo.signalGwStation.localized
case .nextServerCommunication:
return LocalizableString.DeviceInfo.nextServerCommunication.localized
case .stationId:
return LocalizableString.DeviceInfo.stationId.localized
case .signalStationGw:
return LocalizableString.DeviceInfo.signalStationGw.localized
}
}

Expand Down Expand Up @@ -349,10 +374,43 @@
case .lastStationActivity:
return deviceInfo?.weatherStation?.lastActivity?.getFormattedDate(format: .monthLiteralYearDayTime,
timezone: device.timezone?.toTimezone ?? .current).capitalizedSentence
case .stationRssi:
case .stationRssi, .signalStationGw:
return Self.getRssiText(rssi: deviceInfo?.weatherStation?.stationRssi?.formatted(),
lastActivityDate: deviceInfo?.weatherStation?.stationRssiLastActivity,
timezone: device.timezone)
case .gsmSignal:
return Self.getRssiText(rssi: deviceInfo?.gateway?.networkRssi?.formatted(),
lastActivityDate: deviceInfo?.gateway?.networkRssiLastActivity,
timezone: device.timezone)
case .gwFrequency:
guard let frequency = deviceInfo?.gateway?.frequency else {
return nil
}
return "\(frequency) \(LocalizableString.Units.mhz.localized)"
case .externalSim:
guard deviceInfo?.gateway?.sim?.iccid != nil else {
return nil
}

return LocalizableString.DeviceInfo.isInUse.localized
case .iccid:
return deviceInfo?.gateway?.sim?.iccid
case .mobileCountryCode:
guard let mcc = deviceInfo?.gateway?.sim?.mcc, let mnc = deviceInfo?.gateway?.sim?.mnc else {
return nil
}
return LocalizableString.DeviceInfo.mobileCountryNetworkCode(mcc, mnc).localized
case .gwBatteryState:
return deviceInfo?.gateway?.batState?.description
case .signalGwStation:
return Self.getRssiText(rssi: deviceInfo?.gateway?.gatewayRssi?.formatted(),
lastActivityDate: deviceInfo?.gateway?.gatewayRssiLastActivity,
timezone: device.timezone)
case .nextServerCommunication:
return deviceInfo?.gateway?.nextCommunication?.getFormattedDate(format: .monthLiteralYearDayTime,
timezone: device.timezone?.toTimezone ?? .current).capitalizedSentence
case .stationId:
return deviceInfo?.weatherStation?.stationId
}
}

Expand Down Expand Up @@ -383,7 +441,7 @@
case .wifiSignal:
return nil
case .batteryState:
return warningForBatteryState(deviceInfo?.weatherStation?.batState, deviceId: device.id ?? "")
return warningForBatteryState(deviceInfo?.weatherStation?.batState, deviceId: device.id ?? "", isGateway: false)
case .claimedAt:
return nil
case .lastGatewayActivity:
Expand All @@ -393,11 +451,31 @@
case .lastStationActivity:
return nil
case .stationRssi:
return warningForStationRssi(for: deviceInfo?.weatherStation?.stationRssi)
return warningForStationRssi(for: deviceInfo?.weatherStation?.stationRssi, device: device)
case .gsmSignal:
return nil
case .gwFrequency:
return nil
case .externalSim:
return nil
case .iccid:
return nil
case .mobileCountryCode:
return nil
case .gwBatteryState:
return warningForBatteryState(deviceInfo?.gateway?.batState, deviceId: device.id ?? "", isGateway: true)
case .signalGwStation:
return nil
case .nextServerCommunication:
return nil
case .stationId:
return nil
case .signalStationGw:
return warningForStationRssi(for: deviceInfo?.weatherStation?.stationRssi, device: device)
}
}

func warningForBatteryState(_ state: BatteryState?, deviceId: String) -> (CardWarningConfiguration, VoidCallback)? {
func warningForBatteryState(_ state: BatteryState?, deviceId: String, isGateway: Bool) -> (CardWarningConfiguration, VoidCallback)? {
guard let state else {
return nil
}
Expand All @@ -409,16 +487,17 @@
.action: .viewAction,
.itemId: .custom(deviceId)])
}
let message = isGateway ? LocalizableString.DeviceInfo.gatewayLowBatteryWarningMarkdown : LocalizableString.DeviceInfo.lowBatteryWarningMarkdown
return (CardWarningConfiguration(type: .warning,
message: LocalizableString.DeviceInfo.lowBatteryWarningMarkdown.localized,
message: message.localized,
closeAction: nil),
callback)
case .ok:
return nil
}
}

func warningForStationRssi(for rssi: Int?) -> (CardWarningConfiguration, VoidCallback)? {
func warningForStationRssi(for rssi: Int?, device: DeviceDetails) -> (CardWarningConfiguration, VoidCallback)? {
guard let rssi else {
return nil
}
Expand All @@ -430,12 +509,12 @@
case _ where rssi >= -95:
return (CardWarningConfiguration(type: .warning,
message: LocalizableString.DeviceInfo.stationRssiWarning.localized,
linkText: LocalizableString.url(urlText, DisplayedLinks.troubleshooting.linkURL).localized,
linkText: LocalizableString.url(urlText, device.troubleShootingUrl ?? "").localized,
closeAction: nil), {})
default:
return (CardWarningConfiguration(type: .error,
message: LocalizableString.DeviceInfo.stationRssiError.localized,
linkText: LocalizableString.url(urlText, DisplayedLinks.troubleshooting.linkURL).localized,
linkText: LocalizableString.url(urlText, device.troubleShootingUrl ?? "").localized,
closeAction: nil), {})
}
}
Expand Down Expand Up @@ -482,6 +561,26 @@
return nil
case .stationRssi:
return nil
case .gsmSignal:
return nil
case .gwFrequency:
return nil
case .externalSim:
return nil
case .iccid:
return nil
case .mobileCountryCode:
return nil
case .gwBatteryState:
return nil
case .signalGwStation:
return nil
case .nextServerCommunication:
return nil
case .stationId:
return nil
case .signalStationGw:
return nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,14 @@ extension DeviceInfoViewModel {
enum InfoField {
case name
case bundleName
case gsmSignal
case gwFrequency
case externalSim
case iccid
case mobileCountryCode
case gwBatteryState
case signalGwStation
case nextServerCommunication
case devEUI
case gatewayModel
case hardwareVersion
Expand All @@ -105,6 +113,8 @@ extension DeviceInfoViewModel {
case stationModel
case lastStationActivity
case stationRssi
case stationId
case signalStationGw

static var heliumFields: [InfoField] {
[.name, .bundleName, .stationModel, .claimedAt, .devEUI, .firmwareVersion, .hardwareVersion, .batteryState, .lastHotspot, .lastRSSI, .lastStationActivity]
Expand All @@ -127,5 +137,24 @@ extension DeviceInfoViewModel {
static var wifiStationDetailsInfoFields: [InfoField] {
[.stationModel, .hardwareVersion, .stationRssi, .batteryState, .lastStationActivity]
}

static var pulseFields: [InfoField] {
[pulseInfoFields,
pulseGatewayDetailsInfoFields,
pulseStationDetailsInfoFields].flatMap { $0 }
}

static var pulseInfoFields: [InfoField] {
[.name, .bundleName, .claimedAt]
}

static var pulseGatewayDetailsInfoFields: [InfoField] {
[.gatewayModel, .serialNumber, .gsmSignal, .gwFrequency, .externalSim, .iccid, .mobileCountryCode, .firmwareVersion, .gwBatteryState, .lastGatewayActivity, .signalGwStation, .nextServerCommunication]
}

static var pulseStationDetailsInfoFields: [InfoField] {
[.stationModel, .stationId, .batteryState, .hardwareVersion, .signalStationGw, .lastStationActivity]
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,21 @@
}

var infoSections: [StationInfoView.Section] {
if device.isHelium {
return [getInfoSection(title: nil, fields: InfoField.heliumFields)]
} else {
let sections: [StationInfoView.Section] = [getInfoSection(title: nil, fields: InfoField.wifiInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.gatewayDetails.localized, fields: InfoField.wifiGatewayDetailsInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.stationDetails.localized, fields: InfoField.wifiStationDetailsInfoFields)]
return sections
switch device.bundle?.connectivity {
case .wifi:
let sections: [StationInfoView.Section] = [getInfoSection(title: nil, fields: InfoField.wifiInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.gatewayDetails.localized, fields: InfoField.wifiGatewayDetailsInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.stationDetails.localized, fields: InfoField.wifiStationDetailsInfoFields)]
return sections
case .helium:
return [getInfoSection(title: nil, fields: InfoField.heliumFields)]
case .cellular:
let sections: [StationInfoView.Section] = [getInfoSection(title: nil, fields: InfoField.pulseInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.gatewayDetails.localized, fields: InfoField.pulseGatewayDetailsInfoFields),
getInfoSection(title: LocalizableString.DeviceInfo.stationDetails.localized, fields: InfoField.pulseStationDetailsInfoFields)]
return sections
case nil:
return []
}
}

Expand Down Expand Up @@ -179,7 +187,7 @@
}

Task { @MainActor [weak self] in
let photosError = await self?.photoStateViewModel?.refresh()

Check notice on line 190 in PresentationLayer/UIComponents/Screens/DeviceInfo/DeviceInfoViewModel.swift

View check run for this annotation

Xcode Cloud / WeatherXM | Unit tests | wxm-ios - iOS

PresentationLayer/UIComponents/Screens/DeviceInfo/DeviceInfoViewModel.swift#L190

Initialization of immutable value 'photosError' was never used; consider replacing with assignment to '_' or removing it

do {
let response = try await self?.deviceInfoUseCase?.getDeviceInfo(deviceId: deviceId).toAsync()
Expand Down Expand Up @@ -316,6 +324,26 @@
break
case .stationRssi:
break
case .gsmSignal:
break
case .gwFrequency:
break
case .externalSim:
break
case .iccid:
break
case .mobileCountryCode:
break
case .gwBatteryState:
break
case .signalGwStation:
break
case .nextServerCommunication:
break
case .stationId:
break
case .signalStationGw:
break
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
device.bundle = .mock(name: .d1)
#expect(device.troubleShootingUrl == DisplayedLinks.d1Troubleshooting.linkURL)
device.bundle = .mock(name: .pulse)
#expect(device.troubleShootingUrl == nil)
#expect(device.troubleShootingUrl == DisplayedLinks.pulseTroubleshooting.linkURL)
device.bundle = nil
#expect(device.troubleShootingUrl == nil)
}
Expand Down Expand Up @@ -121,7 +121,7 @@

@Test
func testNeedsUpdate() {
var device = DeviceDetails.mockDevice

Check notice on line 124 in WeatherXMTests/PresentationLayer/Extensions/DomainExtensions/DeviceDetailsTests.swift

View check run for this annotation

Xcode Cloud / WeatherXM | Unit tests | wxm-ios - iOS

WeatherXMTests/PresentationLayer/Extensions/DomainExtensions/DeviceDetailsTests.swift#L124

Variable 'device' was never mutated; consider changing to 'let' constant
let now = Date()
let persisted = FirmwareVersion(installDate: now, version: "1.0.1")
// Same version, just installed, should not need update
Expand Down
4 changes: 4 additions & 0 deletions wxm-ios/DataLayer/DataLayer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
26DF1F542D549A310001E936 /* FileUploadMockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26DF1F532D549A310001E936 /* FileUploadMockProtocol.swift */; };
26DF1F602D5611EA0001E936 /* post_login.json in Resources */ = {isa = PBXBuildFile; fileRef = 26DF1F5F2D5611DD0001E936 /* post_login.json */; };
26E2B3BC2982754D00ED9B58 /* MockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E2B3BB2982754D00ED9B58 /* MockProtocol.swift */; };
26E558432E8E8A9D00E834CC /* get_device_info_pulse.json in Resources */ = {isa = PBXBuildFile; fileRef = 26E558422E8E8A8D00E834CC /* get_device_info_pulse.json */; };
26E88B2F29E5717D0023BBD5 /* DatabaseService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E88B2E29E5717D0023BBD5 /* DatabaseService.swift */; };
26E88B3429E582070023BBD5 /* DBWeather+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E88B3329E582070023BBD5 /* DBWeather+CoreDataClass.swift */; };
26E88B3529E582070023BBD5 /* DBWeather+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26E88B3229E582070023BBD5 /* DBWeather+CoreDataProperties.swift */; };
Expand Down Expand Up @@ -183,6 +184,7 @@
26DF1F532D549A310001E936 /* FileUploadMockProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUploadMockProtocol.swift; sourceTree = "<group>"; };
26DF1F5F2D5611DD0001E936 /* post_login.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = post_login.json; sourceTree = "<group>"; };
26E2B3BB2982754D00ED9B58 /* MockProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockProtocol.swift; sourceTree = "<group>"; };
26E558422E8E8A8D00E834CC /* get_device_info_pulse.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = get_device_info_pulse.json; sourceTree = "<group>"; };
26E88B2E29E5717D0023BBD5 /* DatabaseService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseService.swift; sourceTree = "<group>"; };
26E88B3229E582070023BBD5 /* DBWeather+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DBWeather+CoreDataProperties.swift"; sourceTree = "<group>"; };
26E88B3329E582070023BBD5 /* DBWeather+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DBWeather+CoreDataClass.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -264,6 +266,7 @@
2618A6F02A1F61FD00983B7B /* get_device_history_24_samples.json */,
2646D8E729C8B4310000237F /* get_device_info_helium.json */,
2646D8E929C8B8CA0000237F /* get_device_info_m5.json */,
26E558422E8E8A8D00E834CC /* get_device_info_pulse.json */,
26348E262A4456DD000846C6 /* get_network_search.json */,
26ACE8EE2C883BF400EA22DD /* get_devices_rewards_analytics.json */,
26AD3EA52C90748C0040AB09 /* get_devices_rewards_analytics_7d.json */,
Expand Down Expand Up @@ -598,6 +601,7 @@
2646D8EA29C8B8CA0000237F /* get_device_info_m5.json in Resources */,
26348E272A4456DD000846C6 /* get_network_search.json in Resources */,
2674017A2A386DA700E54E35 /* get_network_stats.json in Resources */,
26E558432E8E8A9D00E834CC /* get_device_info_pulse.json in Resources */,
2674EDCE2A3C4C3800616285 /* get_network_stats_alt.json in Resources */,
264CC75D2B986F310060DEA4 /* get_reward_boosts.json in Resources */,
26AD3E9C2C8F3F4C0040AB09 /* get_device_rewards_analytics_year.json in Resources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ extension MeApiRequestBuilder: MockResponseBuilder {
case .getUserDeviceHistoryById:
return "get_device_history"
case .getUserDeviceInfoById:
return "get_device_info_m5"
return "get_device_info_pulse"
case .getUserWallet:
return "get_user_wallet"
case .getUserDeviceForecastById:
Expand Down
Loading
Loading