diff --git a/.gitignore b/.gitignore index 03cdeec..4ed379a 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ secrets.yaml +.esphome/ +__pycache__/ +*.pyc +.DS_Store diff --git a/frame-orchestrator.yaml b/frame-orchestrator.yaml new file mode 100644 index 0000000..4d8d896 --- /dev/null +++ b/frame-orchestrator.yaml @@ -0,0 +1,82 @@ + +esphome: + name: frame-orchestrator + name_add_mac_suffix: true + project: + name: zyberzero.frame-orchestrator + version: "0.1-beta" + +esp32: + board: seeed_xiao_esp32c3 + framework: + type: esp-idf + +dashboard_import: + package_import_url: "https://git.zyberze.ro/zyberzero/esphome-devices/frame-orchestrator.yaml@latest" + +external_components: + - source: + type: local + path: components + +esp32_ble: + enable_on_boot: true + +esp32_ble_tracker: + +bluetooth_proxy: + +ibeacon_rotator: + id: waker + uuid_prefix: !secret ble_uuid_prefix + broadcast_length: 45s + +# Enable logging +logger: + +# Enable Home Assistant API +api: + encryption: + key: !secret api_encryption_key + +ota: + - platform: esphome + + +wifi: + ssid: !secret wifi_ssid + password: !secret wifi_password + use_address: frame-proxy.local + + # Enable fallback hotspot (captive portal) in case wifi connection fails + ap: + ssid: "Frame-Proxy Fallback Hotspot" + password: !secret ap_fallback_password + +captive_portal: +mqtt: + id: mqtt_client + broker: !secret mqtt_broker + username: !secret mqtt_username + password: !secret mqtt_password + on_connect: + - lambda: |- + static bool subscribed = false; + if (!subscribed) { + subscribed = true; + id(mqtt_client)->subscribe("frames/+", + [](const std::string &topic, const std::string &payload) { + auto pos = topic.find_last_of('/'); + std::string leaf = (pos == std::string::npos) + ? topic : topic.substr(pos + 1); + ESP_LOGD("frames", "leaf=%s payload=%s", + leaf.c_str(), payload.c_str()); + // do something with `leaf` here + id(waker)->add_mac_from_string(leaf, ibeacon_rotator::Instruction::REFRESH); + }); + id(mqtt_client)->subscribe("wake/+", + [](const std::string &topic, const std::string &payload) { + // payload is the target MAC, e.g. "AA:BB:CC:DD:EE:FF" + id(waker)->add_mac_from_string(payload, ibeacon_rotator::Instruction::WAKE); + }); + } diff --git a/secrets.yaml.example b/secrets.yaml.example new file mode 100644 index 0000000..6ea8024 --- /dev/null +++ b/secrets.yaml.example @@ -0,0 +1,39 @@ +# Copy this file to secrets.yaml and fill in your own values. +# secrets.yaml is gitignored. + +# WiFi credentials +wifi_ssid: "your-wifi-ssid" +wifi_password: "your-wifi-password" + +# Static IP for the frame device — avoids DHCP delay on every refresh. +static_ip: "192.168.1.249" +gateway: "192.168.1.1" +subnet: "255.255.255.0" +dns1: "192.168.1.1" + +# 10-byte (20 hex chars, no separators) prefix of the iBeacon UUID. +# The full 16-byte UUID a frame device responds to is: +# <6-byte WiFi STA MAC of that device>. +# Pick a random value — anyone who can BLE-sniff your home can read this +# from the air, so don't reuse it as a credential elsewhere. +ble_uuid_prefix: "00000000000000000000" + +# Image source prefix. Full URL fetched per refresh is: +# {image_url_prefix}/{wifi_sta_mac_lowercase_no_separators}.png +image_url_prefix: "http://your-image-host.example/i" + +# MQTT broker the frame-orchestrator connects to. +mqtt_broker: "192.168.1.10" +mqtt_username: "your-mqtt-user" +mqtt_password: "your-mqtt-password" + +# Frame-orchestrator AP fallback hotspot password (used if WiFi is unreachable). +# 8+ chars. +ap_fallback_password: "change-me-8-or-more" + +# ESPHome native API encryption key (32 bytes, base64). +# Generate with: openssl rand -base64 32 +# (or use the "Generate" button in the ESPHome dashboard). +# After changing, reconfigure the Home Assistant ESPHome integration +# with the new value or the device will go unavailable. +api_encryption_key: "REPLACE_WITH_BASE64_32_BYTE_KEY"