diff --git a/README.md b/README.md index ee3b8573..16dc1889 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ For flashing guidance, including when to use `.bin` vs `-merged.bin`, see: The custom firmware flasher site is: -- +- ## Install uv diff --git a/docs/releases.md b/docs/releases.md index 331dc265..e041d537 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -46,15 +46,69 @@ Practical rule: ## Recommended Flasher -For custom firmware files, use: +The recommended flasher is: -- +- + +It includes native support for: + +- `companion_radio_wifi` firmware +- `repeater_mqtt` firmware +- custom firmware files Recommended usage: - use the normal `.bin` there when you are updating an existing device - use the `-merged.bin` there after an erase when you want a clean flash +## Beginner Setup + +If this is your first time flashing EastMesh firmware, the easiest path is: + +1. Open . +2. Select the firmware type you want: + - `Companion WiFi` + - `Repeater MQTT` + - or `Custom` +3. Flash the correct firmware for your board. +4. Use the built-in setup tools in the flasher site to finish first-time configuration. + +The flasher site includes two especially useful actions after flashing: + +- `Repeater Setup` +- `Console` + +### Repeater Setup + +`Repeater Setup` is the guided first-time repeater flow. + +It is the traditional way to configure a repeater after flashing, including: + +- device name +- latitude and longitude +- admin and guest passwords +- radio settings, including preset selection +- advert interval +- flood advert interval +- flood max +- some advanced repeater settings + +As of `v1.2.1`, the local repeater web panel also includes the same common repeater settings, so many users can continue day-to-day configuration there after initial setup. + +### Console + +`Console` is the raw CLI interface. + +It is especially useful, and often required, for the initial Wi-Fi setup on both firmware tracks: + +- `set wifi.ssid ` +- `set wifi.pwd ` + +This applies to: + +- `companion_radio_wifi` +- `repeater_mqtt` + ## Repeater MQTT Notes `repeater_mqtt` builds include the EastMesh MQTT additions. Depending on the board, they may also include the local web panel. diff --git a/examples/simple_repeater/MyMesh.cpp b/examples/simple_repeater/MyMesh.cpp index da232be3..4e4ef4e7 100644 --- a/examples/simple_repeater/MyMesh.cpp +++ b/examples/simple_repeater/MyMesh.cpp @@ -1483,9 +1483,14 @@ void MyMesh::runWebCommand(const char* command, char* reply, size_t reply_size) matches_exact("get name") || matches_exact("get lat") || matches_exact("get lon") || + matches_exact("get radio") || + matches_exact("get prv.key") || + matches_exact("get role") || + matches_exact("get public.key") || matches_exact("get advert.interval") || matches_exact("get flood.advert.interval") || matches_exact("get flood.max") || + matches_exact("get path.hash.mode") || matches_exact("get owner.info") || matches_exact("get guest.password") || matches_prefix("set wifi.ssid ") || @@ -1509,11 +1514,16 @@ void MyMesh::runWebCommand(const char* command, char* reply, size_t reply_size) matches_prefix("set name ") || matches_prefix("set lat ") || matches_prefix("set lon ") || + matches_prefix("set radio ") || + matches_prefix("password ") || matches_prefix("set guest.password ") || matches_prefix("set prv.key ") || matches_prefix("set advert.interval ") || matches_prefix("set flood.advert.interval ") || matches_prefix("set flood.max ") || + matches_prefix("set path.hash.mode ") || + matches_prefix("time ") || + matches_prefix("time.force ") || matches_prefix("set owner.info "); if (!allowed) { diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index 37204b84..8010b823 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -249,6 +249,12 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch uint32_t now = getRTCClock()->getCurrentTime(); DateTime dt = DateTime(now); sprintf(reply, "%02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year()); + } else if (memcmp(command, "time.force ", 11) == 0) { // force set time (to epoch seconds) + uint32_t secs = _atoi(&command[11]); + getRTCClock()->setCurrentTime(secs); + uint32_t now = getRTCClock()->getCurrentTime(); + DateTime dt = DateTime(now); + sprintf(reply, "OK - clock force-set: %02d:%02d - %d/%d/%d UTC", dt.hour(), dt.minute(), dt.day(), dt.month(), dt.year()); } else if (memcmp(command, "time ", 5) == 0) { // set time (to epoch seconds) uint32_t secs = _atoi(&command[5]); uint32_t curr = getRTCClock()->getCurrentTime(); diff --git a/src/helpers/web/WebPanelServer.cpp b/src/helpers/web/WebPanelServer.cpp index 90dfc68e..1ccfef35 100644 --- a/src/helpers/web/WebPanelServer.cpp +++ b/src/helpers/web/WebPanelServer.cpp @@ -194,7 +194,7 @@ const char kWebPanelLoginHtml[] PROGMEM = R"HTML(

Repeater Config

-

Use the repeater admin password to unlock the panel. Accept the self-signed certificate warning in your browser first.

+

Use the repeater admin password to unlock the panel.

@@ -296,6 +296,8 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( button.action-dreamy:hover { background:linear-gradient(135deg,#5c89d4,#9a8cff); } .stack { display:grid; gap:12px; } .field-card { display:grid; gap:10px; } + .section-group { background:var(--surface2); border:1px solid var(--border); border-radius:12px; padding:14px; display:grid; gap:12px; } + .section-group h3 { margin:0; font-size:13px; color:var(--text-muted); text-transform:uppercase; letter-spacing:.08em; } .inline-actions { display:grid; grid-template-columns:minmax(0,1fr) auto auto; gap:8px; align-items:center; } .label { font-size:12px; color:var(--text-muted); margin-bottom:6px; display:block; } .fieldline { display:grid; grid-template-columns:1fr auto; gap:8px; align-items:center; } @@ -332,6 +334,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML( .visually-hidden { position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; } .panel-warning { min-height:1.4em; font-size:13px; color:var(--status-red); } .panel-note { font-size:13px; color:var(--text-muted); } + .panel-status { min-height:1.4em; font-size:13px; color:var(--text-muted); } .themebtn { padding:10px 14px; } #status { white-space:pre-wrap; color:var(--text-muted); min-height:1.4em; } .terminal { background:var(--terminal-bg); border:1px solid var(--terminal-border); border-radius:12px; padding:14px; min-height:180px; max-height:320px; overflow:auto; font-family:inherit; font-size:14px; line-height:1.45; } @@ -399,7 +402,7 @@ const char kWebPanelAppHtml[] PROGMEM = R"HTML(
+ +