Skip to content

Commit

Permalink
UI generator (#3)
Browse files Browse the repository at this point in the history
### Background
This PR introduces better UI generator with new button types and icons

This PR also introduces new route `/infrareds?brand_id=0` to see brand's infrared files
  • Loading branch information
makeevrserg authored Aug 29, 2024
1 parent c789c5e commit 370dd43
Show file tree
Hide file tree
Showing 55 changed files with 1,959 additions and 495 deletions.
2 changes: 1 addition & 1 deletion IRDB
Submodule IRDB updated 5134 files
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ org.gradle.parallel=true
makeevrserg.project.name=IfrBackend
makeevrserg.project.url=https://github.com/makeevrserg/IfrSample
makeevrserg.project.group=com.flipperdevices.ifrmvp.backend
makeevrserg.project.version.string=0.2.1
makeevrserg.project.version.string=0.3.0
makeevrserg.project.description=Api for IfrSample
makeevrserg.project.developers=makeevrserg|Makeev Roman|[email protected]
# Java
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.flipperdevices.infrared.editor.encoding

import com.flipperdevices.ifrmvp.model.IfrKeyIdentifier
import com.flipperdevices.infrared.editor.model.InfraredRemote

/**
Expand All @@ -8,7 +9,7 @@ import com.flipperdevices.infrared.editor.model.InfraredRemote
* Then we flatten it to have single byte array.
*/
object InfraredRemoteEncoder {
fun encode(remote: InfraredRemote): ByteArray {
private fun encode(remote: InfraredRemote): ByteArray {
val bytesList = when (remote) {
is InfraredRemote.Parsed -> listOf(
remote.type,
Expand All @@ -28,4 +29,10 @@ object InfraredRemoteEncoder {
.flatMap(ByteArray::asList)
.toByteArray()
}
val InfraredRemote.identifier: IfrKeyIdentifier.Sha256
get() {
val byteArray = InfraredRemoteEncoder.encode(this)
val sha256 = JvmEncoder(ByteArrayEncoder.Algorithm.SHA_256).encode(byteArray)
return IfrKeyIdentifier.Sha256(name, sha256)
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
package com.flipperdevices.ifrmvp.generator.config

import com.flipperdevices.bridge.dao.api.model.FlipperFileFormat
import com.flipperdevices.ifrmvp.backend.model.CategoryType
import com.flipperdevices.ifrmvp.generator.config.category.api.AllCategoryConfigGenerator
import com.flipperdevices.ifrmvp.backend.model.DeviceKey
import com.flipperdevices.ifrmvp.generator.config.category.api.AirPurifierCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.AvReceiverCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.BoxCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.CameraCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.DeviceKeyExt
import com.flipperdevices.ifrmvp.generator.config.category.api.DeviceKeyExt.getAllowedCategories
import com.flipperdevices.ifrmvp.generator.config.category.api.DvdCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.FanCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.ProjectorCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.category.api.TvsCategoryConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.device.api.DefaultDeviceConfigGenerator
import com.flipperdevices.ifrmvp.generator.config.device.api.any.AnyDeviceKeyNamesProvider
import com.flipperdevices.ifrmvp.parser.util.ParserPathResolver
import com.flipperdevices.infrared.editor.viewmodel.InfraredKeyParser
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json

Expand All @@ -19,7 +31,16 @@ private fun generateCategoriesConfigFiles() {
.categories
.onEach { categoryFolder ->
val categoryType = CategoryType.entries.first { it.folderName == categoryFolder.name }
val config = AllCategoryConfigGenerator.generate(categoryType)
val config = when (categoryType) {
CategoryType.A_V_RECEIVER -> AvReceiverCategoryConfigGenerator.generate(categoryType)
CategoryType.AIR_PURIFIERS -> AirPurifierCategoryConfigGenerator.generate(categoryType)
CategoryType.BOX -> BoxCategoryConfigGenerator.generate(categoryType)
CategoryType.CAMERA -> CameraCategoryConfigGenerator.generate(categoryType)
CategoryType.DVD -> DvdCategoryConfigGenerator.generate(categoryType)
CategoryType.FAN -> FanCategoryConfigGenerator.generate(categoryType)
CategoryType.PROJECTOR -> ProjectorCategoryConfigGenerator.generate(categoryType)
CategoryType.TVS -> TvsCategoryConfigGenerator.generate(categoryType)
}
val configFile = ParserPathResolver.categoryMetaPath(categoryFolder.name).resolve("config.json")
if (configFile.exists()) configFile.delete()
configFile.createNewFile()
Expand Down Expand Up @@ -49,7 +70,46 @@ private fun generateDevicesConfigFiles() {
}
}

fun printAllKeys() {

val keyNames = DeviceKey.entries.associateWith { AnyDeviceKeyNamesProvider.getKeyNames(it) }
val namesToCategories = mutableMapOf<String, MutableSet<String>>()
val nameToCount = mutableMapOf<String, Int>()
ParserPathResolver
.categories
.filter { it.name.equals("TVs", true) }
.flatMap { categoryFolder ->
ParserPathResolver.brands(categoryFolder.name)
.flatMap { brandFolder ->
ParserPathResolver.brandIfrFiles(
category = categoryFolder.name,
brand = brandFolder.name
).flatMap { irFile ->
val signals = irFile
.readText()
.let(FlipperFileFormat.Companion::fromFileContent)
.let(InfraredKeyParser::mapParsedKeyToInfraredRemotes)
.onEach { signal ->
val set = namesToCategories[signal.name.lowercase()] ?: mutableSetOf()
set.add(categoryFolder.name)
namesToCategories[signal.name.lowercase()] = set
nameToCount[signal.name.lowercase()] = (nameToCount[signal.name.lowercase()] ?: 0) + 1
}
signals
}
}
}.distinctBy { it.name.lowercase() }
// .sortedBy { it.name.lowercase() }
.sortedByDescending { nameToCount[it.name.lowercase()] }
.onEach { key ->
val filteredMap = keyNames.filterValues { it.map { it.lowercase() }.contains(key.name.lowercase()) }
println("${key.name.lowercase()} -> ${nameToCount[key.name.lowercase()]} ${namesToCategories[key.name.lowercase()]} -> ${filteredMap.map { (k, v) -> "$k - ${k.getAllowedCategories()} -${v}" }}")
}

}

fun main() {
generateCategoriesConfigFiles()
generateDevicesConfigFiles()
// printAllKeys()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.flipperdevices.ifrmvp.generator.config.category.api

import com.flipperdevices.ifrmvp.backend.model.CategoryConfiguration
import com.flipperdevices.ifrmvp.backend.model.CategoryType
import com.flipperdevices.ifrmvp.backend.model.DeviceKey
import com.flipperdevices.ifrmvp.generator.config.category.api.DeviceKeyExt.getAllowedCategories
import com.flipperdevices.ifrmvp.model.buttondata.IconButtonData
import com.flipperdevices.ifrmvp.model.buttondata.PowerButtonData
import com.flipperdevices.ifrmvp.model.buttondata.ShutterButtonData
import com.flipperdevices.ifrmvp.model.buttondata.TextButtonData

object AirPurifierCategoryConfigGenerator {
@Suppress("LongMethod")
fun generate(): CategoryConfiguration {
var i =0
return CategoryConfiguration(
orders = listOf(
CategoryConfiguration.OrderModel(
data = PowerButtonData(),
message = "Does %s turns on?",
key = DeviceKey.PWR,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Is it oscillated?",
data = TextButtonData(text = "OSC"),
key = DeviceKey.OSCILLATE,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Is Fan speed increased??",
data = TextButtonData(text = "FS+"),
key = DeviceKey.FAN_SPEED_UP,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Is Fan speed decreased?",
data = TextButtonData(text = "FS-"),
key = DeviceKey.FAN_SPEED_DOWN,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Does it swing?",
data = TextButtonData(text = "SW"),
key = DeviceKey.SWING,
index = ++i,
),
)
)
}

fun generate(categoryType: CategoryType): CategoryConfiguration {
val configuration = generate()
return CategoryConfiguration(
orders = configuration.orders.filter {
it.key.getAllowedCategories().contains(categoryType)
}
)
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.flipperdevices.ifrmvp.generator.config.category.api

import com.flipperdevices.ifrmvp.backend.model.CategoryConfiguration
import com.flipperdevices.ifrmvp.backend.model.CategoryType
import com.flipperdevices.ifrmvp.backend.model.DeviceKey
import com.flipperdevices.ifrmvp.generator.config.category.api.DeviceKeyExt.getAllowedCategories
import com.flipperdevices.ifrmvp.model.buttondata.IconButtonData
import com.flipperdevices.ifrmvp.model.buttondata.PowerButtonData
import com.flipperdevices.ifrmvp.model.buttondata.ShutterButtonData
import com.flipperdevices.ifrmvp.model.buttondata.TextButtonData

object AvReceiverCategoryConfigGenerator {
@Suppress("LongMethod")
fun generate(): CategoryConfiguration {
var i = 0
return CategoryConfiguration(
orders = listOf(
CategoryConfiguration.OrderModel(
data = PowerButtonData(),
message = "Does %s turns on?",
key = DeviceKey.PWR,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Does volume go up?",
data = IconButtonData(iconId = IconButtonData.IconType.VOL_UP),
key = DeviceKey.VOL_UP,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Does volume go down?",
data = IconButtonData(iconId = IconButtonData.IconType.VOL_DOWN),
key = DeviceKey.VOL_DOWN,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Is volume muted?",
data = IconButtonData(iconId = IconButtonData.IconType.MUTE),
key = DeviceKey.MUTE,
index = ++i,
),
CategoryConfiguration.OrderModel(
message = "Is menu opened?",
data = IconButtonData(iconId = IconButtonData.IconType.MENU),
key = DeviceKey.MENU,
index = ++i,
)
)
)
}

fun generate(categoryType: CategoryType): CategoryConfiguration {
val configuration = generate()
return CategoryConfiguration(
orders = configuration.orders.filter {
it.key.getAllowedCategories().contains(categoryType)
}
)
}
}
Loading

0 comments on commit 370dd43

Please sign in to comment.