Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codable protocol #23

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
13 changes: 13 additions & 0 deletions Source/Models/BoolResponses.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation

struct BoolResponse: Codable {
let response: Bool
}

struct ResultResponse: Codable {
let response: BoolResult
}

struct BoolResult: Codable {
let result: Bool
}
61 changes: 7 additions & 54 deletions Source/Models/ChargeState.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import Foundation

public class ChargeState {
public enum ChargingState: String {
public class ChargeStateResponse: Codable {
let response: ChargeState
}

public struct ChargeState: Codable {

public enum ChargingState: String, Codable {
case disconnected = "Disconnected"
case charging = "Charging"
case complete = "Complete"
Expand Down Expand Up @@ -48,56 +53,4 @@ public class ChargeState {
public let tripCharging: Bool?
public let usableBatteryLevel: Int
public let userChargeEnableRequest: Bool?

init(dictionary: [String: Any]) {
batteryHeaterOn = dictionary["battery_heater_on"] as? Bool
batteryLevel = dictionary["battery_level"] as! Int
batteryRange = dictionary["battery_range"] as! Double
chargeCurrentRequest = dictionary["charge_current_request"] as! Int
chargeCurrentRequestMax = dictionary["charge_current_request_max"] as! Int
chargeEnableRequest = dictionary["charge_enable_request"] as! Bool
chargeEnergyAdded = dictionary["charge_energy_added"] as! Double
chargeLimitSoc = dictionary["charge_limit_soc"] as! Int
chargeLimitSocMax = dictionary["charge_limit_soc_max"] as! Int
chargeLimitSocMin = dictionary["charge_limit_soc_min"] as! Int
chargeLimitSocStd = dictionary["charge_limit_soc_std"] as! Int
chargeMilesAddedIdeal = dictionary["charge_miles_added_ideal"] as! Double
chargeMilesAddedRated = dictionary["charge_miles_added_rated"] as! Double
chargePortDoorOpen = dictionary["charge_port_door_open"] as? Bool
chargePortLatch = dictionary["charge_port_latch"] as! String
chargeRate = dictionary["charge_rate"] as! Double
chargeToMaxRange = dictionary["charge_to_max_range"] as! Int
chargerActualCurrent = dictionary["charger_actual_current"] as! Int
chargerPhases = dictionary["charger_phases"] as? Int
chargerPilotCurrent = dictionary["charger_pilot_current"] as? Int
chargerPower = dictionary["charger_power"] as! Int
chargerVoltage = dictionary["charger_voltage"] as! Int
chargingState = ChargingState(rawValue: dictionary["charging_state"] as! String)!
estBatteryRange = dictionary["est_battery_range"] as! Double
euVehicle = dictionary["eu_vehicle"] as! Bool
fastChargerPresent = dictionary["fast_charger_present"] as! Bool
fastChargerType = dictionary["fast_charger_type"] as? String
idealBatteryRange = dictionary["ideal_battery_range"] as! Double
managedChargingActive = dictionary["managed_charging_active"] as! Bool
if let timestamp = dictionary["managed_charging_start_time"] as? Double {
managedChargingStartTime = Date(timeIntervalSince1970: timestamp)
} else {
managedChargingStartTime = nil
}
managedChargingUserCanceled = dictionary["managed_charging_user_canceled"] as! Bool
maxRangeChargeCounter = dictionary["max_range_charge_counter"] as! Int
motorizedChargePort = dictionary["motorized_charge_port"] as! Bool
notEnoughPowerToHeat = dictionary["not_enough_power_to_heat"] as? Bool
scheduledChargingPending = dictionary["scheduled_charging_pending"] as! Bool
if let timestamp = dictionary["scheduled_charging_start_time"] as? Double {
scheduledChargingStartTime = Date(timeIntervalSince1970: timestamp)
} else {
scheduledChargingStartTime = nil
}
timeToFullCharge = dictionary["time_to_full_charge"] as! Double
timestamp = Date(timeIntervalSince1970: dictionary["timestamp"] as! Double)
tripCharging = dictionary["trip_charging"] as? Bool
usableBatteryLevel = dictionary["usable_battery_level"] as! Int
userChargeEnableRequest = dictionary["user_charge_enable_request"] as? Bool
}
}
21 changes: 5 additions & 16 deletions Source/Models/Token.swift
Original file line number Diff line number Diff line change
@@ -1,24 +1,13 @@
import Foundation

public class Token {
public class TokenResponse: Codable {
let response: Token
}

public struct Token: Codable {
public let accessToken: String
public let type: String
public let expires: Date
public let created: Date
public let refreshToken: String

init(dictionary: [String: AnyObject]) throws {
guard let accessToken = dictionary["access_token"] as? String,
let type = dictionary["token_type"] as? String,
let expiresInteger = dictionary["expires_in"] as? Double,
let createdInteger = dictionary["created_at"] as? Double,
let refreshToken = dictionary["refresh_token"] as? String else {
throw APIError()
}
self.accessToken = accessToken
self.type = type
self.expires = Date(timeIntervalSince1970: expiresInteger + createdInteger)
self.created = Date(timeIntervalSince1970: createdInteger)
self.refreshToken = refreshToken
}
}
34 changes: 10 additions & 24 deletions Source/Models/Vehicle.swift
Original file line number Diff line number Diff line change
@@ -1,35 +1,21 @@
import Foundation

public class Vehicle {
public enum State: String {
public class VehicleResponse: Codable {
let response: [Vehicle]
}

public struct Vehicle: Codable {

public enum State: String, Codable {
case online
}

public let color: String?
public let displayName: String?
public let identifier: String
public let optionCodes: [String]
public let identifier: Int
public let optionCodes: String
public let vehicleIdentifier: Int
public let vin: String
public let tokens: [String]
public let state: State

init?(dictionary: [String: AnyObject]) {
guard let identifierNumber = dictionary["id"] as? NSNumber,
let optionCodes = dictionary["option_codes"] as? String,
let vehicleIdentifier = dictionary["vehicle_id"] as? Int,
let vin = dictionary["vin"] as? String,
let tokens = dictionary["tokens"] as? [String],
let stateString = dictionary["state"] as? String,
let state = State(rawValue: stateString) else {
return nil
}
self.color = dictionary["color"] as? String
self.displayName = dictionary["display_name"] as? String
self.identifier = identifierNumber.stringValue
self.optionCodes = optionCodes.components(separatedBy: ",")
self.vehicleIdentifier = vehicleIdentifier
self.vin = vin
self.tokens = tokens
self.state = state
}
}
93 changes: 93 additions & 0 deletions Source/Models/VehicleState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import Foundation

public struct VehicleStateResponse: Codable {
let response: VehicleState
}

public struct VehicleState: Codable {
let parsedCalendarSupported: Double
let spoilerType: String
let rt: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'rt' (identifier_name)

let carVersion: String
let rearSeatType: Double
let df: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'df' (identifier_name)

let locked: Double
let thirdRowSeats: String
let sunRoofState: String
let carType: String
let remoteStartSupported: Double
let hasSpoiler: Double
let pf: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'pf' (identifier_name)

let odometer: Double
let lastAutoparkError: String
let darkRims: Double
let autoparkState: String
let sunRoofInstalled: Double
let sunRoofPercentOpen: Double
let exteriorColor: String
let timestamp: Double
let vehicleName: String
let homelinkNearby: Double
let valetPinNeeded: Double
let notificationsSupported: Double
let pr: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'pr' (identifier_name)

let rearSeatHeaters: Double
let valetMode: Double
let calendarSupported: Double
let dr: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'dr' (identifier_name)

let centerDisplayState: Double
let apiVersion: Double
let remoteStart: Double
let ft: Double

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Variable name should be between 3 and 40 characters long: 'ft' (identifier_name)

let autoparkStateV2: String
let wheelType: String
let perfConfig: String
let autoparkStyle: String
let roofColor: String
let rhd: Double
let seatType: Double

private enum CodingKeys: String, CodingKey {
case parsedCalendarSupported = "parsed_calendar_supported"
case spoilerType = "spoiler_type"
case rt

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'rt' (identifier_name)

case carVersion = "car_version"
case rearSeatType = "rear_seat_type"
case df

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'df' (identifier_name)

case locked
case thirdRowSeats = "third_row_seats"
case sunRoofState = "sun_roof_state"
case carType = "car_type"
case remoteStartSupported = "remote_start_supported"
case hasSpoiler = "has_spoiler"
case pf

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'pf' (identifier_name)

case odometer
case lastAutoparkError = "last_autopark_error"
case darkRims = "dark_rims"
case autoparkState = "autopark_state"
case sunRoofInstalled = "sun_roof_installed"
case sunRoofPercentOpen = "sun_roof_percent_open"
case exteriorColor = "exterior_color"
case timestamp
case vehicleName = "vehicle_name"
case homelinkNearby = "homelink_nearby"
case valetPinNeeded = "valet_pin_needed"
case notificationsSupported = "notifications_supported"
case pr

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'pr' (identifier_name)

case rearSeatHeaters = "rear_seat_heaters"
case valetMode = "valet_mode"
case calendarSupported = "calendar_supported"
case dr

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'dr' (identifier_name)

case centerDisplayState = "center_display_state"
case apiVersion = "api_version"
case remoteStart = "remote_start"
case ft

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Identifier Name Violation: Enum element name should be between 3 and 40 characters long: 'ft' (identifier_name)

case autoparkStateV2 = "autopark_state_v2"
case wheelType = "wheel_type"
case perfConfig = "perf_config"
case autoparkStyle = "autopark_style"
case roofColor = "roof_color"
case rhd
case seatType = "seat_type"
}
}
16 changes: 6 additions & 10 deletions Source/Requests/AuthenticateRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,22 +26,18 @@ public struct AuthenticateRequest: RequestProtocol {
WebRequest.request(
path: path,
method: method,
params: params) { response, error in
params: params) { data, error in
if let error = error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
} else {
guard let responseDictionary = response as? [String: AnyObject] else {
DispatchQueue.main.async {
completion(Result.failure(APIError()))
}
return
}
} else if let data = data {
do {
let result = try Result.success(Token(dictionary: responseDictionary))
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let token = try decoder.decode(Token.self, from: data)
DispatchQueue.main.async {
completion(result)
completion(Result.success(token))
}
} catch let error {
DispatchQueue.main.async {
Expand Down
22 changes: 13 additions & 9 deletions Source/Requests/ChargeStateRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,23 @@ public struct ChargeStateRequest: RequestProtocol {
WebRequest.request(
path: path,
method: method,
accessToken: accessToken) { response, error in
accessToken: accessToken) { data, error in
if let error = error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
} else if let response = response as? [String: [String: Any]],
let dictionary = response["response"] {
DispatchQueue.main.async {
completion(Result.success(ChargeState(dictionary: dictionary)))
}
} else {
DispatchQueue.main.async {
completion(Result.failure(APIError()))
} else if let data = data {
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let chargeStateResponse = try decoder.decode(ChargeStateResponse.self, from: data)
DispatchQueue.main.async {
completion(Result.success(chargeStateResponse.response))
}
} catch let error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
}
}
}
Expand Down
20 changes: 11 additions & 9 deletions Source/Requests/ListVehiclesRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,23 @@ public struct ListVehiclesRequest: RequestProtocol {
WebRequest.request(
path: path,
method: method,
accessToken: accessToken) { response, error in
accessToken: accessToken) { data, error in
if let error = error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
} else {
guard let responseArray = response?["response"] as? [[String: AnyObject]] else {
} else if let data = data {
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let vehicleResponse = try decoder.decode(VehicleResponse.self, from: data)
DispatchQueue.main.async {
completion(Result.failure(APIError()))
completion(Result.success(vehicleResponse.response))
}
} catch let error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
return
}
let vehicles = responseArray.flatMap { return Vehicle(dictionary: $0) }
DispatchQueue.main.async {
completion(Result.success(vehicles))
}
}
}
Expand Down
22 changes: 13 additions & 9 deletions Source/Requests/LockRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,23 @@ public struct LockRequest: RequestProtocol {
WebRequest.request(
path: path,
method: method,
accessToken: accessToken) { response, error in
accessToken: accessToken) { data, error in
if let error = error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
} else if let response = response as? [String: [String: Any]],
let resultBool = response["response"]?["result"] as? Bool {
DispatchQueue.main.async {
completion(Result.success(resultBool))
}
} else {
DispatchQueue.main.async {
completion(Result.failure(APIError()))
} else if let data = data {
do {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let resultResponse = try decoder.decode(ResultResponse.self, from: data)
DispatchQueue.main.async {
completion(Result.success(resultResponse.response.result))
}
} catch let error {
DispatchQueue.main.async {
completion(Result.failure(error))
}
}
}
}
Expand Down
Loading