Added support for GridPages

Added color support
Color interpolation
This commit is contained in:
britzelpuf
2022-03-21 00:00:54 +01:00
parent 7a37f58b51
commit a8f2c9d91d
2 changed files with 259 additions and 137 deletions

View File

@@ -1,3 +1,13 @@
type RGB = {
red: number,
green: number,
blue: number
};
const Red: RGB = { red: 255, green: 0, blue: 0 };
const White: RGB = { red: 255, green: 255, blue: 255 };
const Blue: RGB = { red: 68, green: 115, blue: 158 };
type Payload = { type Payload = {
payload: string; payload: string;
}; };
@@ -5,17 +15,21 @@ type Payload = {
type Page = { type Page = {
type: string, type: string,
heading: string heading: string
} };
interface PageEntities extends Page { interface PageEntities extends Page {
type: "cardEntities", type: "cardEntities",
items: string[] items: PageItem[]
} };
interface PageGrid extends Page {
type: "cardGrid",
items: PageItem[]
};
interface PageThermo extends Page { interface PageThermo extends Page {
type: "cardThermo", type: "cardThermo",
item: string item: PageItem
} };
type Config = { type Config = {
panelRecvTopic: string, panelRecvTopic: string,
panelSendTopic: string, panelSendTopic: string,
@@ -35,11 +49,21 @@ type Config = {
rightEntityIcon: number, rightEntityIcon: number,
rightEntityText: string, rightEntityText: string,
rightEntityUnitText: string | null, rightEntityUnitText: string | null,
pages: (PageThermo | PageEntities)[], defaultColor: RGB,
button1Page: (PageThermo | PageEntities | null), gridPageOnColor: RGB,
button2Page: (PageThermo | PageEntities | null), gridPageOffColor: RGB,
} pages: (PageThermo | PageEntities | PageGrid)[],
button1Page: (PageThermo | PageEntities | PageGrid | null),
button2Page: (PageThermo | PageEntities | PageGrid | null),
};
type PageItem = {
id: string,
icon: (string | undefined),
onColor: (RGB | undefined),
offColor: (RGB | undefined),
useColor: (boolean | undefined)
}
var subscriptions: any = {}; var subscriptions: any = {};
var pageId = 0; var pageId = 0;
@@ -49,10 +73,10 @@ var page1: PageEntities =
"type": "cardEntities", "type": "cardEntities",
"heading": "Haus", "heading": "Haus",
"items": [ "items": [
"alias.0.Rolladen_Eltern", <PageItem>{ id: "alias.0.Rolladen_Eltern" },
"alias.0.Erker", <PageItem>{ id: "alias.0.Erker" },
"alias.0.Küche", <PageItem>{ id: "alias.0.Küche", useColor: true },
"alias.0.Wand" <PageItem>{ id: "alias.0.Wand", useColor: true }
] ]
}; };
@@ -61,22 +85,21 @@ var page2: PageEntities =
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"items": [ "items": [
"alias.0.Netz", <PageItem>{ id: "alias.0.Netz" },
"alias.0.Hausverbrauch", <PageItem>{ id: "alias.0.Hausverbrauch" },
"alias.0.Pv", <PageItem>{ id: "alias.0.Pv" },
"alias.0.Batterie" <PageItem>{ id: "alias.0.Batterie" }
] ]
}; };
var button1Page: PageEntities = var button1Page: PageGrid =
{ {
"type": "cardEntities", "type": "cardGrid",
"heading": "Knopf1", "heading": "Radio",
"items": [ "items": [
"alias.0.Schlafen", <PageItem>{ id: "alias.0.Radio.NJoy" },
"alias.0.Stern", <PageItem>{ id: "alias.0.Radio.Delta_Radio" },
"delete", <PageItem>{ id: "alias.0.Radio.NDR2" },
"delete"
] ]
}; };
@@ -86,11 +109,8 @@ var button2Page: PageEntities =
"type": "cardEntities", "type": "cardEntities",
"heading": "Knopf2", "heading": "Knopf2",
"items": [ "items": [
"delete", <PageItem>{ id: "alias.0.Schlafen" },
"delete", <PageItem>{ id: "alias.0.Stern" }
"alias.0.Schlafen",
"alias.0.Stern"
] ]
}; };
@@ -111,14 +131,15 @@ var config: Config = {
timeFormat: "%H:%M", timeFormat: "%H:%M",
dateFormat: "%A, %d. %B %Y", dateFormat: "%A, %d. %B %Y",
weatherEntity: "alias.0.Wetter", weatherEntity: "alias.0.Wetter",
gridPageOffColor: Blue,
gridPageOnColor: White,
defaultColor: Blue,
temperatureUnit: "°C", temperatureUnit: "°C",
pages: [page1, page2, pages: [page1, page2,
{ {
"type": "cardThermo", "type": "cardThermo",
"heading": "Thermostat", "heading": "Thermostat",
"item": "alias.0.WzNsPanel" "item": <PageItem>{ id: "alias.0.WzNsPanel" }
} }
], ],
button1Page: button1Page, button1Page: button1Page,
@@ -132,6 +153,9 @@ schedule("0 * * * *", function () {
SendDate(); SendDate();
}); });
// Only monitor the extra nodes if one or both are present // Only monitor the extra nodes if one or both are present
var updateArray: string[] = []; var updateArray: string[] = [];
if (config.rightEntity !== null && existsState(config.rightEntity)) { if (config.rightEntity !== null && existsState(config.rightEntity)) {
@@ -201,18 +225,22 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
} }
function GeneratePage(page: Page): void { function GeneratePage(page: Page): void {
var retMsgs: Array<Payload> = [];
if (page.type == "cardEntities") {
retMsgs = GenerateEntitiesPage(<PageEntities>config.pages[pageId])
} else if (page.type == "cardThermo") {
retMsgs = GenerateThermoPage(pageId, <PageThermo>config.pages[pageId])
}
SendToPanel(retMsgs) switch (page.type) {
case "cardEntities":
SendToPanel(GenerateEntitiesPage(<PageEntities>page));
break;
case "cardThermo":
SendToPanel(GenerateThermoPage(<PageThermo>page));
break;
case "cardGrid":
SendToPanel(GenerateGridPage(<PageGrid>page));
break;
}
} }
function HandleHardwareButton(method: string): void { function HandleHardwareButton(method: string): void {
let page: (PageThermo | PageEntities); let page: (PageThermo | PageEntities | PageGrid);
if (config.button1Page !== null && method == "button1") { if (config.button1Page !== null && method == "button1") {
page = config.button1Page; page = config.button1Page;
} }
@@ -222,15 +250,18 @@ function HandleHardwareButton(method: string): void {
else { else {
return; return;
} }
SendToPanel({ payload: "wake" }); log("button1");
switch (page.type) { GeneratePage(page);
case "cardEntities":
SendToPanel(GenerateEntitiesPage(page)); //SendToPanel({ payload: "wake" });
break; // switch (page.type) {
case "cardThermo": // case "cardEntities":
SendToPanel(GenerateThermoPage(0, page)); // SendToPanel(GenerateEntitiesPage(page));
break; // break;
} // case "cardThermo":
// SendToPanel(GenerateThermoPage(0, page));
// break;
// }
} }
function HandleStartupProcess(): void { function HandleStartupProcess(): void {
@@ -270,78 +301,110 @@ function SendTime(): void {
function GenerateEntitiesPage(page: PageEntities): Payload[] { function GenerateEntitiesPage(page: PageEntities): Payload[] {
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }] out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }]
let pageData = "entityUpd"; out_msgs.push({ payload: GeneratePageElements(page.items, 4) });
page.items.forEach(function (id, i) {
pageData += CreateEntity(id, i + 1);
})
out_msgs.push({ payload: pageData });
return out_msgs return out_msgs
} }
function CreateEntity(id: string, placeId: number): string { function GenerateGridPage(page: PageGrid): Payload[] {
var type = "delete" var out_msgs: Array<Payload> = [];
var iconId = 0 out_msgs = [{ payload: "pageType,cardGrid" }, { payload: "entityUpdHeading," + page.heading }]
var name = "FriendlyName" out_msgs.push({ payload: GeneratePageElements(page.items, 6, true) });
if (id == "delete") { return out_msgs
return ",delete,,,,"
} }
function GeneratePageElements(pageItems: PageItem[], maxItems: number, useColors: boolean = false): string {
let pageData = "entityUpd";
for (let index = 0; index < maxItems; index++) {
if (pageItems[index] !== undefined) {
pageData += CreateEntity(pageItems[index], index + 1, useColors);
}
else {
pageData += CreateEntity(<PageItem>{ id: "delete" }, index + 1);
}
}
return pageData;
}
function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean = false): string {
var iconId = 0
if (pageItem.id == "delete") {
return ",delete,,,,,"
}
var name: string;
var type: string;
// ioBroker // ioBroker
if (existsObject(id)) { if (existsObject(pageItem.id)) {
let o = getObject(id) let o = getObject(pageItem.id)
var val = null; var val = null;
name = o.common.name.de name = o.common.name.de
if (existsState(id + ".GET")) { if (existsState(pageItem.id + ".GET")) {
val = getState(id + ".GET").val; val = getState(pageItem.id + ".GET").val;
RegisterEntityWatcher(id + ".GET", id, placeId); RegisterEntityWatcher(pageItem.id + ".GET", pageItem.id, placeId);
} }
else if (existsState(id + ".SET")) { else if (existsState(pageItem.id + ".SET")) {
val = getState(id + ".SET").val; val = getState(pageItem.id + ".SET").val;
RegisterEntityWatcher(id + ".SET", id, placeId); RegisterEntityWatcher(pageItem.id + ".SET", pageItem.id, placeId);
} }
var iconColor = rgb_dec565(useColors ? config.gridPageOffColor : config.defaultColor);
switch (o.common.role) { switch (o.common.role) {
case "light": case "light":
type = "light" type = "light"
iconId = 1 iconId = 1
var optVal = "0" var optVal = "0"
if (val === true || val === "true")
if (val === true || val === "true") {
optVal = "1" optVal = "1"
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal iconColor = rgb_dec565(useColors ? config.gridPageOnColor : config.defaultColor);
}
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal
case "dimmer": case "dimmer":
type = "light" type = "light"
iconId = 1 iconId = 1
var optVal = "0" var optVal = "0"
if (existsState(id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
val = getState(id + ".ON_ACTUAL").val; val = getState(pageItem.id + ".ON_ACTUAL").val;
RegisterEntityWatcher(id + ".ON_ACTUAL", id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId);
} }
else if (existsState(id + ".ON_SET")) { else if (existsState(pageItem.id + ".ON_SET")) {
val = getState(id + ".ON_SET").val; val = getState(pageItem.id + ".ON_SET").val;
RegisterEntityWatcher(id + ".ON_SET", id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_SET", pageItem.id, placeId);
} }
if (val === true || val === "true") if (val === true || val === "true") {
optVal = "1" optVal = "1"
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal if ((pageItem.useColor || useColors) && existsState(pageItem.id + ".ACTUAL")) {
let iconColorRgb =
Interpolate(
pageItem.onColor !== undefined ? pageItem.onColor : config.gridPageOffColor,
pageItem.offColor !== undefined ? pageItem.offColor : config.gridPageOnColor,
(getState(pageItem.id + ".ACTUAL").val / 100)
);
iconColor = rgb_dec565(iconColorRgb);
}
}
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal
case "blind": case "blind":
type = "shutter" type = "shutter"
iconId = 0 iconId = 0
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + ","
case "info": case "info":
case "value.temperature": case "value.temperature":
type = "text" type = "text"
var optVal = "0" var optVal = "0"
if (existsState(id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
optVal = getState(id + ".ON_ACTUAL").val + " " + GetUnitOfMeasurement(id + ".ON_ACTUAL"); optVal = getState(pageItem.id + ".ON_ACTUAL").val + " " + GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL");
RegisterEntityWatcher(id + ".ON_ACTUAL", id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId);
} }
else if (existsState(id + ".ACTUAL")) { else if (existsState(pageItem.id + ".ACTUAL")) {
optVal = getState(id + ".ACTUAL").val; optVal = getState(pageItem.id + ".ACTUAL").val;
RegisterEntityWatcher(id + ".ACTUAL", id, placeId); RegisterEntityWatcher(pageItem.id + ".ACTUAL", pageItem.id, placeId);
} }
if (o.common.role == "value.temperature") { if (o.common.role == "value.temperature") {
@@ -349,15 +412,15 @@ function CreateEntity(id: string, placeId: number): string {
optVal += config.temperatureUnit; optVal += config.temperatureUnit;
} }
else { else {
optVal += GetUnitOfMeasurement(id + ".ACTUAL"); optVal += GetUnitOfMeasurement(pageItem.id + ".ACTUAL");
} }
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal; return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal;
case "button": case "button":
type = "button"; type = "button";
iconId = 3; iconId = 3;
var optVal = "PRESS"; var optVal = "PRESS";
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal; return "," + type + "," + pageItem.id + "," + iconId + "," + + iconColor + "," + name + "," + optVal;
default: default:
return ",delete,,,," return ",delete,,,,"
@@ -365,7 +428,7 @@ function CreateEntity(id: string, placeId: number): string {
} }
} }
return ",delete,,,," return ",delete,,,,,"
} }
function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void { function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void {
@@ -402,8 +465,8 @@ function GetUnitOfMeasurement(id: string): string {
return ""; return "";
} }
function GenerateThermoPage(pageNum: number, page: PageThermo): Payload[] { function GenerateThermoPage(page: PageThermo): Payload[] {
var id = page.item var id = page.item.id
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
out_msgs.push({ payload: "pageType,cardThermo" }); out_msgs.push({ payload: "pageType,cardThermo" });
@@ -432,11 +495,38 @@ function GenerateThermoPage(pageNum: number, page: PageThermo): Payload[] {
return out_msgs return out_msgs
} }
function setIfExists(id: string, value: any, type: string | null = null): boolean {
if (type === null) {
if (existsState(id)) {
setState(id, value);
return true;
}
}
else {
let obj = getObject(id);
if (existsState(id) && obj.common.type !== undefined && obj.common.type === type) {
log(id)
setState(id, value);
return true;
}
}
return false;
}
function toggleState(id: string): boolean {
let obj = getObject(id);
if (existsState(id) && obj.common.type !== undefined && obj.common.type === "boolean") {
setState(id, !getState(id).val);
return true;
}
return false;
}
function HandleButtonEvent(words): void { function HandleButtonEvent(words): void {
let id = words[4] let id = words[4]
if (words[6] == "OnOff" && existsObject(id)) { if (words[6] == "OnOff" && existsObject(id)) {
var action = false var action = false
if (words[7] == "1") if (words[7] == "1")
action = true action = true
@@ -459,8 +549,12 @@ function HandleButtonEvent(words): void {
setState(id + ".STOP", true) setState(id + ".STOP", true)
if (words[6] == "down") if (words[6] == "down")
setState(id + ".CLOSE", true) setState(id + ".CLOSE", true)
if (words[6] == "button") if (words[6] == "button") {
setState(id + ".SET", true) let switchOn = true;
if (words[5] !== "1")
switchOn = false;
toggleState(id + ".SET") ? true : toggleState(id + ".ON_SET")
}
if (words[6] == "positionSlider") if (words[6] == "positionSlider")
setState(id + ".SET", parseInt(words[7])) setState(id + ".SET", parseInt(words[7]))
@@ -573,23 +667,19 @@ function HandleScreensaverUpdate(): void {
+ temperature + " " + config.temperatureUnit + "?26?" + temperature + " " + config.temperatureUnit + "?26?"
+ humidity + " %?"; + humidity + " %?";
if(existsState(config.leftEntity)) if (existsState(config.leftEntity)) {
{
let u1 = getState(config.leftEntity).val; let u1 = getState(config.leftEntity).val;
payloadString += config.leftEntityText + "?" + config.leftEntityIcon + "?" + u1 + " " + config.leftEntityUnitText + "?"; payloadString += config.leftEntityText + "?" + config.leftEntityIcon + "?" + u1 + " " + config.leftEntityUnitText + "?";
} }
else else {
{
payloadString += "???"; payloadString += "???";
} }
if(existsState(config.rightEntity)) if (existsState(config.rightEntity)) {
{
let u2 = getState(config.rightEntity).val; let u2 = getState(config.rightEntity).val;
payloadString += config.rightEntityText + "?" + config.rightEntityIcon + "?" + u2 + " " + config.rightEntityUnitText; payloadString += config.rightEntityText + "?" + config.rightEntityIcon + "?" + u2 + " " + config.rightEntityUnitText;
} }
else else {
{
payloadString += "??"; payloadString += "??";
} }
SendToPanel(<Payload>{ payload: payloadString }); SendToPanel(<Payload>{ payload: payloadString });
@@ -671,3 +761,23 @@ function GetAccuWeatherIcon(icon: number): number {
} }
} }
function GetBlendedColor(percentage: number): RGB {
if (percentage < 50)
return Interpolate(config.gridPageOffColor, config.gridPageOnColor, percentage / 50.0);
return Interpolate(Red, White, (percentage - 50) / 50.0);
}
function Interpolate(color1: RGB, color2: RGB, fraction: number): RGB {
var r: number = InterpolateNum(color1.red, color2.red, fraction);
var g: number = InterpolateNum(color1.green, color2.green, fraction);
var b: number = InterpolateNum(color1.blue, color2.blue, fraction);
return <RGB>{ red: Math.round(r), green: Math.round(g), blue: Math.round(b) };
}
function InterpolateNum(d1: number, d2: number, fraction: number): number {
return d1 + (d2 - d1) * fraction;
}
function rgb_dec565(rgb: RGB): number {
return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)))
}

View File

@@ -73,17 +73,19 @@ var config: Config = {
timeFormat: "%H:%M", // not used right now timeFormat: "%H:%M", // not used right now
dateFormat: "%A, %d. %B %Y", // not used right now dateFormat: "%A, %d. %B %Y", // not used right now
weatherEntity: "alias.0.Wetter", weatherEntity: "alias.0.Wetter",
defaultColor: RGB, // Default color of all elements
gridPageOnColor: RGB, // Default on color on grid page
gridPageOffColor: RGB, // Default off color on grid page
temperatureUnit: "°C", // Unit to append on temperature sensors temperatureUnit: "°C", // Unit to append on temperature sensors
pages: [ pages: [
{ {
"type": "cardEntities", // card type (cardEntities, cardThermo) "type": "cardEntities", // card type (cardEntities, cardThermo)
"heading": "Testseite", // heading "heading": "Testseite", // heading
"items": [ // items array (up to 4 on cardEntities, 1 for cardThermo) "items": [ // items array (up to 4 on cardEntities, 1 for cardThermo)
"alias.0.Rolladen_Eltern", // device which must be configured in the device panel. Use only the folder for the device, not the set, get states ... <PageItem>{ id: "alias.0.Rolladen_Eltern" }, // device which must be configured in the device panel. Use only the folder for the device, not the set, get states ...
"alias.0.Erker", <PageItem>{ id: "alias.0.Erker" },
"alias.0.Küche", <PageItem>{ id: "alias.0.Küche", useColor: true },
"alias.0.Wand" <PageItem>{ id: "alias.0.Wand", useColor: true }
] ]
}, },
@@ -91,10 +93,10 @@ var config: Config = {
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"items": [ "items": [
"alias.0.Netz", <PageItem>{ id: "alias.0.Netz" },
"alias.0.Hausverbrauch", <PageItem>{ id: "alias.0.Hausverbrauch" },
"alias.0.Pv", <PageItem>{ id: "alias.0.Pv" },
"alias.0.Batterie" <PageItem>{ id: "alias.0.Batterie" }
] ]
}, },
@@ -109,18 +111,29 @@ var config: Config = {
}; };
``` ```
The pageItem element:
```
type PageItem = {
id: string, // the element in ioBroker devices
icon: (string | undefined), // the icon which should be displayed instead of the default detected. (not implemented)
onColor: (RGB | undefined), // the color the item will get when active
offColor: (RGB | undefined), // the color the item will get when inactive
useColor: (boolean | undefined) // override colors, only Grid pages has colors enabled per default
}
```
If you want you can create dedicated objects, so you don't need to declare them again. Then you can use tehm in the pages array and button pages. If you want you can create dedicated objects, so you don't need to declare them again. Then you can use tehm in the pages array and button pages.
``` ```
var button1Page: PageEntities = var button1Page: PageGrid =
{ {
"type": "cardEntities", "type": "cardGrid",
"heading": "Knopf1", "heading": "Radio",
"items": [ "items": [
"alias.0.Schlafen", <PageItem>{ id: "alias.0.Radio.NJoy" },
"alias.0.Stern", <PageItem>{ id: "alias.0.Radio.Delta_Radio" },
"delete", <PageItem>{ id: "alias.0.Radio.NDR2" },
"delete"
] ]
}; };
``` ```
@@ -134,11 +147,10 @@ pages: [
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"items": [ "items": [
"alias.0.Netz", <PageItem>{ id: "alias.0.Netz" },
"alias.0.Hausverbrauch", <PageItem>{ id: "alias.0.Hausverbrauch" },
"alias.0.Pv", <PageItem>{ id: "alias.0.Pv" },
"alias.0.Batterie" <PageItem>{ id: "alias.0.Batterie" }
] ]
}] }]
``` ```