Skip to content

Commit

Permalink
update for official API
Browse files Browse the repository at this point in the history
  • Loading branch information
tesycharging committed Dec 30, 2023
1 parent b0d6fa9 commit a7db0b1
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 188 deletions.
32 changes: 5 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Task { @MainActor in
try await teslaAPI.registerThirdPartyAPI()
}
} catch (let error) {
//Process error
}
}
```
Expand All @@ -113,8 +114,9 @@ Uses the WebLogin provided by Tesla
WebLogin(teslaAPI: teslaAPI, result: $result, action: {
switch result {
case .success(let token):
UserDefaults.group.teslatoken = token.toJSONString()
UserDefaults.group.teslatoken = token.toJSONString()
case .failure(let error):
//Process error
}
})
```
Expand Down Expand Up @@ -190,31 +192,7 @@ Obtain all data for a vehicle
```
Task { @MainActor in
do {
guard let current_vehicle = try await teslaAPI.getVehicle(vehicle) else { return }
//Process some code
} catch let error {
//Process error
}
}
```

Generic approach to obtain all data or specific data, e.g. driveState
```
Task { @MainActor in
do {
guard let current_vehicle = try await teslaAPI.getVehicleData(.allStates(vehicleID: vehicle.id)) else { return }
//Process some code
} catch let error {
//Process error
}
}
```

or specific data, e.g. driveState
```
Task { @MainActor in
do {
guard let driveState = try await teslaAPI.getVehicleData(.driveState(vehicleID: vehicle.id)) else { return }
guard let current_vehicle = try await teslaAPI.getAllData(vehicle) else { return }
//Process some code
} catch let error {
//Process error
Expand All @@ -227,7 +205,7 @@ fetches the location data like gps dcoordinates
```
Task { @MainActor in
do {
let endpointData: EndpointData = try await teslaAPI.getLEndpoint(id, endpoint: .locationData)
let endpointData: EndpointData = try await teslaAPI.getEndpoint(id, endpoint: .locationData)
//Process some code
} catch (let error) {
//Process error
Expand Down
12 changes: 1 addition & 11 deletions Sources/TeslaKit/Classes/DemoTesla.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ public class DemoTesla {
public var user: User = User()
public var vehicle: Vehicle?
public var vehicles: VehicleCollection = VehicleCollection()
public var endpointData: EndpointData?

public var chargingState: ChargingState = ChargingState.disconnected
public var chargePortLatch: ChargePortLatchState = ChargePortLatchState.disengaged
Expand Down Expand Up @@ -68,19 +67,10 @@ public class DemoTesla {
var vehicles = [Vehicle]()
vehicles.append(self.vehicle ?? Vehicle())
self.vehicles = VehicleCollection(vehicles: vehicles)

self.endpointData = EndpointData()
self.endpointData?.status = .online
self.endpointData?.chargeState = self.vehicle?.chargeState ?? ChargeState()
self.endpointData?.climateState = self.vehicle?.climateState ?? ClimateState()
self.endpointData?.driveState = self.vehicle?.driveState ?? DriveState()
self.endpointData?.guiSettings = self.vehicle?.guiSettings ?? GUISettings()
self.endpointData?.vehicleConfig = self.vehicle?.vehicleConfig ?? VehicleConfig()
self.endpointData?.vehicleState = self.vehicle?.vehicleState ?? VehicleState()
}

public func getEndpoint<T: DataResponse>(endpoint: VehicleEndpoint) -> T? {
var endpointData = EndpointData()
var endpointData = Vehicle()
switch endpoint {
case .chargeState:
endpointData.chargeState = self.vehicle?.chargeState ?? ChargeState()
Expand Down
60 changes: 57 additions & 3 deletions Sources/TeslaKit/Classes/TeslaAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public enum AuthorizationScope: String {
}

open class TeslaAPI: NSObject, URLSessionDelegate {
open var debuggingEnabled = false
open var debuggingEnabled = true
open var demoMode = false
open var addDemoVehicle = true
public var officialAPI = true
Expand Down Expand Up @@ -291,7 +291,7 @@ extension TeslaAPI {
/**
Fetches the endpoint, e.g. location_datas
*/
public func getLEndpoint<T: DataResponse>(_ vehicleID: String, endpoint: VehicleEndpoint) async throws -> T? {
public func getEndpoint<T: DataResponse>(_ vehicleID: String, endpoint: VehicleEndpoint) async throws -> T? {
_ = try await checkAuthentication()
if self.demoMode {
return DemoTesla.shared.getEndpoint(endpoint: endpoint)
Expand Down Expand Up @@ -360,12 +360,31 @@ extension TeslaAPI {
}
}


/**
Fetchs the summary of a vehicle

- returns: A Vehicle.
*/
public func getVehicleInfo(_ vehicleID: String) async throws -> Vehicle? {
return try await getVehicleData(.vehicleSummary(fleet_api_base_url: fleet_api_base_url, vehicleID: vehicleID))
}

/**
Fetchs the summary of a vehicle

- returns: A Vehicle.
*/
public func getVehicleInfo(_ vehicle: Vehicle) async throws -> Vehicle? {
return try await getVehicleData(.vehicleSummary(fleet_api_base_url: fleet_api_base_url, vehicleID: vehicle.id))
}

/**
Fetchs the summary of a vehicle

- returns: A Vehicle.
*/
@available(*, deprecated, message: "getAllData")
public func getVehicle(_ vehicleID: String) async throws -> Vehicle? {
return try await getVehicleData(.allStates(fleet_api_base_url: fleet_api_base_url, vehicleID: vehicleID))
}
Expand All @@ -375,6 +394,7 @@ extension TeslaAPI {

- returns: A Vehicle.
*/
@available(*, deprecated, message: "getAllData")
public func getVehicle(_ vehicle: Vehicle) async throws -> Vehicle? {
return try await getVehicleData(.allStates(fleet_api_base_url: fleet_api_base_url, vehicleID: vehicle.id), demoMode: (vehicle.vin?.vinString == "VIN#DEMO_#TESTING"))
}
Expand Down Expand Up @@ -448,6 +468,36 @@ extension TeslaAPI {
}
}

public func chargingHistory(_ vehicle: Vehicle) async throws -> [ChargingSession] {
if demoMode {
return [ChargingSession]()
} else {
_ = try await checkAuthentication()
let chargingHistory: ChargingHistory = try await self.request(Endpoint.charging_history(fleet_api_base_url: fleet_api_base_url, query: [URLQueryItem(name: "vin", value: vehicle.vin?.vinString),URLQueryItem(name: "startTime", value: "2023-10-10T10:00:00+01:00")]), token: token)
return chargingHistory.data
}
}

public func optionCodes(_ vehicle: Vehicle) async throws -> [OptionCode] {
if demoMode {
return [OptionCode]()
} else {
_ = try await checkAuthentication()
let optionCodes: OptionCodes = try await self.request(Endpoint.options(fleet_api_base_url: fleet_api_base_url, vin: vehicle.vin?.vinString ?? ""), token: token)
return optionCodes.codes
}
}

public func getRecentAlerts(_ vehicle: Vehicle) async throws -> [Recent_Alert] {
if demoMode {
return [Recent_Alert]()
} else {
_ = try await checkAuthentication()
let recentAlerts: Alerts = try await self.request(Endpoint.recent_alerts(fleet_api_base_url: fleet_api_base_url, vehicleID: vehicle.id), token: token)
return recentAlerts.recent_alerts
}
}

}

@available(macOS 13.1, *)
Expand Down Expand Up @@ -560,7 +610,7 @@ extension TeslaAPI {
}
TeslaAPI.logger.debug("\(mappedError.toJSON()), privacy: .public)")
if mappedError.error == "invalid bearer token" {
throw TeslaError.authenticationRequired(code: httpResponse.statusCode, msg: mappedError.error)
throw TeslaError.authenticationFailed(code: httpResponse.statusCode, msg: mappedError.error)
} else {
throw TeslaError.authenticationFailed(code: httpResponse.statusCode, msg: mappedError.toJSONString() ?? "")
}
Expand Down Expand Up @@ -790,6 +840,10 @@ extension TeslaAPI {
DemoTesla.shared.vehicle?.climateState.seatHeaterRight = 0
}
}
case .take_drivenote:
response.result = false
response.reason = "not implemented"
TeslaAPI.logger.debug("not implemented, privacy: .public)")
}
if #available(iOS 16.0, *) {
#if !os(macOS)
Expand Down
2 changes: 2 additions & 0 deletions Sources/TeslaKit/Enumeration/Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ public enum Command: String, CaseIterable, CustomStringConvertible {
case openWindow = "window_control"

case setClimateMode = "set_climate_keeper_mode"

case take_drivenote = "take_drivenote"

///
public var description: String {
Expand Down
28 changes: 26 additions & 2 deletions Sources/TeslaKit/Enumeration/TeslaEndpoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ public enum Endpoint {

case user(fleet_api_base_url: String)
case tripplan(fleet_api_base_url: String)
case charging_history(fleet_api_base_url: String, query: [URLQueryItem])
case options(fleet_api_base_url: String, vin: String)
case recent_alerts(fleet_api_base_url: String, vehicleID: String)
case signed_command(fleet_api_base_url: String, vehicleID: String)

/*case getEnergySiteStatus(siteID: String)
case getEnergySiteLiveStatus(siteID: String)
Expand Down Expand Up @@ -96,6 +100,14 @@ extension Endpoint {
return "/api/1/users/me"
case .tripplan:
return "/trip-planner/api/v1/tripplan"
case .charging_history:
return "/api/1/dx/charging/history"
case .options:
return "/api/1/dx/vehicles/options"
case .recent_alerts(_, let vehicleID):
return "/api/1/vehicles/\(vehicleID)/recent_alerts"
case .signed_command(_, let vehicleID):
return "/api/1/vehicles/\(vehicleID)/signed_command"

/* // Energy Data
case .getEnergySiteStatus(let siteID):
Expand All @@ -117,9 +129,9 @@ extension Endpoint {

var method: String {
switch self {
case .revoke, .oAuth2PartnerAuthorization, .register, .oAuth2Token, .oAuth2TokenCN, .wakeUp, .command, .tripplan:
case .revoke, .oAuth2PartnerAuthorization, .register, .oAuth2Token, .oAuth2TokenCN, .wakeUp, .command, .tripplan, .signed_command:
return "POST"
case .vehicles, .vehicleSummary, .mobileAccess, .allStates, .vehicleEndpoint, .nearbyChargingSites, .oAuth2Authorization, .oAuth2revoke, .oAuth2AuthorizationCN, .region, .oAuth2revokeCN, .products, .user/*, .getEnergySiteStatus, .getEnergySiteLiveStatus, .getEnergySiteInfo, .getEnergySiteHistory, .getBatteryStatus, .getBatteryData, .getBatteryPowerHistory*/:
case .vehicles, .vehicleSummary, .mobileAccess, .allStates, .vehicleEndpoint, .nearbyChargingSites, .oAuth2Authorization, .oAuth2revoke, .oAuth2AuthorizationCN, .region, .oAuth2revokeCN, .products, .user, .charging_history, .options, .recent_alerts/*, .getEnergySiteStatus, .getEnergySiteLiveStatus, .getEnergySiteInfo, .getEnergySiteHistory, .getBatteryStatus, .getBatteryData, .getBatteryPowerHistory*/:
return "GET"
}
}
Expand All @@ -134,6 +146,10 @@ extension Endpoint {
return [URLQueryItem(name: "period", value: period.rawValue), URLQueryItem(name: "kind", value: "energy")]*/
case let .vehicleEndpoint(_,_,endpoint):
return [URLQueryItem(name: "endpoints", value: endpoint.rawValue)]
case let .charging_history(_, query):
return query
case let .options(_, vin):
return [URLQueryItem(name: "vin", value: vin)]
default:
return []
}
Expand Down Expand Up @@ -171,6 +187,14 @@ extension Endpoint {
return fleet_api_base_url
case let .vehicleSummary(fleet_api_base_url, _):
return fleet_api_base_url
case let .charging_history(fleet_api_base_url,_):
return fleet_api_base_url
case let .options(fleet_api_base_url, _):
return fleet_api_base_url
case let .recent_alerts(fleet_api_base_url, _):
return fleet_api_base_url
case let .signed_command(fleet_api_base_url, _):
return fleet_api_base_url
}
}
}
Expand Down
55 changes: 55 additions & 0 deletions Sources/TeslaKit/Structures/Alerts.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//
// Alerts.swift
// TeslaKit
//
// Copyright © 2022 David Lüthi. All rights reserved.
//

import Foundation
import ObjectMapper
import MapKit

public struct Alerts {
public var recent_alerts: [Recent_Alert] = []
public init() {}
public init(recent_alerts: [Recent_Alert]) {
self.recent_alerts = recent_alerts
}
}

extension Alerts: Mappable {
public mutating func mapping(map: Map) {
recent_alerts <- map["recent_alerts"]
}
}

public struct Recent_Alert {
public var allValues: Map
public var name: String = ""
public var time: String = ""
public var audience: [String] = []
public var user_text: String = ""
public init() {
allValues = Map(mappingType: .fromJSON, JSON: ["":""])
}
}

extension Recent_Alert: DataResponse {
public mutating func mapping(map: Map) {
allValues = map
name <- map["name"]
time <- map["time"]
audience <- map["audience"]
user_text <- map["user_text"]
}
}

extension Recent_Alert: Hashable {
public static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name
}

public func hash(into hasher: inout Hasher) {
hasher.combine(name)
}
}
Loading

0 comments on commit a7db0b1

Please sign in to comment.