mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-21 23:14:25 +01:00
Merge pull request #50 from britzelpuf/main
Colors and color interpolation
This commit is contained in:
@@ -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),
|
||||||
|
};
|
||||||
|
|||||||
@@ -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" },
|
||||||
@@ -153,4 +169,4 @@ pages: [
|
|||||||
<PageItem>{ id: "alias.0.Batterie" }
|
<PageItem>{ id: "alias.0.Batterie" }
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user