From 8228681f57cacd6db2ccccebcf5e2876bb0415f9 Mon Sep 17 00:00:00 2001 From: Thies Mueller Date: Wed, 10 Jun 2026 14:20:15 +0200 Subject: [PATCH] initial commit --- .gitignore | 2 + README.MD | 9 ++++ esp32/pager.ino.example | 108 ++++++++++++++++++++++++++++++++++++++++ esp32/signals.h | 7 +++ generate.py | 50 +++++++++++++++++++ 5 files changed, 176 insertions(+) create mode 100644 .gitignore create mode 100644 README.MD create mode 100644 esp32/pager.ino.example create mode 100644 esp32/signals.h create mode 100644 generate.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8aea876 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +esp32/pager.ino +esp32/signals.h \ No newline at end of file diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..c17f600 --- /dev/null +++ b/README.MD @@ -0,0 +1,9 @@ +ESP32 Remote Pager +=== + +Subs sind für "SWTGTEM" Pager + +Station ID ist `531` + +Pager IDs sind `101` - `116` & `201` - `216` + diff --git a/esp32/pager.ino.example b/esp32/pager.ino.example new file mode 100644 index 0000000..8ede592 --- /dev/null +++ b/esp32/pager.ino.example @@ -0,0 +1,108 @@ +#include +#include +#include "driver/rmt.h" +#include "signals.h" + +#define TX_PIN 17 +#define EN_PIN 16 +#define RMT_CHANNEL RMT_CHANNEL_0 +#define CLK_DIV 80 + +const char* ssid = "RegattaTech.DE"; +const char* password = ""; + +WebServer server(80); + +rmt_item32_t items[64]; + +void setupRMT() { + rmt_config_t config = {}; + config.rmt_mode = RMT_MODE_TX; + config.channel = RMT_CHANNEL; + config.gpio_num = (gpio_num_t)TX_PIN; + config.clk_div = CLK_DIV; + config.mem_block_num = 1; + config.tx_config.loop_en = false; + config.tx_config.carrier_en = false; + config.tx_config.idle_level = RMT_IDLE_LEVEL_LOW; + config.tx_config.idle_output_en = true; + + rmt_config(&config); + rmt_driver_install(RMT_CHANNEL, 0, 0); +} + +void sendSignal(const int* rawSignal, int RAW_LEN) { + digitalWrite(EN_PIN, HIGH); + delayMicroseconds(300); + + int idx = 0; + + while (idx < RAW_LEN - 1) { + int itemCount = 0; + + while (itemCount < 64 && idx < RAW_LEN - 1) { + items[itemCount].level0 = rawSignal[idx] > 0 ? 1 : 0; + items[itemCount].duration0 = abs(rawSignal[idx]); + + items[itemCount].level1 = rawSignal[idx+1] > 0 ? 1 : 0; + items[itemCount].duration1 = abs(rawSignal[idx+1]); + + idx += 2; + itemCount++; + } + + rmt_write_items(RMT_CHANNEL, items, itemCount, true); + rmt_wait_tx_done(RMT_CHANNEL, portMAX_DELAY); + } + + digitalWrite(EN_PIN, LOW); +} + +void handleCall() { + String uri = server.uri(); // /call/P101 + String name = uri.substring(6); + + for (int i = 0; i < SIGNAL_COUNT; i++) { + if (name.equals(signals[i].name)) { + sendSignal(signals[i].data, signals[i].len); + server.send(200, "text/plain", "OK"); + return; + } + } + + server.send(404, "text/plain", "Not found"); +} + +void setup() { + Serial.begin(115200); + + pinMode(EN_PIN, OUTPUT); + digitalWrite(EN_PIN, LOW); + + setupRMT(); + + WiFi.begin(ssid, password); + Serial.print("Connecting WiFi"); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println("\nConnected!"); + Serial.println(WiFi.localIP()); + + server.onNotFound([](){ + if (server.uri().startsWith("/call/")) { + handleCall(); + } else { + server.send(404, "text/plain", "Invalid endpoint"); + } + }); + + server.begin(); +} + +void loop() { + server.handleClient(); +} diff --git a/esp32/signals.h b/esp32/signals.h new file mode 100644 index 0000000..9560945 --- /dev/null +++ b/esp32/signals.h @@ -0,0 +1,7 @@ +#pragma once + +struct SignalDef { const char* name; const int* data; int len; }; + +SignalDef signals[] = { +}; +const int SIGNAL_COUNT = 0; diff --git a/generate.py b/generate.py new file mode 100644 index 0000000..cafa49d --- /dev/null +++ b/generate.py @@ -0,0 +1,50 @@ +import os +import re + +SUB_DIR = "subs" +OUT_FILE = "esp32/signals.h" + +def parse_raw(file_path): + with open(file_path, "r") as f: + content = f.read() + + raw_lines = re.findall(r"RAW_Data:\s*(.*)", content) + values = [] + + for line in raw_lines: + parts = line.strip().split() + for p in parts: + try: + values.append(int(p)) + except: + pass + + return values + + +signals = {} + +for fname in os.listdir(SUB_DIR): + if fname.endswith(".sub"): + key = os.path.splitext(fname)[0] + signals[key] = parse_raw(os.path.join(SUB_DIR, fname)) + +with open(OUT_FILE, "w") as f: + f.write("#pragma once\n\n") + + for name, data in signals.items(): + f.write(f"const int {name}_raw[] = {{\n") + f.write(", ".join(map(str, data))) + f.write("\n};\n") + f.write(f"const int {name}_len = {len(data)};\n\n") + + f.write("struct SignalDef { const char* name; const int* data; int len; };\n\n") + + f.write("SignalDef signals[] = {\n") + for name in signals: + f.write(f' {{"{name}", {name}_raw, {name}_len}},\n') + f.write("};\n") + + f.write(f"const int SIGNAL_COUNT = {len(signals)};\n") + +print("signals.h generated")