commit
cd62a024df
|
@ -0,0 +1,5 @@
|
|||
# Gitignore settings for ESPHome
|
||||
# This is an example and may include too much for your use-case.
|
||||
# You can modify this file to suit your needs.
|
||||
/.esphome/
|
||||
/lib/secrets.yaml
|
|
@ -0,0 +1,20 @@
|
|||
d1_mini
|
||||
=======
|
||||
|
||||
https://www.wemos.cc/en/latest/d1/d1_mini.html#pin
|
||||
~/.local/lib/python3.9/site-packages/esphome/components/esp8266/boards.py
|
||||
|
||||
GPIO d1_mini
|
||||
i2c SCL GPIO5 D1
|
||||
SDA GPIO4 D2
|
||||
boot mode GPIO0 D3 careful with this pin!
|
||||
internal led GPIO2 D4,LED
|
||||
spi CLK GPIO14 D5
|
||||
MISO GPIO12 D6
|
||||
MOSI GPIO13 D7
|
||||
|
||||
freely usable GPIO16 D0
|
||||
spi (CS) GPIO15 D8
|
||||
|
||||
GPIO1 (TX)
|
||||
GPIO3 (RX)
|
|
@ -0,0 +1,2 @@
|
|||
platform: status
|
||||
name: "${node_name} status"
|
|
@ -0,0 +1,3 @@
|
|||
platform: status_led
|
||||
name: "Status LED"
|
||||
pin: LED
|
|
@ -0,0 +1,33 @@
|
|||
esphome:
|
||||
name: ${node_name}
|
||||
|
||||
#mqtt:
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
|
||||
# Enable Home Assistant API
|
||||
api:
|
||||
password: !secret api_password
|
||||
|
||||
ota:
|
||||
password: !secret ota_password
|
||||
|
||||
#web_server:
|
||||
#prometheus:
|
||||
|
||||
sensor:
|
||||
- <<: !include sensor-uptime.yaml
|
||||
- <<: !include sensor-wifi_signal.yaml
|
||||
- <<: !include sensor-adc-vcc.yaml
|
||||
|
||||
binary_sensor:
|
||||
- <<: !include binary_sensor-status.yaml
|
||||
|
||||
light:
|
||||
- <<: !include light-status_led.yaml
|
||||
|
||||
switch:
|
||||
- <<: !include switch-restart.yaml
|
||||
- <<: !include switch-safe_mode.yaml
|
||||
- <<: !include switch-shutdown.yaml
|
|
@ -0,0 +1,9 @@
|
|||
wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
|
||||
ap:
|
||||
ssid: "${node_name} Fallback Hotspot"
|
||||
password: !secret wifi_ap_password
|
||||
|
||||
captive_portal:
|
|
@ -0,0 +1,3 @@
|
|||
platform: adc
|
||||
pin: VCC
|
||||
name: "${node_name} VCC"
|
|
@ -0,0 +1,2 @@
|
|||
platform: uptime
|
||||
name: "${node_name} uptime"
|
|
@ -0,0 +1,3 @@
|
|||
platform: wifi_signal
|
||||
name: "${node_name} WiFi Signal"
|
||||
update_interval: 60s
|
|
@ -0,0 +1,2 @@
|
|||
platform: restart
|
||||
name: "${node_name} restart"
|
|
@ -0,0 +1,2 @@
|
|||
platform: safe_mode
|
||||
name: "${node_name} restart (safe mode)"
|
|
@ -0,0 +1,2 @@
|
|||
platform: shutdown
|
||||
name: "${node_name} shutdown"
|
|
@ -0,0 +1,122 @@
|
|||
substitutions:
|
||||
node_name: lvng-xmas
|
||||
timezone: Europe/Warsaw
|
||||
countdown_fill: 'Color(0, 255, 0)'
|
||||
countdown_empty: 'Color(0, 0, 255)'
|
||||
countdown_reversed: 'true'
|
||||
|
||||
packages:
|
||||
common: !include lib/pkg-common.yaml
|
||||
wifi: !include lib/pkg-wifi.yaml
|
||||
|
||||
esphome:
|
||||
platform: ESP8266
|
||||
board: d1_mini
|
||||
|
||||
time:
|
||||
- platform: sntp
|
||||
timezone: ${timezone}
|
||||
id: time_sntp
|
||||
|
||||
on_time:
|
||||
- seconds: 0
|
||||
minutes: 0
|
||||
hours: 6
|
||||
then: &light-turn-on
|
||||
- light.turn_on:
|
||||
id: xmas
|
||||
brightness: 0.9
|
||||
red: 1.0
|
||||
green: 1.0
|
||||
blue: 1.0
|
||||
effect: Random Twinkle
|
||||
|
||||
- seconds: 0
|
||||
minutes: 0
|
||||
hours: 0
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: |-
|
||||
auto time = id(time_sntp).now();
|
||||
return time.day_of_month == 1 && time.month == 1;
|
||||
then: *light-turn-on
|
||||
else: &light-turn-off
|
||||
- light.turn_off:
|
||||
id: xmas
|
||||
|
||||
# New Year
|
||||
- seconds: 0
|
||||
minutes: 0
|
||||
hours: 23
|
||||
days_of_month: 31
|
||||
months: 12
|
||||
then:
|
||||
- light.turn_on:
|
||||
id: xmas
|
||||
brightness: 1.0
|
||||
effect: Countdown to Midnight
|
||||
|
||||
#light:
|
||||
# - name: xmas
|
||||
# id: xmas
|
||||
# platform: fastled_clockless
|
||||
# chipset: WS2811
|
||||
# pin: D1
|
||||
# num_leds: 100
|
||||
|
||||
light:
|
||||
- name: xmas
|
||||
id: xmas
|
||||
platform: neopixelbus
|
||||
|
||||
pin: D1
|
||||
|
||||
# WARNING: THIS IS PIN RX
|
||||
# pin: 3
|
||||
# method:
|
||||
# type: esp8266_dma
|
||||
|
||||
variant: WS2811
|
||||
type: RGB
|
||||
num_leds: 100
|
||||
|
||||
effects:
|
||||
- addressable_twinkle:
|
||||
twinkle_probability: 10%
|
||||
- addressable_random_twinkle:
|
||||
twinkle_probability: 20%
|
||||
- addressable_scan:
|
||||
scan_width: 4
|
||||
- addressable_scan:
|
||||
name: Scan Fast
|
||||
scan_width: 5
|
||||
move_interval: 5ms
|
||||
|
||||
- addressable_lambda:
|
||||
# linear countdown toward midnight
|
||||
name: Countdown to Midnight
|
||||
update_interval: 100ms
|
||||
lambda: !lambda |-
|
||||
const bool reversed = ${countdown_reversed};
|
||||
const Color color_fill = ${countdown_fill};
|
||||
const Color color_empty = ${countdown_empty};
|
||||
|
||||
auto time = id(time_sntp).now();
|
||||
if (time.is_valid()) {
|
||||
it.all() = color_empty;
|
||||
if (time.hour >= 12) {
|
||||
int n = (24 - time.hour) * 60 - time.minute;
|
||||
//ESP_LOGD("midnight", "time.hour=%d time.minute=%d n=%d it.size()=%d", time.hour, time.minute, n, it.size());
|
||||
if (!reversed) {
|
||||
it.range(max(it.size() - 1 - n, 0), it.size() - 1) = color_fill;
|
||||
} else {
|
||||
it.range(0, min(n, it.size() - 1)) = color_fill;
|
||||
}
|
||||
} else {
|
||||
//ESP_LOGD("midnight", "time.hour=%d", time.hour);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGD("midnight", "time is invalid");
|
||||
it.all() = Color(255, 0, 0);
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
lib/secrets.yaml
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/python3 -O
|
||||
|
||||
import asyncio
|
||||
import pathlib
|
||||
import pprint
|
||||
import typing
|
||||
|
||||
import aioesphomeapi
|
||||
import click
|
||||
import yaml
|
||||
|
||||
def load_secret(secret):
|
||||
with open(pathlib.Path(__file__).parent / 'secrets.yaml') as file:
|
||||
return yaml.safe_load(file)[secret]
|
||||
|
||||
async def main_async(device, **kwds):
|
||||
api = aioesphomeapi.APIClient(device, 6053, load_secret('api_password'))
|
||||
await api.connect(login=True)
|
||||
entities, _services = await api.list_entities_services()
|
||||
for entity in entities:
|
||||
if entity.object_id == 'xmas':
|
||||
await api.light_command(entity.key, **kwds)
|
||||
|
||||
#async def main_async(*args, rgb, **kwds):
|
||||
# print(f'{rgb=}')
|
||||
|
||||
class RGB(typing.NamedTuple):
|
||||
r: float
|
||||
g: float
|
||||
b: float
|
||||
|
||||
@classmethod
|
||||
def fromstr(cls, rgb):
|
||||
return cls(*map(float, rgb.split(',')))
|
||||
|
||||
@click.command()
|
||||
@click.option('--device', default='lvng-xmas.lan')
|
||||
@click.option('--effect')
|
||||
@click.option('--on/--off', 'state', default=None)
|
||||
@click.option('--rgb', type=RGB.fromstr)
|
||||
@click.option('--brightness', type=float)
|
||||
def main(*args, **kwds):
|
||||
asyncio.run(main_async(*args, **kwds))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
Loading…
Reference in New Issue