esp-mcmax-example

Example of the component a-barta/esp-mcmax v2.2.0
# esp-mcmax-example

The smallest end-to-end MCMAX node. It declares two string attributes and one
command, then runs a 1 Hz timer that republishes the attribute values. Use it
as a starting point for your own firmware.

## What it demonstrates

| Item | Name | Type | Notes |
|---|---|---|---|
| Attribute | `test_rw` | `str`, `READ_WRITE` | Writes from the bridge are stored and echoed back. |
| Attribute | `test_ro` | `str`, `READ` | Always publishes the constant `"Read only string"`. |
| Command | `toggle_led` | — | Payload `1`/`on`/`On`/`ON` turns the LED on, anything else turns it off. |

The flow, in `main/esp-mcmax-example.c`:

1. Two `tango_attribute_config_t` and one `tango_command_config_t` are declared
   and gathered into pointer arrays.
2. `data_in_callback` reacts to `MCMAX_EVENT_DATA_IN`: it stores writes to
   `test_rw` and drives the LED on `toggle_led`.
3. `mcmax_config_t` is populated with only the attribute/command arrays and the
   callback — the connection settings come from NVS at runtime.
4. `mcmax_init()` brings up every subsystem.
5. A 1 Hz `esp_timer` calls `mcmax_post()` to publish both attribute values.

## Boards

Each supported board has an idf.py argument file in `boards/` that sets the
target and a build directory of its own. `sdkconfig.defaults` describes the
ESP32-POE-ISO, so a plain `idf.py build` with no profile builds for that board.
`sdkconfig.defaults.esp32p4` applies to the esp32p4 target, and the EVB profile
adds `sdkconfig.defaults.esp32-evb`.

| Profile | Board | Ethernet | `toggle_led` |
|---|---|---|---|
| `esp32-poe-iso` | Olimex ESP32-POE-ISO (also ESP32-PoE) | LAN8710A, addr `0`, PHY power on GPIO `12`, RMII clock output on GPIO `17` | GPIO `33` |
| `esp32-evb` | Olimex ESP32-EVB | LAN8710A, addr `0`, no reset GPIO, RMII clock input on GPIO `0` | GPIO `33`: relay 2 and its LED |
| `esp32p4-devkit` | Olimex ESP32-P4-DevKit (optionally with POEv3) | TLK110 (generic PHY), addr `1`, reset GPIO `51`, RMII clock input on GPIO `50` | GPIO `2`: user LED, active-low |

The toggle pin and its level are the `EXAMPLE_TOGGLE_GPIO` and
`EXAMPLE_TOGGLE_ACTIVE_LOW` options under *esp-mcmax-example* in `menuconfig`.

ESP32-P4 chip revisions v0.x/v1.x and v3.x need different builds, and the
revision is not set here. Check yours with `esptool chip-id` and select a
matching range under *Component config -> Hardware Settings -> Chip revision*.

## Building

With ESP-IDF v6.0 or later exported, from this directory:

```bash
idf.py @boards/esp32-poe-iso build flash monitor
idf.py @boards/esp32-evb build flash monitor
idf.py @boards/esp32p4-devkit build flash monitor
```

Add `-p <port>` to pick the serial port. The POE-ISO and EVB appear as
`/dev/ttyUSB*`, the P4-DevKit as `/dev/ttyACM*`. To open `menuconfig` for a
board, pass its profile: `idf.py @boards/esp32p4-devkit menuconfig`.

The component is consumed in-tree via `override_path: ../../../` in
`main/idf_component.yml`, so edits to the root `.c`/`.h` files are picked up
without re-fetching from the Component Registry.

Each board's `sdkconfig` lives in its build directory and is generated from
the defaults files on the first build. Defaults files apply only when that
`sdkconfig` does not exist yet; delete the build directory after editing them.

The partition table (`partitions.csv`) defines **factory + ota_0 + ota_1** —
required so the OTA subsystem has a target partition to flash into.

## Adapting to another board

1. **Profile.** Copy a file in `boards/`, give it its own build directory, and
   list a new defaults file in `SDKCONFIG_DEFAULTS` after `sdkconfig.defaults`.
2. **Ethernet PHY.** In the new defaults file, set the PHY type, reset GPIO,
   PHY address and RMII clock options read by `espressif/ethernet_init`
   (*Component config -> Ethernet* in `menuconfig`).
3. **Toggle GPIO.** Set `CONFIG_EXAMPLE_TOGGLE_GPIO` and, for an active-low
   output, `CONFIG_EXAMPLE_TOGGLE_ACTIVE_LOW=y`.
4. **Flash size / partitions.** Adjust `CONFIG_ESPTOOLPY_FLASHSIZE_*` and
   `partitions.csv` if your module has less than 4 MB of flash.

## Runtime configuration

On first boot the device uses the hard-coded NVS defaults (broker
`test-mqtt.org`, user `user`, password `password`, name `MC-MAX`). Connect to
the device's IP on **port 80** to set the broker, credentials, device name and
OTA endpoint via the configuration form; values persist across reboots and the
device restarts to apply them.

See the [component README](../../README.md) for the MQTT topic layout, the
public API and the OTA server protocol.

To create a project from this example, run:

idf.py create-project-from-example "a-barta/esp-mcmax=2.2.0:esp-mcmax-example"

or download archive (~501.19 KB)