Commit f301fe0f by Dmitry Stepanets

Processing minutely API

parent 85443f4e
...@@ -3,54 +3,4 @@ ...@@ -3,54 +3,4 @@
uuid = "55281C35-FE9F-4CED-865E-FBED0E7393F6" uuid = "55281C35-FE9F-4CED-865E-FBED0E7393F6"
type = "0" type = "0"
version = "2.0"> version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "BD6801C5-CD0B-467D-9B94-1250A8FA6E1D"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "BlendMinutelySource/BlendMinutelySource/BlendMinutelySource.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "49"
endingLineNumber = "49"
landmarkName = "getMinutelyForecast(forLocation:completion:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "A2A04C12-64A5-4FC6-A9A4-2CECEE6DBFE9"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OneWeatherCore/OneWeatherCore/Model/LocationManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "378"
endingLineNumber = "378"
landmarkName = "updateMinutelyForecast(for:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "958DC1E7-7576-44D0-B8D7-5CD5ECB0CDC1"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "OneWeatherCore/OneWeatherCore/Model/LocationManager.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "318"
endingLineNumber = "318"
landmarkName = "updateEverythingIfNeeded()"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket> </Bucket>
...@@ -14,6 +14,7 @@ public enum BlendMinutelySourceError: Error { ...@@ -14,6 +14,7 @@ public enum BlendMinutelySourceError: Error {
case badServerResponse(Error?) case badServerResponse(Error?)
case dataEncodingError(String) case dataEncodingError(String)
case alreadyBeingUpdated case alreadyBeingUpdated
case invalidParameters
} }
public class BlendMinutelySource: MinutelyForecastSource { public class BlendMinutelySource: MinutelyForecastSource {
...@@ -32,9 +33,19 @@ public class BlendMinutelySource: MinutelyForecastSource { ...@@ -32,9 +33,19 @@ public class BlendMinutelySource: MinutelyForecastSource {
}() }()
//Public //Public
#if DEBUG
public let healthUpdateInterval = TimeInterval(2 * 60) // 2 minutes
#else
public let healthUpdateInterval = TimeInterval(15 * 60) // 15 minutes
#endif
public init() {} public init() {}
public func getMinutelyForecast(forLocation location: Location, completion: @escaping MinutelyForecastCompletion) { public func getMinutelyForecast(forLocation location: Location, completion: @escaping MinutelyForecastCompletion) {
guard location.region != nil, location.cityName != nil else {
completion(.failure(BlendMinutelySourceError.invalidParameters))
return
}
let endpointURL = URL(string: kEndpoitURL)! let endpointURL = URL(string: kEndpoitURL)!
let queryItems = [URLQueryItem(name: "lat", value: location.lat), let queryItems = [URLQueryItem(name: "lat", value: location.lat),
URLQueryItem(name: "lon", value: location.lon), URLQueryItem(name: "lon", value: location.lon),
...@@ -82,16 +93,7 @@ public class BlendMinutelySource: MinutelyForecastSource { ...@@ -82,16 +93,7 @@ public class BlendMinutelySource: MinutelyForecastSource {
do { do {
let blendForecast = try decoder.decode(BlendMinutelyForecast.self, from: forecastData) let blendForecast = try decoder.decode(BlendMinutelyForecast.self, from: forecastData)
let forecast = MinutelyForecast(lastUpdateTime: Date(), let forecast = self.covnertToAppModel(itemToConvert: blendForecast)
forecastInterval: blendForecast.forecastInterval,
tempUnit: blendForecast.tempUnit,
windUnit: blendForecast.windUnit,
pressureUnit: blendForecast.pressureUnit,
forecast: blendForecast.forecast.map{ MinutelyItem(time: $0.time,
temp: $0.temp,
precipitation: $0.precipitation,
windSpeed: $0.windSpeed,
pressure: $0.pressure) })
completion(.success(forecast)) completion(.success(forecast))
} }
catch { catch {
...@@ -100,4 +102,19 @@ public class BlendMinutelySource: MinutelyForecastSource { ...@@ -100,4 +102,19 @@ public class BlendMinutelySource: MinutelyForecastSource {
} }
.resume() .resume()
} }
private func covnertToAppModel(itemToConvert: BlendMinutelyForecast) -> MinutelyForecast {
let items = itemToConvert.forecast.map { MinutelyItem(time: $0.time,
temp: .init(value: Double($0.temp), unit: .fahrenheit),
precipitation: $0.precipitation,
windSpeed: .init(value: Double($0.windSpeed), unit: .milesPerHour),
pressure: .init(value: Double($0.pressure), unit: .inchesOfMercury)) }
let minutelyForecast = MinutelyForecast(lastUpdateTime: Date(),
forecastInterval: itemToConvert.forecastInterval,
tempUnit: .fahrenheit,
windUnit: .milesPerHour,
pressureUnit: .inchesOfMercury,
forecast: items)
return minutelyForecast
}
} }
...@@ -374,8 +374,22 @@ public class LocationManager { ...@@ -374,8 +374,22 @@ public class LocationManager {
} }
public func updateMinutelyForecast(for location: Location) { public func updateMinutelyForecast(for location: Location) {
minutelyForecastSource.getMinutelyForecast(forLocation: location) { result in if let lastTimeUpdated = location.minutely?.lastUpdateTime {
print("Break") guard Date().timeIntervalSince(lastTimeUpdated) >= minutelyForecastSource.healthUpdateInterval else {
log.verbose("Update minutely forecast (\(location)): fresh enough (last updated at \(lastTimeUpdated)), skip update.")
return
}
}
log.info("Update minutely forecast for: \(location)")
minutelyForecastSource.getMinutelyForecast(forLocation: location) {[weak self] result in
guard let self = self else { return }
switch result {
case .success(let minutelyForecast):
self.make
case .failure(let error):
self.log.error("Update minutely (\(location) error: \(error)")
}
} }
} }
......
...@@ -7,15 +7,15 @@ ...@@ -7,15 +7,15 @@
import Foundation import Foundation
public struct MinutelyForecast: Codable { public struct MinutelyForecast {
public let lastUpdateTime: Date public let lastUpdateTime: Date
public let forecastInterval: Int public let forecastInterval: Int
public let tempUnit: Temperature public let tempUnit: UnitTemperature
public let windUnit: WindSpeed public let windUnit: UnitSpeed
public let pressureUnit: Pressure public let pressureUnit: UnitPressure
public let forecast: [MinutelyItem] public let forecast: [MinutelyItem]
public init(lastUpdateTime: Date, forecastInterval: Int, tempUnit: Temperature, windUnit: WindSpeed, pressureUnit: Pressure, forecast: [MinutelyItem]) { public init(lastUpdateTime: Date, forecastInterval: Int, tempUnit: UnitTemperature, windUnit: UnitSpeed, pressureUnit: UnitPressure, forecast: [MinutelyItem]) {
self.lastUpdateTime = lastUpdateTime self.lastUpdateTime = lastUpdateTime
self.forecastInterval = forecastInterval self.forecastInterval = forecastInterval
self.tempUnit = tempUnit self.tempUnit = tempUnit
......
...@@ -7,14 +7,14 @@ ...@@ -7,14 +7,14 @@
import Foundation import Foundation
public struct MinutelyItem: Codable { public struct MinutelyItem {
let time: Date let time: Date
let temp: Int let temp: Temperature
let precipitation: Double let precipitation: Double
let windSpeed: Int let windSpeed: WindSpeed
let pressure: Int let pressure: Pressure
public init(time: Date, temp: Int, precipitation: Double, windSpeed: Int, pressure: Int) { public init(time: Date, temp: Temperature, precipitation: Double, windSpeed: WindSpeed, pressure: Pressure) {
self.time = time self.time = time
self.temp = temp self.temp = temp
self.precipitation = precipitation self.precipitation = precipitation
......
...@@ -10,5 +10,7 @@ import Foundation ...@@ -10,5 +10,7 @@ import Foundation
public typealias MinutelyForecastCompletion = (_ result: Result<MinutelyForecast, Error>) -> () public typealias MinutelyForecastCompletion = (_ result: Result<MinutelyForecast, Error>) -> ()
public protocol MinutelyForecastSource { public protocol MinutelyForecastSource {
var healthUpdateInterval: TimeInterval { get }
func getMinutelyForecast(forLocation location: Location, completion: @escaping MinutelyForecastCompletion) func getMinutelyForecast(forLocation location: Location, completion: @escaping MinutelyForecastCompletion)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment