Skip to content

Latest commit

 

History

History
422 lines (310 loc) · 8.46 KB

File metadata and controls

422 lines (310 loc) · 8.46 KB

Coding Guidelines für ESP32 PlatformIO Projekte

Übersicht

Dieses Dokument beschreibt die Coding-Richtlinien für das Pool-Controller Projekt, um Super-Linter Fehler zu vermeiden und Best Practices für ESP32 Entwicklung mit PlatformIO zu befolgen.

1. C++ Code-Formatierung (clang-format)

1.1 Grundlegende Regeln

  • Zeilenlänge: Maximal 130 Zeichen (definiert in .clang-format)
  • Einrückung: 2 Leerzeichen (keine Tabs)
  • Klammern: K&R-Stil (öffnende Klammer auf derselben Zeile)
  • Pointer-Ausrichtung: Links (int* ptr statt int *ptr)

1.2 Wichtige clang-format Anforderungen

Leerzeichen zwischen Code und Kommentaren

// FALSCH
int x = 5;// Kommentar

// RICHTIG
int x = 5;  // Kommentar (mindestens 2 Leerzeichen)

Leerzeichen bei Kontrollstrukturen

// FALSCH
if(condition){
    doSomething();
}

// RICHTIG
if (condition) {
    doSomething();
}

Namespaces-Formatierung

// FALSCH
namespace PoolController
{
    namespace Detail {
        // code
    }
}

// RICHTIG
namespace PoolController {
    namespace Detail {
        // code
    }
}

Initialisierung mit geschweiften Klammern

// FALSCH
static Context context { };

// RICHTIG
static Context context{};

Pointer und NULL

// FALSCH
TimeChangeRule *tcr = NULL;

// RICHTIG
TimeChangeRule* tcr = nullptr;

Alignment von Variablen

// FALSCH
const char* cTimezone     = "timezone";
const char* cTimezoneName = "Timezone";

// RICHTIG (clang-format richtet automatisch aus)
const char* cTimezone     = "timezone";
const char* cTimezoneName = "Timezone";
// Aber achte darauf, dass AlignConsecutiveDeclarations aktiviert ist

1.3 Automatische Formatierung

Führe vor jedem Commit aus:

# Alle C++ Dateien formatieren
clang-format -i src/**/*.cpp src/**/*.hpp

# Oder einzelne Datei
clang-format -i src/PoolController.cpp

# Prüfen ohne Änderungen
clang-format --dry-run --Werror src/**/*.cpp

2. C++ Stil-Richtlinien (cpplint)

2.1 Zeilenlänge

  • Maximal 80 Zeichen für cpplint (strenger als clang-format)
  • Lange Kommentare über mehrere Zeilen aufteilen

2.2 Datentypen

// FALSCH
unsigned long timestamp;
long value;

// RICHTIG
uint32_t timestamp;  // Feste Breite, plattformunabhängig
int32_t value;

2.3 Inklude-Guards

// Verwende #pragma once statt Include-Guards
#pragma once

// Oder klassische Guards
#ifndef POOL_CONTROLLER_MODULE_HPP
#define POOL_CONTROLLER_MODULE_HPP
// ...
#endif  // POOL_CONTROLLER_MODULE_HPP

3. EditorConfig Konformität

3.1 Grundeinstellungen (.editorconfig)

  • Einrückung: 2 Leerzeichen für alle Dateien
  • Keine Tabs: Immer Leerzeichen verwenden
  • Trailing Whitespace: Entfernen
  • Final Newline: Immer einfügen
  • Charset: UTF-8

3.2 Spezifische Datei-Formate

YAML-Dateien (.github/workflows/*.yml)

# Immer doppelte Anführungszeichen
name: "Workflow Name"

# Lange Zeilen mit | oder > aufteilen
run: >
  command with many
  arguments

Markdown-Dateien

  • "Wi-Fi" (not "Wi-Fi" - note the hyphen)
  • URLs in spitze Klammern: <https://example.com>

INI-Dateien (platformio.ini)

# 2 Leerzeichen für Einrückung
[env:esp32dev]
lib_deps =
  me-no-dev/Homie@^3.0.0
  https://github.com/me-no-dev/ESPAsyncWebServer.git

4. ESP32 Spezifische Best Practices

4.1 Speicherverwaltung

// Vermeide große Stack-Allocations
char buffer[1024];  // Könnte Stack Overflow verursachen

// Besser: Heap-Allocation oder kleinere Puffer
String buffer;
buffer.reserve(1024);

4.2 String-Behandlung

// FALSCH - Fragmentiert Heap
String result = "";
for (int i = 0; i < 100; i++) {
    result += String(i);
}

// RICHTIG - Reserve Speicher im Voraus
String result;
result.reserve(300);  // Schätze benötigten Platz
for (int i = 0; i < 100; i++) {
    result += String(i);
}

4.3 Async Operations

// Nutze yield() in langen Schleifen
for (int i = 0; i < 10000; i++) {
    // Arbeit
    if (i % 100 == 0) {
        yield();  // Gibt ESP Zeit für WiFi/System-Tasks
    }
}

4.4 Wi-Fi und Netzwerk

// Prüfe Verbindungsstatus
if (WiFi.status() == WL_CONNECTED) {
    // Netzwerk-Operation
}

// Verwende WiFi.isConnected() für ESP32
if (WiFi.isConnected()) {
    // Netzwerk-Operation
}

5. PlatformIO Best Practices

5.1 Library-Verwaltung

ESPAsyncWebServer

# FALSCH - Package-Name mit Leerzeichen
lib_deps = me-no-dev/ESP Async WebServer @ 1.2.3

# RICHTIG - GitHub URL verwenden
lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git

Duplikate vermeiden

# lib_ignore verwenden, um Konflikte zu vermeiden
[env:esp32dev]
lib_ignore = ESP Async WebServer  # Ignoriert Space-Variante
lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git

Plattform-spezifische Dependencies

# ESP32 verwendet AsyncTCP (ohne "ESP" Präfix)
# ESPAsyncWebServer bringt diese automatisch mit!

5.2 Build-Flags

# Debug-Informationen
build_flags =
  -DDEBUG_ESP_PORT=Serial
  -DDEBUG_ESP_CORE

# Release-Optimierung
build_flags =
  -Os  # Optimiere für Größe

5.3 Monitor-Einstellungen

monitor_speed = 115200
monitor_filters = esp32_exception_decoder  # Für ESP32

6. Git Workflow

6.1 Pre-Commit Checks

# Vor jedem Commit ausführen:

# 1. Formatiere C++ Code
clang-format -i src/**/*.cpp src/**/*.hpp

# 2. Prüfe EditorConfig
# (wird automatisch von Super-Linter gemacht)

# 3. Teste lokale Compilation
pio run -e esp32dev

6.2 Commit Messages

# Format: <type>: <subject>

fix: Correct clang-format violations in PoolController.cpp
feat: Add NTP server configuration support
docs: Update coding guidelines
refactor: Improve memory usage in Timer class

7. Super-Linter Konfiguration

7.1 Aktivierte Linter

  • EditorConfig: Datei-Formatierung
  • YAML: GitHub Actions Workflows
  • Markdown: Dokumentation
  • CPP: C++ Code (clang-format)

7.2 Deaktivierte Linter

  • CHECKOV: Zu viele False Positives (manuell validiert)

7.3 Lokale MegaLinter Ausführung

# Via mega-linter-runner (empfohlen)
npx mega-linter-runner --flavor c_cpp --remove-container

# Oder via Docker direkt (c_cpp flavor)
docker run --rm -v $(pwd):/tmp/lint:rw \
  -e MEGALINTER_CONFIG=.mega-linter.yml \
  ghcr.io/oxsecurity/megalinter-c_cpp:v9

# Oder via Docker (vollständiges Image)
docker run --rm -v $(pwd):/tmp/lint:rw \
  -e MEGALINTER_CONFIG=.mega-linter.yml \
  ghcr.io/oxsecurity/megalinter:v9

8. Häufige Fehler und Lösungen

8.1 "Wrong indent style found (tabs instead of spaces)"

# Tabs durch Leerzeichen ersetzen
find src -name "*.cpp" -o -name "*.hpp" | xargs sed -i 's/\t/  /g'

8.2 "Trailing whitespace"

# Entferne trailing whitespace
find . -name "*.cpp" -o -name "*.hpp" | xargs sed -i 's/[[:space:]]*$//'

8.3 "Line too long"

// Lange Zeilen umbrechen
// VORHER
static const char* veryLongVariableName = "This is a very long string that exceeds the line limit";

// NACHHER
static const char* veryLongVariableName =
    "This is a very long string that exceeds the line limit";

8.4 "clang-format-violations"

# Automatisch beheben
clang-format -i <file>

9. IDE-Integration

9.1 Visual Studio Code

// .vscode/settings.json
{
  "editor.formatOnSave": true,
  "editor.insertSpaces": true,
  "editor.tabSize": 2,
  "C_Cpp.clang_format_style": "file",
  "C_Cpp.clang_format_fallbackStyle": "LLVM",
  "files.insertFinalNewline": true,
  "files.trimTrailingWhitespace": true
}

9.2 Extensions

  • C/C++ (Microsoft)
  • PlatformIO IDE
  • EditorConfig for Visual Studio Code
  • Prettier (für YAML/Markdown)

10. Checkliste vor PR

  • Alle C++ Dateien mit clang-format formatiert
  • Keine Tabs, nur Leerzeichen (2 Spaces)
  • Kein trailing whitespace
  • Zeilenlänge beachtet (80 für cpplint, 130 für clang-format)
  • Fixed-width Typen verwendet (uint32_t statt unsigned long)
  • Alle Tests laufen erfolgreich
  • PlatformIO builds erfolgreich (beide Plattformen)
  • Super-Linter CI läuft erfolgreich durch

Referenzen