mirror of
https://github.com/HASwitchPlate/HASPone.git
synced 2025-07-23 19:26:36 +00:00
commit
08130252d2
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
3D_Printable_Models/HASwitchPlate_front_4in_box.stl
Normal file
BIN
3D_Printable_Models/HASwitchPlate_front_4in_box.stl
Normal file
Binary file not shown.
Binary file not shown.
5
Arduino_Sketch/.gitignore
vendored
Normal file
5
Arduino_Sketch/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
.pio
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
Binary file not shown.
@ -6,7 +6,7 @@
|
||||
// Home Automation Switch Plate
|
||||
// https://github.com/aderusha/HASwitchPlate
|
||||
//
|
||||
// Copyright (c) 2021 Allen Derusha allen@derusha.org
|
||||
// Copyright (c) 2024 Allen Derusha allen@derusha.org
|
||||
//
|
||||
// MIT License
|
||||
//
|
||||
@ -26,6 +26,7 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE PRODUCT OR THE USE OR OTHER DEALINGS IN THE PRODUCT.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#include <EEPROM.h>
|
||||
#include <EspSaveCrash.h>
|
||||
@ -43,6 +44,7 @@
|
||||
#include <MQTT.h>
|
||||
#include <SoftwareSerial.h>
|
||||
#include <ESP8266Ping.h>
|
||||
#include <LittleFS.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// These defaults may be overwritten with values saved by the web interface
|
||||
@ -62,8 +64,7 @@ char motionPinConfig[3] = "0";
|
||||
char nextionBaud[7] = "115200";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const float haspVersion = 1.05; // Current HASPone software release version
|
||||
const float haspVersion = 1.06; // Current HASPone software release version
|
||||
const uint16_t mqttMaxPacketSize = 2048; // Size of buffer for incoming MQTT message
|
||||
byte nextionReturnBuffer[128]; // Byte array to pass around data coming from the panel
|
||||
uint8_t nextionReturnIndex = 0; // Index for nextionReturnBuffer
|
||||
@ -75,7 +76,7 @@ bool shouldSaveConfig = false; // Flag to save json confi
|
||||
bool nextionReportPage0 = false; // If false, don't report page 0 sendme
|
||||
const unsigned long updateCheckInterval = 43200000; // Time in msec between update checks (12 hours)
|
||||
unsigned long updateCheckTimer = updateCheckInterval; // Timer for update check
|
||||
unsigned long updateCheckFirstRun = 60000; // First-run check offset
|
||||
unsigned long updateCheckFirstRun = 30000; // First-run check offset
|
||||
bool updateEspAvailable = false; // Flag for update check to report new ESP FW version
|
||||
float updateEspAvailableVersion; // Float to hold the new ESP FW version number
|
||||
bool updateLcdAvailable = false; // Flag for update check to report new LCD FW version
|
||||
@ -87,6 +88,9 @@ bool nextionBufferOverrun = false; // Set to true if an overr
|
||||
bool nextionAckEnable = false; // Wait for each Nextion command to be acked before continuing
|
||||
bool nextionAckReceived = false; // Ack was received
|
||||
bool rebootOnp0b1 = false; // When true, reboot device on button press of p[0].b[1]
|
||||
bool rebootOnLongPress = true; // When true, reboot device on long press of any button
|
||||
unsigned long rebootOnLongPressTimer = 0; // Clock for long press reboot timer
|
||||
unsigned long rebootOnLongPressTimeout = 10000; // Timeout value for long press reboot timer
|
||||
const unsigned long nextionAckTimeout = 1000; // Timeout to wait for an ack before throwing error
|
||||
unsigned long nextionAckTimer = 0; // Timer to track Nextion ack
|
||||
const unsigned long telnetInputMax = 128; // Size of user input buffer for user telnet session
|
||||
@ -162,13 +166,67 @@ MDNSResponder::hMDNSService hMDNSService; // mDNS
|
||||
EspSaveCrash SaveCrash; // Save crash details to flash
|
||||
|
||||
// URL for auto-update check of "version.json"
|
||||
const char UPDATE_URL[] PROGMEM = "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/update/version.json";
|
||||
const char UPDATE_URL[] PROGMEM = "https://haswitchplate.com/update/version.json";
|
||||
// Additional CSS style to match Hass theme
|
||||
const char HASP_STYLE[] PROGMEM = "<style>button{background-color:#03A9F4;}body{width:60%;margin:auto;}input:invalid{border:1px solid red;}input[type=checkbox]{width:20px;}.wrap{text-align:left;display:inline-block;min-width:260px;max-width:1000px}</style>";
|
||||
// Default link to compiled Arduino firmware image
|
||||
String espFirmwareUrl = "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Arduino_Sketch/HASwitchPlate.ino.d1_mini.bin";
|
||||
String espFirmwareUrl = "https://haswitchplate.com/update/HASwitchPlate.ino.d1_mini.bin";
|
||||
// Default link to compiled Nextion firmware images
|
||||
String lcdFirmwareUrl = "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate.tft";
|
||||
String lcdFirmwareUrl = "https://haswitchplate.com/update/HASwitchPlate.tft";
|
||||
|
||||
void setup();
|
||||
void loop();
|
||||
void mqttConnect();
|
||||
void mqttProcessInput(String &strTopic, String &strPayload);
|
||||
void mqttStatusUpdate();
|
||||
void mqttDiscovery();
|
||||
void nextionHandleInput();
|
||||
void nextionProcessInput();
|
||||
void nextionSendCmd(const String &nextionCmd);
|
||||
void nextionSetAttr(const String &hmiAttribute, const String &hmiValue);
|
||||
void nextionGetAttr(const String &hmiAttribute);
|
||||
void nextionParseJson(const String &strPayload);
|
||||
void nextionOtaStartDownload(const String &lcdOtaUrl);
|
||||
bool nextionOtaResponse();
|
||||
bool nextionConnect();
|
||||
void nextionSetSpeed();
|
||||
void nextionReset();
|
||||
void nextionUpdateProgress(const unsigned int &progress, const unsigned int &total);
|
||||
void espWifiConnect();
|
||||
void espWifiReconnect();
|
||||
void espSetupOta();
|
||||
void espStartOta(const String &espOtaUrl);
|
||||
void espReset();
|
||||
void configRead();
|
||||
void configSaveCallback();
|
||||
void configSave();
|
||||
void configClearSaved();
|
||||
void webHandleNotFound();
|
||||
void webHandleRoot();
|
||||
void webHandleSaveConfig();
|
||||
void webHandleResetConfig();
|
||||
void webHandleShowConfig();
|
||||
void webHandleResetBacklight();
|
||||
void webHandleFirmware();
|
||||
void webHandleEspFirmware();
|
||||
void webHandleLcdUpload();
|
||||
void webHandleLcdUpdateSuccess();
|
||||
void webHandleLcdUpdateFailure();
|
||||
void webHandleLcdDownload();
|
||||
void webHandleTftFileSize();
|
||||
void webHandleReboot();
|
||||
void espWifiConfigCallback(WiFiManager *myWiFiManager);
|
||||
bool updateCheck();
|
||||
void motionSetup();
|
||||
void motionHandle();
|
||||
void beepHandle();
|
||||
void telnetHandleClient();
|
||||
void debugPrintln(const String &debugText);
|
||||
void debugPrint(const String &debugText);
|
||||
void debugPrintCrash();
|
||||
void debugPrintFile(const String &fileName);
|
||||
String getSubtringField(String data, char separator, int index);
|
||||
String printHex8(byte *data, uint8_t length);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void setup()
|
||||
@ -652,65 +710,65 @@ void mqttProcessInput(String &strTopic, String &strPayload)
|
||||
configSave();
|
||||
}
|
||||
else if (strTopic == (mqttCommandTopic + "/debugserialenabled") || strTopic == (mqttGroupCommandTopic + "/debugserialenabled"))
|
||||
{ // '[...]/device/command/debugserialenabled' -m 'true' == enable serial debug output
|
||||
{ // '[...]/device/command/debugserialenabled' -m 'true' == enable serial debug output
|
||||
if (strPayload.equalsIgnoreCase("true"))
|
||||
{
|
||||
debugSerialEnabled = true;
|
||||
configSave();
|
||||
}
|
||||
else if(strPayload.equalsIgnoreCase("false"))
|
||||
else if (strPayload.equalsIgnoreCase("false"))
|
||||
{
|
||||
debugSerialEnabled = false;
|
||||
configSave();
|
||||
}
|
||||
}
|
||||
else if (strTopic == (mqttCommandTopic + "/debugtelnetenabled") || strTopic == (mqttGroupCommandTopic + "/debugtelnetenabled"))
|
||||
{ // '[...]/device/command/debugtelnetenabled' -m 'true' == enable telnet debug output
|
||||
{ // '[...]/device/command/debugtelnetenabled' -m 'true' == enable telnet debug output
|
||||
if (strPayload.equalsIgnoreCase("true"))
|
||||
{
|
||||
debugTelnetEnabled = true;
|
||||
configSave();
|
||||
}
|
||||
else if(strPayload.equalsIgnoreCase("false"))
|
||||
else if (strPayload.equalsIgnoreCase("false"))
|
||||
{
|
||||
debugTelnetEnabled = false;
|
||||
configSave();
|
||||
}
|
||||
}
|
||||
else if (strTopic == (mqttCommandTopic + "/mdnsenabled") || strTopic == (mqttGroupCommandTopic + "/mdnsenabled"))
|
||||
{ // '[...]/device/command/mdnsenabled' -m 'true' == enable mDNS responder
|
||||
{ // '[...]/device/command/mdnsenabled' -m 'true' == enable mDNS responder
|
||||
if (strPayload.equalsIgnoreCase("true"))
|
||||
{
|
||||
mdnsEnabled = true;
|
||||
configSave();
|
||||
}
|
||||
else if(strPayload.equalsIgnoreCase("false"))
|
||||
else if (strPayload.equalsIgnoreCase("false"))
|
||||
{
|
||||
mdnsEnabled = false;
|
||||
configSave();
|
||||
}
|
||||
}
|
||||
else if (strTopic == (mqttCommandTopic + "/beepenabled") || strTopic == (mqttGroupCommandTopic + "/beepenabled"))
|
||||
{ // '[...]/device/command/beepenabled' -m 'true' == enable beep output on keypress
|
||||
{ // '[...]/device/command/beepenabled' -m 'true' == enable beep output on keypress
|
||||
if (strPayload.equalsIgnoreCase("true"))
|
||||
{
|
||||
beepEnabled = true;
|
||||
configSave();
|
||||
}
|
||||
else if(strPayload.equalsIgnoreCase("false"))
|
||||
else if (strPayload.equalsIgnoreCase("false"))
|
||||
{
|
||||
beepEnabled = false;
|
||||
configSave();
|
||||
}
|
||||
}
|
||||
else if (strTopic == (mqttCommandTopic + "/ignoretouchwhenoff") || strTopic == (mqttGroupCommandTopic + "/ignoretouchwhenoff"))
|
||||
{ // '[...]/device/command/ignoretouchwhenoff' -m 'true' == disable actions on keypress
|
||||
{ // '[...]/device/command/ignoretouchwhenoff' -m 'true' == disable actions on keypress
|
||||
if (strPayload.equalsIgnoreCase("true"))
|
||||
{
|
||||
ignoreTouchWhenOff = true;
|
||||
configSave();
|
||||
}
|
||||
else if(strPayload.equalsIgnoreCase("false"))
|
||||
else if (strPayload.equalsIgnoreCase("false"))
|
||||
{
|
||||
ignoreTouchWhenOff = false;
|
||||
configSave();
|
||||
@ -844,8 +902,8 @@ void mqttProcessInput(String &strTopic, String &strPayload)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void mqttStatusUpdate()
|
||||
{ // Periodically publish system status
|
||||
String mqttSensorPayload = "{";
|
||||
mqttSensorPayload += String(F("\"espVersion\":")) + String(haspVersion) + String(F(","));
|
||||
String mqttSensorPayload = String(F("{\"espVersion\":"));
|
||||
mqttSensorPayload += String(haspVersion) + String(F(","));
|
||||
if (updateEspAvailable)
|
||||
{
|
||||
mqttSensorPayload += String(F("\"updateEspAvailable\":true,"));
|
||||
@ -892,24 +950,23 @@ void mqttStatusUpdate()
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void mqttDiscovery()
|
||||
{ // Publish Home Assistant discovery messages
|
||||
|
||||
String macAddress = String(espMac[0], HEX) + String(F(":")) + String(espMac[1], HEX) + String(F(":")) + String(espMac[2], HEX) + String(F(":")) + String(espMac[3], HEX) + String(F(":")) + String(espMac[4], HEX) + String(F(":")) + String(espMac[5], HEX);
|
||||
const String mqttDiscoveryDevice = String(F("\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"configuration_url\":\"http://")) + WiFi.localIP().toString() + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("},\"origin\":{\"name\":\"HASPone\",\"support_url\":\"https://haswitchplate.com\",\"sw\":")) + String(haspVersion) + String(F("}}"));
|
||||
|
||||
// light discovery for backlight
|
||||
String mqttDiscoveryTopic = String(hassDiscovery) + String(F("/light/")) + String(haspNode) + String(F("/config"));
|
||||
String mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" backlight\",\"command_topic\":\"")) + mqttLightCommandTopic + String(F("\",\"state_topic\":\"")) + mqttLightStateTopic + String(F("\",\"brightness_state_topic\":\"")) + mqttLightBrightStateTopic + String(F("\",\"brightness_command_topic\":\"")) + mqttLightBrightCommandTopic + String(F("\",\"availability_topic\":\"")) + mqttStatusTopic + String(F("\",\"brightness_scale\":100,\"unique_id\":\"")) + mqttClientId + String(F("-backlight\",\"payload_on\":\"ON\",\"payload_off\":\"OFF\",\"payload_available\":\"ON\",\"payload_not_available\":\"OFF\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
String mqttDiscoveryPayload = String(F("{\"name\":\"backlight\",\"object_id\":\"")) + String(haspNode) + String(F("_backlight\",\"command_topic\":\"")) + mqttLightCommandTopic + String(F("\",\"state_topic\":\"")) + mqttLightStateTopic + String(F("\",\"brightness_state_topic\":\"")) + mqttLightBrightStateTopic + String(F("\",\"brightness_command_topic\":\"")) + mqttLightBrightCommandTopic + String(F("\",\"availability_topic\":\"")) + mqttStatusTopic + String(F("\",\"brightness_scale\":100,\"unique_id\":\"")) + mqttClientId + String(F("-backlight\",\"payload_on\":\"ON\",\"payload_off\":\"OFF\",\"payload_available\":\"ON\",\"payload_not_available\":\"OFF\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
// sensor discovery for device telemetry
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/sensor/")) + String(haspNode) + String(F("/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" sensor\",\"json_attributes_topic\":\"")) + mqttSensorTopic + String(F("\",\"state_topic\":\"")) + mqttStatusTopic + String(F("\",\"unique_id\":\"")) + mqttClientId + String(F("-sensor\",\"icon\":\"mdi:cellphone-text\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"sensor\",\"object_id\":\"")) + String(haspNode) + String(F("_sensor\",\"json_attributes_topic\":\"")) + mqttSensorTopic + String(F("\",\"state_topic\":\"")) + mqttStatusTopic + String(F("\",\"unique_id\":\"")) + mqttClientId + String(F("-sensor\",\"icon\":\"mdi:cellphone-text\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
// number discovery for active page
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/number/")) + String(haspNode) + String(F("/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" active page\",\"command_topic\":\"")) + mqttCommandTopic + String(F("/page\",\"state_topic\":\"")) + mqttStateTopic + String(F("/page\",\"step\":1,\"min\":0,\"max\":")) + String(nextionMaxPages) + String(F(",\"retain\":true,\"optimistic\":true,\"icon\":\"mdi:page-next-outline\",\"unique_id\":\"")) + mqttClientId + String(F("-page\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"active page\",\"object_id\":\"")) + String(haspNode) + String(F("_active_page\",\"command_topic\":\"")) + mqttCommandTopic + String(F("/page\",\"state_topic\":\"")) + mqttStateTopic + String(F("/page\",\"step\":1,\"min\":0,\"max\":")) + String(nextionMaxPages) + String(F(",\"retain\":true,\"optimistic\":true,\"icon\":\"mdi:page-next-outline\",\"unique_id\":\"")) + mqttClientId + String(F("-page\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
@ -919,33 +976,32 @@ void mqttDiscovery()
|
||||
|
||||
// rgb light discovery for selectedforegroundcolor
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/light/")) + String(haspNode) + String(F("/selectedforegroundcolor/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" selected foreground color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedforegroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedforegroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-selectedforegroundcolor\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"selected foreground color\",\"object_id\":\"")) + String(haspNode) + String(F("_selected_foreground_color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedforegroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedforegroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-selectedforegroundcolor\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
// rgb light discovery for selectedbackgroundcolor
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/light/")) + String(haspNode) + String(F("/selectedbackgroundcolor/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" selected background color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedbackgroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedbackgroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-selectedbackgroundcolor\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"selected background color\",\"object_id\":\"")) + String(haspNode) + String(F("_selected_background_color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedbackgroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/selectedbackgroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-selectedbackgroundcolor\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
// rgb light discovery for unselectedforegroundcolor
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/light/")) + String(haspNode) + String(F("/unselectedforegroundcolor/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" unselected foreground color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedforegroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedforegroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-unselectedforegroundcolor\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"unselected foreground color\",\"object_id\":\"")) + String(haspNode) + String(F("_unselected_foreground_color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedforegroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedforegroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-unselectedforegroundcolor\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
// rgb light discovery for unselectedbackgroundcolor
|
||||
mqttDiscoveryTopic = String(hassDiscovery) + String(F("/light/")) + String(haspNode) + String(F("/unselectedbackgroundcolor/config"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"")) + String(haspNode) + String(F(" unselected background color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedbackgroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedbackgroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-unselectedbackgroundcolor\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
mqttDiscoveryPayload = String(F("{\"name\":\"unselected background color\",\"object_id\":\"")) + String(haspNode) + String(F("_unselected_background_color\",\"command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedbackgroundcolor/switch\",\"state_topic\":\"hasp/")) + String(haspNode) + String(F("/alwayson\",\"rgb_command_topic\":\"hasp/")) + String(haspNode) + String(F("/light/unselectedbackgroundcolor/rgb\",\"rgb_command_template\":\"{{(red|bitwise_and(248)*256)+(green|bitwise_and(252)*8)+(blue|bitwise_and(248)/8)|int }}\",\"retain\":true,\"unique_id\":\"")) + mqttClientId + String(F("-unselectedbackgroundcolor\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
|
||||
if (motionEnabled)
|
||||
{ // binary_sensor for motion
|
||||
String macAddress = String(espMac[0], HEX) + String(F(":")) + String(espMac[1], HEX) + String(F(":")) + String(espMac[2], HEX) + String(F(":")) + String(espMac[3], HEX) + String(F(":")) + String(espMac[4], HEX) + String(F(":")) + String(espMac[5], HEX);
|
||||
String mqttDiscoveryTopic = String(hassDiscovery) + String(F("/binary_sensor/")) + String(haspNode) + String(F("-motion/config"));
|
||||
String mqttDiscoveryPayload = String(F("{\"device_class\":\"motion\",\"name\":\"")) + String(haspNode) + String(F(" motion\",\"state_topic\":\"")) + mqttMotionStateTopic + String(F("\",\"unique_id\":\"")) + mqttClientId + String(F("-motion\",\"payload_on\":\"ON\",\"payload_off\":\"OFF\",\"device\":{\"identifiers\":[\"")) + mqttClientId + String(F("\"],\"name\":\"")) + String(haspNode) + String(F("\",\"manufacturer\":\"HASwitchPlate\",\"model\":\"HASPone v1.0.0\",\"sw_version\":")) + String(haspVersion) + String(F("}}"));
|
||||
String mqttDiscoveryPayload = String(F("{\"device_class\":\"motion\",\"name\":\"motion\",\"object_id\":\"")) + String(haspNode) + String(F("_motion\",\"state_topic\":\"")) + mqttMotionStateTopic + String(F("\",\"unique_id\":\"")) + mqttClientId + String(F("-motion\",\"payload_on\":\"ON\",\"payload_off\":\"OFF\",")) + mqttDiscoveryDevice;
|
||||
mqttClient.publish(mqttDiscoveryTopic, mqttDiscoveryPayload, true, 1);
|
||||
debugPrintln(String(F("MQTT OUT: '")) + mqttDiscoveryTopic + String(F("' : '")) + String(mqttDiscoveryPayload) + String(F("'")));
|
||||
}
|
||||
@ -1250,6 +1306,10 @@ void nextionProcessInput()
|
||||
debugPrintln(String(F("HMI IN: p[0].b[1] pressed during HASPone configuration, rebooting.")));
|
||||
espReset();
|
||||
}
|
||||
if (rebootOnLongPress)
|
||||
{
|
||||
rebootOnLongPressTimer = millis();
|
||||
}
|
||||
}
|
||||
else if (nextionButtonAction == 0x00)
|
||||
{
|
||||
@ -1280,6 +1340,12 @@ void nextionProcessInput()
|
||||
nextionGetAttr("p[" + nextionPage + "].b[" + nextionButtonID + "].val");
|
||||
}
|
||||
}
|
||||
if (rebootOnLongPress && (millis() - rebootOnLongPressTimer > rebootOnLongPressTimeout))
|
||||
{
|
||||
debugPrintln(String(F("HMI IN: Button long press, rebooting.")));
|
||||
espReset();
|
||||
}
|
||||
rebootOnLongPressTimer = millis();
|
||||
}
|
||||
}
|
||||
else if (nextionReturnBuffer[0] == 0x66)
|
||||
@ -1624,8 +1690,6 @@ void nextionParseJson(const String &strPayload)
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
void nextionOtaStartDownload(const String &lcdOtaUrl)
|
||||
{ // Upload firmware to the Nextion LCD via HTTP download
|
||||
// based in large part on code posted by indev2 here:
|
||||
// http://support.iteadstudio.com/support/discussions/topics/11000007686/page/2
|
||||
|
||||
uint32_t lcdOtaFileSize = 0;
|
||||
String lcdOtaNextionCmd;
|
||||
@ -1967,6 +2031,8 @@ void espWifiConnect()
|
||||
nextionSendCmd("page 0");
|
||||
}
|
||||
|
||||
WiFi.persistent(false);
|
||||
enableWiFiAtBootTime();
|
||||
WiFi.macAddress(espMac); // Read our MAC address and save it to espMac
|
||||
WiFi.hostname(haspNode); // Assign our hostname before connecting to WiFi
|
||||
WiFi.setAutoReconnect(true); // Tell WiFi to autoreconnect if connection has dropped
|
||||
@ -1981,7 +2047,9 @@ void espWifiConnect()
|
||||
{
|
||||
nextionSetAttr("p[0].b[1].txt", "\"WiFi Connecting...\\r " + String(WiFi.SSID()) + "\"");
|
||||
unsigned long connectTimer = millis() + 10000;
|
||||
|
||||
debugPrintln(String(F("WIFI: Connecting to previously-saved SSID: ")) + String(WiFi.SSID()));
|
||||
|
||||
WiFi.begin();
|
||||
while ((WiFi.status() != WL_CONNECTED) && (millis() < connectTimer))
|
||||
{
|
||||
@ -2004,13 +2072,19 @@ void espWifiConnect()
|
||||
{
|
||||
yield();
|
||||
}
|
||||
|
||||
if (WiFi.localIP().toString() == "(IP unset)")
|
||||
{ // Check if we have our IP yet
|
||||
debugPrintln(F("WIFI: Failed to lease address from DHCP, disconnecting and trying again"));
|
||||
WiFi.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{ // We gave it a shot, still couldn't connect, so let WiFiManager run to make one last
|
||||
// connection attempt and then flip to AP mode to collect credentials from the user.
|
||||
|
||||
WiFi.persistent(true);
|
||||
WiFiManagerParameter custom_haspNodeHeader("<br/><b>HASPone Node</b>");
|
||||
WiFiManagerParameter custom_haspNode("haspNode", "<br/>Node Name <small>(required: lowercase letters, numbers, and _ only)</small>", haspNode, 15, " maxlength=15 required pattern='[a-z0-9_]*'");
|
||||
WiFiManagerParameter custom_groupName("groupName", "Group Name <small>(required)</small>", groupName, 15, " maxlength=15 required");
|
||||
@ -2170,16 +2244,14 @@ void espSetupOta()
|
||||
debugPrintln(F("ESP OTA: update start"));
|
||||
nextionSetAttr("p[0].b[1].txt", "\"\\rHASPone update:\\r\\r\\r \"");
|
||||
nextionSendCmd("page 0");
|
||||
nextionSendCmd("vis 4,1");
|
||||
});
|
||||
nextionSendCmd("vis 4,1"); });
|
||||
ArduinoOTA.onEnd([]()
|
||||
{
|
||||
debugPrintln(F("ESP OTA: update complete"));
|
||||
nextionSetAttr("p[0].b[1].txt", "\"\\rHASPone update:\\r\\r Complete!\\rRestarting.\"");
|
||||
nextionSendCmd("vis 4,1");
|
||||
delay(1000);
|
||||
espReset();
|
||||
});
|
||||
espReset(); });
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total)
|
||||
{ nextionUpdateProgress(progress, total); });
|
||||
ArduinoOTA.onError([](ota_error_t error)
|
||||
@ -2198,8 +2270,7 @@ void espSetupOta()
|
||||
nextionSendCmd("vis 4,0");
|
||||
nextionSetAttr("p[0].b[1].txt", "\"HASPone update:\\r FAILED\\rerror: " + String(error) + "\"");
|
||||
delay(1000);
|
||||
nextionSendCmd("page " + String(nextionActivePage));
|
||||
});
|
||||
nextionSendCmd("page " + String(nextionActivePage)); });
|
||||
ArduinoOTA.begin();
|
||||
debugPrintln(F("ESP OTA: Over the Air firmware update ready"));
|
||||
}
|
||||
@ -2214,8 +2285,14 @@ void espStartOta(const String &espOtaUrl)
|
||||
|
||||
WiFiUDP::stopAll(); // Keep mDNS responder from breaking things
|
||||
delay(1);
|
||||
|
||||
int startHost = espOtaUrl.indexOf("://") + 3; // Find the end of 'https://'
|
||||
int endHost = espOtaUrl.indexOf('/', startHost); // Find the next '/' after 'https://'
|
||||
String espOtaHost = espOtaUrl.substring(startHost, endHost); // Extract host
|
||||
String espOtaUri = espOtaUrl.substring(endHost); // Extract URI
|
||||
ESPhttpUpdate.rebootOnUpdate(false);
|
||||
ESPhttpUpdate.onProgress(nextionUpdateProgress);
|
||||
ESPhttpUpdate.setFollowRedirects(HTTPC_FORCE_FOLLOW_REDIRECTS);
|
||||
t_httpUpdate_return espOtaUrlReturnCode;
|
||||
if (espOtaUrl.startsWith(F("https")))
|
||||
{
|
||||
@ -2224,6 +2301,7 @@ void espStartOta(const String &espOtaUrl)
|
||||
wifiEspOtaClientSecure.setInsecure();
|
||||
wifiEspOtaClientSecure.setBufferSizes(512, 512);
|
||||
espOtaUrlReturnCode = ESPhttpUpdate.update(wifiEspOtaClientSecure, espOtaUrl);
|
||||
wifiEspOtaClientSecure.stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2579,7 +2657,7 @@ void webHandleNotFound()
|
||||
void webHandleRoot()
|
||||
{ // http://plate01/
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -2832,7 +2910,7 @@ void webHandleRoot()
|
||||
void webHandleSaveConfig()
|
||||
{ // http://plate01/saveConfig
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3028,7 +3106,7 @@ void webHandleSaveConfig()
|
||||
void webHandleResetConfig()
|
||||
{ // http://plate01/resetConfig
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3070,7 +3148,7 @@ void webHandleResetConfig()
|
||||
void webHandleResetBacklight()
|
||||
{ // http://plate01/resetBacklight
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3101,7 +3179,7 @@ void webHandleResetBacklight()
|
||||
void webHandleFirmware()
|
||||
{ // http://plate01/firmware
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3145,7 +3223,7 @@ void webHandleFirmware()
|
||||
{
|
||||
webServer.sendContent(F("<font color='green'><b>HASPone LCD update available!</b></font>"));
|
||||
}
|
||||
webServer.sendContent(F("<br/><b>Update Nextion LCD from URL</b><small><i> http only</i></small>"));
|
||||
webServer.sendContent(F("<br/><b>Update Nextion LCD from URL</b>"));
|
||||
webServer.sendContent(F("<br/><input id='lcdFirmware' name='lcdFirmware' value='"));
|
||||
webServer.sendContent(lcdFirmwareUrl);
|
||||
webServer.sendContent(F("'><br/><br/><button type='submit'>Update LCD from URL</button></form>"));
|
||||
@ -3174,7 +3252,7 @@ void webHandleFirmware()
|
||||
void webHandleEspFirmware()
|
||||
{ // http://plate01/espfirmware
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3209,7 +3287,7 @@ void webHandleLcdUpload()
|
||||
// Upload firmware to the Nextion LCD via HTTP upload
|
||||
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3443,7 +3521,7 @@ void webHandleLcdUpload()
|
||||
void webHandleLcdUpdateSuccess()
|
||||
{ // http://plate01/lcdOtaSuccess
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3471,7 +3549,7 @@ void webHandleLcdUpdateSuccess()
|
||||
void webHandleLcdUpdateFailure()
|
||||
{ // http://plate01/lcdOtaFailure
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3499,7 +3577,7 @@ void webHandleLcdUpdateFailure()
|
||||
void webHandleLcdDownload()
|
||||
{ // http://plate01/lcddownload
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3528,7 +3606,7 @@ void webHandleLcdDownload()
|
||||
void webHandleTftFileSize()
|
||||
{ // http://plate01/tftFileSize
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3548,7 +3626,7 @@ void webHandleTftFileSize()
|
||||
void webHandleReboot()
|
||||
{ // http://plate01/reboot
|
||||
if (configPassword[0] != '\0')
|
||||
{ //Request HTTP auth if configPassword is set
|
||||
{ // Request HTTP auth if configPassword is set
|
||||
if (!webServer.authenticate(configUser, configPassword))
|
||||
{
|
||||
return webServer.requestAuthentication();
|
||||
@ -3726,12 +3804,12 @@ void telnetHandleClient()
|
||||
{
|
||||
telnetClient.stop(); // client disconnected
|
||||
}
|
||||
telnetClient = telnetServer.available(); // ready for new client
|
||||
telnetInputIndex = 0; // reset input buffer index
|
||||
telnetClient = telnetServer.accept(); // ready for new client
|
||||
telnetInputIndex = 0; // reset input buffer index
|
||||
}
|
||||
else
|
||||
{
|
||||
telnetServer.available().stop(); // have client, block new connections
|
||||
telnetServer.accept().stop(); // have client, block new connections
|
||||
}
|
||||
}
|
||||
// Handle client input from telnet connection.
|
Binary file not shown.
@ -9,17 +9,17 @@
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:d1_mini]
|
||||
platform = https://github.com/platformio/platform-espressif8266.git @ ^3.2.0
|
||||
platform = https://github.com/platformio/platform-espressif8266.git @ ^4.2.1
|
||||
board = d1_mini
|
||||
framework = arduino
|
||||
board_build.f_cpu = 160000000L
|
||||
board_build.ldscript = eagle.flash.4m1m.ld
|
||||
build_flags =
|
||||
-D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191122
|
||||
-D PIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK305
|
||||
-D PIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
|
||||
lib_deps =
|
||||
bblanchon/ArduinoJson @ ^6.18.5
|
||||
256dpi/MQTT @ ^2.5.0
|
||||
dancol90/ESP8266Ping @ ^1.0
|
||||
krzychb/EspSaveCrash @ ^1.2.0
|
||||
https://github.com/tzapu/WiFiManager.git#8452df79bbc55265d6a999d7384204220f4d22c6
|
||||
256dpi/MQTT @ ^2.5.2
|
||||
dancol90/ESP8266Ping @ ^1.1.0
|
||||
bblanchon/ArduinoJson @ ^7.0.4
|
||||
krzychb/EspSaveCrash @ ^1.3.0
|
||||
https://github.com/tzapu/WiFiManager.git#e978bc059c522404c01e06cd136fcf23234eb784
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] activates a page"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone activates a selected page after a specified period of inactivity"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -122,7 +122,7 @@ condition:
|
||||
|
||||
action:
|
||||
- delay:
|
||||
seconds: "{{idletime|int}}"
|
||||
seconds: "{{idletime|int(default=30)}}"
|
||||
|
||||
- condition: template
|
||||
value_template: >-
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] has theme colors applied"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
|
326
Home_Assistant/blueprints/hasp_Apply_Theme_Multiple_Buttons.yaml
Normal file
326
Home_Assistant/blueprints/hasp_Apply_Theme_Multiple_Buttons.yaml
Normal file
@ -0,0 +1,326 @@
|
||||
blueprint:
|
||||
name: "HASPone buttons have theme colors applied"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
Several buttons on the HASPone will have the current device theme or custom colors applied.
|
||||
|
||||
## HASPone Page and Button Reference
|
||||
|
||||
<details>
|
||||
|
||||
The images below show each available HASPone page along with the layout of available button objects.
|
||||
|
||||
| Page 0 | Pages 1-3 | Pages 4-5 |
|
||||
|--------|-----------|-----------|
|
||||
|  |  |  |
|
||||
|
||||
| Page 6 | Page 7 | Page 8 |
|
||||
|--------|--------|--------|
|
||||
|  |  |  |
|
||||
|
||||
| Page 9 | Page 10 | Page 11 |
|
||||
|--------|---------|---------|
|
||||
|  |  | 
|
||||
|
||||
</details>
|
||||
|
||||
## Nextion color codes
|
||||
|
||||
<details>
|
||||
|
||||
The Nextion environment utilizes RGB 565 encoding. [Use this handy convertor](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to select your colors and convert to the RGB 565 format.
|
||||
|
||||
Here are some example colors:
|
||||
|
||||
| Color | Code |
|
||||
|--------|-------|
|
||||
| White | 65535 |
|
||||
| Black | 0 |
|
||||
| Grey | 25388 |
|
||||
| Red | 63488 |
|
||||
| Green | 2016 |
|
||||
| Blue | 31 |
|
||||
| Yellow | 65504 |
|
||||
| Orange | 64512 |
|
||||
| Brown | 48192 |
|
||||
|
||||
</details>
|
||||
|
||||
domain: automation
|
||||
input:
|
||||
haspdevice:
|
||||
name: "HASPone Device"
|
||||
description: "Select the HASPone device"
|
||||
selector:
|
||||
device:
|
||||
integration: mqtt
|
||||
manufacturer: "HASwitchPlate"
|
||||
model: "HASPone v1.0.0"
|
||||
objects:
|
||||
name: "HASPone buttons"
|
||||
description: "Apply the current theme or colors defined below to all of the objects in this list"
|
||||
default:
|
||||
- p[1].b[4]
|
||||
- p[1].b[5]
|
||||
- p[1].b[6]
|
||||
- p[1].b[7]
|
||||
selector:
|
||||
object:
|
||||
selected_fgcolor:
|
||||
name: "Selected foreground color"
|
||||
description: 'Selected foreground color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected foreground color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
selected_bgcolor:
|
||||
name: "Selected background color"
|
||||
description: 'Selected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected background color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
unselected_fgcolor:
|
||||
name: "Unselected foreground color"
|
||||
description: 'Unselected foreground color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected foreground color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
unselected_bgcolor:
|
||||
name: "Unselected background color"
|
||||
description: 'Unselected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected background color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
|
||||
mode: parallel
|
||||
max_exceeded: silent
|
||||
|
||||
variables:
|
||||
haspdevice: !input haspdevice
|
||||
haspname: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
objects: !input objects
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
unselected_fgcolor: !input unselected_fgcolor
|
||||
unselected_bgcolor: !input unselected_bgcolor
|
||||
# haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}'
|
||||
# commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}'
|
||||
jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}'
|
||||
selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}'
|
||||
selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}'
|
||||
unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}'
|
||||
unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}'
|
||||
selectedfg: >-
|
||||
{%- if (selected_fgcolor|int) >= 0 -%}
|
||||
{{ selected_fgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
selectedbg: >-
|
||||
{%- if (selected_bgcolor|int) >= 0 -%}
|
||||
{{ selected_bgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
unselectedfg: >-
|
||||
{%- if (unselected_fgcolor|int) >= 0 -%}
|
||||
{{ unselected_fgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
unselectedbg: >-
|
||||
{%- if (unselected_bgcolor|int) >= 0 -%}
|
||||
{{ unselected_bgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
|
||||
trigger_variables:
|
||||
haspdevice: !input haspdevice
|
||||
haspname: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
haspsensor: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{ entity }}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}'
|
||||
selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}'
|
||||
selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}'
|
||||
unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}'
|
||||
unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}'
|
||||
|
||||
trigger:
|
||||
- platform: homeassistant
|
||||
event: start
|
||||
- platform: template
|
||||
value_template: "{{ is_state(haspsensor, 'ON') }}"
|
||||
- platform: mqtt
|
||||
topic: "{{selectedfgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{selectedbgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{unselectedfgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{unselectedbgtopic}}"
|
||||
|
||||
condition:
|
||||
- condition: template
|
||||
value_template: "{{ is_state(haspsensor, 'ON') }}"
|
||||
|
||||
action:
|
||||
- choose:
|
||||
#########################################################################
|
||||
# RUN ACTIONS or Home Assistant Startup or HASPone Connect
|
||||
# Apply text style
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{-
|
||||
(trigger is not defined)
|
||||
or
|
||||
(trigger.platform is none)
|
||||
or
|
||||
((trigger.platform == 'homeassistant') and (trigger.event == 'start'))
|
||||
or
|
||||
((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON'))
|
||||
-}}
|
||||
sequence:
|
||||
- repeat:
|
||||
count: "{{objects|length}}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[
|
||||
"{{objects[repeat.index-1]}}.pco={{selectedfg}}",
|
||||
"{{objects[repeat.index-1]}}.bco={{selectedbg}}",
|
||||
"{{objects[repeat.index-1]}}.pco2={{unselectedfg}}",
|
||||
"{{objects[repeat.index-1]}}.bco2={{unselectedbg}}"
|
||||
]
|
||||
|
||||
#########################################################################
|
||||
# Catch triggers fired by incoming MQTT messages
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: '{{ trigger.platform == "mqtt" }}'
|
||||
sequence:
|
||||
- choose:
|
||||
#########################################################################
|
||||
# Theme: Apply selected foreground color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == selectedfgtopic) and ((selected_fgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- repeat:
|
||||
count: "{{objects|length}}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: '{{ "hasp/" ~ haspname ~ "/command/" ~ objects[repeat.index-1] ~ ".pco" }}'
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply selected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == selectedbgtopic) and ((selected_bgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- repeat:
|
||||
count: "{{objects|length}}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: '{{ "hasp/" ~ haspname ~ "/command/" ~ objects[repeat.index-1] ~ ".bco" }}'
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply unselected foreground color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == unselectedfgtopic) and ((unselected_fgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- repeat:
|
||||
count: "{{objects|length}}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: '{{ "hasp/" ~ haspname ~ "/command/" ~ objects[repeat.index-1] ~ ".pco2" }}'
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply unselected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == unselectedbgtopic) and ((unselected_bgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- repeat:
|
||||
count: "{{objects|length}}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: '{{ "hasp/" ~ haspname ~ "/command/" ~ objects[repeat.index-1] ~ ".bco2" }}'
|
||||
payload: "{{trigger.payload}}"
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone Core functionality"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
@ -234,15 +234,15 @@ variables:
|
||||
{%- endfor -%}
|
||||
page1text: !input page1text
|
||||
page1font_select: !input page1font_select
|
||||
page1font: "{{ page1font_select.split(' - ')[0] | int }}"
|
||||
page1font: "{{ page1font_select.split(' - ')[0] | int(default=6) }}"
|
||||
page1page: !input page1page
|
||||
page2text: !input page2text
|
||||
page2font_select: !input page2font_select
|
||||
page2font: "{{ page2font_select.split(' - ')[0] | int }}"
|
||||
page2font: "{{ page2font_select.split(' - ')[0] | int(default=6) }}"
|
||||
page2page: !input page2page
|
||||
page3text: !input page3text
|
||||
page3font_select: !input page3font_select
|
||||
page3font: "{{ page3font_select.split(' - ')[0] | int }}"
|
||||
page3font: "{{ page3font_select.split(' - ')[0] | int(default=6) }}"
|
||||
page3page: !input page3page
|
||||
page_scroll: !input page_scroll
|
||||
page_scroll_list: !input page_scroll_list
|
||||
@ -289,29 +289,29 @@ variables:
|
||||
page_list: '{{page_scroll_list.split(",")}}'
|
||||
page_previous: >
|
||||
{%- set page = namespace() -%}
|
||||
{%- set page.previous = page_list[(page_list|length)-1]|int -%}
|
||||
{%- set page.next = page_list[0]|int -%}
|
||||
{%- set page.previous = page_list[(page_list|length)-1]|int(default=10) -%}
|
||||
{%- set page.next = page_list[0]|int(default=1) -%}
|
||||
{%- for item in page_list -%}
|
||||
{%- if item|int == activepage -%}
|
||||
{%- if item|int(default=1) == activepage -%}
|
||||
{%- if not loop.first -%}
|
||||
{%- set page.previous = loop.previtem|int -%}
|
||||
{%- set page.previous = loop.previtem|int(default=1) -%}
|
||||
{%- endif -%}
|
||||
{%- if not loop.last -%}
|
||||
{%- set page.next = loop.nextitem|int -%}
|
||||
{%- set page.next = loop.nextitem|int(default=1) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}{{page.previous}}
|
||||
page_next: >
|
||||
{%- set page = namespace() -%}
|
||||
{%- set page.previous = page_list[(page_list|length)-1]|int -%}
|
||||
{%- set page.next = page_list[0]|int -%}
|
||||
{%- set page.previous = page_list[(page_list|length)-1]|int(default=10) -%}
|
||||
{%- set page.next = page_list[0]|int(default=1) -%}
|
||||
{%- for item in page_list -%}
|
||||
{%- if item|int == activepage -%}
|
||||
{%- if item|int(default=1) == activepage -%}
|
||||
{%- if not loop.first -%}
|
||||
{%- set page.previous = loop.previtem|int -%}
|
||||
{%- set page.previous = loop.previtem|int(default=1) -%}
|
||||
{%- endif -%}
|
||||
{%- if not loop.last -%}
|
||||
{%- set page.next = loop.nextitem|int -%}
|
||||
{%- set page.next = loop.nextitem|int(default=1) -%}
|
||||
{%- endif -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}{{page.next}}
|
||||
@ -608,11 +608,11 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=0) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- else -%}{%- for p in range(1,12) %}"p[{{p}}].b[1].pco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- else -%}{%- for p in range(1,12) %}"p[{{p}}].b[3].pco2={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply selected background color to page select buttons
|
||||
data:
|
||||
@ -628,11 +628,11 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=65535) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].bco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].bco2={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply unselected foreground color to page select buttons
|
||||
data:
|
||||
@ -648,11 +648,11 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=59164) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].pco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].pco={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply unselected background color to page select buttons
|
||||
data:
|
||||
@ -668,11 +668,11 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=16904) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].bco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].bco={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
|
||||
#########################################################################
|
||||
@ -707,11 +707,12 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=0) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- else -%}{%- for p in range(1,12) %}"p[{{p}}].b[1].pco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- else -%}{%- for p in range(1,12) %}"p[{{p}}].b[2].pco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- else -%}{%- for p in range(1,12) %}"p[{{p}}].b[3].pco2={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply selected background color to page select buttons
|
||||
data:
|
||||
@ -727,11 +728,12 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=65535) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].bco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco2={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[2].bco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco2={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].bco2={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply unselected foreground color to page select buttons
|
||||
data:
|
||||
@ -747,11 +749,12 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=59164) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].pco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].pco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[2].pco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].pco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].pco={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # apply unselected background color to page select buttons
|
||||
data:
|
||||
@ -767,11 +770,12 @@ action:
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- set colorcode = (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int(default=16904) -%}
|
||||
[{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[1].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[1].bco={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[2].bco={{colorcode}}"{%- endif -%},{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[2].bco2={{colorcode}}",{%- endfor -%}{%- endif -%}
|
||||
{%- if not page_scroll -%}{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco2={{colorcode}}"{%- else -%}"p[{{p}}].b[3].bco={{colorcode}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}
|
||||
{% else %}{%- for p in range(1,12) %}"p[{{p}}].b[3].bco={{colorcode}}"{% if not loop.last %},{% endif %}{%- endfor -%}{%- endif -%}]
|
||||
- service: mqtt.publish # request sensor update
|
||||
data:
|
||||
@ -847,9 +851,9 @@ action:
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].pco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].pco2={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].pco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].pco2={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.platform == 'mqtt') and (trigger.topic == selectedfgtopic) and page_scroll }}"
|
||||
@ -859,7 +863,7 @@ action:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}"p[{{p}}].b[1].pco2={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[2].pco={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[3].pco2={{trigger.payload}}"{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
@ -869,9 +873,9 @@ action:
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].bco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].bco2={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].bco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].bco2={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.platform == 'mqtt') and (trigger.topic == selectedbgtopic) and page_scroll }}"
|
||||
@ -881,7 +885,7 @@ action:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}"p[{{p}}].b[1].bco2={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[2].bco={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[3].bco2={{trigger.payload}}"{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
@ -891,9 +895,9 @@ action:
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].pco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].pco={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].pco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].pco={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.platform == 'mqtt') and (trigger.topic == unselectedfgtopic) and page_scroll }}"
|
||||
@ -903,7 +907,7 @@ action:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}"p[{{p}}].b[1].pco={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].pco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].pco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[2].pco2={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[3].pco={{trigger.payload}}"{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
@ -913,9 +917,9 @@ action:
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int %}"p[{{p}}].b[1].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].bco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int %}"p[{{p}}].b[3].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].bco={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
[{%- for p in range(1,12) %}{%- if p == page1page|int(default=1) %}"p[{{p}}].b[1].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[1].bco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int(default=2) %}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page3page|int(default=3) %}"p[{{p}}].b[3].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[3].bco={{trigger.payload}}"{%- endif -%}{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.platform == 'mqtt') and (trigger.topic == unselectedbgtopic) and page_scroll }}"
|
||||
@ -925,5 +929,5 @@ action:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[{%- for p in range(1,12) %}"p[{{p}}].b[1].bco={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}{%- if p == page2page|int %}"p[{{p}}].b[2].bco2={{trigger.payload}}"{%- else -%}"p[{{p}}].b[2].bco={{trigger.payload}}"{%- endif -%},{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[2].bco2={{trigger.payload}}",{%- endfor -%}
|
||||
{%- for p in range(1,12) %}"p[{{p}}].b[3].bco={{trigger.payload}}"{% if not loop.last %},{% endif %}{%- endfor -%}]
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone create device triggers"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] cycles through multiple automations"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone dim the display screen after a specified period of inactivity"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone dims the backlight with the sun"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[7].b[all] displays an alarm control panel"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the month + date with a calendar icon"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays a clock"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -165,11 +165,11 @@ variables:
|
||||
hasppage: !input hasppage
|
||||
haspbutton: !input haspbutton
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
hour24: !input hour24
|
||||
ampm: !input ampm
|
||||
wrap: !input wrap
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays a clock with a clock icon"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
1216
Home_Assistant/blueprints/hasp_Display_Color_Swatches.yaml
Normal file
1216
Home_Assistant/blueprints/hasp_Display_Color_Swatches.yaml
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays a dimmer with a toggle on/off icon"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -144,11 +144,11 @@ variables:
|
||||
text_on: !input text_on
|
||||
text_off: !input text_off
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=6) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
icon_on: !input icon_on
|
||||
icon_off: !input icon_off
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the state or attribute value of an entity"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -239,11 +239,11 @@ variables:
|
||||
prefix: !input prefix
|
||||
suffix: !input suffix
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
title_case: !input title_case
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
@ -474,4 +474,3 @@ action:
|
||||
data:
|
||||
topic: "{{commandtopic}}.bco2"
|
||||
payload: "{{trigger.payload}}"
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[6].b[all] Page 6 displays Heatpump controls"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[9].b[all] Page 9 displays Heatpump controls"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[8].b[all] Page 8 displays media controls"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the output of a template"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -134,7 +134,7 @@ blueprint:
|
||||
description: "Enter a well-formed [Home Assistant template](https://www.home-assistant.io/docs/configuration/templating/) string. The variable `trigger_entity` will contain the entity name selected above."
|
||||
default: 'Forecast: {{state_attr("weather.home", "forecast")[0].condition|title}}'
|
||||
selector:
|
||||
text:
|
||||
template:
|
||||
font_select:
|
||||
name: "Font"
|
||||
description: "Select the font for the displayed text. Refer to the HASPone Font Reference above."
|
||||
@ -232,11 +232,11 @@ variables:
|
||||
trigger_entity: !input trigger_entity
|
||||
text: !input template
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays text"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
@ -215,11 +215,11 @@ variables:
|
||||
haspbutton: !input haspbutton
|
||||
text: !input text
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays a toggle button"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -268,6 +268,12 @@ blueprint:
|
||||
default: false
|
||||
selector:
|
||||
boolean:
|
||||
text_enable:
|
||||
name: "Text enabled"
|
||||
description: "Enable text, font, and colors. If disabled, no output will be sent to the button but the toggle actions will still be activated on press. Useful to combine with other blueprints that might place output on this button."
|
||||
default: true
|
||||
selector:
|
||||
boolean:
|
||||
|
||||
mode: parallel
|
||||
max_exceeded: silent
|
||||
@ -294,12 +300,13 @@ variables:
|
||||
off_fgcolor: !input off_fgcolor
|
||||
off_bgcolor: !input off_bgcolor
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
text_enable: !input text_enable
|
||||
haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}'
|
||||
commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}'
|
||||
jsontopic: '{{ "hasp/" ~ haspname ~ "/state/json" }}'
|
||||
@ -429,6 +436,8 @@ action:
|
||||
or
|
||||
((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON'))
|
||||
-}}
|
||||
|
||||
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
@ -450,7 +459,7 @@ action:
|
||||
# Update display if our entity has changed state
|
||||
- conditions: # Update display if our entity has changed state
|
||||
- condition: template
|
||||
value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == entity) }}'
|
||||
value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == entity) and (text_enable == true) }}'
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
@ -493,7 +502,7 @@ action:
|
||||
# Theme: Apply selected foreground color when it changes
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.topic == selectedfgtopic }}"
|
||||
value_template: "{{ (trigger.topic == selectedfgtopic) and (text_enable == true) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
@ -503,7 +512,7 @@ action:
|
||||
# Theme: Apply selected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.topic == selectedbgtopic }}"
|
||||
value_template: "{{ (trigger.topic == selectedbgtopic) and (text_enable == true) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
@ -513,7 +522,7 @@ action:
|
||||
# Theme: Apply unselected foreground color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.topic == unselectedfgtopic }}"
|
||||
value_template: "{{ (trigger.topic == unselectedfgtopic) and (text_enable == true) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
@ -523,7 +532,7 @@ action:
|
||||
# Theme: Apply unselected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ trigger.topic == unselectedbgtopic }}"
|
||||
value_template: "{{ (trigger.topic == unselectedbgtopic) and (text_enable == true) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the value of a given entity with icons and colors"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[8].b[9] The slider button on page 8 displays a volume control"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the current weather condition"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -214,11 +214,11 @@ variables:
|
||||
haspbutton: !input haspbutton
|
||||
weather_provider: !input weather_provider
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
wrap: !input wrap
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the current weather condition icon only"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -183,11 +183,11 @@ variables:
|
||||
haspbutton: !input haspbutton
|
||||
weather_provider: !input weather_provider
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
font: '{{ font_select.split(" - ")[0] | int(default=8) }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int(default=1) }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int(default=1) }}'
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
unselected_fgcolor: !input unselected_fgcolor
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the current weather condition with icons"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the weather forecast"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
@ -120,19 +120,29 @@ blueprint:
|
||||
selector:
|
||||
entity:
|
||||
domain: weather
|
||||
forecast_interval:
|
||||
name: "Forecast interval"
|
||||
description: 'Forecast interval, one of "hourly", "twice daily", or "daily". Not all weather providers will offer all options.'
|
||||
default: "daily"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "hourly"
|
||||
- "twice_daily"
|
||||
- "daily"
|
||||
forecast_index:
|
||||
name: "Forecast index"
|
||||
description: 'Weather forecasts are provided at intervals determined by your weather source. The next time interval will be index "0". Increment this number for future forecasts'
|
||||
description: 'Select a specific forecast, the next time interval will be index "0". Increment this number for future forecasts'
|
||||
default: 0
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 10
|
||||
max: 48
|
||||
mode: slider
|
||||
unit_of_measurement: index
|
||||
forecast_attribute:
|
||||
name: "Enter the desired forecast attribute"
|
||||
description: 'Type in the name of the desired forecast attribute for your provider. "condition" is a common attribute for many providers.'
|
||||
description: 'Type in the name of the desired forecast attribute for your provider. "condition" is a common attribute for many providers.'
|
||||
default: "condition"
|
||||
selector:
|
||||
text:
|
||||
@ -243,6 +253,7 @@ variables:
|
||||
hasppage: !input hasppage
|
||||
haspbutton: !input haspbutton
|
||||
weather_provider: !input weather_provider
|
||||
forecast_interval: !input forecast_interval
|
||||
forecast_index: !input forecast_index
|
||||
forecast_attribute: !input forecast_attribute
|
||||
prefix: !input prefix
|
||||
@ -261,15 +272,6 @@ variables:
|
||||
haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}'
|
||||
commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}'
|
||||
jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}'
|
||||
text: >-
|
||||
{%- if prefix|lower != "none" -%}
|
||||
{{ prefix }}
|
||||
{%- endif -%}
|
||||
{%- if title_case -%}
|
||||
{{ state_attr(weather_provider, "forecast")[forecast_index|int(default=0)].get(forecast_attribute)|replace("windy-variant","windy")|replace("clear-night","clear night")|replace("partlycloudy","partly cloudy")|replace("lightning-rainy","lightning & rain")|replace("snowy-rainy","snow & rain") | title }}
|
||||
{%- else -%}
|
||||
{{ state_attr(weather_provider, "forecast")[forecast_index|int(default=0)].get(forecast_attribute)|replace("windy-variant","windy")|replace("clear-night","clear night")|replace("partlycloudy","partly cloudy")|replace("lightning-rainy","lightning & rain")|replace("snowy-rainy","snow & rain") }}
|
||||
{%- endif -%}
|
||||
isbr: "{% if wrap == true %}1{% else %}0{% endif %}"
|
||||
selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}'
|
||||
selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}'
|
||||
@ -380,6 +382,23 @@ condition:
|
||||
value_template: "{{ is_state(haspsensor, 'ON') }}"
|
||||
|
||||
action:
|
||||
- service: weather.get_forecasts
|
||||
target:
|
||||
entity_id: !input weather_provider
|
||||
data:
|
||||
type: "{{forecast_interval}}"
|
||||
response_variable: weather_forecast
|
||||
- variables:
|
||||
text: >-
|
||||
{%- if prefix|lower != "none" -%}
|
||||
{{ prefix }}
|
||||
{%- endif -%}
|
||||
{%- if title_case -%}
|
||||
{{ weather_forecast[weather_provider]['forecast'][forecast_index][forecast_attribute]|replace("windy-variant","windy")|replace("clear-night","clear night")|replace("partlycloudy","partly cloudy")|replace("lightning-rainy","lightning & rain")|replace("snowy-rainy","snow & rain") | title }}
|
||||
{%- else -%}
|
||||
{{ weather_forecast[weather_provider]['forecast'][forecast_index][forecast_attribute]|replace("windy-variant","windy")|replace("clear-night","clear night")|replace("partlycloudy","partly cloudy")|replace("lightning-rainy","lightning & rain")|replace("snowy-rainy","snow & rain") }}
|
||||
{%- endif -%}
|
||||
|
||||
- choose:
|
||||
#########################################################################
|
||||
# Display attribute and apply text style when "RUN ACTIONS" is pressed by the user
|
||||
|
@ -0,0 +1,459 @@
|
||||
blueprint:
|
||||
name: "HASPone p[x].b[y] displays the weather forecast High and Low temperature"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
A HASPone button displays the high and low temperatures from a selected weather forecast.
|
||||
|
||||

|
||||
|
||||
## HASPone Page and Button Reference
|
||||
|
||||
The images below show each available HASPone page along with the layout of available button objects.
|
||||
|
||||
<details>
|
||||
|
||||
| Page 0 | Pages 1-3 | Pages 4-5 |
|
||||
|--------|-----------|-----------|
|
||||
|  |  |  |
|
||||
|
||||
| Page 6 | Page 7 | Page 8 |
|
||||
|--------|--------|--------|
|
||||
|  |  |  |
|
||||
|
||||
| Page 9 | Page 10 | Page 11 |
|
||||
|--------|---------|---------|
|
||||
|  |  | 
|
||||
|
||||
</details>
|
||||
|
||||
## HASPone Font Reference
|
||||
|
||||
<details>
|
||||
|
||||
The Nextion display supports monospaced and proportional fonts. For monospace fonts, the HASPone project includes [Consolas](https://docs.microsoft.com/en-us/typography/font-list/consolas) monospace in 4 sizes, [Webdings](https://en.wikipedia.org/wiki/Webdings#Character_set) in 1 size, and [Google's "Noto Sans"](https://github.com/googlefonts/noto-fonts) proportional in 5 sizes
|
||||
|
||||
| Font | Name | Characters per line | Lines per button |
|
||||
| :--- | :---------------- | :-------------------| :--------------- |
|
||||
| 0 | Consolas 24 | 20 characters | 2 lines |
|
||||
| 1 | Consolas 32 | 15 characters | 2 lines |
|
||||
| 2 | Consolas 48 | 10 characters | 1 line |
|
||||
| 3 | Consolas 80 | 6 characters | 1 line |
|
||||
| 4 | Webdings 56 | 8 characters | 1 line |
|
||||
| 5 | Noto Sans 24 | Proportional | 2 lines |
|
||||
| 6 | Noto Sans 32 | Proportional | 2 lines |
|
||||
| 7 | Noto Sans 48 | Proportional | 1 line |
|
||||
| 8 | Noto Sans 64 | Proportional | 1 line |
|
||||
| 9 | Noto Sans 80 | Proportional | 1 line |
|
||||
| 10 | Noto Sans Bold 80 | Proportional | 1 line |
|
||||
|
||||
### Icons
|
||||
|
||||
Fonts 5-10 also include [1400+ icons which you can copy and paste from here](https://htmlpreview.github.io/?https://github.com/HASwitchPlate/HASPone/blob/main/images/hasp-fontawesome5.html)
|
||||
|
||||
### Font examples
|
||||
|
||||
  
|
||||
|
||||
</details>
|
||||
|
||||
## Nextion color codes
|
||||
|
||||
<details>
|
||||
|
||||
The Nextion environment utilizes RGB 565 encoding. [Use this handy convertor](https://nodtem66.github.io/nextion-hmi-color-convert/index.html) to select your colors and convert to the RGB 565 format.
|
||||
|
||||
Here are some example colors:
|
||||
|
||||
| Color | Code |
|
||||
|--------|-------|
|
||||
| White | 65535 |
|
||||
| Black | 0 |
|
||||
| Grey | 25388 |
|
||||
| Red | 63488 |
|
||||
| Green | 2016 |
|
||||
| Blue | 31 |
|
||||
| Yellow | 65504 |
|
||||
| Orange | 64512 |
|
||||
| Brown | 48192 |
|
||||
|
||||
</details>
|
||||
|
||||
domain: automation
|
||||
input:
|
||||
haspdevice:
|
||||
name: "HASPone Device"
|
||||
description: "Select the HASPone device"
|
||||
selector:
|
||||
device:
|
||||
integration: mqtt
|
||||
manufacturer: "HASwitchPlate"
|
||||
model: "HASPone v1.0.0"
|
||||
hasppage:
|
||||
name: "HASPone Page"
|
||||
description: "Select the HASPone page (1-11) for the forecast. Refer to the HASPone Page and Button reference above."
|
||||
default: 1
|
||||
selector:
|
||||
number:
|
||||
min: 1
|
||||
max: 11
|
||||
mode: slider
|
||||
unit_of_measurement: page
|
||||
haspbutton:
|
||||
name: "HASPone Button"
|
||||
description: "Select the HASPone button (4-15) for the forecast. Refer to the HASPone Page and Button reference above."
|
||||
default: 4
|
||||
selector:
|
||||
number:
|
||||
min: 4
|
||||
max: 15
|
||||
mode: slider
|
||||
unit_of_measurement: button
|
||||
weather_provider:
|
||||
name: "Weather provider"
|
||||
description: "Select the weather provider to obtain the forecast"
|
||||
selector:
|
||||
entity:
|
||||
domain: weather
|
||||
forecast_interval:
|
||||
name: "Forecast interval"
|
||||
description: 'Forecast interval, one of "hourly", "twice daily", or "daily". Not all weather providers will offer all options.'
|
||||
default: "daily"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "hourly"
|
||||
- "twice_daily"
|
||||
- "daily"
|
||||
forecast_index:
|
||||
name: "Forecast index"
|
||||
description: 'Select a specific forecast, the next time interval will be index "0". Increment this number for future forecasts'
|
||||
default: 0
|
||||
selector:
|
||||
number:
|
||||
min: 0
|
||||
max: 48
|
||||
mode: slider
|
||||
unit_of_measurement: index
|
||||
font_select:
|
||||
name: "Font"
|
||||
description: "Select the font for the displayed text. You probably want to leave this as 10, refer to the HASPone Font Reference above."
|
||||
default: "10 - Noto Sans Bold 80"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "0 - Consolas 24"
|
||||
- "1 - Consolas 32"
|
||||
- "2 - Consolas 48"
|
||||
- "3 - Consolas 80"
|
||||
- "4 - Webdings 56"
|
||||
- "5 - Noto Sans 24"
|
||||
- "6 - Noto Sans 32"
|
||||
- "7 - Noto Sans 48"
|
||||
- "8 - Noto Sans 64"
|
||||
- "9 - Noto Sans 80"
|
||||
- "10 - Noto Sans Bold 80"
|
||||
xcen_select:
|
||||
name: "Text horizontal alignment"
|
||||
description: "Horizontal text alignment: 0=Left 1=Center 2=Right"
|
||||
default: "1 - Centered"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "0 - Left aligned"
|
||||
- "1 - Centered"
|
||||
- "2 - Right aligned"
|
||||
ycen_select:
|
||||
name: "Text vertical alignment"
|
||||
description: "Vertical text alignment: 0=Top 1=Center 2=Bottom"
|
||||
default: "1 - Centered"
|
||||
selector:
|
||||
select:
|
||||
options:
|
||||
- "0 - Top aligned"
|
||||
- "1 - Centered"
|
||||
- "2 - Bottom aligned"
|
||||
wrap:
|
||||
name: "Text wrap"
|
||||
default: false
|
||||
description: "Enable line-wrapping text if too long to fit in the button."
|
||||
selector:
|
||||
boolean:
|
||||
selected_fgcolor:
|
||||
name: "Selected foreground color"
|
||||
description: 'Selected foreground color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected foreground color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
selected_bgcolor:
|
||||
name: "Selected background color"
|
||||
description: 'Selected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme selected background color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
unselected_fgcolor:
|
||||
name: "Unselected foreground color"
|
||||
description: 'Unselected foreground color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected foreground color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
unselected_bgcolor:
|
||||
name: "Unselected background color"
|
||||
description: 'Unselected background color in Nextion RGB565 format (see "Nextion color codes" above for reference). -1 = Current theme unselected background color.'
|
||||
default: -1
|
||||
selector:
|
||||
number:
|
||||
min: -1
|
||||
max: 65535
|
||||
mode: slider
|
||||
|
||||
mode: parallel
|
||||
max_exceeded: silent
|
||||
|
||||
variables:
|
||||
haspdevice: !input haspdevice
|
||||
haspname: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
hasppage: !input hasppage
|
||||
haspbutton: !input haspbutton
|
||||
weather_provider: !input weather_provider
|
||||
forecast_interval: !input forecast_interval
|
||||
forecast_index: !input forecast_index
|
||||
font_select: !input font_select
|
||||
font: '{{ font_select.split(" - ")[0] | int }}'
|
||||
xcen_select: !input xcen_select
|
||||
xcen: '{{ xcen_select.split(" - ")[0] | int }}'
|
||||
ycen_select: !input ycen_select
|
||||
ycen: '{{ ycen_select.split(" - ")[0] | int }}'
|
||||
wrap: !input wrap
|
||||
selected_fgcolor: !input selected_fgcolor
|
||||
selected_bgcolor: !input selected_bgcolor
|
||||
unselected_fgcolor: !input unselected_fgcolor
|
||||
unselected_bgcolor: !input unselected_bgcolor
|
||||
haspobject: '{{ "p[" ~ hasppage ~ "].b[" ~ haspbutton ~ "]" }}'
|
||||
commandtopic: '{{ "hasp/" ~ haspname ~ "/command/" ~ haspobject }}'
|
||||
jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}'
|
||||
selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}'
|
||||
selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}'
|
||||
unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}'
|
||||
unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}'
|
||||
selectedfg: >-
|
||||
{%- if (selected_fgcolor|int) >= 0 -%}
|
||||
{{ selected_fgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_selected_foreground_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
selectedbg: >-
|
||||
{%- if (selected_bgcolor|int) >= 0 -%}
|
||||
{{ selected_bgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_selected_background_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
unselectedfg: >-
|
||||
{%- if (unselected_fgcolor|int) >= 0 -%}
|
||||
{{ unselected_fgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_unselected_foreground_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
unselectedbg: >-
|
||||
{%- if (unselected_bgcolor|int) >= 0 -%}
|
||||
{{ unselected_bgcolor }}
|
||||
{%- else -%}
|
||||
{%- set color = namespace() -%}
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^light\..*_unselected_background_color(?:_\d+|)$") -%}
|
||||
{%- set color.source=entity -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- set brightness = state_attr(color.source, "brightness")|int(default=255) / 255 -%}
|
||||
{%- set red=(state_attr(color.source, "rgb_color")[0] * brightness)|int(default=0) -%}
|
||||
{%- set green=(state_attr(color.source, "rgb_color")[1] * brightness)|int(default=0) -%}
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
{%- endif -%}
|
||||
|
||||
trigger_variables:
|
||||
haspdevice: !input haspdevice
|
||||
haspname: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{- entity|regex_replace(find="^sensor\.", replace="", ignorecase=true)|regex_replace(find="_sensor(?:_\d+|)$", replace="", ignorecase=true) -}}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
haspsensor: >-
|
||||
{%- for entity in device_entities(haspdevice) -%}
|
||||
{%- if entity|regex_search("^sensor\..+_sensor(?:_\d+|)$") -%}
|
||||
{{ entity }}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
selectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedforegroundcolor/rgb" }}'
|
||||
selectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/selectedbackgroundcolor/rgb" }}'
|
||||
unselectedfgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedforegroundcolor/rgb" }}'
|
||||
unselectedbgtopic: '{{ "hasp/" ~ haspname ~ "/light/unselectedbackgroundcolor/rgb" }}'
|
||||
|
||||
trigger:
|
||||
- platform: state
|
||||
entity_id: !input weather_provider
|
||||
- platform: template
|
||||
value_template: "{{ is_state(haspsensor, 'ON') }}"
|
||||
- platform: homeassistant
|
||||
event: start
|
||||
- platform: mqtt
|
||||
topic: "{{selectedfgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{selectedbgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{unselectedfgtopic}}"
|
||||
- platform: mqtt
|
||||
topic: "{{unselectedbgtopic}}"
|
||||
|
||||
condition:
|
||||
- condition: template
|
||||
value_template: "{{ is_state(haspsensor, 'ON') }}"
|
||||
|
||||
action:
|
||||
- service: weather.get_forecasts
|
||||
target:
|
||||
entity_id: !input weather_provider
|
||||
data:
|
||||
type: "{{forecast_interval}}"
|
||||
response_variable: weather_forecast
|
||||
- variables:
|
||||
temphigh: '{{ weather_forecast[weather_provider]["forecast"][forecast_index]["temperature"] }}'
|
||||
templow: '{{ weather_forecast[weather_provider]["forecast"][forecast_index]["templow"] }}'
|
||||
text: "{{templow|int(default=0)}}° {{temphigh|int(default=0)}}°"
|
||||
|
||||
- choose:
|
||||
#########################################################################
|
||||
# Display attribute and apply text style when "RUN ACTIONS" is pressed by the user
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: >-
|
||||
{{-
|
||||
(trigger is not defined)
|
||||
or
|
||||
(trigger.platform is none)
|
||||
or
|
||||
((trigger.platform == 'homeassistant') and (trigger.event == 'start'))
|
||||
or
|
||||
((trigger.platform == 'template') and (trigger.entity_id == haspsensor) and (trigger.to_state.state == 'ON'))
|
||||
-}}
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{jsoncommandtopic}}"
|
||||
payload: >-
|
||||
[
|
||||
"{{haspobject}}.font={{font}}",
|
||||
"{{haspobject}}.xcen={{xcen}}",
|
||||
"{{haspobject}}.ycen={{ycen}}",
|
||||
"{{haspobject}}.isbr={{isbr}}",
|
||||
"{{haspobject}}.pco={{selectedfg}}",
|
||||
"{{haspobject}}.bco={{selectedbg}}",
|
||||
"{{haspobject}}.pco2={{unselectedfg}}",
|
||||
"{{haspobject}}.bco2={{unselectedbg}}",
|
||||
"{{haspobject}}.txt=\"{{text}}\""
|
||||
]
|
||||
#########################################################################
|
||||
# Update forecast if our weather provider changed state
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: '{{ (trigger.platform == "state") and (trigger.entity_id == weather_provider) }}'
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{commandtopic}}.txt"
|
||||
payload: '"{{text}}"'
|
||||
#########################################################################
|
||||
# Catch triggers fired by incoming MQTT messages
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: '{{ trigger.platform == "mqtt" }}'
|
||||
sequence:
|
||||
- choose:
|
||||
#########################################################################
|
||||
# Theme: Apply selected foreground color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == selectedfgtopic) and ((selected_fgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{commandtopic}}.pco"
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply selected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == selectedbgtopic) and ((selected_bgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{commandtopic}}.bco"
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply unselected foreground color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == unselectedfgtopic) and ((unselected_fgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{commandtopic}}.pco2"
|
||||
payload: "{{trigger.payload}}"
|
||||
#########################################################################
|
||||
# Theme: Apply unselected background color on change
|
||||
- conditions:
|
||||
- condition: template
|
||||
value_template: "{{ (trigger.topic == unselectedbgtopic) and ((unselected_bgcolor|int) == -1) }}"
|
||||
sequence:
|
||||
- service: mqtt.publish
|
||||
data:
|
||||
topic: "{{commandtopic}}.bco2"
|
||||
payload: "{{trigger.payload}}"
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the current temperature from a weather provider, coloured icon only"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -201,7 +201,7 @@ variables:
|
||||
jsoncommandtopic: '{{ "hasp/" ~ haspname ~ "/command/json" }}'
|
||||
temperature: '{{ state_attr(weather_provider, "temperature") }}'
|
||||
icon: >-
|
||||
{%- set temp = temperature|int -%}
|
||||
{%- set temp = temperature|int(default=0) -%}
|
||||
{%- if temp <= thermometer_quarter_threshold|int -%}
|
||||
|
||||
{%- elif temp < thermometer_half_threshold|int -%}
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] displays the current temperature from a weather provider with icon and colors"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
@ -224,10 +224,10 @@ variables:
|
||||
{%- if roundtemp == true -%}
|
||||
{{- state_attr(weather_provider, "temperature") | round(default=0) -}}
|
||||
{%- else -%}
|
||||
{{- state_attr(weather_provider, "temperature") -}}
|
||||
{{- state_attr(weather_provider, "temperature") | float(default=0) -}}
|
||||
{%- endif -%}
|
||||
icon: >-
|
||||
{%- set temp = temperature|int -%}
|
||||
{%- set temp = temperature|int(default=0) -%}
|
||||
{%- if temp <= thermometer_quarter_threshold|int -%}
|
||||
|
||||
{%- elif temp < thermometer_half_threshold|int -%}
|
||||
@ -310,7 +310,7 @@ variables:
|
||||
{%- set blue=(state_attr(color.source, "rgb_color")[2] * brightness)|int(default=0) -%}
|
||||
{{ (red|bitwise_and(248)*256) + (green|bitwise_and(252)*8) + (blue|bitwise_and(248)/8)|int }}
|
||||
tempcolor: >-
|
||||
{%- set temp = temperature|int -%}
|
||||
{%- set temp = temperature|int(default=0) -%}
|
||||
{%- if temp <= thermometer_quarter_threshold|int -%}
|
||||
{%- set color = thermometer_empty_color -%}
|
||||
{%- elif temp < thermometer_half_threshold|int -%}
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone p[x].b[y] performs an action when pressed"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone Remove MQTT discovery messages"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
# Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone Theme Dark on Light"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone Theme Light on Dark Blue"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
@ -52,7 +52,7 @@ variables:
|
||||
{%- endfor -%}
|
||||
selected_foreground_brightness: "255"
|
||||
selected_foreground_color: "[255, 255, 255]"
|
||||
selected_background_brightness: "1"
|
||||
selected_background_brightness: "32"
|
||||
selected_background_color: "[0, 0, 255]"
|
||||
unselected_foreground_brightness: "224"
|
||||
unselected_foreground_color: "[255, 255, 255]"
|
||||
|
@ -2,7 +2,7 @@ blueprint:
|
||||
name: "HASPone Theme Light on Dark"
|
||||
description: |
|
||||
|
||||
## Blueprint Version: `1.05.00`
|
||||
## Blueprint Version: `1.06.00`
|
||||
|
||||
## Description
|
||||
|
||||
|
75
esphome/haspone.yaml
Normal file
75
esphome/haspone.yaml
Normal file
@ -0,0 +1,75 @@
|
||||
# Example ESPhome configuration for use with the HASPone hardware
|
||||
|
||||
substitutions:
|
||||
device_name: "haspone"
|
||||
friendly_name: "HASPone hardware for ESPhome"
|
||||
project_version: "0.0.1"
|
||||
|
||||
esphome:
|
||||
name: ${device_name}
|
||||
friendly_name: ${friendly_name}
|
||||
comment: "http://haswitchplate.com"
|
||||
project:
|
||||
name: "esphome.${device_name}"
|
||||
version: ${project_version}
|
||||
on_boot:
|
||||
then:
|
||||
- switch.turn_on: switch_lcdpower # Power up the Nextion on boot
|
||||
|
||||
esp8266:
|
||||
board: d1_mini
|
||||
|
||||
logger:
|
||||
|
||||
api:
|
||||
|
||||
ota:
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
web_server:
|
||||
port: 80
|
||||
|
||||
# HASPone switch controls power to the Nextion. Set HIGH at power on to enable the device at boot.
|
||||
switch:
|
||||
- platform: gpio
|
||||
id: switch_lcdpower
|
||||
name: "${friendly_name} Nextion Power"
|
||||
pin: D6 #GPIO12
|
||||
restore_mode: ALWAYS_ON
|
||||
internal: false
|
||||
|
||||
# UART for HASPone communication to Nextion. This will utilize software serial and might not work well for TFT updates.
|
||||
uart:
|
||||
id: uart_nextion
|
||||
tx_pin: D4 #GPIO2
|
||||
rx_pin: D7 #GPIO13
|
||||
baud_rate: 115200
|
||||
|
||||
# Nextion display device
|
||||
display:
|
||||
- platform: nextion
|
||||
id: display_nextion
|
||||
uart_id: uart_nextion
|
||||
on_touch:
|
||||
then:
|
||||
lambda: |-
|
||||
ESP_LOGD("nextion.on_touch", "Nextion touch event detected!");
|
||||
ESP_LOGD("nextion.on_touch", "Page Id: %i", page_id);
|
||||
ESP_LOGD("nextion.on_touch", "Component Id: %i", component_id);
|
||||
ESP_LOGD("nextion.on_touch", "Event type: %s", touch_event ? "Press" : "Release");
|
||||
|
||||
# Nextion backlight control
|
||||
number:
|
||||
- platform: template
|
||||
id: number_brightness
|
||||
name: "${friendly_name} Nextion Brightness"
|
||||
min_value: 0
|
||||
max_value: 100
|
||||
step: 1
|
||||
initial_value: 100
|
||||
optimistic: true
|
||||
set_action:
|
||||
- lambda: id(display_nextion)->set_backlight_brightness(x/100);
|
3
esphome/readme.md
Normal file
3
esphome/readme.md
Normal file
@ -0,0 +1,3 @@
|
||||
# HASPone for ESPhome
|
||||
|
||||
Here you'll find an example ESPhome configuration for use with the HASPone hardware, this should be compatible with existing ESPhome-native Nextion projects for a 2.8" panel.
|
BIN
images/HASP PCB Back.png
Normal file
BIN
images/HASP PCB Back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 149 KiB |
BIN
images/HASP PCB Front and Back.png
Normal file
BIN
images/HASP PCB Front and Back.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 279 KiB |
BIN
images/HASP PCB Front.png
Normal file
BIN
images/HASP PCB Front.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 130 KiB |
@ -1,18 +1,18 @@
|
||||
{
|
||||
"d1_mini": {
|
||||
"version": "1.05",
|
||||
"firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Arduino_Sketch/HASwitchPlate.ino.d1_mini.bin"
|
||||
"version": "1.06",
|
||||
"firmware": "https://haswitchplate.com/update/main/HASwitchPlate.ino.d1_mini.bin"
|
||||
},
|
||||
"NX3224T024_011R": {
|
||||
"version": 3,
|
||||
"firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate.tft"
|
||||
"firmware": "https://haswitchplate.com/update/main/HASwitchPlate.tft"
|
||||
},
|
||||
"NX3224K024_011R": {
|
||||
"version": 3,
|
||||
"firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate-Enhanced.tft"
|
||||
"firmware": "https://haswitchplate.com/update/main/HASwitchPlate-Enhanced.tft"
|
||||
},
|
||||
"NX3224F024_011R": {
|
||||
"version": 3,
|
||||
"firmware": "https://raw.githubusercontent.com/HASwitchPlate/HASPone/main/Nextion_HMI/HASwitchPlate-Discovery.tft"
|
||||
"firmware": "https://haswitchplate.com/update/main/HASwitchPlate-Discovery.tft"
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user