{"id":50857947,"url":"https://github.com/leonidasdev/esp32-light-distance-mqtt","last_synced_at":"2026-06-14T19:32:11.637Z","repository":{"id":319888073,"uuid":"1079984568","full_name":"leonidasdev/esp32-light-distance-mqtt","owner":"leonidasdev","description":"ESP32 test project that combines LDR + ultrasonic sensing, Wi-Fi, MQTT, and ThingsBoard integration","archived":false,"fork":false,"pushed_at":"2025-10-20T19:03:15.000Z","size":62,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-20T19:29:00.606Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/leonidasdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-20T17:33:15.000Z","updated_at":"2025-10-20T19:03:18.000Z","dependencies_parsed_at":"2025-10-20T19:29:18.755Z","dependency_job_id":null,"html_url":"https://github.com/leonidasdev/esp32-light-distance-mqtt","commit_stats":null,"previous_names":["leonidasdev/esp32-light-distance-mqtt"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/leonidasdev/esp32-light-distance-mqtt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidasdev%2Fesp32-light-distance-mqtt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidasdev%2Fesp32-light-distance-mqtt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidasdev%2Fesp32-light-distance-mqtt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidasdev%2Fesp32-light-distance-mqtt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/leonidasdev","download_url":"https://codeload.github.com/leonidasdev/esp32-light-distance-mqtt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/leonidasdev%2Fesp32-light-distance-mqtt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34335688,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-14T02:00:07.365Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-14T19:32:10.812Z","updated_at":"2026-06-14T19:32:11.631Z","avatar_url":"https://github.com/leonidasdev.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"ESP32 project — filesystem contents and setup\n\nThis repository expects a FAT-formatted data partition (mounted at `/filesystem`) that contains configuration and credential files the firmware reads at boot. The device uses this partition for Wi‑Fi credentials, MQTT token, Telegram token, CA certificate (for TLS) and the static files served by the onboard webserver.\n\nThis README documents what files are expected, their formats, examples and recommended ways to prepare and flash the data partition image.\n\n## Files expected on the data partition\nPlace the files at the root of the FAT partition (the firmware mounts the partition at `/filesystem`):\n\n- `wifi.txt`\n  - Format: two lines\n    - Line 1: SSID\n    - Line 2: Password\n  - Example:\n\n    MyWiFiNetwork\n    s3cr3tPassw0rd\n\n  - Behavior: If `wifi.txt` is present and valid the device attempts to connect as a station using these credentials. If absent or connection fails the device starts a soft-AP and a local webserver to let you configure Wi‑Fi.\n\n- `mqtt.txt`\n  - Format: single line containing the ThingsBoard device access token (or other MQTT username/token).\n  - Example:\n\n    MY_DEVICE_ACCESS_TOKEN\n\n  - Behavior: The `components/mqtt_manager` module reads this token and uses it as the MQTT username when connecting to the broker. If missing the MQTT client is not started.\n\n- `tele.txt`\n  - Format: up to three lines (the firmware reads the first three lines):\n    - Line 1: Telegram bot token (required to enable the Telegram feature)\n    - Line 2: Optional admin chat id (numeric)\n    - Line 3: Optional last_update_id (an integer that the firmware may use to resume Telegram polling safely)\n  - Example:\n\n    123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11\n    987654321\n    42\n\n  - Behavior: If `tele.txt` exists the firmware initializes the Telegram module and may use the additional lines as persisted state.\n\n- `ca_root.pem` (or `ca-root.pem` or `cacert.pem`)\n  - Format: PEM file containing one or more trusted CA certificate(s).\n  - Behavior: The firmware will check for these filenames on the data partition and — if found — register the PEM content with the TLS certificate bundle helper. This allows HTTPS downloads (OTA, manifest fetching) and secure MQTT connections to work with private CAs.\n\n- `index.htm`\n  - The HTML page served when the device is running in AP + webserver configuration. The project already includes a default `index.htm` in the repo's `filesystem/` folder; you can customize it.\n\n- Other files\n  - `mqtt.txt`, `wifi.txt`, `tele.txt` and `ca_root.pem` are the most important. The `filesystem/` folder may also contain other static files that the webserver serves.\n\n## OTA support (ThingsBoard \u0026 URL/GitHub)\n\nThis project includes a full device-side OTA flow using ThingsBoard-hosted firmware as well as URL-based OTA (for GitHub releases or other HTTPS hosts).\n\nHigh-level behavior\n\n- The device listens for ThingsBoard attribute updates. When a shared attribute set includes firmware metadata (for example `fw_title` + `fw_version` or a `fw_url`), the device will perform a secure preflight check and then download and apply the firmware.\n- If the attribute contains `fw_url`, the device uses `esp_https_ota()` to download that URL and apply the image.\n- If ThingsBoard provides `fw_title` + `fw_version` (no `fw_url`), the device uses the ThingsBoard device firmware API (v1) to request the firmware package and streams it to the OTA partition while computing SHA256 to validate the package before switching boot partition.\n\nPersistence \u0026 confirmation\n\n- After a successful OTA write/verification the device persists the firmware identity to NVS (namespace `ota`, keys: `version`, `title`) and sets an internal `confirmed` flag to `0`.\n- On the next boot the device will publish the persisted firmware identity as client attributes (`current_fw_title` and `current_fw_version`) and then publish a one-time confirmation telemetry `{ \"fw_state\": \"UPDATED\", \"current_fw_version\": \"\u003cversion\u003e\" }`. That confirmation sets `confirmed=1` in NVS so the device doesn't repeatedly confirm the same update.\n\nThingsBoard attribute shape (example)\n\nIf you manage OTA from ThingsBoard, set shared attributes similar to the following. Two example flows are shown below:\n\n- URL-based OTA (use an HTTPS URL for `fw_url`):\n\n```json\n{\n  \"fw_title\": \"esp_sbc_ota\",\n  \"fw_version\": \"1.4\",\n  \"fw_size\": 1099120,\n  \"fw_checksum\": \"9af6211b58966ae9728fcfe8cb13fb68b5ceebf24472adb77c0b0d8a2eadbc4b\",\n  \"fw_checksum_algorithm\": \"SHA256\",\n  \"fw_url\": \"https://my.cdn.example.com/firmware/esp_sbc_ota-1.4.bin\"\n}\n```\n\n- ThingsBoard-hosted package (no `fw_url`): the device will use the v1 firmware API and the device access token to download by title+version:\n\n```json\n{\n  \"fw_title\": \"esp_sbc_ota\",\n  \"fw_version\": \"1.4\",\n  \"fw_size\": 1099120,\n  \"fw_checksum\": \"9af6211b58966ae9728fcfe8cb13fb68b5ceebf24472adb77c0b0d8a2eadbc4b\",\n  \"fw_checksum_algorithm\": \"SHA256\"\n}\n```\n\nTelemetry and attribute keys produced by the device\n\n- The device publishes these client attributes on MQTT connect: `current_fw_title`, `current_fw_version`.\n- The device publishes telemetry states during OTA: `fw_state` values include `DOWNLOADING`, `DOWNLOADED`, `VERIFIED`, `UPDATED`, and `FAILED`. When failed the device publishes `fw_error` (for example `checksum_mismatch` or `empty_download`).\n\nDiagnostics\n\n- The OTA code includes extra diagnostics for ThingsBoard downloads: it logs HTTP status, content-length, total bytes downloaded, and a small hex preview of the first bytes of the payload. These logs help determine if ThingsBoard returned an empty response, JSON wrapper, redirect, or the expected raw firmware.\n\nSecurity notes and behavior\n\n- Before attempting TLS connections the device ensures the system time is sane (SNTP) to avoid certificate validation failures.\n- The device prefers a runtime CA PEM loaded from the data partition (see CA PEM section below), but will fall back to the global CA store when no filesystem PEM is present.\n\nGitHub-hosted OTA\n\n- If you host a firmware binary on GitHub (release asset or raw file), provide a stable HTTPS `fw_url` pointing to the asset or a CDN-backed URL. The device will call `esp_https_ota()` to download and apply the image.\n- Ensure the device trusts the host certificate chain (GitHub's CA chain is typically trusted by default, but if you use a custom host or CDN you must include the root certificate in the `ca_root.pem`).\n\nImplementation notes\n\n- On success the device persists `version` and `title` in NVS (namespace `ota`) and sets `confirmed=0`. On boot it publishes attributes and sends one confirmation telemetry which sets `confirmed=1`.\n- The device will compare incoming OTA metadata against the persisted NVS `version` and will skip OTA if the device already reports the same version (this prevents reapplying the same firmware repeatedly when ThingsBoard and the device attribute sync are out of sync).\n\n## Example filesystem contents (from this repo)\n\nThe repository already contains a `filesystem/` folder with example files. To mirror that structure to your device data partition, place the same files at the root of the FAT partition.\n\nSuggested minimal set for a production device:\n\n- `wifi.txt` (two lines)\n- `mqtt.txt` (one line with access token)\n- `ca_root.pem` (if your broker or update server uses a CA not present in the default bundle)\n\n## How to prepare the FAT image and flash it (overview)\n\nThe firmware mounts the partition with the ESP-IDF wear-levelling FAT helper, so the partition must already contain a valid FAT filesystem with the files in its root.\n\nThere are multiple ways to create and flash the data partition image. The exact partition offset depends on your `partitions.csv`. The project `partitions.csv` currently defines a `storage` partition that the firmware mounts. Use the partition table and `parttool.py` / `idf.py` to find the flash offset for the `storage` partition.\n\nLinux / WSL example (recommended):\n\n1. Create a FAT image from the `filesystem/` folder (1MiB example size):\n\n```bash\n# from the repo root\nfallocate -l 1M build/fs_image.img\nmkfs.vfat build/fs_image.img\n# copy files from `filesystem/` into the image using mtools (mcopy)\n# install mtools if needed: sudo apt install mtools\nmcopy -i build/fs_image.img -s filesystem/* ::\n```\n\n2. Write the image to the storage partition on the ESP32 flash (replace OFFSET with the partition offset found using idf.py or partition tool):\n\n```bash\n# WARNING: the offset must match the `storage` partition offset in your partition table\nesptool.py --chip esp32c3 write_flash OFFSET build/fs_image.img\n```\n\nWindows (PowerShell) options:\n\n- Use WSL and follow the Linux instructions above (recommended).\n- Or use a tool that can create FAT images and write them to flash. Many users find WSL simpler.\n\nImportant notes:\n\n- The partition offset / address is driven by your `partitions.csv`; do not guess it. Use `idf.py partition-table` or the `parttool.py` script from ESP-IDF to query the partition addresses:\n\n```bash\n# print partition table addresses\npython $IDF_PATH/components/partition_table/parttool.py -q partition-table.csv\n```\n\n## Troubleshooting\n\n- If the device fails to connect to Wi‑Fi, check `wifi.txt` line endings and ensure the SSID/password are correct. The `persistence_read_config` helper strips CR/LF, but file corruption or binary data may break parsing.\n- If TLS connections fail, ensure `ca_root.pem` is present (if your server uses a non-public CA) or rely on the built-in certificate bundle (ESP-IDF) if your endpoints use widely trusted CAs.\n- If MQTT doesn't start, verify `mqtt.txt` contains the correct access token (no extra whitespace lines).\n\n- If you format the partition on-device the bootloader or firmware must support formatting; this project currently mounts the FAT partition with `format_if_mount_failed = false`, so the partition must be pre-populated.\n\nOTA-specific troubleshooting\n\n- If ThingsBoard OTA fails with a checksum mismatch, check the `fw_checksum` value you provided in ThingsBoard (it must be the SHA256 hex digest of the binary that the device will download).\n- If ThingsBoard downloads return empty or a small JSON error/redirect, the OTA diagnostics log will show the HTTP status and the first bytes (hex) of the response. That usually indicates an authentication or URL issue (check the token, or if using a package-id endpoint ensure Bearer auth is used).\n- If TLS verification fails for ThingsBoard but other HTTPS (telegram) succeeds, verify the runtime `ca_root.pem` includes the correct root/intermediate certificates for the ThingsBoard host. The included CA PEM used during testing contains both ThingsBoard (demo.thingsboard.io) and Telegram (api.telegram.org) roots so the device can reach both services.\n\n## Example sample files\n\nwifi.txt\n\n```text\nMySSID\nMyPassword123\n```\n\nmqtt.txt\n\n```text\nMY_DEVICE_ACCESS_TOKEN\n```\n\ntele.txt\n\n```text\n123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11\n987654321\n0\n```\n\n`ca_root.pem`\n\n- Add your CA certificate(s) in PEM format. This file may contain multiple `-----BEGIN CERTIFICATE-----` blocks.\n\n## License\n\nThis project is licensed under the Apache 2.0 License. See the [LICENSE](./LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonidasdev%2Fesp32-light-distance-mqtt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fleonidasdev%2Fesp32-light-distance-mqtt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fleonidasdev%2Fesp32-light-distance-mqtt/lists"}