Skip to content

Commit

Permalink
Extensive restructuring, added unofficial Polestar API
Browse files Browse the repository at this point in the history
  • Loading branch information
Ixam97 committed Dec 29, 2023
1 parent 2f6b5f2 commit 0728e02
Show file tree
Hide file tree
Showing 54 changed files with 1,931 additions and 215 deletions.
2 changes: 1 addition & 1 deletion .idea/deploymentTargetDropDown.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CarStatsWidget

Modern android app utilizing the public Tibber API to provide responsive home screen widgets to see the vehicle state of charge at a glance.
Modern android app utilizing the public Tibber API or (**not officially supported**) Polestar API to provide responsive home screen widgets to see the vehicle state of charge at a glance.

![Screenshot_1](/docs/screenshot_2.png)

Expand Down
5 changes: 3 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId = "de.ixam97.carstatswidget"
minSdk = 24
targetSdk = 34
versionCode = 5
versionName = "0.1.5"
versionCode = 6
versionName = "0.2.0"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand Down Expand Up @@ -88,4 +88,5 @@ dependencies {
androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest)
implementation(kotlin("reflect"))
}
11 changes: 7 additions & 4 deletions app/src/main/java/de/ixam97/carstatswidget/CarStatsWidget.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.content.Intent
import android.os.SystemClock
import android.util.Log
import de.ixam97.carstatswidget.repository.CarDataRepository
import de.ixam97.carstatswidget.repository.TibberRepository
import de.ixam97.carstatswidget.repository.CarDataStatus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
Expand All @@ -31,7 +32,7 @@ class CarStatsWidget: Application() {
_gitHubVersionStateFlow.update {
null
}
val gitHubVersion = CarDataRepository.getGitHubVersion()
val gitHubVersion = TibberRepository.getGitHubVersion()
_gitHubVersionStateFlow.update {
gitHubVersion
}
Expand All @@ -42,8 +43,10 @@ class CarStatsWidget: Application() {
override fun onCreate() {
super.onCreate()
CoroutineScope(Dispatchers.IO).launch {
CarDataRepository.carDataInfoState.collect { carDataInfo ->
if (carDataInfo.status == CarDataStatus.Unavailable) {
// TibberRepository.carDataInfoState.collect { carDataInfo ->
CarDataRepository.networkState.collect { networkState ->
Log.w(TAG, "Network state: $networkState")
if (networkState.connected == false) {
val alarmManager =
applicationContext.getSystemService(Context.ALARM_SERVICE) as AlarmManager
val pendingIntent = PendingIntent.getBroadcast(
Expand All @@ -52,7 +55,7 @@ class CarStatsWidget: Application() {
Intent(applicationContext, WidgetUpdateReceiver::class.java),
PendingIntent.FLAG_IMMUTABLE
)
Log.d(TAG, "Reattempting Tibber fetch")
Log.d(TAG, "Reattempting connection")
// sendBroadcast(Intent(applicationContext, WidgetUpdateReceiver::class.java))
alarmManager.set(
AlarmManager.ELAPSED_REALTIME,
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/de/ixam97/carstatswidget/RetrofitInstance.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
package de.ixam97.carstatswidget

import de.ixam97.carstatswidget.repository.GitHubVersionChecker
import de.ixam97.carstatswidget.repository.PolestarAuthApi
import de.ixam97.carstatswidget.repository.PolestarDataApi
import de.ixam97.carstatswidget.repository.TibberApi
import okhttp3.OkHttpClient
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitInstance {

val noRedirectClient: OkHttpClient by lazy {
OkHttpClient.Builder()
.followRedirects(false)
.followSslRedirects(false)
.build()
}

val tibberApi: TibberApi by lazy {
Retrofit.Builder()
.baseUrl("https://app.tibber.com")
Expand All @@ -19,4 +30,20 @@ object RetrofitInstance {
.build()
.create(GitHubVersionChecker::class.java)
}
val polestarAuthApi: PolestarAuthApi by lazy {
Retrofit.Builder()
.baseUrl("https://polestarid.eu.polestar.com")
.addConverterFactory(GsonConverterFactory.create())
.client(noRedirectClient)
.build()
.create(PolestarAuthApi::class.java)

}
val polestarDataApi: PolestarDataApi by lazy {
Retrofit.Builder()
.baseUrl("https://pc-api.polestar.com")
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(PolestarDataApi::class.java)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ sealed interface CarDataStatus {
object Unavailable: CarDataStatus
@Serializable
object Loading: CarDataStatus
@Serializable
object ConfigChanged: CarDataStatus
}

@Serializable
Expand All @@ -41,7 +43,10 @@ data class CarDataInfo(
val lastUpdated: String,
val imgUrl: String,
val name: String,
val shortName: String,
val id: String
val shortName: String = "",
val id: String,
val api: String,
val isCharging: Boolean? = null,
val isConnected: Boolean? = null,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package de.ixam97.carstatswidget.repository

import android.content.Context
import android.util.Log

abstract class CarDataInterface {
abstract val passwordKey: String
abstract val mailKey: String
abstract val name: String

// final var status: CarDataStatus = CarDataStatus.NotLoggedIn
// protected set
// final var message: String = ""
// protected set

var networkStatus: Boolean? = null
protected set

abstract suspend fun login(apiCredentials: ApiCredentials, context: Context): Boolean

abstract suspend fun logout(context: Context)

abstract suspend fun verifyLogin(context: Context): Boolean

abstract suspend fun getVehicles(context: Context): List<CarDataInfo.CarData>?

protected fun handleException(e: Exception, tag: String) {
if (e is java.net.UnknownHostException || e is java.net.SocketTimeoutException) {
// status = CarDataStatus.Unavailable
// message = "Network connection error"
Log.e(tag, "Network connection error: ${e.message}")
CarDataRepository.setNetworkError(e.message?:"Unknown error")
} else {
Log.e(tag, e.stackTraceToString())
}
}
}

data class ApiCredentials(
val email: String,
val password: String
)

0 comments on commit 0728e02

Please sign in to comment.