Update firmware-encry

This commit is contained in:
Timo 2025-05-02 13:26:16 +02:00 committed by GitHub
parent cd80cfd77a
commit bec06107dc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -4,8 +4,6 @@
#include <ArduinoHttpClient.h> #include <ArduinoHttpClient.h>
#include <WiFiUdp.h> #include <WiFiUdp.h>
#include <NTPClient.h> #include <NTPClient.h>
#include <Crypto.h>
#include <AES.h>
// WLAN-Zugangsdaten // WLAN-Zugangsdaten
#define SSID "" #define SSID ""
@ -14,52 +12,12 @@
// API-Konfiguration // API-Konfiguration
#define API_HOST "" #define API_HOST ""
#define API_PORT 8080 #define API_PORT 8080
#define API_ENDPOINT "/sensors/push-data-encrypted" #define API_ENDPOINT "/sensors/push-data/secure"
#define CLIENT_ID "" #define CLIENT_ID ""
#define API_TOKEN "" #define API_TOKEN ""
// AES-Schlüssel (128 Bit) const String ALPHABET = "";
AES128 aes; const String KEY = "";
byte aes_key[] = {
};
// Base64-Zeichen
const char base64_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// Funktionen für Base64-Encoding
String base64Encode(byte* data, int len) {
String out = "";
for (int i = 0; i < len; i += 3) {
int val = (data[i] << 16) + (i + 1 < len ? data[i + 1] << 8 : 0) + (i + 2 < len ? data[i + 2] : 0);
out += base64_chars[(val >> 18) & 0x3F];
out += base64_chars[(val >> 12) & 0x3F];
out += (i + 1 < len) ? base64_chars[(val >> 6) & 0x3F] : '=';
out += (i + 2 < len) ? base64_chars[val & 0x3F] : '=';
}
return out;
}
String padToBlock(String input) {
int pad = 16 - (input.length() % 16);
for (int i = 0; i < pad; i++) input += '\0';
return input;
}
String encryptAndBase64(String plainText) {
String padded = padToBlock(plainText);
int len = padded.length();
byte plain[len];
byte encrypted[len];
padded.getBytes((unsigned char*)plain, len + 1);
aes.setKey(aes_key, sizeof(aes_key));
for (int i = 0; i < len; i += 16) {
aes.encryptBlock(encrypted + i, plain + i);
}
return base64Encode(encrypted, len);
}
// Sensor & Netzwerk // Sensor & Netzwerk
Bsec iaqSensor; Bsec iaqSensor;
@ -74,6 +32,7 @@ NTPClient timeClient(ntpUDP, "pool.ntp.org", utcOffsetInSeconds);
// Sendeintervall // Sendeintervall
unsigned long sendInterval = 30000; unsigned long sendInterval = 30000;
// Fehlercode per LED ausgeben (Morse-artig)
void errorBlink(int code) { void errorBlink(int code) {
while (true) { while (true) {
for (int i = 0; i < code; i++) { for (int i = 0; i < code; i++) {
@ -82,16 +41,18 @@ void errorBlink(int code) {
digitalWrite(LED_BUILTIN, LOW); digitalWrite(LED_BUILTIN, LOW);
delay(150); delay(150);
} }
delay(1000); delay(1000); // Pause zwischen Zyklen
} }
} }
// Werte begrenzen
float clampValue(float val) { float clampValue(float val) {
if (val >= 1000.0) return 999.999; if (val >= 1000.0) return 999.999;
if (val <= -1000.0) return -999.999; if (val <= -1000.0) return -999.999;
return val; return val;
} }
// ISO-Zeitstempel generieren
String getTimestamp() { String getTimestamp() {
timeClient.update(); timeClient.update();
unsigned long epochTime = timeClient.getEpochTime(); unsigned long epochTime = timeClient.getEpochTime();
@ -104,18 +65,24 @@ String getTimestamp() {
if (seconds >= daysInYear * 86400UL) { if (seconds >= daysInYear * 86400UL) {
seconds -= daysInYear * 86400UL; seconds -= daysInYear * 86400UL;
year++; year++;
} else break; } else {
break;
}
} }
int month = 1; int month = 1;
const int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; const int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31};
while (month <= 12) { while (month <= 12) {
int dim = daysInMonth[month - 1]; int dim = daysInMonth[month - 1];
if (month == 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) dim = 29; if (month == 2 && (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0))) {
dim = 29;
}
if (seconds >= dim * 86400UL) { if (seconds >= dim * 86400UL) {
seconds -= dim * 86400UL; seconds -= dim * 86400UL;
month++; month++;
} else break; } else {
break;
}
} }
int day = seconds / 86400UL + 1; int day = seconds / 86400UL + 1;
@ -130,6 +97,7 @@ String getTimestamp() {
return String(buf); return String(buf);
} }
// API-Health-Check
bool checkApiHealth() { bool checkApiHealth() {
HttpClient healthClient = HttpClient(wifi, API_HOST, API_PORT); HttpClient healthClient = HttpClient(wifi, API_HOST, API_PORT);
healthClient.get("/health"); healthClient.get("/health");
@ -138,25 +106,49 @@ bool checkApiHealth() {
return statusCode == 200; return statusCode == 200;
} }
// Funktion zum Substituieren (Verschlüsseln) eines Strings
String substituteString(String input, String alphabet, String key) {
input.toUpperCase();
String output = "";
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
int index = alphabet.indexOf(c);
if (index == -1) { // Zeichen nicht im Alphabet, unverändert belassen (z.B. Leerzeichen?)
output += c;
} else {
output += key.charAt(index);
}
}
return output;
}
void setup() { void setup() {
Serial.begin(9600);
while (!Serial);
Serial.println("Start");
pinMode(LED_BUILTIN, OUTPUT); pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW); digitalWrite(LED_BUILTIN, LOW);
// WLAN verbinden mit Timeout
WiFi.begin(SSID, PASSWORT); WiFi.begin(SSID, PASSWORT);
unsigned long startAttemptTime = millis(); unsigned long startAttemptTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 20000) { while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < 20000) {
delay(500); delay(500);
} }
if (WiFi.status() != WL_CONNECTED) { if (WiFi.status() != WL_CONNECTED) {
errorBlink(1); errorBlink(1); // Fehlercode 1: WLAN-Fehler
} }
// API-Healthcheck
if (!checkApiHealth()) { if (!checkApiHealth()) {
errorBlink(4); errorBlink(4); // Fehlercode 4: API nicht erreichbar
} }
Wire.begin(); Wire.begin();
// Automatische Sensor-Erkennung
byte sensorAddress = 0; byte sensorAddress = 0;
byte possibleAddresses[] = {0x76, 0x77}; byte possibleAddresses[] = {0x76, 0x77};
bool sensorFound = false; bool sensorFound = false;
@ -171,12 +163,12 @@ void setup() {
} }
if (!sensorFound) { if (!sensorFound) {
errorBlink(2); errorBlink(2); // Fehlercode 2: Sensor nicht gefunden
} }
iaqSensor.begin(sensorAddress, Wire); iaqSensor.begin(sensorAddress, Wire);
if (iaqSensor.bsecStatus != BSEC_OK) { if (iaqSensor.bsecStatus != BSEC_OK) {
errorBlink(3); errorBlink(3); // Fehlercode 3: Sensor-Init fehlgeschlagen
} }
bsec_virtual_sensor_t sensorList[] = { bsec_virtual_sensor_t sensorList[] = {
@ -193,53 +185,67 @@ void setup() {
timeClient.forceUpdate(); timeClient.forceUpdate();
} }
digitalWrite(LED_BUILTIN, HIGH); digitalWrite(LED_BUILTIN, HIGH); // Alles bereit LED dauerhaft an
} }
void loop() { void loop() {
if (iaqSensor.run()) { if (iaqSensor.run()) {
// Kurzes LED-Blink zur Messanzeige
digitalWrite(LED_BUILTIN, LOW);
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
float temperature = clampValue(iaqSensor.temperature); float temperature = clampValue(iaqSensor.temperature);
float humidity = clampValue(iaqSensor.humidity); float humidity = clampValue(iaqSensor.humidity);
float voc = clampValue(iaqSensor.iaq); float voc = clampValue(iaqSensor.iaq);
float gas = clampValue(iaqSensor.gasResistance / 1000.0); float gas = clampValue(iaqSensor.gasResistance / 1000.0);
float pressure = iaqSensor.pressure / 100.0; float pressure = iaqSensor.pressure / 100.0;
String timestamp = getTimestamp(); String timestamp = getTimestamp();
String jsonPayload = "{"; // Werte in Strings mit z.B. 3 Dezimalstellen
jsonPayload += "\"timestamp\": \"" + timestamp + "\","; String temperatureStr = String(temperature, 3);
jsonPayload += "\"temperature\": " + String(temperature, 3) + ","; String humidityStr = String(humidity, 3);
jsonPayload += "\"humidity\": " + String(humidity, 3) + ","; String vocStr = String(voc, 3);
jsonPayload += "\"pressure\": " + String(pressure, 3) + ","; String gasStr = String(gas, 3);
jsonPayload += "\"voc\": " + String(voc, 3) + ","; String pressureStr = String(pressure, 3);
jsonPayload += "\"gas\": " + String(gas, 3);
jsonPayload += "}";
String encryptedPayload = encryptAndBase64(jsonPayload); // Alle Strings verschlüsseln (substituieren)
String encryptedTimestamp = substituteString(timestamp, ALPHABET, KEY);
String encryptedTemperature = substituteString(temperatureStr, ALPHABET, KEY);
String encryptedHumidity = substituteString(humidityStr, ALPHABET, KEY);
String encryptedVoc = substituteString(vocStr, ALPHABET, KEY);
String encryptedGas = substituteString(gasStr, ALPHABET, KEY);
String encryptedPressure = substituteString(pressureStr, ALPHABET, KEY);
// JSON-Payload mit verschlüsselten Strings
String payload = "{";
payload += "\"timestamp\": \"" + encryptedTimestamp + "\",";
payload += "\"temperature\": \"" + encryptedTemperature + "\",";
payload += "\"humidity\": \"" + encryptedHumidity + "\",";
payload += "\"pressure\": \"" + encryptedPressure + "\",";
payload += "\"voc\": \"" + encryptedVoc + "\",";
payload += "\"gas\": \"" + encryptedGas + "\"";
payload += "}";
// Sende Request
String fullPath = String(API_ENDPOINT) + "?client=" + CLIENT_ID; String fullPath = String(API_ENDPOINT) + "?client=" + CLIENT_ID;
client.beginRequest(); client.beginRequest();
client.post(fullPath); client.post(fullPath);
client.sendHeader("Content-Type", "text/plain"); client.sendHeader("Content-Type", "application/json");
client.sendHeader("token", API_TOKEN); client.sendHeader("token", API_TOKEN);
client.sendHeader("Content-Length", encryptedPayload.length()); client.sendHeader("Content-Length", payload.length());
client.beginBody(); client.beginBody();
client.print(encryptedPayload); client.print(payload);
client.endRequest(); client.endRequest();
Serial.println(payload);
Serial.println(fullPath);
int statusCode = client.responseStatusCode(); int statusCode = client.responseStatusCode();
client.responseBody(); String response = client.responseBody();
Serial.println(statusCode);
Serial.println(response);
if (statusCode == 200) {
digitalWrite(LED_BUILTIN, LOW);
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
}
if (statusCode < 200 || statusCode >= 300) {
digitalWrite(LED_BUILTIN, LOW);
}
} }
delay(sendInterval); delay(sendInterval);