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

Migrate FapHub to new api #1003

Open
wants to merge 7 commits into
base: makeevrserg/new-ble-api/info
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ internal object HardwareColorSerializer : KSerializer<HardwareColor> {
override fun serialize(encoder: Encoder, value: HardwareColor) {
encoder.encodeInt(value.value)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ commonDependencies {
implementation(projects.components.bridge.connection.feature.getinfo.api)
implementation(projects.components.bridge.connection.feature.alarm.api)
implementation(projects.components.bridge.connection.feature.deviceColor.api)
implementation(projects.components.bridge.connection.feature.appstart.api)

implementation(libs.kotlin.coroutines)
implementation(libs.kotlin.immutable.collections)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.flipperdevices.bridge.connection.device.fzero.impl.utils

import com.flipperdevices.bridge.connection.feature.alarm.api.FAlarmFeatureApi
import com.flipperdevices.bridge.connection.feature.appstart.api.FAppStartFeatureApi
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeature
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureApi
import com.flipperdevices.bridge.connection.feature.devicecolor.api.FDeviceColorFeatureApi
import com.flipperdevices.bridge.connection.feature.getinfo.api.FGattInfoFeatureApi
import com.flipperdevices.bridge.connection.feature.getinfo.api.FGetInfoFeatureApi
import com.flipperdevices.bridge.connection.feature.protocolversion.api.FSdkVersionFeatureApi
import com.flipperdevices.bridge.connection.feature.protocolversion.api.FVersionFeatureApi
import com.flipperdevices.bridge.connection.feature.restartrpc.api.FRestartRpcFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.api.FRpcFeatureApi
Expand All @@ -22,6 +24,7 @@ object FZeroFeatureClassToEnumMapper {
private val classToEnumMap: ImmutableMap<KClass<out FDeviceFeatureApi>, FDeviceFeature> =
FDeviceFeature.entries.associateBy { featureEnumToClass(it) }.toPersistentMap()

@Suppress("CyclomaticComplexMethod")
private fun featureEnumToClass(feature: FDeviceFeature): KClass<out FDeviceFeatureApi> {
return when (feature) {
FDeviceFeature.RPC -> FRpcFeatureApi::class
Expand All @@ -36,6 +39,8 @@ object FZeroFeatureClassToEnumMapper {
FDeviceFeature.ALARM -> FAlarmFeatureApi::class
FDeviceFeature.DEVICE_COLOR -> FDeviceColorFeatureApi::class
FDeviceFeature.GATT_INFO -> FGattInfoFeatureApi::class
FDeviceFeature.SDK_VERSION -> FSdkVersionFeatureApi::class
FDeviceFeature.APP_START -> FAppStartFeatureApi::class
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
plugins {
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
}

android.namespace = "com.flipperdevices.bridge.connection.feature.appstart.api"

commonDependencies {
implementation(projects.components.core.data)
implementation(projects.components.core.ktx)

implementation(projects.components.bridge.connection.feature.common.api)
implementation(projects.components.bridge.connection.transport.common.api)
implementation(projects.components.bridge.connection.feature.rpcinfo.api)

implementation(libs.kotlin.immutable.collections)
implementation(libs.kotlin.coroutines)
implementation(libs.okio)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.flipperdevices.bridge.connection.feature.appstart.api

import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureApi

interface FAppStartFeatureApi : FDeviceFeatureApi {
suspend fun startApp(path: okio.Path): Result<Unit>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
plugins {
id("flipper.multiplatform")
id("flipper.multiplatform-dependencies")
id("flipper.anvil-multiplatform")
}

android.namespace = "com.flipperdevices.bridge.connection.feature.appstart.impl"

commonDependencies {
implementation(projects.components.bridge.connection.feature.appstart.api)

implementation(projects.components.core.di)
implementation(projects.components.core.log)
implementation(projects.components.core.ktx)
implementation(projects.components.core.data)

implementation(projects.components.bridge.connection.feature.common.api)
implementation(projects.components.bridge.connection.transport.common.api)
implementation(projects.components.bridge.connection.feature.rpc.api)
implementation(projects.components.bridge.connection.feature.rpc.model)
implementation(projects.components.bridge.connection.feature.rpcinfo.api)
implementation(projects.components.bridge.connection.feature.protocolversion.api)

implementation(projects.components.bridge.connection.pbutils)

implementation(libs.kotlin.coroutines)
implementation(libs.okio)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package com.flipperdevices.bridge.connection.feature.appstart.impl.api

import com.flipperdevices.bridge.connection.feature.appstart.api.FAppStartFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.api.FRpcFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.model.wrapToRequest
import com.flipperdevices.core.log.LogTagProvider
import com.flipperdevices.core.log.info
import com.flipperdevices.protobuf.Main
import com.flipperdevices.protobuf.app.StartRequest
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import okio.Path

class FAppStartFeatureApiImpl @AssistedInject constructor(
@Assisted private val rpcFeatureApi: FRpcFeatureApi,
) : FAppStartFeatureApi,
LogTagProvider {
override val TAG = "FAlarmFeatureApi"

override suspend fun startApp(path: Path): Result<Unit> {
info { "#startApp path: $path" }
return rpcFeatureApi.requestOnce(
Main(
app_start_request = StartRequest(path.toString())
).wrapToRequest()
).map { }
}

@AssistedFactory
fun interface InternalFactory {
operator fun invoke(
rpcFeatureApi: FRpcFeatureApi,
): FAppStartFeatureApiImpl
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.flipperdevices.bridge.connection.feature.appstart.impl.api

import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeature
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureApi
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureQualifier
import com.flipperdevices.bridge.connection.feature.common.api.FUnsafeDeviceFeatureApi
import com.flipperdevices.bridge.connection.feature.protocolversion.api.FVersionFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.api.FRpcFeatureApi
import com.flipperdevices.bridge.connection.transport.common.api.FConnectedDeviceApi
import com.flipperdevices.core.data.SemVer
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.core.log.error
import com.flipperdevices.core.log.info
import com.squareup.anvil.annotations.ContributesMultibinding
import kotlinx.coroutines.CoroutineScope
import javax.inject.Inject

// TODO move to consts
val API_SUPPORTED_LOAD_FAP = SemVer(
majorVersion = 0,
minorVersion = 18
)

@FDeviceFeatureQualifier(FDeviceFeature.APP_START)
@ContributesMultibinding(AppGraph::class, FDeviceFeatureApi.Factory::class)
class FAppStartFeatureFactoryImpl @Inject constructor(
private val factory: FAppStartFeatureApiImpl.InternalFactory
) : FDeviceFeatureApi.Factory {
override suspend fun invoke(
unsafeFeatureDeviceApi: FUnsafeDeviceFeatureApi,
scope: CoroutineScope,
connectedDevice: FConnectedDeviceApi
): FDeviceFeatureApi? {
val versionApi = unsafeFeatureDeviceApi.getUnsafe(FVersionFeatureApi::class) ?: return null
info { "Start request supported state for api level $API_SUPPORTED_LOAD_FAP" }
val isSupported = versionApi.isSupported(API_SUPPORTED_LOAD_FAP)
if (!isSupported) {
error { "Failed init FDeviceColorFeatureApi, because isSupported=false" }
return null
}
val rpcApi = unsafeFeatureDeviceApi.getUnsafe(FRpcFeatureApi::class) ?: return null
return factory(
rpcFeatureApi = rpcApi,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ enum class FDeviceFeature {
ALARM,
DEVICE_COLOR,
GATT_INFO,
SDK_VERSION,
APP_START
}

@Retention(AnnotationRetention.RUNTIME)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ class FDeviceColorFeatureApiImpl @AssistedInject constructor(
}

val intHardwareColor = fGetInfoFeatureApi.get(FGetInfoApiProperty.DeviceInfo.HARDWARE_COLOR)
.onFailure { error(
it
) { "#updateAndGetColorFlow could not fetch ${FGetInfoApiProperty.DeviceInfo.HARDWARE_COLOR}" } }
.onFailure {
error(
it
) { "#updateAndGetColorFlow could not fetch ${FGetInfoApiProperty.DeviceInfo.HARDWARE_COLOR}" }
}
.map { it.toIntOrNull() }
.getOrNull()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.flipperdevices.bridge.connection.feature.protocolversion.api

import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureApi
import com.flipperdevices.core.data.SemVer

interface FSdkVersionFeatureApi : FDeviceFeatureApi {
suspend fun getSdkVersion(): Result<SemVer>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ android.namespace = "com.flipperdevices.bridge.connection.feature.protocolversio

commonDependencies {
implementation(projects.components.bridge.connection.feature.protocolversion.api)
implementation(projects.components.bridge.connection.feature.rpc.api)
implementation(projects.components.bridge.connection.feature.rpc.model)

implementation(projects.components.bridge.connection.pbutils)

implementation(projects.components.core.di)
implementation(projects.components.core.data)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package com.flipperdevices.bridge.connection.feature.protocolversion.impl.api

import com.flipperdevices.bridge.connection.feature.protocolversion.api.FSdkVersionFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.api.FRpcFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.model.wrapToRequest
import com.flipperdevices.core.data.SemVer
import com.flipperdevices.core.log.info
import com.flipperdevices.protobuf.Main
import com.flipperdevices.protobuf.property.GetRequest
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.flow.toList

class FSdkVersionFeatureApiImpl @AssistedInject constructor(
@Assisted private val rpcFeatureApi: FRpcFeatureApi,
) : FSdkVersionFeatureApi {

override suspend fun getSdkVersion(): Result<SemVer> = runCatching {
val answers = rpcFeatureApi.request(
Main(
property_get_request = GetRequest(
key = RPC_SDK_KEY
)
).wrapToRequest()
).toList()
info { "Receive ${answers.size} answers by $RPC_SDK_KEY, $answers" }
val major = answers
.firstOrNull { result ->
result.getOrNull()?.property_get_response?.key == RPC_SDK_MAJOR_KEY
}
?.getOrNull()?.property_get_response
?.value_
?.toIntOrNull()
?: error("Answer doesn't contains $RPC_SDK_MAJOR_KEY")

val minor = answers
.firstOrNull { result ->
result.getOrNull()?.property_get_response?.key == RPC_SDK_MINOR_KEY
}
?.getOrNull()?.property_get_response
?.value_
?.toIntOrNull()
?: error("Answer doesn't contains $RPC_SDK_MINOR_KEY")

info { "Receive version $major and $minor" }

SemVer(
majorVersion = major,
minorVersion = minor
)
}

@AssistedFactory
fun interface InternalFactory {
operator fun invoke(
rpcFeatureApi: FRpcFeatureApi,
): FSdkVersionFeatureApiImpl
}

companion object {
private const val RPC_SDK_KEY = "devinfo.firmware.api"
private const val RPC_SDK_MAJOR_KEY = "firmware.api.major"
private const val RPC_SDK_MINOR_KEY = "firmware.api.minor"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.flipperdevices.bridge.connection.feature.protocolversion.impl.api

import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeature
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureApi
import com.flipperdevices.bridge.connection.feature.common.api.FDeviceFeatureQualifier
import com.flipperdevices.bridge.connection.feature.common.api.FUnsafeDeviceFeatureApi
import com.flipperdevices.bridge.connection.feature.protocolversion.api.FVersionFeatureApi
import com.flipperdevices.bridge.connection.feature.rpc.api.FRpcFeatureApi
import com.flipperdevices.bridge.connection.transport.common.api.FConnectedDeviceApi
import com.flipperdevices.core.data.SemVer
import com.flipperdevices.core.di.AppGraph
import com.flipperdevices.core.log.error
import com.flipperdevices.core.log.info
import com.squareup.anvil.annotations.ContributesMultibinding
import kotlinx.coroutines.CoroutineScope
import javax.inject.Inject

// todo move to shared const
private val API_SUPPORTED_GET_REQUEST = SemVer(
majorVersion = 0,
minorVersion = 14
)

@FDeviceFeatureQualifier(FDeviceFeature.SDK_VERSION)
@ContributesMultibinding(AppGraph::class, FDeviceFeatureApi.Factory::class)
class FSdkVersionFeatureFactoryImpl @Inject constructor(
private val factory: FSdkVersionFeatureApiImpl.InternalFactory
) : FDeviceFeatureApi.Factory {
override suspend fun invoke(
unsafeFeatureDeviceApi: FUnsafeDeviceFeatureApi,
scope: CoroutineScope,
connectedDevice: FConnectedDeviceApi
): FDeviceFeatureApi? {
val versionApi = unsafeFeatureDeviceApi.getUnsafe(FVersionFeatureApi::class) ?: return null
info { "Start request supported state for api level $API_SUPPORTED_GET_REQUEST" }
val isSupported = versionApi.isSupported(API_SUPPORTED_GET_REQUEST)
if (!isSupported) {
error { "Failed init FDeviceColorFeatureApi, because isSupported=false" }
return null
}
val rpcApi = unsafeFeatureDeviceApi.getUnsafe(FRpcFeatureApi::class) ?: return null
return factory(
rpcFeatureApi = rpcApi
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class FlipperService : LifecycleService(), LogTagProvider {
override fun onCreate() {
super.onCreate()
info { "Start flipper service" }
return

val component = ComponentHolder
.component<FlipperServiceComponent>()
Expand Down
11 changes: 8 additions & 3 deletions components/faphub/installation/button/impl/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ dependencies {
implementation(projects.components.rootscreen.api)
implementation(projects.components.deeplink.api)

implementation(projects.components.bridge.api)
implementation(projects.components.bridge.service.api)
implementation(projects.components.bridge.pbutils)
implementation(projects.components.bridge.connection.feature.common.api)
implementation(projects.components.bridge.connection.feature.rpcinfo.api)
implementation(projects.components.bridge.connection.feature.provider.api)
implementation(projects.components.bridge.connection.feature.storage.api)
implementation(projects.components.bridge.connection.feature.protocolversion.api)
implementation(projects.components.bridge.connection.feature.appstart.api)
implementation(projects.components.bridge.connection.feature.rpc.api)

implementation(projects.components.faphub.installation.stateprovider.api)
implementation(projects.components.faphub.installation.manifest.api)
Expand All @@ -43,4 +47,5 @@ dependencies {

implementation(libs.kotlin.coroutines)
implementation(libs.lifecycle.viewmodel.ktx)
implementation(libs.okio)
}
Loading