From ce9b819b1804561b574c9aba644a946d308fb5da Mon Sep 17 00:00:00 2001 From: Jonas Hahn Date: Sat, 20 Dec 2025 20:39:35 +0100 Subject: [PATCH] Better makefile, plotting, saving the data, and cleanup --- .gitignore | 1 + Makefile | 11 +++++++++ main.go | 47 ++++++++++++++++++++++++++++++++++++- main/station_example_main.c | 37 ++++------------------------- plot.py | 31 ++++++++++++++++++++++++ pytest_wifi_station.py | 43 --------------------------------- shell.nix | 10 ++++++++ 7 files changed, 103 insertions(+), 77 deletions(-) create mode 100644 plot.py delete mode 100755 pytest_wifi_station.py create mode 100644 shell.nix diff --git a/.gitignore b/.gitignore index 0c25d4f..5704eda 100755 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/ .cache/ sdkconfig* +data/ diff --git a/Makefile b/Makefile index 3293c42..46c6075 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,17 @@ +help: + # plot - Plot the latest measurement + # monitor - Build and monitor onto esp if connected to /dev/ttyUSB0 + # env - Start the esp environment on nix + # server - Start the go server + monitor: idf.py -p /dev/ttyUSB0 flash monitor + env: nix --experimental-features 'nix-command flakes' develop github:mirrexagon/nixpkgs-esp-dev#esp32-idf + +plot: + nix-shell --pure --run "python plot.py" + server: go run main.go diff --git a/main.go b/main.go index 34dead5..0177447 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,39 @@ package main import ( + "encoding/json" "fmt" "io" "log" "net/http" + "os" + "path/filepath" + "time" ) +var dataFile *os.File + +type VoltageData struct { + Voltage float64 `json:"voltage"` +} + +func initDataFile() { + // Ensure the data/ directory exists + if err := os.MkdirAll("data", os.ModePerm); err != nil { + log.Fatalf("Failed to create data directory: %v", err) + } + + // Generate a filename with timestamp + filename := filepath.Join("data", fmt.Sprintf("voltages_%s.txt", time.Now().Format("20060102_150405"))) + file, err := os.OpenFile(filename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) + if err != nil { + log.Fatalf("Failed to open data file: %v", err) + } + + dataFile = file + log.Printf("Logging voltage data to %s\n", filename) +} + func handler(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "POST only", http.StatusMethodNotAllowed) @@ -20,13 +47,31 @@ func handler(w http.ResponseWriter, r *http.Request) { } defer r.Body.Close() - fmt.Println("Received:", string(body)) + // Parse JSON + var v VoltageData + if err := json.Unmarshal(body, &v); err != nil { + http.Error(w, "invalid JSON", http.StatusBadRequest) + return + } + + // Print voltage to console + fmt.Println("Received voltage:", v.Voltage) + + // Append voltage number to file + if dataFile != nil { + if _, err := dataFile.WriteString(fmt.Sprintf("%f\n", v.Voltage)); err != nil { + log.Printf("Failed to write to file: %v", err) + } + } w.WriteHeader(http.StatusOK) w.Write([]byte("ok")) } func main() { + initDataFile() + defer dataFile.Close() + http.HandleFunc("/data", handler) addr := ":8080" diff --git a/main/station_example_main.c b/main/station_example_main.c index 4095c8a..39e72ec 100755 --- a/main/station_example_main.c +++ b/main/station_example_main.c @@ -1,6 +1,6 @@ /* Voltage measurement device over wifi from WiFi station Example - */ +*/ #include @@ -33,42 +33,13 @@ // TODO: Determine this #define CALIBRATION_FACTOR 1650.0f -/* The examples use WiFi configuration that you can set via project configuration menu - - If you'd rather not, just change the below entries to strings with - the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid" -*/ -#define EXAMPLE_ESP_WIFI_SSID CONFIG_ESP_WIFI_SSID +// Settings for wifi +#define EXAMPLE_ESP_WIFI_SSID "Jaguar" #define EXAMPLE_ESP_WIFI_PASS CONFIG_ESP_WIFI_PASSWORD -#define EXAMPLE_ESP_MAXIMUM_RETRY CONFIG_ESP_MAXIMUM_RETRY -#if CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HUNT_AND_PECK -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HUNT_AND_PECK -#define EXAMPLE_H2E_IDENTIFIER "" -#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_HASH_TO_ELEMENT -#define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_HASH_TO_ELEMENT -#define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID -#elif CONFIG_ESP_STATION_EXAMPLE_WPA3_SAE_PWE_BOTH #define ESP_WIFI_SAE_MODE WPA3_SAE_PWE_BOTH #define EXAMPLE_H2E_IDENTIFIER CONFIG_ESP_WIFI_PW_ID -#endif -#if CONFIG_ESP_WIFI_AUTH_OPEN -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_OPEN -#elif CONFIG_ESP_WIFI_AUTH_WEP -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WEP -#elif CONFIG_ESP_WIFI_AUTH_WPA_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA2_PSK #define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA_WPA2_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA_WPA2_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA3_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA3_PSK -#elif CONFIG_ESP_WIFI_AUTH_WPA2_WPA3_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WPA2_WPA3_PSK -#elif CONFIG_ESP_WIFI_AUTH_WAPI_PSK -#define ESP_WIFI_SCAN_AUTH_MODE_THRESHOLD WIFI_AUTH_WAPI_PSK -#endif // Tag for logging static const char *TAG = "VoltageSensor"; @@ -93,7 +64,7 @@ static void event_handler(void* arg, esp_event_base_t event_base, if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { - if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) { + if (s_retry_num < 3) { esp_wifi_connect(); s_retry_num++; ESP_LOGI(TAG, "retry to connect to the AP"); diff --git a/plot.py b/plot.py new file mode 100644 index 0000000..1073ae0 --- /dev/null +++ b/plot.py @@ -0,0 +1,31 @@ +import os +import matplotlib.pyplot as plt +import numpy as np + +DATA_DIR = "data" +SAMPLE_INTERVAL_MS = 300 # time between measurements in milliseconds + +# Find the latest data file +files = [f for f in os.listdir(DATA_DIR) if f.startswith("voltages_") and f.endswith(".txt")] +if not files: + raise FileNotFoundError("No voltage data files found in 'data/'") + +latest_file = max(files, key=lambda f: os.path.getmtime(os.path.join(DATA_DIR, f))) +filepath = os.path.join(DATA_DIR, latest_file) +print(f"Plotting data from {filepath}") + +# Load voltage values +voltages = np.loadtxt(filepath) + +# Create time axis (in seconds) +times = np.arange(len(voltages)) * (SAMPLE_INTERVAL_MS / 1000.0) + +# Plot +plt.figure(figsize=(10, 5)) +plt.plot(times, voltages, marker='o', linestyle='-') +plt.xlabel("Time (s)") +plt.ylabel("Voltage (V)") +plt.title(f"Voltage Measurements ({latest_file})") +plt.grid(True) +plt.tight_layout() +plt.show() diff --git a/pytest_wifi_station.py b/pytest_wifi_station.py deleted file mode 100755 index 5a93da1..0000000 --- a/pytest_wifi_station.py +++ /dev/null @@ -1,43 +0,0 @@ -# SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD -# SPDX-License-Identifier: Unlicense OR CC0-1.0 -import os -from typing import Callable -from typing import Tuple - -import pytest -from pytest_embedded import Dut -from pytest_embedded_idf.utils import idf_parametrize -# diff of esp32s2/esp32s3 ~45K, others ~50K - -DIFF_THRESHOLD = { - 'esp32s2': 40 * 1000, - 'esp32s3': 40 * 1000, - 'default': 45 * 1000, -} - - -@pytest.mark.wifi_two_dut -@pytest.mark.parametrize('count, config, skip_autoflash', [(2, 'default|enable_softap', 'y')], indirect=True) -@idf_parametrize( - 'target', - ['esp32', 'esp32c2', 'esp32c3', 'esp32s2', 'esp32s3', 'esp32c5', 'esp32c6', 'esp32c61'], - indirect=['target'], -) -def test_wifi_sdkconfig_disable_softap_save_binary_size( - dut: Tuple[Dut, Dut], - log_performance: Callable[[str, object], None], -) -> None: - # dut logs are not needed - dut[0].serial.close() - dut[1].serial.close() - - app_without_softap = dut[0].app - app_with_softap = dut[1].app - assert app_without_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is False - assert app_with_softap.sdkconfig['ESP_WIFI_SOFTAP_SUPPORT'] is True - - diff = os.path.getsize(app_with_softap.bin_file) - os.path.getsize(app_without_softap.bin_file) - log_performance('wifi_disable_softap_save_bin_size', f'{diff} bytes') - - diff_threshold = DIFF_THRESHOLD.get(dut[0].target) or DIFF_THRESHOLD['default'] - assert diff > diff_threshold diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..ed83d5f --- /dev/null +++ b/shell.nix @@ -0,0 +1,10 @@ +{ pkgs ? import {} }: + +pkgs.mkShell { + buildInputs = with pkgs; [ + (pkgs.python313.withPackages (p: with p; [ + matplotlib + numpy + ])) + ]; +}