mirror of
https://github.com/joBr99/nspanel-lovelace-ui.git
synced 2025-12-19 22:24:15 +01:00
Fixed Typo in HMI/README.md
Updated to NsPanelTs.ts to support new FW Updated README.md
This commit is contained in:
@@ -95,7 +95,7 @@ The following message can be used to update the content on the cardEntities Page
|
||||
|
||||
`,text,sensor.entityName,3,17299,Temperature,content`
|
||||
|
||||
`button,button.entityName,3,17299,bt-name,bt-text`
|
||||
`,button,button.entityName,3,17299,bt-name,bt-text`
|
||||
|
||||
`,switch,switch.entityName,4,17299,Switch1,0`
|
||||
|
||||
|
||||
@@ -27,31 +27,25 @@ type Config = {
|
||||
dateFormat: string,
|
||||
weatherEntity: string | null,
|
||||
temperatureUnit: string,
|
||||
batEntity: string,
|
||||
pvEntity: string,
|
||||
pages: (PageThermo | PageEntities)[]
|
||||
leftEntity: string,
|
||||
leftEntityIcon: number,
|
||||
leftEntityText: string,
|
||||
leftEntityUnitText: string | null,
|
||||
rightEntity: string,
|
||||
rightEntityIcon: number,
|
||||
rightEntityText: string,
|
||||
rightEntityUnitText: string | null,
|
||||
pages: (PageThermo | PageEntities)[],
|
||||
button1Page: (PageThermo | PageEntities | null),
|
||||
button2Page: (PageThermo | PageEntities | null),
|
||||
}
|
||||
|
||||
|
||||
var subscriptions: any = {};
|
||||
|
||||
var pageId = 0;
|
||||
|
||||
var config: Config = {
|
||||
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
|
||||
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
|
||||
batEntity: "alias.0.Batterie.ACTUAL",
|
||||
pvEntity: "alias.0.Pv.ACTUAL",
|
||||
timeoutScreensaver: 15,
|
||||
dimmode: 8,
|
||||
locale: "de_DE",
|
||||
timeFormat: "%H:%M",
|
||||
dateFormat: "%A, %d. %B %Y",
|
||||
weatherEntity: "alias.0.Wetter",
|
||||
|
||||
temperatureUnit: "°C",
|
||||
pages: [
|
||||
{
|
||||
var page1: PageEntities =
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Haus",
|
||||
"items": [
|
||||
@@ -60,8 +54,10 @@ var config: Config = {
|
||||
"alias.0.Küche",
|
||||
"alias.0.Wand"
|
||||
]
|
||||
},
|
||||
{
|
||||
};
|
||||
|
||||
var page2: PageEntities =
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Strom",
|
||||
"items": [
|
||||
@@ -70,13 +66,63 @@ var config: Config = {
|
||||
"alias.0.Pv",
|
||||
"alias.0.Batterie"
|
||||
]
|
||||
},
|
||||
};
|
||||
|
||||
var button1Page: PageEntities =
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Knopf1",
|
||||
"items": [
|
||||
"alias.0.Schlafen",
|
||||
"alias.0.Stern",
|
||||
"delete",
|
||||
"delete"
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
var button2Page: PageEntities =
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Knopf2",
|
||||
"items": [
|
||||
"delete",
|
||||
"delete",
|
||||
"alias.0.Schlafen",
|
||||
"alias.0.Stern"
|
||||
|
||||
]
|
||||
};
|
||||
|
||||
var config: Config = {
|
||||
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT",
|
||||
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend",
|
||||
leftEntity: "alias.0.Batterie.ACTUAL",
|
||||
leftEntityIcon: 34,
|
||||
leftEntityText: "Batterie",
|
||||
leftEntityUnitText: "%",
|
||||
rightEntity: "alias.0.Pv.ACTUAL",
|
||||
rightEntityIcon: 32,
|
||||
rightEntityText: "PV",
|
||||
rightEntityUnitText: "W",
|
||||
timeoutScreensaver: 15,
|
||||
dimmode: 8,
|
||||
locale: "de_DE",
|
||||
timeFormat: "%H:%M",
|
||||
dateFormat: "%A, %d. %B %Y",
|
||||
weatherEntity: "alias.0.Wetter",
|
||||
|
||||
temperatureUnit: "°C",
|
||||
pages: [page1, page2,
|
||||
|
||||
{
|
||||
"type": "cardThermo",
|
||||
"heading": "Thermostat",
|
||||
"item": "alias.0.WzNsPanel"
|
||||
}
|
||||
]
|
||||
],
|
||||
button1Page: button1Page,
|
||||
button2Page: button2Page
|
||||
};
|
||||
|
||||
schedule("* * * * *", function () {
|
||||
@@ -86,10 +132,20 @@ schedule("0 * * * *", function () {
|
||||
SendDate();
|
||||
});
|
||||
|
||||
on([config.pvEntity, config.batEntity], function () {
|
||||
HandleScreensaverUpdate();
|
||||
})
|
||||
// Only monitor the extra nodes if one or both are present
|
||||
var updateArray: string[] = [];
|
||||
if (config.rightEntity !== null && existsState(config.rightEntity)) {
|
||||
updateArray.push(config.rightEntity)
|
||||
}
|
||||
|
||||
if (config.leftEntity !== null && existsState(config.leftEntity)) {
|
||||
updateArray.push(config.leftEntity)
|
||||
}
|
||||
if (updateArray.length > 0) {
|
||||
on(updateArray, function () {
|
||||
HandleScreensaverUpdate();
|
||||
})
|
||||
}
|
||||
on({ id: config.panelRecvTopic }, function (obj) {
|
||||
if (obj.state.val.startsWith('\{"CustomRecv":')) {
|
||||
var json = JSON.parse(obj.state.val);
|
||||
@@ -123,15 +179,11 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
|
||||
|
||||
if (method == 'pageOpen' || method == 'startup') {
|
||||
UnsubscribeWatcher();
|
||||
var retMsgs: Array<Payload> = [];
|
||||
if (config.pages[pageId].type == "cardEntities") {
|
||||
retMsgs = GenerateEntitiesPage(pageId, <PageEntities>config.pages[pageId])
|
||||
} else if (config.pages[pageId].type == "cardThermo") {
|
||||
retMsgs = GenerateThermoPage(pageId, <PageThermo>config.pages[pageId])
|
||||
}
|
||||
|
||||
if (method == 'startup')
|
||||
HandleStartupProcess();
|
||||
SendToPanel(retMsgs)
|
||||
|
||||
GeneratePage(config.pages[pageId]);
|
||||
}
|
||||
|
||||
if (method == 'buttonPress' || method == "tempUpd") {
|
||||
@@ -141,6 +193,43 @@ function HandleMessage(typ: string, method: string, page: number, words: Array<s
|
||||
if (method == 'screensaverOpen') {
|
||||
HandleScreensaver()
|
||||
}
|
||||
|
||||
if (method == 'button1' || method == 'button2') {
|
||||
HandleHardwareButton(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
function HandleHardwareButton(method: string): void {
|
||||
let page: (PageThermo | PageEntities);
|
||||
if (config.button1Page !== null && method == "button1") {
|
||||
page = config.button1Page;
|
||||
}
|
||||
else if (config.button2Page !== null && method == "button2") {
|
||||
page = config.button2Page;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
SendToPanel({ payload: "wake" });
|
||||
switch (page.type) {
|
||||
case "cardEntities":
|
||||
SendToPanel(GenerateEntitiesPage(page));
|
||||
break;
|
||||
case "cardThermo":
|
||||
SendToPanel(GenerateThermoPage(0, page));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,22 +267,23 @@ function SendTime(): void {
|
||||
SendToPanel(<Payload>{ payload: "time," + hr + ":" + min });
|
||||
}
|
||||
|
||||
function GenerateEntitiesPage(pageNum: number, page: PageEntities): Payload[] {
|
||||
function GenerateEntitiesPage(page: PageEntities): Payload[] {
|
||||
var out_msgs: Array<Payload> = [];
|
||||
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + config.pages[pageNum].heading }]
|
||||
|
||||
out_msgs = [{ payload: "pageType,cardEntities" }, { payload: "entityUpdHeading," + page.heading }]
|
||||
let pageData = "entityUpd";
|
||||
page.items.forEach(function (id, i) {
|
||||
out_msgs.push(CreateEntity(id, i + 1));
|
||||
pageData += CreateEntity(id, i + 1);
|
||||
})
|
||||
out_msgs.push({ payload: pageData });
|
||||
return out_msgs
|
||||
}
|
||||
|
||||
function CreateEntity(id: string, placeId: number): Payload {
|
||||
function CreateEntity(id: string, placeId: number): string {
|
||||
var type = "delete"
|
||||
var iconId = 0
|
||||
var name = "FriendlyName"
|
||||
if (id == "delete") {
|
||||
return { payload: "entityUpd," + placeId + "," + type };
|
||||
return ",delete,,,,"
|
||||
}
|
||||
|
||||
// ioBroker
|
||||
@@ -217,7 +307,7 @@ function CreateEntity(id: string, placeId: number): Payload {
|
||||
var optVal = "0"
|
||||
if (val === true || val === "true")
|
||||
optVal = "1"
|
||||
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal }
|
||||
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal
|
||||
|
||||
case "dimmer":
|
||||
type = "light"
|
||||
@@ -233,12 +323,12 @@ function CreateEntity(id: string, placeId: number): Payload {
|
||||
}
|
||||
if (val === true || val === "true")
|
||||
optVal = "1"
|
||||
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal }
|
||||
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal
|
||||
|
||||
case "blind":
|
||||
type = "shutter"
|
||||
iconId = 0
|
||||
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name }
|
||||
return "," + type + "," + id + "," + iconId + "," + "17299," + name + ","
|
||||
|
||||
case "info":
|
||||
case "value.temperature":
|
||||
@@ -261,19 +351,21 @@ function CreateEntity(id: string, placeId: number): Payload {
|
||||
else {
|
||||
optVal += GetUnitOfMeasurement(id + ".ACTUAL");
|
||||
}
|
||||
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal };
|
||||
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal;
|
||||
|
||||
case "button":
|
||||
type = "button";
|
||||
iconId = 3;
|
||||
var optVal = "PRESS";
|
||||
return { payload: "entityUpd," + placeId + "," + type + "," + id + "," + iconId + "," + name + "," + optVal };
|
||||
return "," + type + "," + id + "," + iconId + "," + "17299," + name + "," + optVal;
|
||||
|
||||
default:
|
||||
break
|
||||
return ",delete,,,,"
|
||||
|
||||
}
|
||||
}
|
||||
return { payload: "entityUpd," + placeId + "," + type };
|
||||
|
||||
return ",delete,,,,"
|
||||
}
|
||||
|
||||
function RegisterEntityWatcher(id: string, entityId: string, placeId: number): void {
|
||||
@@ -281,7 +373,7 @@ function RegisterEntityWatcher(id: string, entityId: string, placeId: number): v
|
||||
return;
|
||||
}
|
||||
subscriptions[id] = (on({ id: id, change: 'any' }, function (data) {
|
||||
SendToPanel(CreateEntity(entityId, placeId));
|
||||
GeneratePage(config.pages[pageId]);
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -392,6 +484,7 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
|
||||
if (existsObject(id)) {
|
||||
var o = getObject(id)
|
||||
var val = null;
|
||||
let icon = 1;
|
||||
if (type == "popupLight") {
|
||||
let switchVal = "0"
|
||||
if (o.common.role == "light") {
|
||||
@@ -407,7 +500,7 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
|
||||
if (val)
|
||||
switchVal = "1"
|
||||
|
||||
out_msgs.push({ payload: "entityUpdateDetail," + switchVal + ",disable,disable,disable" })
|
||||
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + ",disable,disable,disable" })
|
||||
}
|
||||
|
||||
if (o.common.role == "dimmer") {
|
||||
@@ -433,7 +526,7 @@ function GenerateDetailPage(type: string, entityId: string): Payload[] {
|
||||
//if (attr_support_color.includes("color_temp"))
|
||||
// colortemp = Math.trunc(scale(attr.color_temp, attr.min_mireds, attr.max_mireds, 0, 100))
|
||||
|
||||
out_msgs.push({ payload: "entityUpdateDetail," + switchVal + "," + brightness + "," + colortemp })
|
||||
out_msgs.push({ payload: "entityUpdateDetail," + icon + "," + "17299," + switchVal + "," + brightness + "," + colortemp })
|
||||
}
|
||||
|
||||
}
|
||||
@@ -469,12 +562,37 @@ function HandleScreensaverUpdate(): void {
|
||||
if (config.weatherEntity != null && existsObject(config.weatherEntity)) {
|
||||
var icon = getState(config.weatherEntity + ".ICON").val;
|
||||
|
||||
let temperature: string = getState(config.weatherEntity + ".TEMP").val;
|
||||
let temperature: string =
|
||||
existsState(config.weatherEntity + ".ACTUAL") ? getState(config.weatherEntity + ".ACTUAL").val :
|
||||
existsState(config.weatherEntity + ".TEMP") ? getState(config.weatherEntity + ".TEMP").val: "null";
|
||||
let humidity = getState(config.weatherEntity + ".HUMIDITY").val;
|
||||
let u1 = getState(config.batEntity).val;
|
||||
let u2 = getState(config.pvEntity).val;
|
||||
|
||||
SendToPanel(<Payload>{ payload: "weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?" + temperature.toString() + " " + config.temperatureUnit + "?26?" + humidity + " %?Batterie?34?" + u1 + "%?PV?32?" + u2 + "W" })
|
||||
|
||||
let payloadString =
|
||||
"weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?"
|
||||
+ temperature + " " + config.temperatureUnit + "?26?"
|
||||
+ humidity + " %?" ;
|
||||
|
||||
if(existsState(config.leftEntity))
|
||||
{
|
||||
let u1 = getState(config.leftEntity).val;
|
||||
payloadString += config.leftEntityText + "?" + config.leftEntityIcon + "?" + u1 + " " + config.leftEntityUnitText + "?";
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadString += "???";
|
||||
}
|
||||
|
||||
if(existsState(config.rightEntity))
|
||||
{
|
||||
let u2 = getState(config.rightEntity).val;
|
||||
payloadString += config.rightEntityText + "?" + config.rightEntityIcon + "?" + u2 + " " + config.rightEntityUnitText;
|
||||
}
|
||||
else
|
||||
{
|
||||
payloadString += "??";
|
||||
}
|
||||
SendToPanel(<Payload>{ payload: payloadString});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,8 +24,13 @@ You can find this in the device raw settings.
|
||||
|
||||
## Installation
|
||||
- Import this script into the ioBroker javascript instance and choose Typescript.
|
||||
- Make sure the version of the adapter is not to old.
|
||||
- Find the config variable and update to your needs.
|
||||
- The format strings are not used right now.
|
||||
- Make sure your device is connected with the mqtt instance. I didn't get it working with the sonoff adapter, but I didn't tried it too long.
|
||||
- Create a state with a mqtt client or create one per hand. The mqtt adapter will not create the state CustomSend
|
||||
- you only need to send a dummy message to cmnd/<yourPanel>/CustomSend
|
||||
- then the state will be created
|
||||
|
||||
## Update the screensaver string
|
||||
The screensaver string which is send to the display looks something like this:
|
||||
@@ -37,21 +42,16 @@ See the icons currently usable in the following table:
|
||||
|
||||
[Icon Table](../HMI#icons-ids)
|
||||
|
||||
You can change the string in this function:
|
||||
You can change the string and devices in the config object.
|
||||
|
||||
## 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.
|
||||
|
||||
First you need to add this rule to Tasmota:
|
||||
|
||||
```
|
||||
function HandleScreensaverUpdate(): void {
|
||||
if (config.weatherEntity != null && existsObject(config.weatherEntity)) {
|
||||
var icon = getState(config.weatherEntity + ".ICON").val;
|
||||
|
||||
let temperature: string = getState(config.weatherEntity + ".TEMP").val;
|
||||
let humidity = getState(config.weatherEntity + ".HUMIDITY").val;
|
||||
let u1 = getState(config.batEntity).val;
|
||||
let u2 = getState(config.pvEntity).val;
|
||||
|
||||
SendToPanel(<Payload>{ payload: "weatherUpdate,?" + GetAccuWeatherIcon(parseInt(icon)) + "?" + temperature.toString() + " " + config.temperatureUnit + "?26?" + humidity + " %?Batterie?4?" + u1 + "%?PV?23?" + u2 + "W" })
|
||||
}
|
||||
}
|
||||
|
||||
Rule2 on Button1#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,button1"} endon on Button2#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,button2"} endon
|
||||
Rule2
|
||||
```
|
||||
|
||||
## The config element in the script which needs to be configured
|
||||
@@ -59,11 +59,14 @@ function HandleScreensaverUpdate(): void {
|
||||
var config: Config = {
|
||||
panelRecvTopic: "mqtt.0.tele.WzDisplay.RESULT", // This is the object where the panel send the data to.
|
||||
panelSendTopic: "mqtt.0.cmnd.WzDisplay.CustomSend", // This is the object where data is send to the panel.
|
||||
batEntity: "alias.0.Batterie.ACTUAL", // This is a state which can be used to display the battery state.
|
||||
pvEntity: "alias.0.Pv.ACTUAL", // This is a state which can be used to display the current solar yield.
|
||||
// Both values are send via the HandleScreensaverUpdate() function, you need to update this string to your needs.
|
||||
// Currently the icons are hardcoded.
|
||||
|
||||
leftEntity: "alias.0.Batterie.ACTUAL", // This is a state will be displayed on the left side.
|
||||
leftEntityIcon: 34, // This is a icon which will be displayed on the left side.
|
||||
leftEntityText: "Batterie", // The label for the left side.
|
||||
leftEntityUnitText: "%", // The unit which will be appendon the left side.
|
||||
rightEntity: "alias.0.Pv.ACTUAL", // The same but for the right side.
|
||||
rightEntityIcon: 32,
|
||||
rightEntityText: "PV",
|
||||
rightEntityUnitText: "W",
|
||||
timeoutScreensaver: 15, // Timeout for screensaver
|
||||
dimmode: 8, // Display dim
|
||||
locale: "de_DE", // not used right now
|
||||
@@ -100,7 +103,42 @@ var config: Config = {
|
||||
"heading": "Thermostat",
|
||||
"item": "alias.0.WzNsPanel" // Needs to be a thermostat in the device panel
|
||||
}
|
||||
],
|
||||
button1Page: button1Page, // A cardEntities, cardThermo or nothing. This will be opened when pressing button1
|
||||
button2Page: button2Page // you guess it
|
||||
};
|
||||
```
|
||||
|
||||
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 =
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Knopf1",
|
||||
"items": [
|
||||
"alias.0.Schlafen",
|
||||
"alias.0.Stern",
|
||||
"delete",
|
||||
"delete"
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
Pages array can look like this:
|
||||
|
||||
```
|
||||
pages: [
|
||||
button1Page,
|
||||
{
|
||||
"type": "cardEntities",
|
||||
"heading": "Strom",
|
||||
"items": [
|
||||
"alias.0.Netz",
|
||||
"alias.0.Hausverbrauch",
|
||||
"alias.0.Pv",
|
||||
"alias.0.Batterie"
|
||||
|
||||
]
|
||||
}]
|
||||
```
|
||||
Reference in New Issue
Block a user