docs(awning): spec for standalone WiFi reed "closed" sensor (Option 1)
ESP32-C3 + weatherproof reed on OmnissiahsReach WiFi (no Zigbee mesh) for true stowed/not-stowed state: BOM, wiring, ESPHome config, HA/bridge integration, optional truthful template cover, and the Option-2 (wire-to-CAN-node) note. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,192 @@
|
|||||||
|
# Awning "Closed" Sensor — Spec (Option 1: standalone WiFi reed node)
|
||||||
|
|
||||||
|
**Goal:** give the campsite awning a *true* stowed/not-stowed state instead of the
|
||||||
|
`assumed_state` the CAN cover currently reports. A magnetic reed switch at the
|
||||||
|
fully-retracted position, read by a small ESP running ESPHome over the existing
|
||||||
|
`OmnissiahsReach` WiFi — **no Zigbee mesh, no coordinator, no new ecosystem.**
|
||||||
|
|
||||||
|
This is "Option 1" (standalone node). Option 2 (wire the reed back to a spare GPIO
|
||||||
|
on the CAN node `192.168.69.18` so the cover entity itself becomes truthful) is the
|
||||||
|
more-integrated alternative but needs a 2-wire run from the awning to the control
|
||||||
|
panel; it's noted at the end. Pairs with the current-sensing auto-retract already
|
||||||
|
in `esphome/onecontrol-canbus.yaml` (README "awning" section): current does the
|
||||||
|
*dynamic* stop during retract, the reed gives *persistent* truth afterward.
|
||||||
|
|
||||||
|
## What it delivers (and what it doesn't)
|
||||||
|
|
||||||
|
- **Reliable CLOSED (stowed) detection.** Awnings extend to an arbitrary spot, so
|
||||||
|
there's no meaningful "fully open" endpoint — but the fully-retracted position is
|
||||||
|
hard and repeatable. That's the state that matters (don't drive off / don't let
|
||||||
|
it flap): a single reed there answers *stowed vs. not*.
|
||||||
|
- It does **not** measure extension %. If you ever want an "opening/closing"
|
||||||
|
animation you already get that from the CAN motion byte; the reed just pins down
|
||||||
|
the resting truth.
|
||||||
|
|
||||||
|
## Bill of materials (~$15–20)
|
||||||
|
|
||||||
|
| Part | Notes |
|
||||||
|
|------|-------|
|
||||||
|
| **ESP32-C3 SuperMini** (or Wemos D1 mini / ESP8266) | Tiny, WiFi, 3.3 V logic. C3 recommended (native ESP-IDF, cheap, plenty of GPIO). |
|
||||||
|
| **Weatherproof reed switch** | RV-compartment / garage-door style, **potted + leaded**, normally-open. Get a wide-gap one (pull-in ≥ 15–20 mm) so alignment is forgiving. |
|
||||||
|
| **Bar/block magnet** | Match/exceed the reed's rated gap. Rare-earth block for margin. |
|
||||||
|
| **12 V → 5 V buck** (MP1584 / mini360 or an automotive USB buck) | Tap the awning motor's 12 V; always-on beats battery/deep-sleep for instant state and no maintenance. |
|
||||||
|
| **Small IP65 enclosure + gland** | Mount the ESP + buck out of the weather. |
|
||||||
|
| Fused 12 V tap (inline 1 A) | Protect the tap off the motor harness. |
|
||||||
|
|
||||||
|
## Wiring
|
||||||
|
|
||||||
|
```
|
||||||
|
awning 12V harness --[inline 1A fuse]--> buck IN+ buck OUT+ (5V) --> ESP 5V
|
||||||
|
chassis GND -----> buck IN- ----buck OUT- ------> ESP GND
|
||||||
|
|
||||||
|
reed leg A --> ESP GPIO4
|
||||||
|
reed leg B --> ESP GND
|
||||||
|
```
|
||||||
|
|
||||||
|
- Reed to GND with the **internal pull-up** enabled: pin idles HIGH (not stowed),
|
||||||
|
goes LOW when the magnet is present (stowed). The ESPHome config below inverts
|
||||||
|
that so the sensor reads ON = stowed.
|
||||||
|
- No external resistor needed. An optional 0.1 µF across the reed helps debounce,
|
||||||
|
but the software `delayed_on/off` below is enough.
|
||||||
|
- Avoid the C3 strapping pins (GPIO2, 8, 9); GPIO4 is safe. GPIO8 has the onboard
|
||||||
|
LED if you want a status blink.
|
||||||
|
|
||||||
|
## Mounting
|
||||||
|
|
||||||
|
- **Magnet on the moving part** (the lead rail / roller endcap that seats when
|
||||||
|
stowed); **reed on the fixed part** (mounting rail or a bracket on the coach).
|
||||||
|
- Aim for the magnet to land within the reed's pull-in gap when the awning is
|
||||||
|
pulled in tight — the same "closed" position the current-stall stop lands on.
|
||||||
|
Expect a test-fit: mark where the rail seats, mount, confirm the sensor flips.
|
||||||
|
- Outdoor: use the potted reed, point the gland down, silicone the entry, and
|
||||||
|
strain-relief the lead so awning motion doesn't fatigue it.
|
||||||
|
|
||||||
|
## ESPHome config
|
||||||
|
|
||||||
|
New device `awning-sensor` (mirror the conventions in `onecontrol-canbus.yaml` /
|
||||||
|
`gazebo-fan-proxy.yaml`: `secrets.yaml` for WiFi + API key, OTA after first USB
|
||||||
|
flash, fallback AP + captive portal). DHCP on `OmnissiahsReach`.
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
substitutions:
|
||||||
|
name: awning-sensor
|
||||||
|
friendly_name: Awning Sensor
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: ${name}
|
||||||
|
friendly_name: ${friendly_name}
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-c3-devkitm-1
|
||||||
|
framework:
|
||||||
|
type: esp-idf
|
||||||
|
|
||||||
|
logger:
|
||||||
|
api:
|
||||||
|
encryption:
|
||||||
|
key: !secret api_key
|
||||||
|
ota:
|
||||||
|
- platform: esphome
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid # OmnissiahsReach
|
||||||
|
password: !secret wifi_password
|
||||||
|
ap:
|
||||||
|
ssid: "Awning-Sensor Fallback"
|
||||||
|
password: !secret fallback_ap_password
|
||||||
|
captive_portal:
|
||||||
|
|
||||||
|
binary_sensor:
|
||||||
|
- platform: gpio
|
||||||
|
name: "Awning Stowed"
|
||||||
|
id: awning_stowed
|
||||||
|
pin:
|
||||||
|
number: GPIO4
|
||||||
|
mode:
|
||||||
|
input: true
|
||||||
|
pullup: true
|
||||||
|
inverted: true # reed->GND: magnet present = LOW = ON (stowed)
|
||||||
|
filters:
|
||||||
|
- delay_on: 200ms # debounce the rail seating
|
||||||
|
- delay_off: 200ms
|
||||||
|
# ON = awning pulled in tight (stowed / closed)
|
||||||
|
# OFF = not stowed (extended, or mid-travel)
|
||||||
|
```
|
||||||
|
|
||||||
|
`secrets.yaml` needs `wifi_ssid`, `wifi_password`, `fallback_ap_password`,
|
||||||
|
`api_key` (generate with `esphome`). First flash over USB (`esphome run ... `),
|
||||||
|
thereafter OTA — same as the other campsite nodes.
|
||||||
|
|
||||||
|
## HA integration
|
||||||
|
|
||||||
|
The reed is a separate device from the CAN node, so it lands as its own entity:
|
||||||
|
|
||||||
|
1. **Campsite Pi** auto-discovers it via the ESPHome integration →
|
||||||
|
`binary_sensor.awning_sensor_awning_stowed` (rename to
|
||||||
|
`binary_sensor.awning_stowed`). ON = stowed.
|
||||||
|
2. **Bridge to home HA** — add to `/config/packages/mqtt_bridge.yaml` (repo:
|
||||||
|
`canbus/ha/mqtt_bridge_onecontrol.yaml`) next to the other campsite entities:
|
||||||
|
a discovery block (`homeassistant/binary_sensor/campsite/awning_stowed/config`,
|
||||||
|
device `campsite_onecontrol`, `device_class: "opening"` reads on=open/off=closed,
|
||||||
|
or leave classless for a plain stowed/clear), plus a state-forward trigger on
|
||||||
|
`binary_sensor.awning_stowed` → `campsite/binary_sensor/awning_stowed/state`.
|
||||||
|
Appears on home as `binary_sensor.campsite_onecontrol_awning_stowed`.
|
||||||
|
3. Add the tile to home HA **Overview → Camper → OneControl** section.
|
||||||
|
|
||||||
|
### Optional: make the cover *truthful* (template cover)
|
||||||
|
|
||||||
|
Right now `cover.onecontrol_can_awning` is `assumed_state`. With the reed you can
|
||||||
|
wrap it in a template cover on the Pi whose closed state is the *real* reed, while
|
||||||
|
commands still hit the CAN cover:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
cover:
|
||||||
|
- platform: template
|
||||||
|
covers:
|
||||||
|
awning_true:
|
||||||
|
friendly_name: "Awning"
|
||||||
|
device_class: awning
|
||||||
|
value_template: "{{ 'closed' if is_state('binary_sensor.awning_stowed','on') else 'open' }}"
|
||||||
|
close_cover:
|
||||||
|
- action: cover.close_cover # -> CAN cover auto-retract
|
||||||
|
target: { entity_id: cover.onecontrol_can_awning }
|
||||||
|
stop_cover:
|
||||||
|
- action: cover.stop_cover
|
||||||
|
target: { entity_id: cover.onecontrol_can_awning }
|
||||||
|
```
|
||||||
|
|
||||||
|
Bridge `cover.awning_true` to home instead of the raw CAN cover, and you get a
|
||||||
|
cover that shows genuine open/closed. (Keep `payload_open` disabled as today.)
|
||||||
|
|
||||||
|
### Automations this unlocks
|
||||||
|
|
||||||
|
- **Left-it-out alarm:** awning `not stowed` + (leaving geofence / wind gust > X /
|
||||||
|
rain) → Discord ping, or auto-fire `cover.close_cover`.
|
||||||
|
- **Confirm the retract actually seated:** after an auto-retract, if the current
|
||||||
|
stall fired but the reed is still OFF a few seconds later → alert (mis-seat).
|
||||||
|
|
||||||
|
> **Option-1 limitation:** because the reed is on a *separate* device from the CAN
|
||||||
|
> node, the auto-retract's stall gate can't consume it on-device — any
|
||||||
|
> reed↔retract logic is a cross-device HA automation, not firmware. If you want
|
||||||
|
> the ESP to stop the motor *on the reed itself* (belt-and-suspenders with the
|
||||||
|
> current stall), that's Option 2 (wire the reed to a spare GPIO on the CAN node
|
||||||
|
> `192.168.69.18`; the cover entity then reads it directly and becomes truthful
|
||||||
|
> with no template cover).
|
||||||
|
|
||||||
|
## Touchpoints checklist (campsite ESPHome node)
|
||||||
|
|
||||||
|
- [ ] `secrets.yaml` (WiFi = OmnissiahsReach, API key, fallback AP pw)
|
||||||
|
- [ ] USB flash once, confirm on `OmnissiahsReach` (DHCP `192.168.69.x`); OTA after
|
||||||
|
- [ ] Adopt in campsite Pi HA (ESPHome integration), rename entity
|
||||||
|
- [ ] Mount reed + magnet, verify it flips exactly at the stowed position
|
||||||
|
- [ ] `mqtt_bridge.yaml`: discovery + state-forward → home HA; add dashboard tile
|
||||||
|
- [ ] (optional) template cover `awning_true`; bridge it instead of the raw cover
|
||||||
|
- [ ] (optional) automations: left-out alarm, retract-seat confirmation
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
1. USB-flash, join WiFi, adopt in HA. Toggle by hand with a magnet → `awning_stowed`
|
||||||
|
flips ON/OFF with the 200 ms debounce.
|
||||||
|
2. Mount, retract via the dashboard (auto-retract): at full stow the reed should go
|
||||||
|
ON right around when the current-stall stop fires.
|
||||||
|
3. Extend at the OEM wall switch → reed OFF. Confirm home HA mirrors it.
|
||||||
Reference in New Issue
Block a user