Merge pull request #50 from britzelpuf/main

Colors and color interpolation
This commit is contained in:
Johannes
2022-03-21 20:30:20 +01:00
committed by GitHub
2 changed files with 211 additions and 164 deletions

View File

@@ -1,101 +1,45 @@
type RGB = {
red: number,
green: number,
blue: number
};
const Months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
const Days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
const Red: RGB = { red: 255, green: 0, blue: 0 }; const Red: RGB = { red: 255, green: 0, blue: 0 };
const White: RGB = { red: 255, green: 255, blue: 255 }; const White: RGB = { red: 255, green: 255, blue: 255 };
const Blue: RGB = { red: 68, green: 115, blue: 158 }; const Off: RGB = { red: 68, green: 115, blue: 158 };
const On: RGB = { red: 253, green: 216, blue: 53 };
const BatteryFull: RGB = { red: 96, green: 176, blue: 62 }
const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }
type Payload = { var Wohnen: PageEntities =
payload: string;
};
type Page = {
type: string,
heading: string
};
interface PageEntities extends Page {
type: "cardEntities",
items: PageItem[]
};
interface PageGrid extends Page {
type: "cardGrid",
items: PageItem[]
};
interface PageThermo extends Page {
type: "cardThermo",
item: PageItem
};
type Config = {
panelRecvTopic: string,
panelSendTopic: string,
timeoutScreensaver: number,
dimmode: number,
//brightnessScreensaver:
locale: string,
timeFormat: string,
dateFormat: string,
weatherEntity: string | null,
temperatureUnit: string,
leftEntity: string,
leftEntityIcon: number,
leftEntityText: string,
leftEntityUnitText: string | null,
rightEntity: string,
rightEntityIcon: number,
rightEntityText: string,
rightEntityUnitText: string | null,
defaultColor: RGB,
gridPageOnColor: RGB,
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 pageId = 0;
var page1: PageEntities =
{ {
"type": "cardEntities", "type": "cardEntities",
"heading": "Haus", "heading": "Haus",
"useColor": true,
"items": [ "items": [
<PageItem>{ id: "alias.0.Rolladen_Eltern" }, <PageItem>{ id: "alias.0.Stern"},
<PageItem>{ id: "alias.0.Erker"}, <PageItem>{ id: "alias.0.Erker"},
<PageItem>{ id: "alias.0.Küche", useColor: true }, <PageItem>{ id: "alias.0.Küche", interpolateColor: true },
<PageItem>{ id: "alias.0.Wand", useColor: true } <PageItem>{ id: "alias.0.Wand" }
] ]
}; };
var page2: PageEntities = var Strom: PageEntities =
{ {
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"useColor": true,
"items": [ "items": [
<PageItem>{ id: "alias.0.Netz" }, <PageItem>{ id: "alias.0.Netz", icon: 4, interpolateColor: true, offColor: BatteryFull, onColor: Red , minValue: -1000, maxValue: 1000 },
<PageItem>{ id: "alias.0.Hausverbrauch" }, <PageItem>{ id: "alias.0.Hausverbrauch", icon: 4, interpolateColor: true, offColor: BatteryFull, onColor: Red , maxValue: 1000 },
<PageItem>{ id: "alias.0.Pv" }, <PageItem>{ id: "alias.0.Pv", icon: 4, interpolateColor: true, offColor: Off, onColor: BatteryFull , maxValue: 1000 },
<PageItem>{ id: "alias.0.Batterie" } <PageItem>{ id: "alias.0.Batterie", icon: 34, interpolateColor: true, offColor: BatteryEmpty, onColor: BatteryFull }
] ]
}; };
var button1Page: PageGrid = var button1Page: PageGrid =
{ {
"type": "cardGrid", "type": "cardGrid",
"heading": "Radio", "heading": "Radio",
"useColor": true,
"items": [ "items": [
<PageItem>{ id: "alias.0.Radio.NJoy" }, <PageItem>{ id: "alias.0.Radio.NJoy" },
<PageItem>{ id: "alias.0.Radio.Delta_Radio" }, <PageItem>{ id: "alias.0.Radio.Delta_Radio" },
@@ -108,13 +52,14 @@ var button2Page: PageEntities =
{ {
"type": "cardEntities", "type": "cardEntities",
"heading": "Knopf2", "heading": "Knopf2",
"useColor": true,
"items": [ "items": [
<PageItem>{ id: "alias.0.Schlafen" }, <PageItem>{ id: "alias.0.Schlafen" },
<PageItem>{ id: "alias.0.Stern" } <PageItem>{ id: "alias.0.Stern" }
] ]
}; };
var config: Config = { export const config: Config = {
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
leftEntity: "alias.0.Batterie.ACTUAL", leftEntity: "alias.0.Batterie.ACTUAL",
@@ -131,21 +76,28 @@ 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, defaultOffColor: Off,
gridPageOnColor: White, defaultOnColor: On,
defaultColor: Blue, defaultColor: Off,
temperatureUnit: "°C", temperatureUnit: "°C",
pages: [page1, page2, pages: [Wohnen, Strom,
{ {
"type": "cardThermo", "type": "cardThermo",
"heading": "Thermostat", "heading": "Thermostat",
"item": <PageItem>{ id: "alias.0.WzNsPanel" } "useColor": true,
"items": [<PageItem>{ id: "alias.0.WzNsPanel" }]
} }
], ],
button1Page: button1Page, button1Page: button1Page,
button2Page: button2Page button2Page: button2Page
}; };
var subscriptions: any = {};
var pageId = 0;
schedule("* * * * *", function () { schedule("* * * * *", function () {
SendTime(); SendTime();
}); });
@@ -154,8 +106,6 @@ schedule("0 * * * *", function () {
}); });
// 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)) {
@@ -177,7 +127,9 @@ on({ id: config.panelRecvTopic }, function (obj) {
var split = json.CustomRecv.split(","); var split = json.CustomRecv.split(",");
if (split[1] == "pageOpenDetail") { if (split[1] == "pageOpenDetail") {
UnsubscribeWatcher(); UnsubscribeWatcher();
SendToPanel(GenerateDetailPage(split[2], split[3])); let pageItem = config.pages[pageId].items.find(e => e.id === split[3]);
if (pageItem !== undefined)
SendToPanel(GenerateDetailPage(split[2], pageItem));
} }
else { else {
HandleMessage(split[0], split[1], parseInt(split[2]), split); HandleMessage(split[0], split[1], parseInt(split[2]), split);
@@ -186,7 +138,6 @@ on({ id: config.panelRecvTopic }, function (obj) {
}); });
function SendToPanel(val: Payload | Payload[]): void { function SendToPanel(val: Payload | Payload[]): void {
if (Array.isArray(val)) { if (Array.isArray(val)) {
val.forEach(function (id, i) { val.forEach(function (id, i) {
setState(config.panelSendTopic, id.payload); setState(config.panelSendTopic, id.payload);
@@ -225,7 +176,6 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
} }
function GeneratePage(page: Page): void { function GeneratePage(page: Page): void {
switch (page.type) { switch (page.type) {
case "cardEntities": case "cardEntities":
SendToPanel(GenerateEntitiesPage(<PageEntities>page)); SendToPanel(GenerateEntitiesPage(<PageEntities>page));
@@ -250,18 +200,7 @@ function HandleHardwareButton(method: string): void {
else { else {
return; return;
} }
log("button1");
GeneratePage(page); GeneratePage(page);
//SendToPanel({ payload: "wake" });
// switch (page.type) {
// case "cardEntities":
// SendToPanel(GenerateEntitiesPage(page));
// break;
// case "cardThermo":
// SendToPanel(GenerateThermoPage(0, page));
// break;
// }
} }
function HandleStartupProcess(): void { function HandleStartupProcess(): void {
@@ -272,16 +211,13 @@ function HandleStartupProcess(): void {
} }
function SendDate(): void { function SendDate(): void {
var months = ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"];
var days = ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"];
var d = new Date(); var d = new Date();
var day = days[d.getDay()]; var day = Days[d.getDay()];
var date = d.getDate(); var date = d.getDate();
var month = months[d.getMonth()]; var month = Months[d.getMonth()];
var year = d.getFullYear(); var year = d.getFullYear();
var _sendDate = "date,?" + day + " " + date + " " + month + " " + year; var _sendDate = "date,?" + day + " " + date + " " + month + " " + year;
SendToPanel(<Payload>{ payload: _sendDate }); SendToPanel(<Payload>{ payload: _sendDate });
} }
function SendTime(): void { function SendTime(): void {
@@ -301,14 +237,14 @@ 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 }]
out_msgs.push({ payload: GeneratePageElements(page.items, 4) }); out_msgs.push({ payload: GeneratePageElements(page.items, 4,page.useColor) });
return out_msgs return out_msgs
} }
function GenerateGridPage(page: PageGrid): Payload[] { function GenerateGridPage(page: PageGrid): Payload[] {
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
out_msgs = [{ payload: "pageType,cardGrid" }, { payload: "entityUpdHeading," + page.heading }] out_msgs = [{ payload: "pageType,cardGrid" }, { payload: "entityUpdHeading," + page.heading }]
out_msgs.push({ payload: GeneratePageElements(page.items, 6, true) }); out_msgs.push({ payload: GeneratePageElements(page.items, 6, page.useColor) });
return out_msgs return out_msgs
} }
@@ -346,23 +282,24 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean =
val = getState(pageItem.id + ".SET").val; val = getState(pageItem.id + ".SET").val;
RegisterEntityWatcher(pageItem.id + ".SET", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".SET", pageItem.id, placeId);
} }
var iconColor = rgb_dec565(useColors ? config.gridPageOffColor : config.defaultColor); var iconColor = rgb_dec565(config.defaultColor);
switch (o.common.role) { switch (o.common.role) {
case "light": case "light":
type = "light" type = "light"
iconId = 1 iconId = pageItem.icon !== undefined ? pageItem.icon : 1;
var optVal = "0" var optVal = "0"
if (val === true || val === "true") { if (val === true || val === "true") {
optVal = "1" optVal = "1"
iconColor = rgb_dec565(useColors ? config.gridPageOnColor : config.defaultColor); iconColor = GetIconColor(pageItem, true, useColors);
} }
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal;
case "dimmer": case "dimmer":
type = "light" type = "light"
iconId = 1 iconId = pageItem.icon !== undefined ? pageItem.icon : 1;
var optVal = "0" var optVal = "0"
if (existsState(pageItem.id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
val = getState(pageItem.id + ".ON_ACTUAL").val; val = getState(pageItem.id + ".ON_ACTUAL").val;
@@ -374,63 +311,79 @@ function CreateEntity(pageItem: PageItem, placeId: number, useColors: boolean =
} }
if (val === true || val === "true") { if (val === true || val === "true") {
optVal = "1" optVal = "1"
if ((pageItem.useColor || useColors) && existsState(pageItem.id + ".ACTUAL")) { iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors);
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 return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal;
case "blind": case "blind":
type = "shutter" type = "shutter"
iconId = 0 iconId = pageItem.icon !== undefined ? pageItem.icon : 0;
iconColor = GetIconColor(pageItem, existsState(pageItem.id + ".ACTUAL") ? getState(pageItem.id + ".ACTUAL").val : true, useColors);
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + ","
case "info": case "info":
case "value.temperature": case "value.temperature":
type = "text" type = "text";
iconId = pageItem.icon !== undefined ? pageItem.icon : 11;
let unit = "";
var optVal = "0" var optVal = "0"
if (existsState(pageItem.id + ".ON_ACTUAL")) { if (existsState(pageItem.id + ".ON_ACTUAL")) {
optVal = getState(pageItem.id + ".ON_ACTUAL").val + " " + GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL"); optVal = getState(pageItem.id + ".ON_ACTUAL").val;
unit = GetUnitOfMeasurement(pageItem.id + ".ON_ACTUAL");
RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ON_ACTUAL", pageItem.id, placeId);
} }
else if (existsState(pageItem.id + ".ACTUAL")) { else if (existsState(pageItem.id + ".ACTUAL")) {
optVal = getState(pageItem.id + ".ACTUAL").val; optVal = getState(pageItem.id + ".ACTUAL").val;
unit = GetUnitOfMeasurement(pageItem.id + ".ACTUAL");
RegisterEntityWatcher(pageItem.id + ".ACTUAL", pageItem.id, placeId); RegisterEntityWatcher(pageItem.id + ".ACTUAL", pageItem.id, placeId);
} }
if (o.common.role == "value.temperature") { if (o.common.role == "value.temperature") {
iconId = 2; iconId = pageItem.icon !== undefined ? pageItem.icon : 2;
optVal += config.temperatureUnit;
} }
else {
optVal += GetUnitOfMeasurement(pageItem.id + ".ACTUAL"); iconColor = GetIconColor(pageItem, parseInt(optVal), useColors);
}
return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal; return "," + type + "," + pageItem.id + "," + iconId + "," + iconColor + "," + name + "," + optVal + " " + unit;
case "button": case "button":
type = "button"; type = "button";
iconId = 3; iconId = pageItem.icon !== undefined ? pageItem.icon : 3;
var optVal = "PRESS"; let buttonText = pageItem.buttonText !== undefined ? pageItem.buttonText : "PRESS";
return "," + type + "," + pageItem.id + "," + iconId + "," + + iconColor + "," + name + "," + optVal; iconColor = GetIconColor(pageItem, true, useColors);
return "," + type + "," + pageItem.id + "," + iconId + "," + + iconColor + "," + name + "," + buttonText;
default: default:
return ",delete,,,," return ",delete,,,,";
} }
} }
return ",delete,,,,," return ",delete,,,,,"
} }
function GetIconColor(pageItem: PageItem, value: (boolean | number), useColors: boolean): number {
// dimmer
if ((pageItem.useColor || useColors) && pageItem.interpolateColor && typeof (value) === "number") {
let maxValue = pageItem.maxValue !== undefined ? pageItem.maxValue : 100;
let minValue = pageItem.minValue !== undefined ? pageItem.minValue : 0;
value = value > maxValue ? maxValue : value;
value = value < minValue ? minValue : value;
return rgb_dec565(
Interpolate(
pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor,
pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor,
scale(value, minValue, maxValue, 0, 1)
));
}
if ((pageItem.useColor || useColors) && ((typeof (value) === "boolean" && value) || value > (pageItem.minValue !== undefined ? pageItem.minValue : 0))) {
return rgb_dec565(pageItem.onColor !== undefined ? pageItem.onColor : config.defaultOnColor)
}
return rgb_dec565(pageItem.offColor !== undefined ? pageItem.offColor : config.defaultOffColor);
}
function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void { function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void {
if (subscriptions.hasOwnProperty(id)) { if (subscriptions.hasOwnProperty(id)) {
return; return;
@@ -441,12 +394,12 @@ function RegisterEntityWatcher(id: string, entityId: string, placeId: number): v
} }
function RegisterDetailEntityWatcher(id: string, entityId: string, type: string): void { function RegisterDetailEntityWatcher(id: string, pageItem: PageItem, type: string): void {
if (subscriptions.hasOwnProperty(id)) { if (subscriptions.hasOwnProperty(id)) {
return; return;
} }
subscriptions[id] = (on({ id: id, change: 'any' }, function () { subscriptions[id] = (on({ id: id, change: 'any' }, function () {
SendToPanel(GenerateDetailPage(type, entityId)); SendToPanel(GenerateDetailPage(type, pageItem));
})) }))
} }
@@ -466,7 +419,7 @@ function GetUnitOfMeasurement(id: string): string {
} }
function GenerateThermoPage(page: PageThermo): Payload[] { function GenerateThermoPage(page: PageThermo): Payload[] {
var id = page.item.id var id = page.items[0].id
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
out_msgs.push({ payload: "pageType,cardThermo" }); out_msgs.push({ payload: "pageType,cardThermo" });
@@ -571,56 +524,63 @@ function HandleButtonEvent(words): void {
} }
} }
function GenerateDetailPage(type: string, entityId: string): Payload[] { function GenerateDetailPage(type: string, pageItem: PageItem): Payload[] {
var out_msgs: Array<Payload> = []; var out_msgs: Array<Payload> = [];
let id = entityId let id = pageItem.id
if (existsObject(id)) { if (existsObject(id)) {
var o = getObject(id) var o = getObject(id)
var val = null; var val: (boolean | number) = 0;
let icon = 1; let icon = 1;
var iconColor = rgb_dec565(config.defaultColor);
if (type == "popupLight") { if (type == "popupLight") {
let switchVal = "0" let switchVal = "0"
if (o.common.role == "light") { if (o.common.role == "light") {
if (existsState(id + ".GET")) { if (existsState(id + ".GET")) {
val = getState(id + ".GET").val; val = getState(id + ".GET").val;
RegisterDetailEntityWatcher(id + ".GET", id, type); RegisterDetailEntityWatcher(id + ".GET", pageItem, type);
} }
else if (existsState(id + ".SET")) { else if (existsState(id + ".SET")) {
val = getState(id + ".SET").val; val = getState(id + ".SET").val;
RegisterDetailEntityWatcher(id + ".SET", id, type); RegisterDetailEntityWatcher(id + ".SET", pageItem, type);
} }
if (val) if (val) {
switchVal = "1" switchVal = "1";
iconColor = GetIconColor(pageItem, true, false);
}
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + ",disable,disable,disable" }) out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + + iconColor + "," + switchVal + ",disable,disable,disable" })
} }
if (o.common.role == "dimmer") { if (o.common.role == "dimmer") {
if (existsState(id + ".ON_ACTUAL")) { if (existsState(id + ".ON_ACTUAL")) {
val = getState(id + ".ON_ACTUAL").val; val = getState(id + ".ON_ACTUAL").val;
RegisterDetailEntityWatcher(id + ".ON_ACTUAL", id, type); RegisterDetailEntityWatcher(id + ".ON_ACTUAL", pageItem, type);
} }
else if (existsState(id + ".ON_SET")) { else if (existsState(id + ".ON_SET")) {
val = getState(id + ".ON_SET").val; val = getState(id + ".ON_SET").val;
RegisterDetailEntityWatcher(id + ".ON_SET", id, type); RegisterDetailEntityWatcher(id + ".ON_SET", pageItem, type);
} }
if (val === true || val === "true") if (val === true) {
var iconColor = GetIconColor(pageItem, val, false);
switchVal = "1" switchVal = "1"
}
let brightness = 0; let brightness = 0;
if (existsState(id + ".ACTUAL")) { if (existsState(id + ".ACTUAL")) {
brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, 0, 100, 0, 100)) brightness = Math.trunc(scale(getState(id + ".ACTUAL").val, 0, 100, 0, 100))
RegisterDetailEntityWatcher(id + ".ACTUAL", id, type); iconColor = GetIconColor(pageItem, brightness, false);
RegisterDetailEntityWatcher(id + ".ACTUAL", pageItem, type);
} }
let colortemp = "disable" let colorTemp = "disable"
let colorMode = "disable"
//let attr_support_color = attr.supported_color_modes //let attr_support_color = attr.supported_color_modes
//if (attr_support_color.includes("color_temp")) //if (attr_support_color.includes("color_temp"))
// colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100)) // colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100))
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + "," + brightness + "," + colortemp }) out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + iconColor + "," + switchVal + "," + brightness + "," + colorTemp + "," + colorMode })
} }
} }
@@ -763,7 +723,7 @@ function GetAccuWeatherIcon(icon: number): number {
function GetBlendedColor(percentage: number): RGB { function GetBlendedColor(percentage: number): RGB {
if (percentage < 50) if (percentage < 50)
return Interpolate(config.gridPageOffColor, config.gridPageOnColor, percentage / 50.0); return Interpolate(config.defaultOffColor, config.defaultOnColor, percentage / 50.0);
return Interpolate(Red, White, (percentage - 50) / 50.0); return Interpolate(Red, White, (percentage - 50) / 50.0);
} }
@@ -779,5 +739,76 @@ function InterpolateNum(d1: number, d2: number, fraction: number): number {
} }
function rgb_dec565(rgb: RGB): number { 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))) return ((Math.floor(rgb.red / 255 * 31) << 11) | (Math.floor(rgb.green / 255 * 63) << 5) | (Math.floor(rgb.blue / 255 * 31)));
} }
type RGB = {
red: number,
green: number,
blue: number
};
type Payload = {
payload: string;
};
type Page = {
type: string,
heading: string,
items: PageItem[],
useColor: boolean
};
interface PageEntities extends Page {
type: "cardEntities",
items: PageItem[],
};
interface PageGrid extends Page {
type: "cardGrid",
items: PageItem[],
};
interface PageThermo extends Page {
type: "cardThermo",
items: PageItem[],
};
type PageItem = {
id: string,
icon: (number | undefined),
onColor: (RGB | undefined),
offColor: (RGB | undefined),
useColor: (boolean | undefined),
interpolateColor: (boolean | undefined),
minValue: (number | undefined),
maxValue: (number | undefined),
buttonText: (string | undefined)
}
type Config = {
panelRecvTopic: string,
panelSendTopic: string,
timeoutScreensaver: number,
dimmode: number,
//brightnessScreensaver:
locale: string,
timeFormat: string,
dateFormat: string,
weatherEntity: string | null,
temperatureUnit: string,
leftEntity: string,
leftEntityIcon: number,
leftEntityText: string,
leftEntityUnitText: string | null,
rightEntity: string,
rightEntityIcon: number,
rightEntityText: string,
rightEntityUnitText: string | null,
defaultColor: RGB,
defaultOnColor: RGB,
defaultOffColor: RGB,
pages: (PageThermo | PageEntities | PageGrid)[],
button1Page: (PageThermo | PageEntities | PageGrid | null),
button2Page: (PageThermo | PageEntities | PageGrid | null),
};

View File

@@ -4,6 +4,7 @@
- Thermostat Card - Thermostat Card
- Entity Card (Temperature, Switches and sensors, the script tries to figure the unit of measurement automatically) - Entity Card (Temperature, Switches and sensors, the script tries to figure the unit of measurement automatically)
- Grid Card
- Detail Card (only switch and normal dimmer) - Detail Card (only switch and normal dimmer)
- Live update (when value was changed in the backend and the page is currently open) - Live update (when value was changed in the backend and the page is currently open)
- Screensaver Page with Time, Date and Weather Information. - Screensaver Page with Time, Date and Weather Information.
@@ -44,8 +45,8 @@ See the icons currently usable in the following table:
You can change the string and devices in the config object. You can change the string and devices in the config object.
## Buttons ## Hardware buttons
If you like you can add special pages for the buttons, but there is a problem currently which will open the last page again. But if you press the button again, the correct page will open. If you like you can add special pages for the buttons.
First you need to add this rule to Tasmota: First you need to add this rule to Tasmota:
@@ -54,6 +55,12 @@ Rule2 on Button1#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,butto
Rule2 Rule2
``` ```
## Colors
You can define colors this way and use them later in the PageItem element
```
const BatteryFull: RGB = { red: 96, green: 176, blue: 62 }
const BatteryEmpty: RGB = { red: 179, green: 45, blue: 25 }
```
## The config element in the script which needs to be configured ## The config element in the script which needs to be configured
``` ```
var config: Config = { var config: Config = {
@@ -73,14 +80,15 @@ 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 defaultColor: Off, // Default color of all elements
gridPageOnColor: RGB, // Default on color on grid page defaultOnColor: RGB, // Default on state color for items
gridPageOffColor: RGB, // Default off color on grid page defaultOffColor: RGB, // Default off state color for 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
"useColor": false, // should colors be enabled on this page, can be overridden in PageItem
"items": [ // items array (up to 4 on cardEntities, 1 for cardThermo) "items": [ // items array (up to 4 on cardEntities, 1 for cardThermo)
<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 ... <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 ...
<PageItem>{ id: "alias.0.Erker" }, <PageItem>{ id: "alias.0.Erker" },
@@ -92,17 +100,19 @@ var config: Config = {
{ {
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"useColor": true, // should colors be enabled on this page, can be overridden in PageItem
"items": [ "items": [
<PageItem>{ id: "alias.0.Netz" }, <PageItem>{ id: "alias.0.Netz" },
<PageItem>{ id: "alias.0.Hausverbrauch" }, <PageItem>{ id: "alias.0.Hausverbrauch", icon: 4, interpolateColor: true, offColor: BatteryFull, onColor: Red , maxValue: 1000 },
<PageItem>{ id: "alias.0.Pv" }, <PageItem>{ id: "alias.0.Pv" },
<PageItem>{ id: "alias.0.Batterie" } <PageItem>{ id: "alias.0.Batterie", icon: 34, interpolateColor: true, offColor: BatteryEmpty, onColor: BatteryFull }
] ]
}, },
{ {
"type": "cardThermo", "type": "cardThermo",
"heading": "Thermostat", "heading": "Thermostat",
"useColor": false, // should colors be enabled on this page, can be overridden in PageItem
"item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel "item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel
} }
], ],
@@ -119,6 +129,10 @@ type PageItem = {
onColor: (RGB | undefined), // the color the item will get when active onColor: (RGB | undefined), // the color the item will get when active
offColor: (RGB | undefined), // the color the item will get when inactive offColor: (RGB | undefined), // the color the item will get when inactive
useColor: (boolean | undefined) // override colors, only Grid pages has colors enabled per default useColor: (boolean | undefined) // override colors, only Grid pages has colors enabled per default
interpolateColor: (boolean | undefined),// fade between color on and off, useColor on Page or PageItem must be enabled
minValue: (number | undefined), // the minimum value for the fade calculation, if smaller the minimum value will be used
maxValue: (number | undefined), // the maximum value for the fade calculation, if larger the maximum value will be used
buttonText: (string | undefined) // the Button Text, default is "Press"
} }
``` ```
@@ -130,6 +144,7 @@ var button1Page: PageGrid =
{ {
"type": "cardGrid", "type": "cardGrid",
"heading": "Radio", "heading": "Radio",
"useColor": true, // should colors be enabled on this page, can be overridden in PageItem
"items": [ "items": [
<PageItem>{ id: "alias.0.Radio.NJoy" }, <PageItem>{ id: "alias.0.Radio.NJoy" },
<PageItem>{ id: "alias.0.Radio.Delta_Radio" }, <PageItem>{ id: "alias.0.Radio.Delta_Radio" },
@@ -138,7 +153,7 @@ var button1Page: PageGrid =
}; };
``` ```
Pages array can look like this: Pages array can look like this, so you can add the pages as object or define them in the array itself. This is up to you.
``` ```
pages: [ pages: [
@@ -146,6 +161,7 @@ pages: [
{ {
"type": "cardEntities", "type": "cardEntities",
"heading": "Strom", "heading": "Strom",
"useColor": true, // should colors be enabled on this page, can be overridden in PageItem
"items": [ "items": [
<PageItem>{ id: "alias.0.Netz" }, <PageItem>{ id: "alias.0.Netz" },
<PageItem>{ id: "alias.0.Hausverbrauch" }, <PageItem>{ id: "alias.0.Hausverbrauch" },