Open uwap opened 7 years ago
Is there a list, what issues exist with the existing format?
Am 27.10.2017 22:25 schrieb "uwap" notifications@github.com:
We should design a new config format which is cleaner
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/uwap/space-map/issues/7, or mute the thread https://github.com/notifications/unsubscribe-auth/AAvaC0EhTmA1Lp4EcKIHTfDZKQML6mW9ks5swjw0gaJpZM4QJkwK .
it is clumsy. especially it will get more clumsy when I change a bit about the ui part. I guess I should first make the changes before thinking about how to clean up the config format.
We should definely change
my_component = {
icon: "home",
iconColor: ({some_topic}) => some_topic == "some_value" ? "#000" : "#111"
}
to
my_component = {
icon: {
name: "home",
color: ({some_topic}) => some_topic == "some_value" ? "#000" : "#111"
}
}
or even to
my_component = {
icon: {
mdi-name: "home",
color: ({some_topic}) => some_topic == "some_value" ? "#000" : "#111"
}
}
A further idea would be to also add a <component>.icon.topic
option for a more consistent behavior of functions in the config. That would lead to something like:
my_component = {
icon: {
mdi-name: "home",
color: (value) => value == "some_value" ? "#000" : "#111",
topic: "some_topic"
}
}
it would also allow to mix different icon sets:
first_component = {
icon: {
mdi-name: "home" // material design icons
}
},
second_component = {
icon: {
fa-name: "bell" // font awesome icons
}
}
Edit: Maybe do it like this:
first_component = {
icon: {
name: mdi("home") // material design icons
}
},
second_component = {
icon: {
name: font-awesome("bell") // font awesome icons
}
}
Additionally to the icons being weird in the config format, I think that the topics section is weird too.
I think it is not great that parseState
is needed that often. For the esper support in utils I needed to make the topics section an array. It is now an array of javascript objects, that gets merged. This is totally weird and provides possible error sources.
First of all, I want to provide a new way to describe message types. So instead of
onkyo_mute: {
state: "/service/onkyo/status/audio-muting",
command: "/service/onkyo/command",
defaultValue: "AMT00",
values: { off: "AMT00", on: "AMT01" },
parseState: msg => JSON.parse(msg.toString()).onkyo_raw
}
I want it to be like:
onkyo_mute: {
state: "/service/onkyo/status/audio-muting",
command: "/service/onkyo/command",
defaultValue: "AMT00",
values: { off: "AMT00", on: "AMT01" },
type: json("onkyo_raw")
}
Possible types would be string, number, json and date.
For the array part I need to brainstorm a bit more about possible ideas. cc @Bfritz0815 @Ranlvor
I like to rewrite icon colors.
Right now it is always a function. I don't like it. Instead, I want it to be either a color newtype or a javascript object or a function.
Examples:
icon: {
color: hex("#333333")
}
icon: {
color: rgb(255, 255, 100)
}
icon: {
topic: "lightswitch",
color: {
on: hex("#333999"),
off: rgba(255, 100, 100, 0.2)
}
}
icon: {
topic: "lightswitch",
color: {
on: hex("#333999"),
off: rgba(255, 100, 100, 0.2)
default: hex("#FFFFFF")
}
}
Maybe default should be always required or maybe the map should do a check if all possible values are covered.
Last but not least only for complex setups it should be possible to use a function:
icon: {
color: ({lightswitch}) => lightswitch == "on" ? hex("#333999") : hex("#001122")
}
Maybe flows $Keys type could be used to force the use of all values for colors if default is not given:
We should make the type
option for a topic required and not only have it define parseState
but also let it define values
(and maybe defaultValue too?).
This could result in this for example:
my_toggle: {
state: "/service/toggle/status",
command: "/service/toggle/command",
type: types.enum({on: "ON", off: "OFF"})
}
I always thought the internal representation of values was kind of redundant and unintuitive but sadly I couldn't find a way around that. Now that I'm looking at the topic types again I really think I've found a way.
Originally the parseState function was only a way around the lack of representations in the config format. But we could actually use it to emulate the internal representation thing. The best example is the my_toggle
topic from above. We could have types like types.enum
that actually map a value onto a representation. This could also work the other way around.
The only problem with this representation now is that parseState
only worked on the state and the internal representation work on both and we still want to support having different types in both directions.
I also thought about the types.json
example. A json could contain all sorts of values. Therefore I thought about making the following types valid
type: types.json("volume", types.number)
type: types.json("name", types.string)
type: types.json("switchState", types.enum({on: "POWERED", off: "DOWN"}))
In the very beginning of this project, we had actions. Each UI control would trigger an action. The action itself would then do something on certain topics. This seemed redundant to me, so we removed it really quickly. Especially since it had some flaws. A slider, mutating values, and a toggle button could in no way share the same actions. But the way we defined actions had no way of preventing it.
We need to reinvent actions in a non redundant way. One slider for example could easily modify multiple values, for example when changing the brightness of a lighting group. A toggle button could toggle multiple things at once. It should be even possible to have it toggle between two of many options.
One way I can think of this is expanding the topic
setting to actual allow multiple topics.
For example an old way of defining a button could look like this:
{
type: "toggle",
on: "50",
off: "0",
toggled: n => parseInt(n) > 0,
topic: "kitchen_light_brightness",
text: "Ein/Ausschalten",
icon: mdi("power")
}
A new way could look like this:
{
type: "toggle",
topics: {
kitchen_light_brightness: {
on: "50",
off: "0",
toggled: n => parseInt(n) > 0
},
kitchen_light_color: {
on: "50",
off: "0",
toggled: true
}
},
text: "Ein/Ausschalten",
icon: mdi("power")
},
This already has multiple drawbacks:
{}
or anything else unintuitive.The slider is a more interesting topic though. If a slider changes a light group consisting out of 3 light bulbs, each with their own mqtt topic, which one sets the actual light brightness / the state for this component?
Another thing that should be possible is having a slider controlling the light for example. When the slider is turned down to 0 is should be able to send "OFF", when it is turned higher than 0 it should sent "ON", but only once. I want the new actions to capable of doing so.
I thought about it. Maybe we can do something like this:
{
type: "slider",
topic: "kitchen_light_brightness",
text: "Brightness",
icon: mdi("power"),
actions: [
onDrag.oldValueEquals(0).newValueAbove(0).trigger("kitchen_light_power", "on"),
onDrag.oldValueAbove(0).newValueEquals(0).trigger("kitchen_light_power", "off")
]
}
This, but with a more elegant API would be a valid way to describe actions, I think.
With the config being essential close to JSON, the syntax seems increadibly bloaty. While actions might be a solution to increase the complexity of what we can express and might have the change to express this in a short and eloquent manner, it would be nice to have a custom syntax.
@ Define Config
[Space]
name: "Entropia"
color: "orange"
mqtt: "ws://...:1884"
[Topics]
"hauptraumTableLight" defaults to: "off"
- command topic "/public/sensoren/TPH/leinwand/control" as option("A1 ON" -> "on", "A1 OFF" -> "off")
"hauptraumTableLightOnHack" defaults to: "on"
- command topic "/public/sensoren/TPH/leinwand/control" as option("A1 ON" -> "on", "A1 OFF" -> "off")
[Controls]
Define "Hauptraum Tisch" for "hauptraumTableLight" at [450, 450]:
- icon: mdi("white-balance-iridescent"
- iconColor: hex("#000000")
With "Licht" as "toggle":
- topic: "hauptraumTableLight"
- icon: mdi("power")
With "Licht" as "toggle":
- topic: "hauptraumTableLightOnHack"
- icon: mdi("power")
// Define ... for ... etc.
[Layers]
Define BaseLayer "Entropia" from "./assets/layers/rooms.svg" as default "visible":
- opacity: 0.7
With Bounds:
- topLeft: [0, 0]
- bottomRight: [720, 680]
@ End Config
I could imagine something like this instead of the current entropia config. There might be a way to parse custom javascript syntax using Babel. We could then transform it to javascript. The only issue here would be the flow type checker, as it's important that it runs through AFTER transforming the custom syntax into javascript.
We should design a new config format which is cleaner.
Open questions: