multiple buttons
This commit is contained in:
+34
-6
@@ -125,6 +125,9 @@ size_t telnetLineLen[MAX_TELNET] = {0};
|
||||
volatile uint32_t rxBytes = 0; // from target
|
||||
volatile uint32_t txBytes = 0; // to target
|
||||
|
||||
// Button line held active (latched) rather than momentary-pulsed.
|
||||
bool buttonLatched = false;
|
||||
|
||||
// SD logging (T3-S3)
|
||||
bool sdAvailable = false;
|
||||
bool logEnabled = true; // ON by default once we have a date
|
||||
@@ -190,6 +193,17 @@ static void gpioPulse(int pin, uint32_t ms, Stream* reply, const char* name) {
|
||||
if (reply) reply->printf("[ctrl] %s pulsed pin %d for %lu ms\r\n", name, pin, (unsigned long)ms);
|
||||
}
|
||||
|
||||
// Hold a control line active (on) or release it (off) -- a latched "press".
|
||||
static void gpioLatch(int pin, bool on, Stream* reply, const char* name) {
|
||||
if (pin < 0) { if (reply) reply->printf("[ctrl] %s pin not configured\r\n", name); return; }
|
||||
int active = GPIO_CTRL_ACTIVE_LOW ? LOW : HIGH;
|
||||
int inactive = GPIO_CTRL_ACTIVE_LOW ? HIGH : LOW;
|
||||
pinMode(pin, OUTPUT);
|
||||
digitalWrite(pin, on ? active : inactive);
|
||||
if (reply) reply->printf("[ctrl] %s latch=%s (pin %d %s)\r\n",
|
||||
name, on ? "on" : "off", pin, on ? "held" : "released");
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SD logging (T3-S3)
|
||||
// ============================================================================
|
||||
@@ -364,7 +378,7 @@ void handleCommand(const char* line, Stream* reply) {
|
||||
const char* args = line[n] ? line + n + 1 : line + n;
|
||||
|
||||
if (!strcmp(verb, "help")) {
|
||||
reply->print("[help] ~status ~reset [ms] ~button [ms] ~baud <n> "
|
||||
reply->print("[help] ~status ~reset [ms] ~button [ms|on|off] ~baud <n> "
|
||||
"~port <int|usb|ext> ~log on|off ~gpio <pin> <0|1>\r\n"
|
||||
" ~mesh [on|off] ~psk <base64key> ~chan <name> <base64key> ~msg <text>\r\n"
|
||||
" (any non-~ line is sent to the target UART)\r\n");
|
||||
@@ -373,7 +387,9 @@ void handleCommand(const char* line, Stream* reply) {
|
||||
} else if (!strcmp(verb, "reset")) {
|
||||
gpioPulse(GPIO_RESET_PIN, (uint32_t)strtoul(args, nullptr, 10), reply, "reset");
|
||||
} else if (!strcmp(verb, "wake") || !strcmp(verb, "button")) {
|
||||
gpioPulse(GPIO_WAKE_PIN, (uint32_t)strtoul(args, nullptr, 10), reply, "button");
|
||||
if (!strncmp(args, "on", 2)) { gpioLatch(GPIO_WAKE_PIN, true, reply, "button"); buttonLatched = true; }
|
||||
else if (!strncmp(args, "off", 3)) { gpioLatch(GPIO_WAKE_PIN, false, reply, "button"); buttonLatched = false; }
|
||||
else { gpioPulse(GPIO_WAKE_PIN, (uint32_t)strtoul(args, nullptr, 10), reply, "button"); buttonLatched = false; }
|
||||
} else if (!strcmp(verb, "baud")) {
|
||||
uint32_t b = strtoul(args, nullptr, 10);
|
||||
if (b) { setBaudRate(b); reply->printf("[ctrl] baud=%lu\r\n", (unsigned long)b); }
|
||||
@@ -495,6 +511,7 @@ void handleWebSocketMessage(AsyncWebSocketClient* client, uint8_t* data, size_t
|
||||
r["baudSerial1"] = baudSerial1;
|
||||
r["rx"] = rxBytes; r["tx"] = txBytes;
|
||||
r["log"] = logEnabled; r["ntp"] = ntpSynced; r["sd"] = sdAvailable;
|
||||
r["buttonLatch"] = buttonLatched;
|
||||
#if BOARD_T3S3
|
||||
r["logfile"] = logFile ? logPath : "";
|
||||
#endif
|
||||
@@ -539,6 +556,7 @@ static String statusJson() {
|
||||
doc["baudSerial1"] = baudSerial1;
|
||||
doc["rx"] = rxBytes; doc["tx"] = txBytes;
|
||||
doc["log"] = logEnabled; doc["ntp"] = ntpSynced; doc["sd"] = sdAvailable;
|
||||
doc["buttonLatch"] = buttonLatched;
|
||||
#if BOARD_T3S3
|
||||
doc["logfile"] = logFile ? logPath : "";
|
||||
#endif
|
||||
@@ -563,13 +581,23 @@ void setupWebServer() {
|
||||
gpioPulse(GPIO_RESET_PIN, ms, nullptr, "reset");
|
||||
req->send(200, "text/plain", "reset pulsed\n");
|
||||
});
|
||||
auto pulseButton = [](AsyncWebServerRequest* req) {
|
||||
// Momentary pulse (?ms=), or latch the line held (?latch=on|off|1|0).
|
||||
auto doButton = [](AsyncWebServerRequest* req) {
|
||||
if (req->hasParam("latch")) {
|
||||
String v = req->getParam("latch")->value();
|
||||
bool on = (v == "1" || v.startsWith("on") || v == "true");
|
||||
gpioLatch(GPIO_WAKE_PIN, on, nullptr, "button");
|
||||
buttonLatched = on;
|
||||
req->send(200, "application/json", statusJson());
|
||||
return;
|
||||
}
|
||||
uint32_t ms = req->hasParam("ms") ? req->getParam("ms")->value().toInt() : 0;
|
||||
gpioPulse(GPIO_WAKE_PIN, ms, nullptr, "button");
|
||||
req->send(200, "text/plain", "button pulsed\n");
|
||||
buttonLatched = false;
|
||||
req->send(200, "application/json", statusJson());
|
||||
};
|
||||
server.on("/api/button", HTTP_GET, pulseButton);
|
||||
server.on("/api/wake", HTTP_GET, pulseButton); // back-compat alias
|
||||
server.on("/api/button", HTTP_GET, doButton);
|
||||
server.on("/api/wake", HTTP_GET, doButton); // back-compat alias
|
||||
server.on("/api/baud", HTTP_GET, [](AsyncWebServerRequest* req) {
|
||||
if (req->hasParam("baud")) setBaudRate(req->getParam("baud")->value().toInt());
|
||||
req->send(200, "application/json", statusJson());
|
||||
|
||||
Reference in New Issue
Block a user