Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efc3feb031 | ||
|
|
1ec3e1879f | ||
|
|
7ae92918d3 | ||
|
|
aa58222296 | ||
|
|
b12b6a7d69 | ||
|
|
088db53a47 | ||
|
|
92ed59f869 | ||
|
|
51bdcac3e0 | ||
|
|
34c06a3e0b | ||
|
|
279319ed0c | ||
|
|
ec3acfe28e | ||
|
|
0bdb67e20e | ||
|
|
3e4654b4e0 | ||
|
|
f1e722cd3b | ||
|
|
01020a20d0 | ||
|
|
147a99cd8a | ||
|
|
868cf2ab70 | ||
|
|
0752709e09 | ||
|
|
cc88e7ba21 | ||
|
|
6525a0b400 | ||
|
|
e46215e7fb | ||
|
|
3b5cbb362c | ||
|
|
6bc1297eab | ||
|
|
95657fcb08 | ||
|
|
302c4a88f8 | ||
|
|
6de0d94dca | ||
|
|
34ef0d0f99 | ||
|
|
c1cde0f159 | ||
|
|
e81582f7da | ||
|
|
c5bdb903c0 | ||
|
|
b726af5c72 | ||
|
|
6531708579 | ||
|
|
262bb7dd0d | ||
|
|
c345fe0f0b | ||
|
|
485fa923fb | ||
|
|
c03360a381 | ||
|
|
72ce117299 | ||
|
|
8815f5e113 | ||
|
|
13763326ce | ||
|
|
3fa067ba37 | ||
|
|
b1271c8c12 | ||
|
|
bf606810b7 | ||
|
|
aa262f7546 | ||
|
|
54d1e432f3 | ||
|
|
1b2e11ed8c | ||
|
|
946ae2c6d1 | ||
|
|
db555ce359 | ||
|
|
7b238ac2d8 | ||
|
|
6de381b32f | ||
|
|
aaa1d6421d | ||
|
|
ae34e28ed2 | ||
|
|
f0a99c50fd | ||
|
|
5efc0b7671 | ||
|
|
11a0ef1ff0 | ||
|
|
8f460f5cb9 | ||
|
|
4536e15b7b | ||
|
|
46c003cf08 | ||
|
|
0446120b22 | ||
|
|
f4f8ba7df9 |
+1
-23
@@ -1,23 +1 @@
|
||||
# === .gitignore for Global/VisualStudioCode (https://raw.githubusercontent.com/github/gitignore/main/Global/VisualStudioCode.gitignore) ===
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
!*.code-workspace
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
|
||||
# === .gitignore for community/embedded/esp-idf (https://raw.githubusercontent.com/github/gitignore/main/community/embedded/esp-idf.gitignore) ===
|
||||
|
||||
# gitignore template for esp-idf, the official development framework for ESP32
|
||||
# https://github.com/espressif/esp-idf
|
||||
|
||||
build/
|
||||
sdkconfig
|
||||
sdkconfig.old
|
||||
.vscode/settings.json
|
||||
|
||||
Vendored
-5
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"esphome.esphome-vscode"
|
||||
]
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
# Base module V2
|
||||
|
||||
## Controller
|
||||
Brand: Espressif
|
||||
Type: ESP32-S3-WROOM-1-N16R8
|
||||
Driver IC: ST7735S (ESPHome compatible)
|
||||
|
||||
[Datasheet](../Datasheets/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf)
|
||||
|
||||
### Pinout / IO
|
||||
|
||||
```
|
||||
1 GND
|
||||
2 3.3V
|
||||
3 EN
|
||||
4 IO4 Neopixel LED's
|
||||
5 IO5 SPI MOSI
|
||||
6 IO6 SPI SCK
|
||||
7 IO7 SPI Register select
|
||||
8 IO15
|
||||
9 IO16
|
||||
10 IO17
|
||||
11 IO18
|
||||
12 IO8
|
||||
13 IO19
|
||||
14 IO20
|
||||
15 IO3 Backlight main display
|
||||
16 IO46 Backlight mini displays
|
||||
17 IO9
|
||||
18 IO10
|
||||
19 IO11
|
||||
20 IO12
|
||||
21 IO13
|
||||
22 IO14
|
||||
23 IO21
|
||||
24 IO47 I2C SDA > Buttons
|
||||
25 IO48 I2C SCL > Buttons
|
||||
26 IO45
|
||||
27 IO0
|
||||
28 IO35
|
||||
29 IO36
|
||||
30 IO37
|
||||
31 IO38
|
||||
32 IO39
|
||||
33 IO40
|
||||
34 IO41
|
||||
35 IO42
|
||||
36 TXD0
|
||||
37 RXD0
|
||||
38 IO1 I2C SDA > Temperature & Ambient Sensor
|
||||
39 IO2 I2S SCL > Temperature & Ambient Sensor
|
||||
40 GND
|
||||
```
|
||||
|
||||
## Connectors
|
||||
|
||||
### Connector J0
|
||||
|
||||
```
|
||||
MCP I2C address: 0x20
|
||||
|
||||
PIN Description Destination
|
||||
1 GND
|
||||
2 +3.3V
|
||||
3 Reset ESP32 #3 EN
|
||||
4 I2C SDA ESP32 #24 IO47
|
||||
5 SPI MOSI ESP32 #5 IO5
|
||||
6 I2C SCK ESP32 #25 IO48
|
||||
7 SPI SCK ESP32 #6 IO6
|
||||
8 I2C Address MSP A0 GND
|
||||
9 SPI Register select ESP32 #7 IO7
|
||||
10 I2C Address MSP A1 GND
|
||||
11 Mini Display Backlight anode ESP32 #16 IO46 (via transistor)
|
||||
12 I2C Address MSP A2 GND
|
||||
13 Extensionplate...
|
||||
14 Connected with J1,2,3
|
||||
15 Main Display Backlight anode ESP32 #15 IO3 (via transistor)
|
||||
16 Neopixel Data OUT J1 #17
|
||||
17 Neopixel Data IN ESP32 #4 IO4
|
||||
```
|
||||
|
||||
### Connector J1
|
||||
|
||||
```
|
||||
MCP I2C address: 0x21
|
||||
|
||||
PIN Description Destination
|
||||
1 GND
|
||||
2 +3.3V
|
||||
3 Reset ESP32 #3 EN
|
||||
4 I2C SDA ESP32 #24 IO47
|
||||
5 SPI MOSI ESP32 #5 IO5
|
||||
6 I2C SCK ESP32 #25 IO48
|
||||
7 SPI SCK ESP32 #6 IO6
|
||||
8 I2C Address MSP A0 3.3V
|
||||
9 SPI Register select ESP32 #7 IO7
|
||||
10 I2C Address MSP A1 GND
|
||||
11 Mini Display Backlight anode ESP32 #16 IO46 (via transistor)
|
||||
12 I2C Address MSP A2 GND
|
||||
13 Extensionplate...
|
||||
14 Connected with J0,2,3
|
||||
15 Main Display Backlight anode ESP32 #15 IO3 (via transistor)
|
||||
16 Neopixel Data OUT J2 #17
|
||||
17 Neopixel Data IN J0 #16
|
||||
```
|
||||
|
||||
### Connector J2
|
||||
|
||||
```
|
||||
MCP I2C address: 0x22
|
||||
|
||||
PIN Description Destination
|
||||
1 GND
|
||||
2 +3.3V
|
||||
3 Reset ESP32 #3 EN
|
||||
4 I2C SDA ESP32 #24 IO47
|
||||
5 SPI MOSI ESP32 #5 IO5
|
||||
6 I2C SCK ESP32 #25 IO48
|
||||
7 SPI SCK ESP32 #6 IO6
|
||||
8 I2C Address MSP A0 GND
|
||||
9 SPI Register select ESP32 #7 IO7
|
||||
10 I2C Address MSP A1 3.3V
|
||||
11 Mini Display Backlight anode ESP32 #16 IO46 (via transistor)
|
||||
12 I2C Address MSP A2 GND
|
||||
13 Extensionplate...
|
||||
14 Connected with J0,1,3
|
||||
15 Main Display Backlight anode ESP32 #15 IO3 (via transistor)
|
||||
16 Neopixel Data OUT J3 #17
|
||||
17 Neopixel Data IN J1 #16
|
||||
```
|
||||
|
||||
### Connector J3
|
||||
|
||||
```
|
||||
MCP I2C address: 0x23
|
||||
|
||||
PIN Description Destination
|
||||
1 GND
|
||||
2 +3.3V
|
||||
3 Reset ESP32 #3 EN
|
||||
4 I2C SDA ESP32 #24 IO47
|
||||
5 SPI MOSI ESP32 #5 IO5
|
||||
6 I2C SCK ESP32 #25 IO48
|
||||
7 SPI SCL ESP32 #6 IO6
|
||||
8 I2C Address MSP A0 3.3V
|
||||
9 SPI Register select ESP32 #7 IO7
|
||||
10 I2C Address MSP A1 3.3V
|
||||
11 Mini Display Backlight anode ESP32 #16 IO46 (via transistor)
|
||||
12 I2C Address MSP A2 GND
|
||||
13 Extensionplate...
|
||||
14 Connected with J0,1,2
|
||||
15 Main Display Backlight anode ESP32 #15 IO3 (via transistor)
|
||||
16 Neopixel Data OUT Extensionplate #5
|
||||
17 Neopixel Data IN J2 #16
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 446 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
@@ -0,0 +1,35 @@
|
||||
# ESPHome Button+ Integration
|
||||
|
||||
*work in progress*
|
||||
|
||||
## Initial firmware load
|
||||
|
||||
### Required
|
||||
|
||||
- Button+ Base Module
|
||||
- 1x Button+ Main Display
|
||||
- 1x Button+ BAR module
|
||||
- USB-C cable
|
||||
- ESPHome installed on Home-Assistant
|
||||
- [Getting started guide by @balk77](./GettingStarted.md)
|
||||
- [Official ESPhome guide](https://esphome.io/guides/getting_started_hassio.html)
|
||||
- Chrome/Edge or a [WebSerial compatible Browser](https://webserial.io/)
|
||||
|
||||
### Steps
|
||||
|
||||
1. Go to ESPHome in Home Assistant.
|
||||
2. Click on the bottom right on "Add Device"
|
||||
3. Click "Continue"
|
||||
4. Give the device a name you can remember (e.g. "Button+ Kitchen") and click "Next"
|
||||
5. Click "Skip This Step"
|
||||
6. Select the "ESP32-S3"
|
||||
7. Click "Skip"
|
||||
8. On the ESPHome main screen find the device you've just created, on the device card click "Edit"
|
||||
9. Find in the links below the initial script for your setup. Copy
|
||||
- [1 BAR 1 Display](../Examples/1BAR_1Display_Basic.yaml)
|
||||
- [2 BAR 1 Display](../Examples/2BAR_1Display_Basic.yaml)
|
||||
- [3 BAR 1 Display](../Examples/3BAR_1Display_Basic.yaml)
|
||||
10. Klik rechts boven in op "Save" en vervolgens op "Install"
|
||||
11. Kies "Plug into this computer" en volg de instructies. Als je Firefox gebruikt kun je ook "Manual Download" kiezen en de image met ESP tool laden
|
||||
|
||||
Na de initiële upload met USB kun je de Button+ met de Wireless optie laden.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Getting Started
|
||||
|
||||
In order to get started with a 3 bar module, you should
|
||||
1. Make sure you have [ESPHome](https://esphome.io) installed
|
||||
2. Copy the file [3pages_TotalExample.yml](/examples/3pages_TotalExample.yml) to the root of the repository
|
||||
3. Create a file secrets.yaml and add the following
|
||||
```
|
||||
wifi_ssid: "YOUR_SSID"
|
||||
wifi_password: "YOUR_PASSWORD"
|
||||
```
|
||||
5. modify the yml file to your liking (optional)
|
||||
6. Compile (Install, manual download) and download in modern format
|
||||
7. Connect the B+ to your computer
|
||||
8. Open a compatible browser such as Chrome and visit https://web.esphome.io
|
||||
9. Load the downloaded file to your device and enjoy
|
||||
@@ -1,27 +0,0 @@
|
||||
# Getting Started
|
||||
In order to get started with a 3 bar module, you should
|
||||
1. Make sure you have [ESPHome](https://esphome.io) installed
|
||||
2. Copy the file [3BAR_1Display.yml](/Examples/3BAR_1Display.yml) to the root of the repository
|
||||
3. Create a file secrets.yaml and add the following
|
||||
```
|
||||
wifi_ssid: "YOUR_SSID"
|
||||
wifi_password: "YOUR_PASSWORD"
|
||||
```
|
||||
5. modify the yml file to your liking (optional)
|
||||
6. Compile (Install, manual download) and download in modern format
|
||||
7. Connect the B+ to your computer
|
||||
8. Open a compatible browser such as Chrome and visit https://web.esphome.io
|
||||
9. Load the downloaded file to your device and enjoy
|
||||
|
||||
# Generating different events / pages
|
||||
If you want a different number of pages, and you want the matching events, you can generate a new [3bar_1display_events.yaml](/package/3bar_1display_events.yaml) file using python.
|
||||
|
||||
The python file is called [generate_events.py](/generate/generate_events.py). The top of the file has three configuration options:
|
||||
|
||||
```python
|
||||
NR_OF_PAGES = 3
|
||||
INCLUDE_DISPLAY_EXTRA = True # Enable Double, Triple, Hold for main display buttons
|
||||
LED_CONFIRMATION = True # Flash LED on press
|
||||
```
|
||||
|
||||
Set these to your preferred config before running. Then run `python generate_events.py`. Copy the output file to the package folder, and use that package in your main config. Make sure the number of pages in your main config and the generated file are the same.
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files:
|
||||
- 'package/1bar_1display.yaml'
|
||||
ref: main
|
||||
refresh: 1d
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '1'
|
||||
|
||||
globals:
|
||||
- id: !extend page_names
|
||||
initial_value: '{"Page 1"}'
|
||||
- id: !extend active_page_name
|
||||
initial_value: ""
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 64
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 24
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
- id: grey
|
||||
hex: A6A6A6
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: BAR1 button Left event
|
||||
id: bar1_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR1 button Right event
|
||||
id: bar1_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
|
||||
binary_sensor:
|
||||
- id: !extend main_display_btn_left
|
||||
on_click:
|
||||
- script.execute: prev_page
|
||||
- id: !extend main_display_btn_right
|
||||
on_click:
|
||||
- script.execute: next_page
|
||||
- id: !extend bar1_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
|
||||
display:
|
||||
#########
|
||||
# MAIN ##
|
||||
#########
|
||||
- id: !extend main_display
|
||||
# data_rate: 40MHz
|
||||
lambda: |-
|
||||
id(all_pages_main).execute();
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
it.print(100, 160, id(font_arial20), "This is page 0!");
|
||||
break;
|
||||
}
|
||||
|
||||
script:
|
||||
- id: all_pages_main
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(red));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(red));
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(36, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(inside_temperature).state);
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
- id: !extend bar1_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files:
|
||||
- 'package/2bar_1display.yaml'
|
||||
ref: main
|
||||
refresh: 1d
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '1'
|
||||
|
||||
globals:
|
||||
- id: !extend page_names
|
||||
initial_value: '{"Page 1"}'
|
||||
- id: !extend active_page_name
|
||||
initial_value: ""
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 64
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 24
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
- id: grey
|
||||
hex: A6A6A6
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: BAR1 button Left event
|
||||
id: bar1_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR1 button Right event
|
||||
id: bar1_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR2 button Left event
|
||||
id: bar2_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR2 button Right event
|
||||
id: bar2_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
|
||||
binary_sensor:
|
||||
- id: !extend main_display_btn_left
|
||||
on_click:
|
||||
- script.execute: prev_page
|
||||
- id: !extend main_display_btn_right
|
||||
on_click:
|
||||
- script.execute: next_page
|
||||
- id: !extend bar1_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
display:
|
||||
#########
|
||||
# MAIN ##
|
||||
#########
|
||||
- id: !extend main_display
|
||||
# data_rate: 40MHz
|
||||
lambda: |-
|
||||
id(all_pages_main).execute();
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
it.print(100, 160, id(font_arial20), "This is page 0!");
|
||||
break;
|
||||
}
|
||||
|
||||
script:
|
||||
- id: all_pages_main
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(red));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(red));
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(36, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(inside_temperature).state);
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
- id: !extend bar1_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
esphome:
|
||||
name: buttonplus
|
||||
friendly_name: ButtonPlus
|
||||
|
||||
esp32:
|
||||
variant: ESP32S3
|
||||
board: esp32-s3-devkitc1-n16r8
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: esp-idf
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
encryption:
|
||||
key: ""
|
||||
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ""
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
# Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||
ap:
|
||||
ssid: "Buttonplus"
|
||||
password: ""
|
||||
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://gitea.furb.it/kennyboy55/ESPHome_ButtonPlusV2
|
||||
ref: main
|
||||
files:
|
||||
- path: 'package/3bar_1display.yaml'
|
||||
vars:
|
||||
nr_of_pages: '3'
|
||||
page_names: '{"Start", "Music", "Page 3"}'
|
||||
- path: 'package/cards/music.yaml'
|
||||
vars:
|
||||
music_card_entity_id: 'media_player.spotifyplus_kennyboy44'
|
||||
music_card_text_color: FFFFFF
|
||||
music_card_icon_main_color: FF7F00
|
||||
music_card_icon_bar_color: FF7F00
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 64
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 24
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
type: GRAYSCALE
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
type: GRAYSCALE
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
type: GRAYSCALE
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
type: GRAYSCALE
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
type: GRAYSCALE
|
||||
- file: mdi:brightness-percent
|
||||
id: icon_ambient_inside
|
||||
resize: 40x40
|
||||
type: GRAYSCALE
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
- id: grey
|
||||
hex: A6A6A6
|
||||
|
||||
display:
|
||||
#########
|
||||
# MAIN ##
|
||||
#########
|
||||
- id: !extend main_display
|
||||
# data_rate: 40MHz
|
||||
lambda: |-
|
||||
id(all_pages_main).execute();
|
||||
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
it.print(100, 150, id(font_arial20), "Hooray, it works!");
|
||||
break;
|
||||
case 1:
|
||||
id(music_card).execute(20, 125);
|
||||
break;
|
||||
case 2:
|
||||
it.print(100, 150, id(font_arial20), "Last Page");
|
||||
break;
|
||||
}
|
||||
|
||||
script:
|
||||
- id: all_pages_main
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(red));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(red));
|
||||
//
|
||||
//>>> Page name
|
||||
id(main_display).print(100, 208, id(font_arial20), id(active_page_name).c_str());
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(36, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(buttonplus_temperature).state);
|
||||
//
|
||||
//>>> ambient light:
|
||||
id(main_display).image(285, 15, id(icon_ambient_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(285, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1flux", id(buttonplus_ambientlight).state);
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
- id: !extend bar1_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("volume_down");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("volume_up");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("prev");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("next");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("power");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 1:
|
||||
id(music_card_bar).execute("playpause");
|
||||
break;
|
||||
}
|
||||
|
||||
event:
|
||||
- id: !extend bar1_btn_left_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR1LEFT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_vol_down).execute();
|
||||
ESP_LOGD("main", "VOL DOWN");
|
||||
}
|
||||
- id: !extend bar1_btn_right_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR1RIGHT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_vol_up).execute();
|
||||
ESP_LOGD("main", "VOL UP");
|
||||
}
|
||||
- id: !extend bar2_btn_left_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR2LEFT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_prev).execute();
|
||||
ESP_LOGD("main", "PREV");
|
||||
}
|
||||
- id: !extend bar2_btn_right_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR2RIGHT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_next).execute();
|
||||
ESP_LOGD("main", "NEXT");
|
||||
}
|
||||
- id: !extend bar3_btn_left_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR3LEFT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_power).execute();
|
||||
ESP_LOGD("main", "POWER");
|
||||
}
|
||||
- id: !extend bar3_btn_right_event
|
||||
on_event:
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGD("main", "BAR3RIGHT event %s triggered.", event_type.c_str());
|
||||
- lambda: |-
|
||||
if (event_type == "click page 1"){
|
||||
id(music_card_playpause).execute();
|
||||
ESP_LOGD("main", "PLAY PAUSE");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,343 @@
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files:
|
||||
- 'package/3bar_1display.yaml'
|
||||
ref: main
|
||||
refresh: 1d
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '1'
|
||||
|
||||
globals:
|
||||
- id: !extend page_names
|
||||
initial_value: '{"Page 1"}'
|
||||
- id: !extend active_page_name
|
||||
initial_value: ""
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 64
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 24
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
- id: grey
|
||||
hex: A6A6A6
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: BAR1 button Left event
|
||||
id: bar1_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR1 button Right event
|
||||
id: bar1_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR2 button Left event
|
||||
id: bar2_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR2 button Right event
|
||||
id: bar2_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR3 button Left event
|
||||
id: bar3_btn_left_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
- platform: template
|
||||
name: BAR3 button Right event
|
||||
id: bar3_btn_right_event
|
||||
event_types:
|
||||
- "press page 0"
|
||||
- "release page 0"
|
||||
- "long press page 0"
|
||||
|
||||
binary_sensor:
|
||||
- id: !extend main_display_btn_left
|
||||
on_click:
|
||||
- script.execute: prev_page
|
||||
- id: !extend main_display_btn_right
|
||||
on_click:
|
||||
- script.execute: next_page
|
||||
- id: !extend bar1_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar1_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar2_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_left_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_left_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_left_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_right_event).trigger("press page 0");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_right_event).trigger("release page 0");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar3_btn_right_event).trigger("long press page 0");
|
||||
break;
|
||||
}
|
||||
|
||||
display:
|
||||
#########
|
||||
# MAIN ##
|
||||
#########
|
||||
- id: !extend main_display
|
||||
# data_rate: 40MHz
|
||||
lambda: |-
|
||||
id(all_pages_main).execute();
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
it.print(100, 160, id(font_arial20), "This is page 0!");
|
||||
break;
|
||||
}
|
||||
|
||||
script:
|
||||
- id: all_pages_main
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(red));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(red));
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(36, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(inside_temperature).state);
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
- id: !extend bar1_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 0:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,638 @@
|
||||
esphome:
|
||||
name: button-keuken
|
||||
friendly_name: Button+ Keuken
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: arduino
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
level: DEBUG
|
||||
|
||||
debug:
|
||||
update_interval: 5s
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
encryption:
|
||||
key: "*"
|
||||
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: "*"
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '3'
|
||||
music_card_enity_id: 'media_player.media_keuken_2'
|
||||
music_card_text_color: FFFFFF
|
||||
music_card_icon_main_color: FF7F00
|
||||
music_card_icon_bar_color: FF7F00
|
||||
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files:
|
||||
- 'package/3bar_1display.yaml'
|
||||
- 'package/cards/music.yaml'
|
||||
ref: main
|
||||
refresh: 1d
|
||||
|
||||
globals:
|
||||
- id: !extend page_names
|
||||
initial_value: '{"page 2","Music","Page 3"}'
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 64
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 24
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
- file: mdi:sun-thermometer-outline
|
||||
id: icon_temp_outside
|
||||
resize: 40x40
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
- file: mdi:trash-can
|
||||
id: icon_trashcan
|
||||
resize: 20x20
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
- id: grey
|
||||
hex: A6A6A6
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: BAR1 button Left event
|
||||
id: bar1_btn_left_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
- platform: template
|
||||
name: BAR1 button Right event
|
||||
id: bar1_btn_right_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
- platform: template
|
||||
name: BAR2 button Left event
|
||||
id: bar2_btn_left_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
- platform: template
|
||||
name: BAR2 button Right event
|
||||
id: bar2_btn_right_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
- platform: template
|
||||
name: BAR3 button Left event
|
||||
id: bar3_btn_left_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
- platform: template
|
||||
name: BAR3 button Right event
|
||||
id: bar3_btn_right_event
|
||||
event_types:
|
||||
- "press page 1"
|
||||
- "release page 1"
|
||||
- "long press page 1"
|
||||
- "press page 2"
|
||||
- "release page 2"
|
||||
- "long press page 2"
|
||||
- "press page 3"
|
||||
- "release page 3"
|
||||
- "long press page 3"
|
||||
|
||||
binary_sensor:
|
||||
- id: !extend main_display_btn_left
|
||||
on_click:
|
||||
- script.execute: prev_page
|
||||
- id: !extend main_display_btn_right
|
||||
on_click:
|
||||
- script.execute: next_page
|
||||
- id: !extend bar1_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_left_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_left_event).trigger("press page 2");
|
||||
id(music_card_vol_down).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_left_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_left_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_left_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_left_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_left_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_left_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_left_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_right_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_right_event).trigger("press page 2");
|
||||
id(music_card_vol_up).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_right_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_right_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_right_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_right_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar1_btn_right_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar1_btn_right_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar1_btn_right_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_left_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_left_event).trigger("press page 2");
|
||||
id(music_card_prev).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_left_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_left_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_left_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_left_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_left_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_left_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_left_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_right_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_right_event).trigger("press page 2");
|
||||
id(music_card_next).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_right_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_right_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_right_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_right_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar2_btn_right_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar2_btn_right_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar2_btn_right_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_btn_left
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_left_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_left_event).trigger("press page 2");
|
||||
id(music_card_power).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_left_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_left_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_left_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_left_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_left_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_left_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_left_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_btn_right
|
||||
on_click:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_right_event).trigger("press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_right_event).trigger("press page 2");
|
||||
id(music_card_playpause).execute();
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_right_event).trigger("press page 3");
|
||||
break;
|
||||
}
|
||||
on_release:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_right_event).trigger("release page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_right_event).trigger("release page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_right_event).trigger("release page 3");
|
||||
break;
|
||||
}
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at least 2s
|
||||
then:
|
||||
lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar3_btn_right_event).trigger("long press page 1");
|
||||
break;
|
||||
case 2:
|
||||
id(bar3_btn_right_event).trigger("long press page 2");
|
||||
break;
|
||||
case 3:
|
||||
id(bar3_btn_right_event).trigger("long press page 3");
|
||||
break;
|
||||
}
|
||||
|
||||
sensor:
|
||||
- platform: homeassistant
|
||||
entity_id: sensor.gw1100a_outdoor_temperature
|
||||
id: outside_temperature
|
||||
###################
|
||||
### containers: ###
|
||||
###################
|
||||
- platform: debug
|
||||
free:
|
||||
name: "Heap Free"
|
||||
loop_time:
|
||||
name: "Loop Time"
|
||||
|
||||
text_sensor:
|
||||
- platform: homeassistant
|
||||
id: container_first
|
||||
entity_id: sensor.afvalinfo_containers_first_trash
|
||||
- platform: homeassistant
|
||||
id: container_first_color
|
||||
entity_id: sensor.afvalinfo_containers_first_trash_color
|
||||
- platform: homeassistant
|
||||
id: container_second
|
||||
entity_id: sensor.afvalinfo_containers_second_trash
|
||||
- platform: homeassistant
|
||||
id: container_second_color
|
||||
entity_id: sensor.afvalinfo_containers_second_trash_color
|
||||
|
||||
display:
|
||||
#########
|
||||
# MAIN ##
|
||||
#########
|
||||
- id: !extend main_display
|
||||
# data_rate: 40MHz
|
||||
lambda: |-
|
||||
id(all_pages_main).execute();
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(containers).execute();
|
||||
// Example display item
|
||||
id(displayitem).execute(160,2,"External","size_3_label","orange",id(outside_temperature).state,1,"","size_3_value","white","°C","size_3_unit","grey","TOP_LEFT");
|
||||
break;
|
||||
case 2:
|
||||
id(music_card).execute(20, 125);
|
||||
break;
|
||||
case 3:
|
||||
it.print(100, 160, id(font_arial20), "This is page 3!");
|
||||
break;
|
||||
}
|
||||
|
||||
script:
|
||||
- id: containers
|
||||
then:
|
||||
- lambda: |-
|
||||
// first trashcan:
|
||||
int x = 23;
|
||||
int y = 125;
|
||||
if(strcmp(id(container_first_color).state.c_str(), "grey") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(grey));
|
||||
} else if (strcmp(id(container_first_color).state.c_str(), "green") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(green));
|
||||
} else if (strcmp(id(container_first_color).state.c_str(), "blue") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(blue));
|
||||
} else if (strcmp(id(container_first_color).state.c_str(), "orange") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(orange));
|
||||
}
|
||||
id(main_display).print(x+22, y, id(font_arial20), id(music_card_text_color), TextAlign::TOP_LEFT , id(container_first).state.c_str());
|
||||
// secomnd trashcan:
|
||||
y = 151;
|
||||
if(strcmp(id(container_second_color).state.c_str(), "grey") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(grey));
|
||||
} else if (strcmp(id(container_second_color).state.c_str(), "green") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(green));
|
||||
} else if (strcmp(id(container_second_color).state.c_str(), "blue") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(blue));
|
||||
} else if (strcmp(id(container_second_color).state.c_str(), "orange") == 0) {
|
||||
id(main_display).image(x, y+4, id(icon_trashcan), ImageAlign::TOP_LEFT, id(orange));
|
||||
}
|
||||
id(main_display).print(x+22, y, id(font_arial20), id(music_card_text_color), TextAlign::TOP_LEFT , id(container_second).state.c_str());
|
||||
- id: all_pages_main
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(red));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(red));
|
||||
//
|
||||
//>>> Show page name at bottom of display
|
||||
id(main_display).printf(160, 238, id(font_arial20), id(white), TextAlign::BASELINE_CENTER, "%s", id(active_page_name).c_str());
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(36, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(inside_temperature).state);
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
//
|
||||
//>>> outside temperature
|
||||
id(main_display).image(285, 15, id(icon_temp_outside), ImageAlign::TOP_CENTER, id(red));
|
||||
id(main_display).printf(285, 80, id(font_arial20), id(white), TextAlign::TOP_CENTER , "%.1f°", id(outside_temperature).state);
|
||||
- id: !extend bar1_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("volume_down");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar1_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("volume_up");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("prev");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar2_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("next");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_left_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("power");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
- id: !extend bar3_right_draw
|
||||
then:
|
||||
- lambda: |-
|
||||
switch (id(actual_page)){
|
||||
case 1:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
break;
|
||||
case 2:
|
||||
id(music_card_bar).execute("playpause");
|
||||
break;
|
||||
case 3:
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(blue));
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
###
|
||||
### This is a basic example, showing all features of the Button+
|
||||
###
|
||||
|
||||
esphome:
|
||||
name: buttonplus-test
|
||||
friendly_name: ButtonPlus_test
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: arduino
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
encryption:
|
||||
key: "xxx"
|
||||
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: "xxx"
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
###
|
||||
### Code below is specific for the Button+
|
||||
###
|
||||
|
||||
packages:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files: [package/1bar_1display.yaml]
|
||||
ref: main
|
||||
refresh: 1d
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: my_font20
|
||||
size: 20
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: my_font15
|
||||
size: 15
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: my_font40
|
||||
size: 40
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: "https://i.postimg.cc/CMXFmZ5n/henk.png"
|
||||
id: henk
|
||||
resize: 120x100
|
||||
type: RGB565
|
||||
use_transparency: true
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
|
||||
display:
|
||||
- id: !extend display_j2_main
|
||||
lambda: |-
|
||||
// Print inside temperature (from homeassistant sensor)
|
||||
if (id(inside_temperature).has_state()) {
|
||||
it.printf(2, 60, id(my_font20), id(blue), TextAlign::BASELINE_LEFT , "%.1f°", id(inside_temperature).state);
|
||||
}
|
||||
it.printf(2, 80, id(my_font15), id(blue), TextAlign::BASELINE_LEFT, "Binnen");
|
||||
|
||||
// Print time and date
|
||||
it.strftime(160, 60, id(my_font40), TextAlign::BASELINE_CENTER, "%H:%M", id(datetime).now());
|
||||
it.strftime(160, 80, id(my_font20), id(red), TextAlign::BASELINE_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
|
||||
// Draw the image my_online_image at position
|
||||
// it.image(160, 100, id(henk), ImageAlign::TOP_CENTER);
|
||||
- id: !extend display_j3_Left
|
||||
lambda: |-
|
||||
it.image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(red));
|
||||
- id: !extend display_j3_Right
|
||||
lambda: |-
|
||||
it.image(80, 0, id(alert), ImageAlign::TOP_CENTER);
|
||||
@@ -1,7 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 Martijn
|
||||
Copyright (c) 2026 Kenneth van Ewijk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,32 +1,68 @@
|
||||
> Forked from [https://github.com/dixi83/ESPhome_ButtonPlus](https://github.com/dixi83/ESPhome_ButtonPlus), all initial effort for this was done by [dixi83](https://github.com/dixi83) and [balk77](https://github.com/balk77)
|
||||
# ESPhome_ButtonPlus
|
||||
|
||||
# ESPhome_ButtonPlus V2
|
||||
|
||||
*ESPHome documentation and examples to make ESPHome working on the Button+ with the V2 PCB*
|
||||
_(not yet tested with the V2 display module and buttons, only with the V2 PCB with the old display and bars)_
|
||||
*ESPHome documentation and examples to make ESPHome working on the Button+*
|
||||
|
||||
<img src="./Docs/ButtonPlusImage.png" alt="Buttonplus running ESPhome" width="300" height="397"/>
|
||||
|
||||
## Changes compared to V1
|
||||
This project was intended for the Button+ V1. Now that the V2 is out, I wanted to also try this out. However, the original project did not work out of the box. This version is currently only for the 1Display+3Bars version. It now uses the esp-idf framework instead of arduino. PSRAM is configured. The GPIO pins have been updated to match the V2 PCB, and the ambient light sensor has been added.
|
||||
|
||||
### Generating events for all pages
|
||||
I also added an events yaml generator, written in python (mostly by AI). It can be used to generate a `3bar_1display_events.yaml` file that defines events for all buttons for the number of pages you want.
|
||||
|
||||
## Button+ (V2)
|
||||
## Button+
|
||||
|
||||
The Button+ is a modular control panel for home automation systems. It is designed to work with MQTT. It has several modules: a "Base module", a "Main display" and "BAR modules" where the position and amount can be changed according your needs.
|
||||
|
||||
__You can order the Button+ on there [website](https://button.plus).__ this is also the place to find the original firmware, in case you want to revert back.
|
||||
|
||||
[Dutch support topic on Tweakers.net](https://gathering.tweakers.net/forum/list_messages/2270086)
|
||||
To make the Button+ work with ESPHome we needed at least a list of used components and a pinout/IO-list. I spend a couple of evenings with my multimeter, making my wife crazy with the beeps, googled and collected data sheets of the components, broke a the display of 1 BAR module and did a trail-on-error to make stuff work with ESPHome. Here in this repo you'll find the [results](./Components) of my journey.
|
||||
|
||||
## Usefull Links
|
||||
The ESPHome integration adds more flexibility and features, but also add some more complexity. To minimize the complexity I started this repo to collect examples and improve my work.
|
||||
|
||||
> Want to help? Pull requests are welcome!
|
||||
|
||||
[Dutch support topic on Tweakers.net](https://gathering.tweakers.net/forum/list_messages/2270086)
|
||||
<!--
|
||||
[English support topic on Home Assistant Community:](https://)
|
||||
TODO
|
||||
-->
|
||||
|
||||
## Documentation
|
||||
|
||||
The documentation of the Button+ ESPHome integration can be found in the [Docs directory](./Docs/DOCS.md)
|
||||
|
||||
## Useful Links
|
||||
|
||||
* Display Items: https://esphome.io/components/display/
|
||||
* Fonts: https://esphome.io/components/font#display-fonts
|
||||
* Icon's and images: https://esphome.io/components/image#display-image
|
||||
|
||||
## Changes:
|
||||
|
||||
## Documentation
|
||||
### NEXT: 0.2.0
|
||||
#### NEW:
|
||||
- added [display item card](./package/cards/display_item.md) (thanks @balk77)
|
||||
- menu can now be controlled from HA and has page naming (thanks @balk77)
|
||||
- the [music card](./package/cards/music.md) now changes the play/pause icon depending on the players state (thanks @balk77)
|
||||
|
||||
The documentaion of the Button+ ESPHome integration can befound in the [Docs directory](./Docs)
|
||||
#### BREAKING:
|
||||
- global `nr_of_pages` is now replaced by `nr_of_pages` ***substitution***, if you have compile errors please see the basic examples
|
||||
- paging is now indexed by 1 > first page has number 1. Page 0>1, 1>2 etc.
|
||||
|
||||
|
||||
### 0.1.1
|
||||
Serialized the mini displays, by toggling the CS pins we need only 1 display instance now.
|
||||
|
||||
### 0.1.0
|
||||
Created a Package
|
||||
|
||||
### Before 0.1.0
|
||||
versions with first prove of concepts
|
||||
|
||||
## Status
|
||||
|
||||
All the features the Button+ has to offer should work with the [`3pages_TotalExample.yaml`](./Examples/3pages_TotalExample.yml). Please refer the ESPHome documentation for more information on how to build your own menu or ... (?)
|
||||
|
||||
The documentation is work in progress.. Again If you want to help... Pull requests are welcome!
|
||||
|
||||
## TODO:
|
||||
|
||||
- [ ] Documentation
|
||||
- [x] initial firmware load
|
||||
- [ ] links to the card documentation
|
||||
- [ ] More examples
|
||||
|
||||
@@ -0,0 +1,529 @@
|
||||
esphome:
|
||||
name: buttonplus-test
|
||||
friendly_name: ButtonPlus_test
|
||||
on_boot:
|
||||
priority: -100
|
||||
then:
|
||||
- script.execute: setup_bar_displays
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
- script.execute: update_bar2_left
|
||||
- script.execute: update_bar2_right
|
||||
- script.execute: update_bar3_left
|
||||
- script.execute: update_bar3_right
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: arduino
|
||||
|
||||
debug:
|
||||
update_interval: 5s
|
||||
|
||||
text_sensor:
|
||||
- platform: debug
|
||||
device:
|
||||
name: "Device Info"
|
||||
reset_reason:
|
||||
name: "Reset Reason"
|
||||
|
||||
# Logger must be at least debug (default)
|
||||
logger:
|
||||
level: debug
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
encryption:
|
||||
key: ""
|
||||
|
||||
ota:
|
||||
- platform: esphome
|
||||
password: ""
|
||||
|
||||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
output_power: 15.5dB
|
||||
|
||||
i2c:
|
||||
- id: temperature_sensor
|
||||
sda: GPIO1
|
||||
scl: GPIO2
|
||||
- id: buttons
|
||||
sda: GPIO47
|
||||
scl: GPIO48
|
||||
frequency: 400khz
|
||||
|
||||
spi:
|
||||
clk_pin: GPIO36
|
||||
mosi_pin: GPIO35
|
||||
|
||||
mcp23008:
|
||||
- id: base_J0
|
||||
i2c_id: buttons
|
||||
address: 0x20
|
||||
- id: base_J1
|
||||
i2c_id: buttons
|
||||
address: 0x21
|
||||
- id: base_J2
|
||||
i2c_id: buttons
|
||||
address: 0x22
|
||||
- id: base_J3
|
||||
i2c_id: buttons
|
||||
address: 0x23
|
||||
|
||||
output:
|
||||
- platform: ledc
|
||||
pin: GPIO3
|
||||
id: display_main_backlight_pwm
|
||||
inverted: True
|
||||
max_power: 1.0
|
||||
frequency: 500Hz
|
||||
- platform: ledc
|
||||
pin: GPIO46
|
||||
id: displays_mini_backlight_pwm
|
||||
inverted: True
|
||||
max_power: 0.6
|
||||
frequency: 500Hz
|
||||
- id: cs_pin_bar1_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J1
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar1_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J1
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar2_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar2_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar3_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar3_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
|
||||
sensor:
|
||||
- platform: sts3x
|
||||
id: inside_temperature
|
||||
i2c_id: temperature_sensor
|
||||
name: "Temperature"
|
||||
address: 0x4A
|
||||
update_interval: 10s
|
||||
- platform: homeassistant
|
||||
entity_id: sensor.gw1100a_outdoor_temperature
|
||||
id: outside_temperature
|
||||
- platform: debug
|
||||
free:
|
||||
name: "Heap Free"
|
||||
block:
|
||||
name: "Heap Max Block"
|
||||
loop_time:
|
||||
name: "Loop Time"
|
||||
psram:
|
||||
name: "Free PSRAM"
|
||||
|
||||
time:
|
||||
- platform: homeassistant
|
||||
id: datetime
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial20
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial15
|
||||
size: 15
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: font_arial40
|
||||
size: 40
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_clock
|
||||
size: 80
|
||||
bpp: 4
|
||||
- file: "https://torinak.com/font/7segment.ttf"
|
||||
id: font_date
|
||||
size: 30
|
||||
bpp: 4
|
||||
|
||||
image:
|
||||
- file: mdi:lightbulb
|
||||
id: lightbulb
|
||||
resize: 80x80
|
||||
- file: mdi:alert
|
||||
id: alert
|
||||
resize: 80x80
|
||||
- file: mdi:chevron-right
|
||||
id: icon_next_page
|
||||
resize: 30x30
|
||||
- file: mdi:chevron-left
|
||||
id: icon_prev_page
|
||||
resize: 30x30
|
||||
- file: mdi:sun-thermometer-outline
|
||||
id: icon_temp_outside
|
||||
resize: 40x40
|
||||
- file: mdi:home-thermometer-outline
|
||||
id: icon_temp_inside
|
||||
resize: 40x40
|
||||
|
||||
color:
|
||||
- id: red
|
||||
hex: FF0000
|
||||
- id: blue
|
||||
hex: 0000FF
|
||||
- id: yellow
|
||||
hex: FFFF00
|
||||
- id: green
|
||||
hex: 00FF00
|
||||
- id: orange
|
||||
hex: FF7F00
|
||||
- id: white
|
||||
hex: FFFFFF
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_left'
|
||||
name: "Main Display button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
on_click:
|
||||
- script.execute: prev_page_all
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_right'
|
||||
name: "Main Display button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
on_click:
|
||||
- script.execute: next_page_all
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_left'
|
||||
name: "BAR 1 button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_right'
|
||||
name: "BAR 1 button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
light:
|
||||
- platform: neopixelbus
|
||||
id: neopixels
|
||||
type: RGB
|
||||
variant: WS2812
|
||||
pin: GPIO4
|
||||
num_leds: 5
|
||||
- platform: monochromatic
|
||||
output: display_main_backlight_pwm
|
||||
gamma_correct : 2.2
|
||||
name: "Main Display Backlight"
|
||||
id: display_main_backlight
|
||||
restore_mode: ALWAYS_ON
|
||||
- platform: monochromatic
|
||||
output: displays_mini_backlight_pwm
|
||||
gamma_correct : 2.2
|
||||
name: "Mini Display Backlight"
|
||||
id: displays_mini_backlight
|
||||
restore_mode: ALWAYS_ON
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Front"
|
||||
id: bar1_left_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 0
|
||||
to: 0
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Back"
|
||||
id: bar1_left_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 1
|
||||
to: 1
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Front"
|
||||
id: bar1_right_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 2
|
||||
to: 2
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Back"
|
||||
id: bar1_right_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 3
|
||||
to: 3
|
||||
|
||||
display:
|
||||
- id: main_display
|
||||
platform: ili9xxx
|
||||
model: ili9341
|
||||
color_order: rgb
|
||||
update_interval: 30s
|
||||
invert_colors: false
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
cs_pin:
|
||||
mcp23xxx: base_J0
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: false
|
||||
show_test_card: false
|
||||
dimensions:
|
||||
height: 240
|
||||
width: 320
|
||||
rotation: 180
|
||||
pages:
|
||||
- id: page1
|
||||
lambda: |-
|
||||
id(all_pages).execute();
|
||||
it.print(100, 160, id(font_arial20), "This is page 1!");
|
||||
- id: bar_display
|
||||
platform: ili9xxx
|
||||
model: ST7735
|
||||
color_order: bgr
|
||||
update_interval: never
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
invert_colors: false
|
||||
show_test_card: false
|
||||
auto_clear_enabled: false
|
||||
dimensions:
|
||||
height: 160
|
||||
width: 80
|
||||
offset_width: 24
|
||||
|
||||
script:
|
||||
- id: update_bar1_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on(); // <<
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES);
|
||||
id(bar1_left_page1).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
- id: update_bar1_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_on(); // <<
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES);
|
||||
id(bar1_right_page1).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
- id: update_bar2_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_on(); // <<
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
//
|
||||
id(bar_display).fill(id(orange));
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
- id: update_bar2_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_on(); // <<
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
//
|
||||
id(bar_display).fill(id(orange));
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
- id: update_bar3_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(cs_pin_bar3_left).turn_on(); // <<
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
//
|
||||
id(bar_display).fill(id(orange));
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
- id: update_bar3_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
id(cs_pin_bar3_right).turn_on();
|
||||
//
|
||||
id(bar_display).fill(id(orange));
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
- id: bar1_left_page1
|
||||
then:
|
||||
- lambda: |-
|
||||
id(bar_display).image(80, 0, id(lightbulb), ImageAlign::TOP_CENTER, id(orange));
|
||||
- id: bar1_right_page1
|
||||
then:
|
||||
- lambda: |-
|
||||
id(bar_display).image(80, 0, id(alert), ImageAlign::TOP_CENTER, id(red));
|
||||
- id: setup_bar_displays
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar1_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar2_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar2_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar3_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar3_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar3_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar3_right).turn_off();
|
||||
- id: update_main
|
||||
then:
|
||||
- component.update: main_display
|
||||
- id: update_all
|
||||
then:
|
||||
- component.update: main_display
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
- script.execute: update_bar2_left
|
||||
- script.execute: update_bar2_right
|
||||
- script.execute: update_bar3_left
|
||||
- script.execute: update_bar3_right
|
||||
- id: next_page_main
|
||||
then:
|
||||
- display.page.show_next: main_display
|
||||
- script.execute: update_main
|
||||
- id: next_page_all
|
||||
then:
|
||||
- display.page.show_next: main_display
|
||||
- script.execute: update_all
|
||||
- id: prev_page_main
|
||||
then:
|
||||
- display.page.show_previous: main_display
|
||||
- script.execute: update_main
|
||||
- id: prev_page_all
|
||||
then:
|
||||
- display.page.show_previous: main_display
|
||||
- script.execute: update_all
|
||||
- id: all_pages
|
||||
then:
|
||||
- lambda: |-
|
||||
//>>> make a border arround the display
|
||||
id(main_display).filled_rectangle( 0, 0, 320, 3, id(red));
|
||||
id(main_display).filled_rectangle( 0, 0, 3, 240, id(red));
|
||||
id(main_display).filled_rectangle( 0, 237, 320, 3, id(red));
|
||||
//id(main_display).filled_rectangle( 0, 206, 320, 3, id(red));
|
||||
id(main_display).filled_rectangle(317, 0, 3, 240, id(red));
|
||||
//
|
||||
//>>> prev/next icons next to butotns
|
||||
id(main_display).image(0, 208, id(icon_prev_page), ImageAlign::TOP_LEFT, id(orange));
|
||||
id(main_display).image(320, 208, id(icon_next_page), ImageAlign::TOP_RIGHT, id(orange));
|
||||
//
|
||||
//>>> temperature inside:
|
||||
id(main_display).image(36, 15, id(icon_temp_inside), ImageAlign::TOP_CENTER, id(orange));
|
||||
id(main_display).printf(36, 85, id(font_arial20), id(white), TextAlign::BASELINE_CENTER , "%.1f°", id(inside_temperature).state);
|
||||
//
|
||||
//>>> vertical line:
|
||||
id(main_display).filled_rectangle(70, 0, 3, 115, id(red));
|
||||
//
|
||||
//>>> print time and date
|
||||
id(main_display).strftime(160, 5, id(font_clock), TextAlign::TOP_CENTER, "%H:%M", id(datetime).now());
|
||||
id(main_display).strftime(160, 80, id(font_date), TextAlign::TOP_CENTER, "%d-%m-%Y", id(datetime).now());
|
||||
//
|
||||
//>>> vertical line:
|
||||
id(main_display).filled_rectangle(250, 0, 3, 115, id(red));
|
||||
//
|
||||
//>>> outside temperature
|
||||
id(main_display).image(285, 15, id(icon_temp_outside), ImageAlign::TOP_CENTER, id(orange));
|
||||
id(main_display).printf(285, 85, id(font_arial20), id(white), TextAlign::BASELINE_CENTER , "%.1f°", id(outside_temperature).state);
|
||||
//
|
||||
//>>> horizontal line:
|
||||
id(main_display).filled_rectangle(0, 115, 320, 3, id(red));
|
||||
|
||||
@@ -1,358 +0,0 @@
|
||||
## Dynamically generated on xx-xx-xxxx
|
||||
## Run python script again to update
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: 2
|
||||
|
||||
# Dynamically generated list
|
||||
display_events:
|
||||
- "double_click page 0"
|
||||
- "triple_click page 0"
|
||||
- "hold page 0"
|
||||
- "double_click page 1"
|
||||
- "triple_click page 1"
|
||||
- "hold page 1"
|
||||
|
||||
# Dynamically generated list
|
||||
button_events:
|
||||
- "click page 0"
|
||||
- "double_click page 0"
|
||||
- "triple_click page 0"
|
||||
- "hold page 0"
|
||||
- "click page 1"
|
||||
- "double_click page 1"
|
||||
- "triple_click page 1"
|
||||
- "hold page 1"
|
||||
|
||||
event:
|
||||
- platform: template
|
||||
name: DISPLAY Button Left event
|
||||
id: display_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${display_events}
|
||||
- platform: template
|
||||
name: DISPLAY Button Right event
|
||||
id: display_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${display_events}
|
||||
- platform: template
|
||||
name: BAR1 Button Left event
|
||||
id: bar1_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR1 Button Right event
|
||||
id: bar1_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR2 Button Left event
|
||||
id: bar2_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR2 Button Right event
|
||||
id: bar2_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR3 Button Left event
|
||||
id: bar3_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR3 Button Right event
|
||||
id: bar3_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
|
||||
binary_sensor:
|
||||
- id: !extend main_display_btn_left
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute: prev_page
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_left_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_left_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_left_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
- id: !extend main_display_btn_right
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute: next_page
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_right_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_right_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(display_btn_right_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
- id: !extend bar1_btn_left
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_left_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_left_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_left_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_left_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
|
||||
- id: !extend bar1_btn_right
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_right_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_right_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_right_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar1_btn_right_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
|
||||
- id: !extend bar2_btn_left
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_left_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_left_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_left_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_left_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
- id: !extend bar2_btn_right
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_right_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_right_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_right_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar2_btn_right_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
|
||||
- id: !extend bar3_btn_left
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_left_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_left_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_left_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_left_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
|
||||
|
||||
- id: !extend bar3_btn_right
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_right_event).trigger("click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_right_event).trigger("double_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_right_event).trigger("triple_click page " + std::to_string(id(actual_page)));
|
||||
- timing:
|
||||
- ON for 1s to 5s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
lambda: |-
|
||||
id(bar3_btn_right_event).trigger("hold page " + std::to_string(id(actual_page)));
|
||||
@@ -1,162 +0,0 @@
|
||||
import yaml
|
||||
|
||||
# CONFIGURATION
|
||||
NR_OF_PAGES = 3
|
||||
INCLUDE_DISPLAY_EXTRA = True # Enable Double, Triple, Hold for main display buttons
|
||||
LED_CONFIRMATION = True # Flash LED on press
|
||||
FILENAME = "3bar_1display_events.yaml"
|
||||
|
||||
# --- ESPHome YAML Handling Fixes ---
|
||||
class ESPHomeExtend:
|
||||
def __init__(self, value): self.value = value
|
||||
|
||||
class ESPHomeLambda:
|
||||
def __init__(self, value): self.value = value
|
||||
|
||||
class LiteralString(str): pass
|
||||
|
||||
def represent_extend(dumper, data):
|
||||
return dumper.represent_scalar('!extend', data.value)
|
||||
|
||||
def represent_lambda(dumper, data):
|
||||
# Ensures !lambda is followed by a quoted string or block for ESPHome compatibility
|
||||
return dumper.represent_scalar('!lambda', data.value, style='"')
|
||||
|
||||
def represent_literal(dumper, data):
|
||||
return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
|
||||
|
||||
yaml.add_representer(ESPHomeExtend, represent_extend)
|
||||
yaml.add_representer(ESPHomeLambda, represent_lambda)
|
||||
yaml.add_representer(LiteralString, represent_literal)
|
||||
# -----------------------------------
|
||||
|
||||
def generate():
|
||||
# 1. Define event lists for substitutions
|
||||
base_types = ["click", "double_click", "triple_click", "hold"]
|
||||
display_types = [] + (base_types[1:] if INCLUDE_DISPLAY_EXTRA else [])
|
||||
|
||||
display_events = []
|
||||
button_events = []
|
||||
for p in range(NR_OF_PAGES):
|
||||
display_events.extend([f"{t} page {p}" for t in display_types])
|
||||
button_events.extend([f"{t} page {p}" for t in base_types])
|
||||
|
||||
data = {
|
||||
"substitutions": {
|
||||
"nr_of_pages": str(NR_OF_PAGES),
|
||||
"display_events": display_events,
|
||||
"button_events": button_events
|
||||
},
|
||||
"script": [{
|
||||
"id": "trigger_with_feedback",
|
||||
"parameters": {
|
||||
"event_id": "esphome::template_::TemplateEvent*",
|
||||
"event_msg": "std::string",
|
||||
"led_id": "light::LightState*",
|
||||
"r": "float", "g": "float", "b": "float"
|
||||
},
|
||||
"then": [
|
||||
{"lambda": "event_id->trigger(event_msg);"},
|
||||
{"if": {
|
||||
"condition": {"lambda": "return led_id != nullptr;"},
|
||||
"then": [{"lambda": LiteralString(
|
||||
"auto call = led_id->make_call();\n"
|
||||
"call.set_state(true);\n"
|
||||
"call.set_rgb(r, g, b);\n"
|
||||
"call.set_brightness(1.0);\n"
|
||||
"call.set_flash_length(200); // Returns to previous state automatically\n"
|
||||
"call.perform();"
|
||||
)}]
|
||||
}}
|
||||
]
|
||||
}],
|
||||
"event": []
|
||||
}
|
||||
|
||||
# 2. Event Entities
|
||||
buttons = [
|
||||
("DISPLAY Button Left", "display_btn_left_event", "${display_events}"),
|
||||
("DISPLAY Button Right", "display_btn_right_event", "${display_events}"),
|
||||
("BAR1 Button Left", "bar1_btn_left_event", "${button_events}"),
|
||||
("BAR1 Button Right", "bar1_btn_right_event", "${button_events}"),
|
||||
("BAR2 Button Left", "bar2_btn_left_event", "${button_events}"),
|
||||
("BAR2 Button Right", "bar2_btn_right_event", "${button_events}"),
|
||||
("BAR3 Button Left", "bar3_btn_left_event", "${button_events}"),
|
||||
("BAR3 Button Right", "bar3_btn_right_event", "${button_events}"),
|
||||
]
|
||||
for name, eid, types in buttons:
|
||||
data["event"].append({
|
||||
"platform": "template", "name": name, "id": eid,
|
||||
"device_class": "button", "event_types": types
|
||||
})
|
||||
|
||||
# 3. Binary Sensor Extensions
|
||||
data["binary_sensor"] = []
|
||||
triggers = {
|
||||
"click": (0.0, 1.0, 0.0), # Green
|
||||
"double_click": (0.0, 0.0, 1.0), # Blue
|
||||
"triple_click": (1.0, 0.0, 1.0), # Purple
|
||||
"hold": (1.0, 0.5, 0.0) # Orange
|
||||
}
|
||||
|
||||
btn_configs = [
|
||||
("main_display_btn_left", "display_btn_left_event", None, "prev_page"),
|
||||
("main_display_btn_right", "display_btn_right_event", None, "next_page"),
|
||||
("bar1_btn_left", "bar1_btn_left_event", "bar1_left_rgb_front", None),
|
||||
("bar1_btn_right", "bar1_btn_right_event", "bar1_right_rgb_front", None),
|
||||
("bar2_btn_left", "bar2_btn_left_event", "bar2_left_rgb_front", None),
|
||||
("bar2_btn_right", "bar2_btn_right_event", "bar2_right_rgb_front", None),
|
||||
("bar3_btn_left", "bar3_btn_left_event", "bar3_left_rgb_front", None),
|
||||
("bar3_btn_right", "bar3_btn_right_event", "bar3_right_rgb_front", None),
|
||||
]
|
||||
|
||||
for btn_id, event_id, led_id, page_script in btn_configs:
|
||||
sensor = {
|
||||
"id": ESPHomeExtend(btn_id),
|
||||
"filters": [{"delayed_off": "10ms"}],
|
||||
"internal": True,
|
||||
"on_multi_click": []
|
||||
}
|
||||
|
||||
is_display = "main_display" in btn_id
|
||||
for t_name, color in triggers.items():
|
||||
if is_display and t_name != "click" and not INCLUDE_DISPLAY_EXTRA:
|
||||
continue
|
||||
|
||||
multi_click = {"timing": []}
|
||||
if t_name == "click":
|
||||
multi_click["timing"] = ["ON for at most 300ms", "OFF for at least 0.2s"]
|
||||
elif t_name == "double_click":
|
||||
multi_click["timing"] = ["ON for at most 300ms", "OFF for at most 0.2s", "ON for at most 300ms", "OFF for at least 0.2s"]
|
||||
elif t_name == "triple_click":
|
||||
multi_click["timing"] = ["ON for at most 300ms", "OFF for at most 0.2s", "ON for at most 300ms", "OFF for at most 0.2s", "ON for at most 300ms", "OFF for at least 0.2s"]
|
||||
elif t_name == "hold":
|
||||
multi_click["timing"] = ["ON for at least 1s", "OFF for at least 0.2s"]
|
||||
|
||||
actions = []
|
||||
if t_name == "click" and page_script:
|
||||
actions.append({"script.execute": page_script})
|
||||
else:
|
||||
# The Feedback call with proper ESPHome formatting
|
||||
actions.append({
|
||||
"script.execute": {
|
||||
"id": "trigger_with_feedback",
|
||||
"event_id": event_id,
|
||||
"event_msg": ESPHomeLambda(f'return "{t_name} page " + std::to_string(id(actual_page));'),
|
||||
"led_id": led_id if (led_id and LED_CONFIRMATION) else ESPHomeLambda("return nullptr;"),
|
||||
"r": color[0], "g": color[1], "b": color[2]
|
||||
}
|
||||
})
|
||||
multi_click["then"] = actions
|
||||
sensor["on_multi_click"].append(multi_click)
|
||||
data["binary_sensor"].append(sensor)
|
||||
|
||||
# 4. Write output
|
||||
with open(FILENAME, "w") as f:
|
||||
f.write("## Dynamically generated event configuration\n")
|
||||
f.write("## Do not edit manually - run generator script to update\n\n")
|
||||
yaml.dump(data, f, sort_keys=False, default_flow_style=False)
|
||||
print(f"Generated {FILENAME} successfully.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate()
|
||||
@@ -0,0 +1,168 @@
|
||||
############################################
|
||||
## ##
|
||||
## filename: 1bar_1display.yaml ##
|
||||
## description: Specific configuration ##
|
||||
## for the 1 BAR 1 Display setup ##
|
||||
## ##
|
||||
############################################
|
||||
|
||||
packages:
|
||||
base: !include base.yaml
|
||||
scripts: !include 1bar_1display_scripts.yaml
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
priority: -100
|
||||
then:
|
||||
- script.execute: setup_bar_displays
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
|
||||
mcp23008:
|
||||
- id: 'base_J2'
|
||||
i2c_id: buttons
|
||||
address: 0x22
|
||||
- id: 'base_J3'
|
||||
i2c_id: buttons
|
||||
address: 0x23
|
||||
|
||||
binary_sensor:
|
||||
############################
|
||||
### Buttons Main Display ###
|
||||
############################
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_left'
|
||||
name: "Main Display button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_right'
|
||||
name: "Main Display button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
############################
|
||||
### Buttons BAR module 1 ###
|
||||
############################
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_left'
|
||||
name: "BAR 1 button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_right'
|
||||
name: "BAR 1 button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
light:
|
||||
- id: !extend neopixels
|
||||
num_leds: 5
|
||||
############################
|
||||
### RGB LED's BAR module ###
|
||||
############################
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Front"
|
||||
id: bar1_left_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 0
|
||||
to: 0
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Back"
|
||||
id: bar1_left_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 1
|
||||
to: 1
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Front"
|
||||
id: bar1_right_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 2
|
||||
to: 2
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Back"
|
||||
id: bar1_right_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 3
|
||||
to: 3
|
||||
|
||||
output:
|
||||
#######################################
|
||||
### CS pins to control BAR Displays ###
|
||||
#######################################
|
||||
- id: cs_pin_bar1_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar1_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
|
||||
display:
|
||||
####################
|
||||
### Main Display ###
|
||||
####################
|
||||
- id: main_display
|
||||
platform: ili9xxx
|
||||
model: ili9341
|
||||
invert_colors: false
|
||||
color_order: rgb
|
||||
update_interval: 30s
|
||||
color_palette: 8BIT
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
cs_pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: false
|
||||
show_test_card: false
|
||||
dimensions:
|
||||
height: 240
|
||||
width: 320
|
||||
rotation: 180
|
||||
##################
|
||||
### BAR module ###
|
||||
##################
|
||||
- id: bar_display
|
||||
platform: ili9xxx
|
||||
model: ST7735
|
||||
color_order: bgr
|
||||
update_interval: never
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
invert_colors: false
|
||||
show_test_card: false
|
||||
auto_clear_enabled: false
|
||||
dimensions:
|
||||
height: 160
|
||||
width: 80
|
||||
offset_width: 24
|
||||
@@ -0,0 +1,65 @@
|
||||
##############################################
|
||||
## ##
|
||||
## filename: 1bar_1display_scripts.yaml ##
|
||||
## description: Specific pre-defined ##
|
||||
## scripts for 1 BAR 1 Display setup ##
|
||||
## ##
|
||||
##############################################
|
||||
|
||||
script:
|
||||
######################
|
||||
### update scripts ###
|
||||
######################
|
||||
- id: update_bar1_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on(); // <<
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES);
|
||||
id(bar1_left_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(2);
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
- id: update_bar1_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_on(); // <<
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES);
|
||||
id(bar1_right_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(2);
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
##################################
|
||||
### setup mini display scripts ###
|
||||
##################################
|
||||
- id: setup_bar_displays
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar1_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
####################
|
||||
### draw scripts ###
|
||||
####################
|
||||
- id: bar1_left_draw
|
||||
then:
|
||||
- id: bar1_right_draw
|
||||
then:
|
||||
##############################
|
||||
### other handling scripts ###
|
||||
##############################
|
||||
- id: update_main
|
||||
then:
|
||||
- component.update: main_display
|
||||
- id: update_all
|
||||
then:
|
||||
- component.update: main_display
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
@@ -0,0 +1,240 @@
|
||||
############################################
|
||||
## ##
|
||||
## filename: 2bar_1display.yaml ##
|
||||
## description: Specific configuration ##
|
||||
## for the 2 BAR's, 1 Display setup ##
|
||||
## ##
|
||||
############################################
|
||||
|
||||
packages:
|
||||
base: !include base.yaml
|
||||
scripts: !include 2bar_1display_scripts.yaml
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
priority: -100
|
||||
then:
|
||||
- script.execute: setup_bar_displays
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
- script.execute: update_bar2_left
|
||||
- script.execute: update_bar2_right
|
||||
|
||||
mcp23008:
|
||||
- id: 'base_J1'
|
||||
i2c_id: buttons
|
||||
address: 0x21
|
||||
- id: 'base_J2'
|
||||
i2c_id: buttons
|
||||
address: 0x22
|
||||
- id: 'base_J3'
|
||||
i2c_id: buttons
|
||||
address: 0x23
|
||||
|
||||
binary_sensor:
|
||||
############################
|
||||
### Buttons Main Display ###
|
||||
############################
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_left'
|
||||
name: "Main Display button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J1
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'main_display_btn_right'
|
||||
name: "Main Display button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J1
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
############################
|
||||
### Buttons BAR module 1 ###
|
||||
############################
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_left'
|
||||
name: "BAR 1 button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'bar1_btn_right'
|
||||
name: "BAR 1 button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
############################
|
||||
### Buttons BAR module 2 ###
|
||||
############################
|
||||
- platform: gpio
|
||||
id: 'bar2_btn_left'
|
||||
name: "BAR 2 button Left"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 6
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: 'bar2_btn_right'
|
||||
name: "BAR 2 button Right"
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 2
|
||||
mode: INPUT_PULLUP
|
||||
inverted: true
|
||||
|
||||
light:
|
||||
- id: !extend neopixels
|
||||
num_leds: 9
|
||||
##############################
|
||||
### RGB LED's BAR module 1 ###
|
||||
##############################
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Front"
|
||||
id: bar1_left_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 0
|
||||
to: 0
|
||||
- platform: partition
|
||||
name: "BAR 1 Left RGB Back"
|
||||
id: bar1_left_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 1
|
||||
to: 1
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Front"
|
||||
id: bar1_right_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 2
|
||||
to: 2
|
||||
- platform: partition
|
||||
name: "BAR 1 Right RGB Back"
|
||||
id: bar1_right_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 3
|
||||
to: 3
|
||||
##############################
|
||||
### RGB LED's BAR module 2 ###
|
||||
##############################
|
||||
- platform: partition
|
||||
name: "BAR 2 Left RGB Front"
|
||||
id: bar2_left_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 4
|
||||
to: 4
|
||||
- platform: partition
|
||||
name: "BAR 2 Left RGB Back"
|
||||
id: bar2_left_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 5
|
||||
to: 5
|
||||
- platform: partition
|
||||
name: "BAR 2 Right RGB Front"
|
||||
id: bar2_right_rgb_front
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 6
|
||||
to: 6
|
||||
- platform: partition
|
||||
name: "BAR 2 Right RGB Back"
|
||||
id: bar2_right_rgb_back
|
||||
segments:
|
||||
- id: neopixels
|
||||
from: 7
|
||||
to: 7
|
||||
|
||||
output:
|
||||
#######################################
|
||||
### CS pins to control BAR Displays ###
|
||||
#######################################
|
||||
- id: cs_pin_bar1_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar1_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J2
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar2_left
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
- id: cs_pin_bar2_right
|
||||
platform: gpio
|
||||
pin:
|
||||
mcp23xxx: base_J3
|
||||
number: 1
|
||||
mode:
|
||||
output: true
|
||||
inverted: true
|
||||
|
||||
display:
|
||||
####################
|
||||
### Main Display ###
|
||||
####################
|
||||
- id: main_display
|
||||
platform: ili9xxx
|
||||
model: ili9341
|
||||
invert_colors: false
|
||||
color_order: rgb
|
||||
update_interval: 30s
|
||||
color_palette: 8BIT
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
cs_pin:
|
||||
mcp23xxx: base_J1
|
||||
number: 5
|
||||
mode:
|
||||
output: true
|
||||
inverted: false
|
||||
show_test_card: false
|
||||
dimensions:
|
||||
height: 240
|
||||
width: 320
|
||||
rotation: 180
|
||||
###################
|
||||
### BAR modules ###
|
||||
###################
|
||||
- id: bar_display
|
||||
platform: ili9xxx
|
||||
model: ST7735
|
||||
color_order: bgr
|
||||
update_interval: never
|
||||
dc_pin:
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
invert_colors: false
|
||||
show_test_card: false
|
||||
auto_clear_enabled: false
|
||||
dimensions:
|
||||
height: 160
|
||||
width: 80
|
||||
offset_width: 24
|
||||
@@ -0,0 +1,109 @@
|
||||
##############################################
|
||||
## ##
|
||||
## filename: 1bar_1display_scripts.yaml ##
|
||||
## description: Specific pre-defined ##
|
||||
## scripts for 2 BAR 1 Display setup ##
|
||||
## ##
|
||||
##############################################
|
||||
|
||||
script:
|
||||
######################
|
||||
### update scripts ###
|
||||
######################
|
||||
- id: update_bar1_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on(); // <<
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES);
|
||||
id(bar1_left_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
- id: update_bar1_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_on(); // <<
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES);
|
||||
id(bar1_right_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
- id: update_bar2_left
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_on(); // <<
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_270_DEGREES);
|
||||
id(bar2_left_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
- id: update_bar2_right
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
id(cs_pin_bar2_right).turn_on(); // <<
|
||||
id(bar_display).clear();
|
||||
id(bar_display).set_rotation(display::DisplayRotation::DISPLAY_ROTATION_90_DEGREES);
|
||||
id(bar2_right_draw).execute();
|
||||
id(bar_display).update();
|
||||
delay(1);
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
##################################
|
||||
### setup mini display scripts ###
|
||||
##################################
|
||||
- id: setup_bar_displays
|
||||
then:
|
||||
- lambda: |-
|
||||
id(cs_pin_bar1_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar1_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar1_right).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar2_left).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar2_left).turn_off();
|
||||
delay(5);
|
||||
id(cs_pin_bar2_right).turn_on();
|
||||
id(bar_display).setup();
|
||||
id(cs_pin_bar2_right).turn_off();
|
||||
####################
|
||||
### draw scripts ###
|
||||
####################
|
||||
- id: bar1_left_draw
|
||||
then:
|
||||
- id: bar1_right_draw
|
||||
then:
|
||||
- id: bar2_left_draw
|
||||
then:
|
||||
- id: bar2_right_draw
|
||||
then:
|
||||
##############################
|
||||
### other handling scripts ###
|
||||
##############################
|
||||
- id: update_main
|
||||
then:
|
||||
- component.update: main_display
|
||||
- id: update_all
|
||||
then:
|
||||
- component.update: main_display
|
||||
- script.execute: update_bar1_left
|
||||
- script.execute: update_bar1_right
|
||||
- script.execute: update_bar2_left
|
||||
- script.execute: update_bar2_right
|
||||
@@ -9,7 +9,6 @@
|
||||
packages:
|
||||
base: !include base.yaml
|
||||
scripts: !include 3bar_1display_scripts.yaml
|
||||
events: !include 3bar_1display_events.yaml
|
||||
|
||||
esphome:
|
||||
on_boot:
|
||||
@@ -278,8 +277,9 @@ display:
|
||||
invert_colors: false
|
||||
color_order: rgb
|
||||
update_interval: 30s
|
||||
color_palette: 8BIT
|
||||
dc_pin:
|
||||
number: GPIO7
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
cs_pin:
|
||||
mcp23xxx: base_J0
|
||||
@@ -301,7 +301,7 @@ display:
|
||||
color_order: bgr
|
||||
update_interval: never
|
||||
dc_pin:
|
||||
number: GPIO7
|
||||
number: GPIO37
|
||||
allow_other_uses: true
|
||||
invert_colors: false
|
||||
show_test_card: false
|
||||
|
||||
@@ -1,550 +0,0 @@
|
||||
## Dynamically generated event configuration
|
||||
## Do not edit manually - run generator script to update
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '3'
|
||||
display_events:
|
||||
- double_click page 0
|
||||
- triple_click page 0
|
||||
- hold page 0
|
||||
- double_click page 1
|
||||
- triple_click page 1
|
||||
- hold page 1
|
||||
- double_click page 2
|
||||
- triple_click page 2
|
||||
- hold page 2
|
||||
button_events:
|
||||
- click page 0
|
||||
- double_click page 0
|
||||
- triple_click page 0
|
||||
- hold page 0
|
||||
- click page 1
|
||||
- double_click page 1
|
||||
- triple_click page 1
|
||||
- hold page 1
|
||||
- click page 2
|
||||
- double_click page 2
|
||||
- triple_click page 2
|
||||
- hold page 2
|
||||
script:
|
||||
- id: trigger_with_feedback
|
||||
parameters:
|
||||
event_id: esphome::template_::TemplateEvent*
|
||||
event_msg: std::string
|
||||
led_id: light::LightState*
|
||||
r: float
|
||||
g: float
|
||||
b: float
|
||||
then:
|
||||
- lambda: event_id->trigger(event_msg);
|
||||
- if:
|
||||
condition:
|
||||
lambda: return led_id != nullptr;
|
||||
then:
|
||||
- lambda: |-
|
||||
auto call = led_id->make_call();
|
||||
call.set_state(true);
|
||||
call.set_rgb(r, g, b);
|
||||
call.set_brightness(1.0);
|
||||
call.set_flash_length(200); // Returns to previous state automatically
|
||||
call.perform();
|
||||
event:
|
||||
- platform: template
|
||||
name: DISPLAY Button Left
|
||||
id: display_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${display_events}
|
||||
- platform: template
|
||||
name: DISPLAY Button Right
|
||||
id: display_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${display_events}
|
||||
- platform: template
|
||||
name: BAR1 Button Left
|
||||
id: bar1_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR1 Button Right
|
||||
id: bar1_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR2 Button Left
|
||||
id: bar2_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR2 Button Right
|
||||
id: bar2_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR3 Button Left
|
||||
id: bar3_btn_left_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
- platform: template
|
||||
name: BAR3 Button Right
|
||||
id: bar3_btn_right_event
|
||||
device_class: button
|
||||
event_types: ${button_events}
|
||||
binary_sensor:
|
||||
- id: !extend 'main_display_btn_left'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute: prev_page
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_left_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_left_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_left_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'main_display_btn_right'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute: next_page
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_right_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_right_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: display_btn_right_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: !lambda "return nullptr;"
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar1_btn_left'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_left_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_left_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_left_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_left_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_left_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_left_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar1_btn_right'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_right_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_right_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_right_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_right_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_right_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar1_btn_right_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar1_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar2_btn_left'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_left_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_left_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_left_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_left_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_left_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_left_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar2_btn_right'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_right_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_right_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_right_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_right_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_right_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar2_btn_right_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar2_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar3_btn_left'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_left_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_left_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_left_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_left_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_left_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_left_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_left_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
- id: !extend 'bar3_btn_right'
|
||||
filters:
|
||||
- delayed_off: 10ms
|
||||
internal: true
|
||||
on_multi_click:
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_right_event
|
||||
event_msg: !lambda "return \"click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_right_rgb_front
|
||||
r: 0.0
|
||||
g: 1.0
|
||||
b: 0.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_right_event
|
||||
event_msg: !lambda "return \"double_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_right_rgb_front
|
||||
r: 0.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at most 0.2s
|
||||
- ON for at most 300ms
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_right_event
|
||||
event_msg: !lambda "return \"triple_click page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.0
|
||||
b: 1.0
|
||||
- timing:
|
||||
- ON for at least 1s
|
||||
- OFF for at least 0.2s
|
||||
then:
|
||||
- script.execute:
|
||||
id: trigger_with_feedback
|
||||
event_id: bar3_btn_right_event
|
||||
event_msg: !lambda "return \"hold page \" + std::to_string(id(actual_page));"
|
||||
led_id: bar3_right_rgb_front
|
||||
r: 1.0
|
||||
g: 0.5
|
||||
b: 0.0
|
||||
@@ -154,15 +154,15 @@ script:
|
||||
- id: update_all
|
||||
then:
|
||||
- component.update: main_display
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar1_left
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar1_right
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar2_left
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar2_right
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar3_left
|
||||
- delay: 0.1s
|
||||
- delay: 5ms
|
||||
- script.execute: update_bar3_right
|
||||
|
||||
+30
-104
@@ -10,46 +10,31 @@
|
||||
esp32:
|
||||
flash_size: 16MB
|
||||
|
||||
psram:
|
||||
mode: octal
|
||||
speed: 80MHz
|
||||
|
||||
interval:
|
||||
- interval: 1min
|
||||
then:
|
||||
- logger.log: "ESPHome for Button+ V2 v0.1.0"
|
||||
- logger.log: "ESPHome for Button+ v0.2.0_dev"
|
||||
|
||||
i2c:
|
||||
# Devices at 0x20, 0x21, 0x22, 0x23
|
||||
- id: buttons
|
||||
- id: temperature_sensor
|
||||
sda: GPIO1
|
||||
scl: GPIO2
|
||||
frequency: 50khz
|
||||
|
||||
# Devices at 0x29 (ambient), 0x4A (temp)
|
||||
- id: sensors
|
||||
- id: buttons
|
||||
sda: GPIO47
|
||||
scl: GPIO48
|
||||
frequency: 50khz
|
||||
frequency: 400khz
|
||||
|
||||
spi:
|
||||
clk_pin: GPIO6
|
||||
mosi_pin: GPIO5
|
||||
|
||||
substitutions:
|
||||
nr_of_pages: '"2"'
|
||||
page_names: '{"Page 1", "Page 2"}'
|
||||
clk_pin: GPIO36
|
||||
mosi_pin: GPIO35
|
||||
|
||||
globals:
|
||||
- id: nr_of_pages
|
||||
type: int
|
||||
initial_value: ${nr_of_pages}
|
||||
- id: actual_page
|
||||
type: int
|
||||
initial_value: '0'
|
||||
initial_value: '1'
|
||||
- id: page_names
|
||||
type: std::vector<std::string>
|
||||
initial_value: ${page_names}
|
||||
initial_value: '{"Page 1"}'
|
||||
- id: active_page_name
|
||||
type: std::string
|
||||
initial_value: ""
|
||||
@@ -70,67 +55,27 @@ output:
|
||||
|
||||
sensor:
|
||||
- platform: sts3x
|
||||
address: 0x4A
|
||||
id: buttonplus_temperature
|
||||
i2c_id: sensors
|
||||
id: inside_temperature
|
||||
i2c_id: temperature_sensor
|
||||
name: "Temperature"
|
||||
address: 0x4A
|
||||
update_interval: 10s
|
||||
unit_of_measurement: "°C"
|
||||
icon: "mdi:thermometer"
|
||||
device_class: "temperature"
|
||||
state_class: "measurement"
|
||||
accuracy_decimals: 1
|
||||
- platform: ltr_als_ps
|
||||
address: 0x29
|
||||
i2c_id: sensors
|
||||
update_interval: 10s
|
||||
type: ALS
|
||||
auto_mode: false
|
||||
gain: 48x
|
||||
ambient_light:
|
||||
name: "Ambient Light"
|
||||
id: buttonplus_ambientlight
|
||||
unit_of_measurement: "lx"
|
||||
icon: "mdi:brightness-6"
|
||||
device_class: "illuminance"
|
||||
state_class: "measurement"
|
||||
accuracy_decimals: 1
|
||||
infrared_counts:
|
||||
name: "Infrared Counts"
|
||||
id: buttonplus_infraredcounts
|
||||
unit_of_measurement: "#"
|
||||
icon: "mdi:brightness-5"
|
||||
accuracy_decimals: 0
|
||||
full_spectrum_counts :
|
||||
name: "Full Spectrum Counts"
|
||||
id: buttonplus_fullspectrumcounts
|
||||
unit_of_measurement: "#"
|
||||
icon: "mdi:brightness-7"
|
||||
accuracy_decimals: 0
|
||||
actual_gain:
|
||||
name: "Actual Gain"
|
||||
id: buttonplus_actualgain
|
||||
icon: "mdi:multiplication"
|
||||
accuracy_decimals: 0
|
||||
- platform: template
|
||||
name: "Active Page ID"
|
||||
icon: "mdi:order-numeric-ascending"
|
||||
id: active_page_id_ha
|
||||
update_interval: never
|
||||
accuracy_decimals: 0
|
||||
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: "Active Page Name"
|
||||
icon: "mdi:order-alphabetical-ascending"
|
||||
id: active_page_name_ha
|
||||
update_interval: never
|
||||
|
||||
light:
|
||||
- platform: esp32_rmt_led_strip
|
||||
- platform: neopixelbus
|
||||
id: neopixels
|
||||
rgb_order: RGB
|
||||
chipset: ws2812
|
||||
type: RGB
|
||||
variant: WS2812
|
||||
pin: GPIO4
|
||||
num_leds: 17
|
||||
- platform: monochromatic
|
||||
@@ -142,7 +87,7 @@ light:
|
||||
- platform: monochromatic
|
||||
output: displays_mini_backlight_pwm
|
||||
gamma_correct : 2.2
|
||||
name: "Bars Display Backlight"
|
||||
name: "Mini Display Backlight"
|
||||
id: displays_mini_backlight
|
||||
restore_mode: ALWAYS_ON
|
||||
|
||||
@@ -151,25 +96,22 @@ time:
|
||||
id: datetime
|
||||
|
||||
number:
|
||||
## Creates a number entity in Home Assistant
|
||||
# Creates a number entity in Home Assistant
|
||||
# It sets the menu of the Button Plus
|
||||
- platform: template
|
||||
name: "Menu Selector"
|
||||
id: menuselector
|
||||
id: menu_selector
|
||||
optimistic: true
|
||||
min_value: 0
|
||||
max_value: ${nr_of_pages | int - 1}
|
||||
min_value: 1
|
||||
max_value: ${nr_of_pages}
|
||||
step: 1
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
if(id(menuselector).state >= id(nr_of_pages)) {
|
||||
id(actual_page) = id(nr_of_pages)-1;
|
||||
} else {
|
||||
id(actual_page) = id(menuselector).state;
|
||||
}
|
||||
- logger.log: "Changing page"
|
||||
- script.execute: set_page
|
||||
- globals.set:
|
||||
id: actual_page
|
||||
value: !lambda 'return x;'
|
||||
- script.execute: update_page_naming
|
||||
- script.execute: update_all
|
||||
|
||||
script:
|
||||
######################
|
||||
@@ -177,35 +119,19 @@ script:
|
||||
######################
|
||||
- id: next_page
|
||||
then:
|
||||
- lambda: |-
|
||||
id(actual_page) = id(actual_page) + 1;
|
||||
if(id(actual_page) >= id(nr_of_pages)) {
|
||||
id(actual_page) = 0;
|
||||
}
|
||||
- script.execute: update_page
|
||||
- number.increment:
|
||||
id: menu_selector
|
||||
- id: prev_page
|
||||
then:
|
||||
- lambda: |-
|
||||
id(actual_page) = id(actual_page) - 1;
|
||||
if(id(actual_page) < 0) {
|
||||
id(actual_page) = id(nr_of_pages) - 1;
|
||||
}
|
||||
- script.execute: update_page
|
||||
- id: set_page
|
||||
- number.decrement:
|
||||
id: menu_selector
|
||||
- id: update_page_naming
|
||||
then:
|
||||
- lambda: |-
|
||||
id(active_page_name) = id(page_names)[id(actual_page)];
|
||||
id(active_page_name) = id(page_names)[id(actual_page) - 1];
|
||||
- sensor.template.publish:
|
||||
id: active_page_id_ha
|
||||
state: !lambda 'return id(actual_page);'
|
||||
- text_sensor.template.publish:
|
||||
id: active_page_name_ha
|
||||
state: !lambda 'return id(active_page_name);'
|
||||
- script.execute: update_all
|
||||
- id: update_page
|
||||
then:
|
||||
- number.set:
|
||||
id: menuselector
|
||||
value: !lambda 'return id(actual_page);'
|
||||
- script.execute: set_page
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
# ESPHome Button+ - Music card
|
||||
|
||||
## Usage
|
||||
|
||||
* Add the music card file to the package files
|
||||
```
|
||||
package:
|
||||
remote_package_files:
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files: [<other files>,'package/cards/display_item.yaml']
|
||||
```
|
||||
* Add the display item card to the (main) display `lambda` and give it the position and [parameters](#parameters) you want
|
||||
It requires fonts and colors to be defined, this can be called as lambda, for instance:
|
||||
```
|
||||
//id(display_item).execute(x, y, label, labelfont, labelcolor, valuenum, decimals, valuestr, valuefont, valuecolor, unit, unitfont, unitcolor, align)
|
||||
id(display_item).execute(160, 2, "External", "size_3_label", "orange", id(outside_temperature).state, 1, "", "size_3_value", "white", "°C", "size_3_unit", "grey", "TOP_LEFT");
|
||||
```
|
||||
This will position a block with label "External" in size 3 and color orange, below that a value with 1 decimal, in white, size 3. Next to that unit "°C", size 3 in grey, anchored at x,y = 160,2 top left corner
|
||||
|
||||
|
||||
## Parameters:
|
||||
|
||||
```
|
||||
x: int x of anchor point
|
||||
y: int y of anchor point
|
||||
label: string label, to be shown above the value
|
||||
labelfont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
labelcolor: string any of white, orange, red, green or grey
|
||||
valuenum: float value to display (numerical)
|
||||
decimals: int rounding of value to display
|
||||
valuestr: string if left empty it will select display the value float
|
||||
valuefont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
valuecolor: string any of white, orange, red, green or grey
|
||||
unit: string displayed unit
|
||||
unitfont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
unitcolor: string any of white, orange, red, green or grey
|
||||
align: string TOP_LEFT, TOP_CENTER or TOP_RIGHT
|
||||
```
|
||||
@@ -0,0 +1,210 @@
|
||||
|
||||
#####################################################
|
||||
##
|
||||
## FILENAME: cards/display_item.yaml
|
||||
## NAME: Display item constructor
|
||||
## DESCRIPTION: creates display items like
|
||||
## the original firmware
|
||||
## PARAMETERS:
|
||||
## x: int x of anchor point
|
||||
## y: int y of anchor point
|
||||
## label: string label, to be shown above the value
|
||||
## labelfont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
## labelcolor: string any of white, orange, red, green or grey
|
||||
## valuenum: float value to display (numerical)
|
||||
## decimals: int rounding of value to display
|
||||
## valuestr: string if left empty it will select display the value float
|
||||
## valuefont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
## valuecolor: string any of white, orange, red, green or grey
|
||||
## unit: string displayed unit
|
||||
## unitfont: string any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
## unitcolor: string any of white, orange, red, green or grey
|
||||
## align: string TOP_LEFT, TOP_CENTER or TOP_RIGHT
|
||||
## USAGE:
|
||||
## package:
|
||||
## remote_package_files:
|
||||
## url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
## files: [<other files>,'package/cards/display_item.yaml']
|
||||
##
|
||||
## display:
|
||||
## - id: !extend main_display
|
||||
## lambda: |-
|
||||
## id(display_item).execute(160,2,"External","size_3_label","orange",id(outside_temperature).state,1,"","size_3_value","white","°C","size_3_unit","grey","TOP_LEFT");
|
||||
##
|
||||
#####################################################
|
||||
|
||||
font:
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_1_label
|
||||
size: 10
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_2_label
|
||||
size: 12
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_3_label
|
||||
size: 14
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_1_value
|
||||
size: 15
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_2_value
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_3_value
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_1_unit
|
||||
size: 15
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_2_unit
|
||||
size: 20
|
||||
bpp: 4
|
||||
- file: "https://github.com/web-fonts/ttf/raw/refs/heads/master/bpg-ingiri-arial-webfont.ttf"
|
||||
id: display_item_size_3_unit
|
||||
size: 20
|
||||
bpp: 4
|
||||
|
||||
color:
|
||||
- id: display_item_red
|
||||
hex: FF0000
|
||||
- id: display_item_blue
|
||||
hex: 0000FF
|
||||
- id: display_item_yellow
|
||||
hex: FFFF00
|
||||
- id: display_item_green
|
||||
hex: 00FF00
|
||||
- id: display_item_orange
|
||||
hex: FF7F00
|
||||
- id: display_item_white
|
||||
hex: FFFFFF
|
||||
- id: display_item_grey
|
||||
hex: A6A6A6
|
||||
|
||||
script:
|
||||
- id: display_item
|
||||
parameters:
|
||||
x: int # x of anchor point
|
||||
y: int # y of anchor point
|
||||
label: string # label, to be shown above the value
|
||||
labelfont: string # any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
labelcolor: string # any of white, orange, red, green or grey
|
||||
valuenum: float # value to display (numerical)
|
||||
decimals: int # rounding of value to display
|
||||
valuestr: string # if left empty it will select display the value float
|
||||
valuefont: string # any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
valuecolor: string # any of white, orange, red, green or grey
|
||||
unit: string # displayed unit
|
||||
unitfont: string # any of size_1_value, size_2_unit, size_3_label and everything in between
|
||||
unitcolor: string # any of white, orange, red, green or grey
|
||||
align: string # TOP_LEFT, TOP_CENTER or TOP_RIGHT
|
||||
then:
|
||||
lambda: |-
|
||||
// Helper to get the font object from its ID string
|
||||
// This lambda function maps font ID strings to their corresponding font objects.
|
||||
// If the provided font_id matches a known font, it returns the appropriate font object.
|
||||
// Otherwise, it returns nullptr.
|
||||
auto get_font = [](const std::string &font_id) -> esphome::font::Font* {
|
||||
if (font_id == "size_1_value") return id(display_item_size_1_value);
|
||||
if (font_id == "size_1_label") return id(display_item_size_1_label);
|
||||
if (font_id == "size_1_unit") return id(display_item_size_1_unit);
|
||||
if (font_id == "size_2_value") return id(display_item_size_2_value);
|
||||
if (font_id == "size_2_label") return id(display_item_size_2_label);
|
||||
if (font_id == "size_2_unit") return id(display_item_size_2_unit);
|
||||
if (font_id == "size_3_value") return id(display_item_size_3_value);
|
||||
if (font_id == "size_3_label") return id(display_item_size_3_label);
|
||||
if (font_id == "size_3_unit") return id(display_item_size_3_unit);
|
||||
return nullptr; // Return nullptr if the font ID doesn't match any known font.
|
||||
};
|
||||
|
||||
auto get_color = [](const std::string &color_id) -> esphome::Color {
|
||||
if (color_id == "white") return id(display_item_white);
|
||||
if (color_id == "blue") return id(display_item_blue);
|
||||
if (color_id == "orange") return id(display_item_orange);
|
||||
if (color_id == "red") return id(display_item_red);
|
||||
if (color_id == "green") return id(display_item_green);
|
||||
if (color_id == "grey") return id(display_item_grey);
|
||||
return esphome::Color::WHITE; // Default color if no match
|
||||
};
|
||||
|
||||
esphome::Color labelcolor_script = get_color(labelcolor);
|
||||
esphome::Color valuecolor_script = get_color(valuecolor);
|
||||
esphome::Color unitcolor_script = get_color(unitcolor);
|
||||
|
||||
// Resolve font objects based on the provided font IDs.
|
||||
// These objects will later be used to measure text dimensions and render text on the display.
|
||||
auto *labelfont_obj = get_font(labelfont);
|
||||
auto *valuefont_obj = get_font(valuefont);
|
||||
auto *unitfont_obj = get_font(unitfont);
|
||||
|
||||
// Format the numeric value as a string with the specified number of decimals.
|
||||
// snprintf safely formats the float into a fixed-width character buffer.
|
||||
char value_str[40];
|
||||
// Check if valuestr is not empty
|
||||
if (valuestr.empty()) { // Check if valuestr has any content
|
||||
snprintf(value_str, sizeof(value_str), "%.*f", decimals, valuenum);
|
||||
} else {
|
||||
// If valuestr is empty, copy a default or alternative string into value_str
|
||||
strncpy(value_str, valuestr.c_str(), sizeof(value_str)); // Example default value
|
||||
value_str[sizeof(value_str) - 1] = '\0'; // Ensure null-termination
|
||||
}
|
||||
|
||||
// Helper function to calculate text dimensions.
|
||||
// This lambda takes a font object and a text string as input,
|
||||
// and it calculates the text's width and height (returned via reference parameters).
|
||||
auto calculate_text_dimensions = [](esphome::font::Font *font, const char *text, int &width, int &baseline) {
|
||||
int x_offset = 0, height = 0;
|
||||
font->measure(text, &width, &x_offset, &baseline, &height);
|
||||
};
|
||||
|
||||
// Calculate the dimensions of the label text.
|
||||
int label_width = 0, label_height = 0;
|
||||
calculate_text_dimensions(labelfont_obj, label.c_str(), label_width, label_height);
|
||||
|
||||
// Calculate the dimensions of the value text.
|
||||
int value_width = 0, value_height = 0;
|
||||
calculate_text_dimensions(valuefont_obj, value_str, value_width, value_height);
|
||||
|
||||
// Calculate the dimensions of the unit text.
|
||||
int unit_width = 0, unit_height = 0;
|
||||
calculate_text_dimensions(unitfont_obj, unit.c_str(), unit_width, unit_height);
|
||||
|
||||
if (align == "TOP_RIGHT" ){
|
||||
// Render the label on the display at the specified position (x, y).
|
||||
id(main_display).printf(x, y, labelfont_obj, labelcolor_script, TextAlign::TOP_RIGHT, "%s", label.c_str());
|
||||
|
||||
// Render the value below the label with a vertical offset equal to the label's height.
|
||||
id(main_display).printf(x - unit_width, y - 2 + label_height , valuefont_obj, valuecolor_script, TextAlign::TOP_RIGHT, "%s", value_str);
|
||||
|
||||
// Render the unit text to the right of the value text with appropriate offsets.
|
||||
id(main_display).printf(x, y - 2 + label_height + value_height - unit_height, unitfont_obj, unitcolor_script, TextAlign::TOP_RIGHT, "%s", unit.c_str());
|
||||
} else if (align == "TOP_CENTER" ){
|
||||
// Calculate the maximum width of the display item, being the label or value+unit
|
||||
// subtract half of that from the anchor point and position based on top left corner of the text fields
|
||||
int offset = (std::max(label_width, value_width + unit_width) + 1) / 2;
|
||||
|
||||
// Render the label on the display at the specified position (x, y).
|
||||
id(main_display).printf(x - offset, y, labelfont_obj, labelcolor_script, TextAlign::TOP_LEFT, "%s", label.c_str());
|
||||
|
||||
// Render the value below the label with a vertical offset equal to the label's height.
|
||||
id(main_display).printf(x - offset, y - 2 + label_height , valuefont_obj, valuecolor_script, TextAlign::TOP_LEFT, "%s", value_str);
|
||||
|
||||
// Render the unit text to the right of the value text with appropriate offsets.
|
||||
id(main_display).printf(x - offset + value_width, y -2+ label_height + value_height - unit_height, unitfont_obj, unitcolor_script, TextAlign::TOP_LEFT, "%s", unit.c_str());
|
||||
} else {
|
||||
// Render the label on the display at the specified position (x, y).
|
||||
id(main_display).printf(x, y, labelfont_obj, labelcolor_script, TextAlign::TOP_LEFT, "%s", label.c_str());
|
||||
|
||||
// Render the value below the label with a vertical offset equal to the label's height.
|
||||
id(main_display).printf(x, y - 2 + label_height , valuefont_obj, valuecolor_script, TextAlign::TOP_LEFT, "%s", value_str);
|
||||
|
||||
// Render the unit text to the right of the value text with appropriate offsets.
|
||||
id(main_display).printf(x + value_width, y - 2 + label_height + value_height - unit_height , unitfont_obj, unitcolor_script, TextAlign::TOP_LEFT, "%s", unit.c_str());
|
||||
}
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
|
||||
## Usage
|
||||
|
||||
* Add the music card file to youre files and supply the `entity_id`
|
||||
* Add the music card file to the package files and supply the `entity_id`
|
||||
```
|
||||
substitutions:
|
||||
music_card_enity_id: 'media_player.media_keuken_2'
|
||||
package:
|
||||
remote_package_files:
|
||||
url: https://gitea.furb.it/kennyboy55/ESPHome_ButtonPlusV2
|
||||
url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
files: [<other files>,'package/cards/music.yaml']
|
||||
```
|
||||
* Add the music card to the main display `lambda` and give it the position you want
|
||||
|
||||
+32
-38
@@ -6,96 +6,90 @@
|
||||
## players current state
|
||||
## USAGE:
|
||||
## substitutions:
|
||||
## music_card_entity_id: 'media_player.media_keuken_2'
|
||||
## music_card_enity_id: 'media_player.media_keuken_2'
|
||||
## package:
|
||||
## remote_package_files:
|
||||
## url: https://gitea.furb.it/kennyboy55/ESPHome_ButtonPlusV2
|
||||
## url: https://github.com/dixi83/ESPHome_ButtonPlus
|
||||
## files: [<other files>,'package/cards/music.yaml']
|
||||
##
|
||||
## display:
|
||||
## - id: !extend main_display
|
||||
## pages:
|
||||
## - id: player_page
|
||||
## lambda: |-
|
||||
## id(all_pages).execute();
|
||||
## // insert music card:
|
||||
## // >> id(music_card).execute(x, y);
|
||||
## id(music_card).execute(20, 125);
|
||||
## - id: !extend bar1_left
|
||||
## lambda: |-
|
||||
## id(music_card).execute(20, 125);
|
||||
##
|
||||
#####################################################
|
||||
|
||||
image:
|
||||
- file: mdi:music-box-outline
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_album
|
||||
resize: 20x20
|
||||
- file: mdi:account-music
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_artist
|
||||
resize: 20x20
|
||||
- file: mdi:music-note
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_songtitle
|
||||
resize: 20x20
|
||||
- file: mdi:power-off
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_off
|
||||
resize: 75x75
|
||||
- file: mdi:power-on
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_on
|
||||
resize: 75x75
|
||||
- file: mdi:power
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_power
|
||||
resize: 75x75
|
||||
- file: mdi:timer-sand-empty
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_idle
|
||||
resize: 75x75
|
||||
- file: mdi:play-pause
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_playpause
|
||||
resize: 75x75
|
||||
- file: mdi:play-box-outline
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_play_box
|
||||
resize: 75x75
|
||||
- file: mdi:pause-box-outline
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_pause_box
|
||||
resize: 75x75
|
||||
- file: mdi:power
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_standby
|
||||
resize: 75x75
|
||||
- file: mdi:download-box-outline
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_buffering
|
||||
resize: 75x75
|
||||
- file: mdi:volume-plus
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_vol_up
|
||||
resize: 75x75
|
||||
- file: mdi:volume-minus
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_vol_down
|
||||
resize: 75x75
|
||||
- file: mdi:skip-forward
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_next
|
||||
resize: 75x75
|
||||
- file: mdi:skip-backward
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_prev
|
||||
resize: 75x75
|
||||
- file: mdi:play
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_play
|
||||
resize: 75x75
|
||||
- file: mdi:pause
|
||||
type: GRAYSCALE
|
||||
type: binary
|
||||
id: icon_music_pause
|
||||
resize: 75x75
|
||||
|
||||
@@ -110,25 +104,25 @@ color:
|
||||
text_sensor:
|
||||
- platform: homeassistant
|
||||
id: music_album
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
attribute: media_album_name
|
||||
on_value:
|
||||
- delay: 500ms
|
||||
- script.execute: update_main
|
||||
- platform: homeassistant
|
||||
id: music_artist
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
attribute: media_artist
|
||||
- platform: homeassistant
|
||||
id: music_title
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
attribute: media_title
|
||||
on_value:
|
||||
- delay: 500ms
|
||||
- script.execute: update_main
|
||||
- platform: homeassistant
|
||||
id: music_playerstate
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
on_value:
|
||||
- script.execute: update_all
|
||||
|
||||
@@ -194,34 +188,34 @@ script:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_up
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
- id: music_card_vol_down
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.volume_down
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
- id: music_card_next
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_next_track
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
- id: music_card_prev
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_previous_track
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
- id: music_card_playpause
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.media_play_pause
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
- id: music_card_power
|
||||
then:
|
||||
- homeassistant.action:
|
||||
action: media_player.toggle
|
||||
data:
|
||||
entity_id: ${music_card_entity_id}
|
||||
entity_id: ${music_card_enity_id}
|
||||
|
||||
Reference in New Issue
Block a user