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

Update Kuksa SDK to 0.2.1 #68

Merged
merged 6 commits into from
Mar 28, 2024
Merged
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
9 changes: 7 additions & 2 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import org.eclipse.kuksa.companion.property.PropertiesLoader
plugins {
id("com.android.application")
id("com.google.devtools.ksp")
alias(libs.plugins.vss.processor)
alias(libs.plugins.kotlin.serialization)
kotlin("kapt")
alias(libs.plugins.hilt.android)
kotlin("kapt")
kotlin("android")
}

Expand All @@ -35,7 +36,7 @@ android {
defaultConfig {
applicationId = "org.eclipse.kuksa.companion"
minSdk = 27
targetSdk = 33
targetSdk = 33 // TODO: 34+ is unsupported by the Ramses SDK
versionCode = rootProject.extra["projectVersionCode"].toString().toInt()
versionName = rootProject.extra["projectVersion"].toString()

Expand Down Expand Up @@ -100,6 +101,10 @@ android {
}
}

vssProcessor {
searchPath = "$rootDir/spec"
}

dependencies {
ksp(libs.vss.processor) {
isChanging = true
Expand Down
63 changes: 37 additions & 26 deletions app/src/main/kotlin/org/eclipse/kuksa/companion/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
import org.eclipse.kuksa.DataBrokerConnection
import org.eclipse.kuksa.DataBrokerException
import org.eclipse.kuksa.companion.extension.TAG
import org.eclipse.kuksa.companion.feature.connection.factory.DataBrokerConnectorFactory
import org.eclipse.kuksa.companion.feature.connection.repository.ConnectionInfoRepository
Expand All @@ -51,20 +49,24 @@ import org.eclipse.kuksa.companion.feature.settings.viewModel.SettingsViewModel
import org.eclipse.kuksa.companion.feature.temperature.viewmodel.TemperatureViewModel
import org.eclipse.kuksa.companion.feature.wheel.pressure.viewmodel.WheelPressureViewModel
import org.eclipse.kuksa.companion.ui.theme.KuksaCompanionTheme
import org.eclipse.kuksa.extension.vssProperty.not
import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection
import org.eclipse.kuksa.connectivity.databroker.DataBrokerException
import org.eclipse.kuksa.connectivity.databroker.request.VssNodeSubscribeRequest
import org.eclipse.kuksa.connectivity.databroker.request.VssNodeUpdateRequest
import org.eclipse.kuksa.extension.vss.not
import org.eclipse.kuksa.proto.v1.Types.Field
import org.eclipse.kuksa.vss.VssAxle
import org.eclipse.kuksa.vss.VssDoor
import org.eclipse.kuksa.vss.VssHvac
import org.eclipse.kuksa.vss.VssLights
import org.eclipse.kuksa.vss.VssStation
import org.eclipse.kuksa.vss.VssTrunk
import org.eclipse.kuksa.vsscore.annotation.VssDefinition
import org.eclipse.kuksa.vsscore.model.VssSpecification
import org.eclipse.kuksa.vsscore.annotation.VssModelGenerator
import org.eclipse.kuksa.vsscore.model.VssNode
import javax.inject.Inject

@AndroidEntryPoint
@VssDefinition("vss_rel_4.0.yaml")
@VssModelGenerator
class MainActivity : ComponentActivity() {
@Inject
lateinit var connectionInfoRepository: ConnectionInfoRepository
Expand Down Expand Up @@ -134,7 +136,7 @@ class MainActivity : ComponentActivity() {
}

doorControlViewModel.onClickOpenAll = {
updateSpecification(
updateVssNode(
DOOR_ALL_OPEN.row1.driverSide.isOpen,
DOOR_ALL_OPEN.row1.passengerSide.isOpen,
DOOR_ALL_OPEN.row2.driverSide.isOpen,
Expand All @@ -145,7 +147,7 @@ class MainActivity : ComponentActivity() {
}

doorControlViewModel.onClickCloseAll = {
updateSpecification(
updateVssNode(
DOOR_ALL_CLOSED.row1.driverSide.isOpen,
DOOR_ALL_CLOSED.row1.passengerSide.isOpen,
DOOR_ALL_CLOSED.row2.driverSide.isOpen,
Expand All @@ -155,20 +157,20 @@ class MainActivity : ComponentActivity() {
)
}

doorControlViewModel.onClickToggleDoor = { toggledProperty ->
updateSpecification(!toggledProperty, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
doorControlViewModel.onClickToggleDoor = { toggledSignal ->
updateVssNode(!toggledSignal, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
}

doorControlViewModel.onClickToggleTrunk = { toggledProperty ->
updateSpecification(!toggledProperty, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
doorControlViewModel.onClickToggleTrunk = { toggledSignal ->
updateVssNode(!toggledSignal, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
}

temperatureViewModel.onPlannedTemperatureChanged = { plannedTemperature ->
updatePlannedTemperature(plannedTemperature)
}

lightControlViewModel.onClickToggleLight = { vssProperty ->
updateSpecification(!vssProperty, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
lightControlViewModel.onClickToggleLight = { vssSignal ->
updateVssNode(!vssSignal, fields = listOf(Field.FIELD_ACTUATOR_TARGET))
}

connectToDataBroker {
Expand All @@ -192,37 +194,46 @@ class MainActivity : ComponentActivity() {

private fun updatePlannedTemperature(plannedTemperature: Int) {
lifecycleScope.launch {
val vssProperties = listOf(
val vssNodes = listOf(
VssStation.VssRow1.VssDriver.VssTemperature(plannedTemperature),
VssStation.VssRow1.VssPassenger.VssTemperature(plannedTemperature),
VssStation.VssRow2.VssDriver.VssTemperature(plannedTemperature),
VssStation.VssRow2.VssPassenger.VssTemperature(plannedTemperature),
)

vssProperties.forEach { vssProperty ->
dataBrokerConnection?.update(vssProperty, listOf(Field.FIELD_ACTUATOR_TARGET))
vssNodes.forEach { vssNode ->
val updateRequest = VssNodeUpdateRequest(vssNode, Field.FIELD_ACTUATOR_TARGET)
dataBrokerConnection?.update(updateRequest)
}
}
}

private fun subscribe() {
dataBrokerConnection?.apply {
subscribe(VssDoor(), listener = doorControlViewModel.vssDoorListener)
subscribe(VssTrunk(), listener = doorControlViewModel.vssTrunkListener)
subscribe(VssHvac(), listener = temperatureViewModel.vssTemperatureListener)
subscribe(VssAxle(), listener = wheelPressureViewModel.vssWheelPressureListener)
subscribe(VssLights(), listener = lightControlViewModel.vssLightListener)
val vssDoorSubscribeRequest = VssNodeSubscribeRequest(VssDoor())
val vssTrunkSubscribeRequest = VssNodeSubscribeRequest(VssTrunk())
val vssHvacSubscribeRequest = VssNodeSubscribeRequest(VssHvac())
val vssAxleSubscribeRequest = VssNodeSubscribeRequest(VssAxle())
val vssLightsSubscribeRequest = VssNodeSubscribeRequest(VssLights())

subscribe(vssDoorSubscribeRequest, listener = doorControlViewModel.vssDoorListener)
subscribe(vssTrunkSubscribeRequest, listener = doorControlViewModel.vssTrunkListener)
subscribe(vssHvacSubscribeRequest, listener = temperatureViewModel.vssTemperatureListener)
subscribe(vssAxleSubscribeRequest, listener = wheelPressureViewModel.vssWheelPressureListener)
subscribe(vssLightsSubscribeRequest, listener = lightControlViewModel.vssLightListener)
}
}

private fun updateSpecification(
vararg specifications: VssSpecification,
@Suppress("performance:SpreadOperator") // Neglectable: Field types are 1-2 elements mostly
private fun updateVssNode(
vararg vssNodes: VssNode,
fields: List<Field> = listOf(Field.FIELD_VALUE),
) {
lifecycleScope.launch {
try {
specifications.forEach { specifications ->
dataBrokerConnection?.update(specifications, fields)
vssNodes.forEach { vssNode ->
val updateRequest = VssNodeUpdateRequest(vssNode, *fields.toTypedArray())
dataBrokerConnection?.update(updateRequest)
}
} catch (e: DataBrokerException) {
Log.w(TAG, "Failed to update door: $e")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import io.grpc.ChannelCredentials
import io.grpc.Grpc
import io.grpc.ManagedChannelBuilder
import io.grpc.TlsChannelCredentials
import org.eclipse.kuksa.DataBrokerConnector
import org.eclipse.kuksa.DataBrokerException
import org.eclipse.kuksa.companion.feature.connection.model.ConnectionInfo
import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnector
import org.eclipse.kuksa.connectivity.databroker.DataBrokerException
import java.io.IOException

class DataBrokerConnectorFactory {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import org.eclipse.kuksa.DataBrokerConnection
import org.eclipse.kuksa.DisconnectListener
import org.eclipse.kuksa.connectivity.databroker.DataBrokerConnection
import org.eclipse.kuksa.connectivity.databroker.listener.DisconnectListener
import kotlin.properties.Delegates

class ConnectionViewModel : ViewModel() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ import org.eclipse.kuksa.companion.feature.door.viewModel.DoorControlViewModel
import org.eclipse.kuksa.companion.ramses.AndroidRamsesScene
import org.eclipse.kuksa.vss.VssDoor
import org.eclipse.kuksa.vss.VssTrunk
import org.eclipse.kuksa.vsscore.model.VssProperty
import org.eclipse.kuksa.vsscore.model.findProperties
import org.eclipse.kuksa.vsscore.model.findProperty
import org.eclipse.kuksa.vsscore.model.VssSignal
import org.eclipse.kuksa.vsscore.model.findSignal

interface DoorVehicleScene : AndroidRamsesScene {
fun updateDoors(door: VssDoor)
Expand All @@ -46,16 +45,16 @@ interface DoorVehicleScene : AndroidRamsesScene {
// - remove touch-related events: onTouchUp, onMotion
// - Couple to ViewModels and implement DoorVehicleScene interface
// - Rename variable names
// - Uses generated VssSpecifications for the models
// - Uses generated VssNodes for the models
class DoorVehicleSceneThread(
threadName: String,
private val viewModel: DoorControlViewModel,
) : RamsesThread(threadName, viewModel.getApplication()), DoorVehicleScene {
private var doorRow1DriverSide: VssProperty<Boolean> = VssDoor.VssRow1.VssDriverSide.VssIsOpen()
private var doorRow1PassengerSide: VssProperty<Boolean> = VssDoor.VssRow1.VssPassengerSide.VssIsOpen()
private var doorRow2DriverSide: VssProperty<Boolean> = VssDoor.VssRow2.VssDriverSide.VssIsOpen()
private var doorRow2PassengerSide: VssProperty<Boolean> = VssDoor.VssRow2.VssPassengerSide.VssIsOpen()
private var doorTrunkRear: VssProperty<Boolean> = VssTrunk.VssRear.VssIsOpen()
private var doorRow1DriverSide: VssSignal<Boolean> = VssDoor.VssRow1.VssDriverSide.VssIsOpen()
private var doorRow1PassengerSide: VssSignal<Boolean> = VssDoor.VssRow1.VssPassengerSide.VssIsOpen()
private var doorRow2DriverSide: VssSignal<Boolean> = VssDoor.VssRow2.VssDriverSide.VssIsOpen()
private var doorRow2PassengerSide: VssSignal<Boolean> = VssDoor.VssRow2.VssPassengerSide.VssIsOpen()
private var doorTrunkRear: VssSignal<Boolean> = VssTrunk.VssRear.VssIsOpen()

private var yawValue = 0f
private var pitchValue = 0f
Expand Down Expand Up @@ -184,20 +183,26 @@ class DoorVehicleSceneThread(
}

// region: VehicleScene
@Suppress("UNCHECKED_CAST") // TODO: Remove cast when .findSignal is fixed inside the SDK
override fun updateDoors(door: VssDoor) {
addRunnableToThreadQueue {
door.findProperties(VssDoor.VssRow1.VssPassengerSide.VssIsOpen::class).apply {
door.findSignal(VssDoor.VssRow1.VssPassengerSide.VssIsOpen::class).apply {
doorRow1DriverSide = getOrDefault(doorRow1DriverSide.vssPath, doorRow1DriverSide)
as VssSignal<Boolean>
doorRow1PassengerSide = getOrDefault(doorRow1PassengerSide.vssPath, doorRow1PassengerSide)
as VssSignal<Boolean>
doorRow2DriverSide = getOrDefault(doorRow2DriverSide.vssPath, doorRow2DriverSide)
as VssSignal<Boolean>
doorRow2PassengerSide = getOrDefault(doorRow2PassengerSide.vssPath, doorRow2PassengerSide)
as VssSignal<Boolean>
}
}
}

@Suppress("UNCHECKED_CAST") // TODO: Remove cast when .findSignal is fixed inside the SDK
override fun updateTrunk(trunk: VssTrunk) {
addRunnableToThreadQueue {
doorTrunkRear = trunk.findProperty(VssTrunk.VssRear.VssIsOpen())
doorTrunkRear = trunk.findSignal(VssTrunk.VssRear.VssIsOpen()) as VssSignal<Boolean>
}
}
// endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ fun DoorOverlayView(
ConstraintLayout(
modifier = modifier.fillMaxSize(),
) {
val (driverSide, passengerSide, driverSideBack, passengerSideBack, trunkRear) = createRefs()
val (driverSideRef, driverSideBackRef, trunkRearRef) = createRefs()
val (passengerSideRef, passengerSideBackRef) = createRefs()

val isLockedDriverSide = viewModel.door.row1.driverSide.isLocked
val isLockedPassengerSide = viewModel.door.row1.passengerSide.isLocked
Expand Down Expand Up @@ -82,7 +83,7 @@ fun DoorOverlayView(
.size(60.dp)
Box(
modifier = imageModifier
.constrainAs(driverSide) {
.constrainAs(driverSideRef) {
driverFrontDoorAnchor.align(this)
}
.clickable {
Expand All @@ -98,7 +99,7 @@ fun DoorOverlayView(

Box(
modifier = imageModifier
.constrainAs(passengerSide) {
.constrainAs(passengerSideRef) {
passengerFrontDoorAnchor.align(this)
}
.clickable {
Expand All @@ -115,7 +116,7 @@ fun DoorOverlayView(
painter = painterResource(id = viewModel.fetchLockDrawable(isLockedDriverSideBack.value)),
contentDescription = "Lock bottom left",
modifier = imageModifier
.constrainAs(driverSideBack) {
.constrainAs(driverSideBackRef) {
driverBackDoorAnchor.align(this)
}
.clickable {
Expand All @@ -124,7 +125,7 @@ fun DoorOverlayView(
)
Box(
modifier = imageModifier
.constrainAs(passengerSideBack) {
.constrainAs(passengerSideBackRef) {
passengerBackDoorAnchor.align(this)
}
.clickable {
Expand All @@ -140,7 +141,7 @@ fun DoorOverlayView(

Box(
modifier = imageModifier
.constrainAs(trunkRear) {
.constrainAs(trunkRearRef) {
trunkAnchor.align(this)
}
.clickable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,42 +29,42 @@ import androidx.lifecycle.AndroidViewModel
import org.eclipse.kuksa.companion.R
import org.eclipse.kuksa.companion.extension.TAG
import org.eclipse.kuksa.companion.feature.door.surface.DoorVehicleScene
import org.eclipse.kuksa.companion.listener.FilteredVssSpecificationListener
import org.eclipse.kuksa.companion.listener.FilteredVssNodeListener
import org.eclipse.kuksa.vss.VssDoor
import org.eclipse.kuksa.vss.VssTrunk
import org.eclipse.kuksa.vsscore.model.VssProperty
import org.eclipse.kuksa.vsscore.model.VssSignal

class DoorControlViewModel(application: Application) : AndroidViewModel(application) {
var doorVehicleSceneDelegate: DoorVehicleScene? = null

val vssDoorListener = object : FilteredVssSpecificationListener<VssDoor>() {
override fun onSpecificationChanged(vssSpecification: VssDoor) {
door = vssSpecification
doorVehicleSceneDelegate?.updateDoors(vssSpecification)
val vssDoorListener = object : FilteredVssNodeListener<VssDoor>() {
override fun onNodeChanged(vssNode: VssDoor) {
door = vssNode
doorVehicleSceneDelegate?.updateDoors(vssNode)
}

override fun onPostFilterError(throwable: Throwable) {
Log.e(TAG, "Failed to subscribe to specification: $throwable")
Log.e(TAG, "Failed to subscribe to node: $throwable")
}
}
val vssTrunkListener = object : FilteredVssSpecificationListener<VssTrunk>() {
override fun onSpecificationChanged(vssSpecification: VssTrunk) {
trunk = vssSpecification
doorVehicleSceneDelegate?.updateTrunk(vssSpecification)
val vssTrunkListener = object : FilteredVssNodeListener<VssTrunk>() {
override fun onNodeChanged(vssNode: VssTrunk) {
trunk = vssNode
doorVehicleSceneDelegate?.updateTrunk(vssNode)
}

override fun onPostFilterError(throwable: Throwable) {
Log.e(TAG, "Failed to subscribe to specification: $throwable")
Log.e(TAG, "Failed to subscribe to node: $throwable")
}
}

var onClickOpenAll: () -> Unit = {}

var onClickCloseAll: () -> Unit = {}

var onClickToggleDoor: (VssProperty<Boolean>) -> Unit = {}
var onClickToggleDoor: (VssSignal<Boolean>) -> Unit = {}

var onClickToggleTrunk: (VssProperty<Boolean>) -> Unit = {}
var onClickToggleTrunk: (VssSignal<Boolean>) -> Unit = {}

var trunk by mutableStateOf(VssTrunk())
private set
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import org.eclipse.kuksa.companion.extension.DarkGreen
import org.eclipse.kuksa.companion.feature.light.viewmodel.LightControlViewModel
import org.eclipse.kuksa.vsscore.model.VssProperty
import org.eclipse.kuksa.vsscore.model.VssSignal

@Composable
fun LightControlView(
Expand Down Expand Up @@ -104,7 +104,7 @@ fun LightControlView(
@Composable
private fun LightButton(
viewModel: LightControlViewModel,
vssProperty: VssProperty<Boolean>,
vssProperty: VssSignal<Boolean>,
text: String,
) {
val containerColor = if (vssProperty.value) Color.DarkGreen else Color.Red
Expand Down
Loading
Loading