@@ -40,6 +40,7 @@ final class MeterViewModel: ObservableObject {
4040 @Published var isOK : Bool = false
4141
4242 private let ble = BLEManager ( )
43+ private let urlSession : URLSession
4344 private var fetchTimer : Timer ?
4445 private var bleTimer : Timer ?
4546 private var mdnsTask : Task < Void , Never > ?
@@ -103,10 +104,12 @@ final class MeterViewModel: ObservableObject {
103104 }
104105 }
105106
106- init ( ) {
107+ init ( urlSession: URLSession = . shared, startsDiscovery: Bool = true ) {
108+ self . urlSession = urlSession
107109 ble. onRefreshRequested = { [ weak self] in
108110 Task { @MainActor [ weak self] in await self ? . fetchUsage ( ) }
109111 }
112+ guard startsDiscovery else { return }
110113 // Start an async task to consume async discoveries stream
111114 mdnsTask = Task { [ weak self] in
112115 guard let self else { return }
@@ -255,37 +258,55 @@ final class MeterViewModel: ObservableObject {
255258 isFetching = true
256259 defer { isFetching = false }
257260
258- do {
259- var selectedJSON : String ?
260- var selectedStatusData : Data ?
261- for provider in UsageProviderKind . allCases {
261+ var selectedJSON : String ?
262+ var selectedStatusData : Data ?
263+ var selectedError : Error ?
264+
265+ for provider in UsageProviderKind . allCases {
266+ do {
262267 guard let result = try await fetchUsagePayload ( provider) else { continue }
263268 persist ( json: result. json, statusData: result. statusData, provider: provider)
264269 if provider == selectedProvider {
265270 selectedJSON = result. json
266271 selectedStatusData = result. statusData
267272 }
273+ } catch {
274+ if provider == selectedProvider {
275+ selectedError = error
276+ }
268277 }
278+ }
269279
270- guard let json = selectedJSON else {
271- errorMessage = " Cannot reach \( selectedProvider. title) server "
280+ guard let json = selectedJSON else {
281+ if hasCurrentPayload {
282+ errorMessage = nil
283+ await fetchDaemonStatus ( )
272284 return
273285 }
274- usageJSON = json
275- lastUpdate = Date ( )
276- errorMessage = nil
277-
278- parseJSON ( json)
279- if let selectedStatusData {
280- parseDaemonStatus ( selectedStatusData)
281- } else {
286+ if let selectedError {
287+ errorMessage = selectedError. localizedDescription
282288 await fetchDaemonStatus ( )
289+ } else {
290+ errorMessage = " Cannot reach \( selectedProvider. title) server "
283291 }
284- sendToBLE ( )
285- } catch {
286- errorMessage = error. localizedDescription
292+ return
293+ }
294+
295+ usageJSON = json
296+ lastUpdate = Date ( )
297+ errorMessage = nil
298+
299+ parseJSON ( json)
300+ if let selectedStatusData {
301+ parseDaemonStatus ( selectedStatusData)
302+ } else {
287303 await fetchDaemonStatus ( )
288304 }
305+ sendToBLE ( )
306+ }
307+
308+ private var hasCurrentPayload : Bool {
309+ usageJSON. trimmingCharacters ( in: . whitespacesAndNewlines) != " {} " || lastUpdate != nil
289310 }
290311
291312 private func fetchUsagePayload( _ provider: UsageProviderKind ) async throws -> ( json: String , statusData: Data ? ) ? {
@@ -294,7 +315,7 @@ final class MeterViewModel: ObservableObject {
294315
295316 var request = URLRequest ( url: usageURL)
296317 request. cachePolicy = . reloadIgnoringLocalAndRemoteCacheData
297- let ( data, response) = try await URLSession . shared . data ( for: request)
318+ let ( data, response) = try await urlSession . data ( for: request)
298319 guard let httpResponse = response as? HTTPURLResponse , httpResponse. statusCode == 200 else {
299320 return nil
300321 }
@@ -303,7 +324,7 @@ final class MeterViewModel: ObservableObject {
303324 if let statusURL = endpointURL ( " status " , base: base) {
304325 var statusRequest = URLRequest ( url: statusURL)
305326 statusRequest. cachePolicy = . reloadIgnoringLocalAndRemoteCacheData
306- let ( data, response) = try await URLSession . shared . data ( for: statusRequest)
327+ let ( data, response) = try await urlSession . data ( for: statusRequest)
307328 statusData = ( response as? HTTPURLResponse ) ? . statusCode == 200 ? data : nil
308329 } else {
309330 statusData = nil
@@ -359,7 +380,7 @@ final class MeterViewModel: ObservableObject {
359380 do {
360381 var request = URLRequest ( url: requestURL)
361382 request. cachePolicy = . reloadIgnoringLocalAndRemoteCacheData
362- let ( data, response) = try await URLSession . shared . data ( for: request)
383+ let ( data, response) = try await urlSession . data ( for: request)
363384 guard let httpResponse = response as? HTTPURLResponse , httpResponse. statusCode == 200 else { return }
364385 parseDaemonStatus ( data)
365386 } catch {
0 commit comments