This commit is contained in:
Flo
2026-05-07 08:51:32 +02:00
parent 210bf06952
commit 604c8a3eaf
10 changed files with 153 additions and 192 deletions
+1
View File
@@ -3,3 +3,4 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.aider*
-83
View File
@@ -1,83 +0,0 @@
/*
* DataSender.cpp
*
* Created on: 08.10.2022
* Author: flori
*/
#include "main.h"
#include "MyWifiClient.h"
#include "Seconds.h"
#include "DataSender.h"
DataSender dataSender;
#define SEND_INTERVAL_SECONDS 120
#define DATA_SIZE_PER_FENSTER 11
static uint8_t buf[DATA_SIZE_PER_FENSTER * NUM_FENSTER];
DataSender::DataSender()
{
bRequestSendWifi = true;
tNextSend = SEND_INTERVAL_SECONDS;
}
DataSender::~DataSender()
{
// TODO Auto-generated destructor stub
}
/**
*
*/
void DataSender::onSetup(void)
{
myWifiClient.onSetup();
}
/**
*
*/
void DataSender::onLoop(void)
{
if (Seconds::Get() >= tNextSend )
{
bRequestSendWifi = true;
}
if (bRequestSendWifi && myWifiClient.canSend())
{
bRequestSendWifi = false;
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
uint8_t offset = DATA_SIZE_PER_FENSTER * i;
memcpy( &buf[offset], alleFenster[i]->name, 8 );
uint16_t remainingTime = (uint16_t) alleFenster[i]->GetRemainingTime();
memcpy( &buf[offset+8], &remainingTime , 2);
uint8_t state = alleFenster[i]->IsOpen() ? 1 : 0;
state |= alleFenster[i]->ShallPiep() ? 2 : 0;
memcpy( &buf[offset+10], &state , 1);
}
myWifiClient.send(buf, sizeof(buf));
tNextSend = Seconds::Get() + SEND_INTERVAL_SECONDS;
}
myWifiClient.onLoop();
}
/**
*
*/
void DataSender::requestSend(void)
{
bRequestSendWifi = true;
}
-27
View File
@@ -1,27 +0,0 @@
/*
* DataSender.h
*
* Created on: 08.10.2022
* Author: flori
*/
#ifndef DATASENDER_H_
#define DATASENDER_H_
class DataSender
{
public:
DataSender();
virtual ~DataSender();
void onSetup(void);
void onLoop(void);
void requestSend(void);
private:
bool bRequestSendWifi;
uint32_t tNextSend;
};
extern DataSender dataSender;
#endif /* DATASENDER_H_ */
+31 -13
View File
@@ -5,6 +5,7 @@
*/
#include <WiFi.h>
#include <time.h>
#include "MyMqttClient.h"
#include "Version.h"
@@ -14,12 +15,12 @@
MyMqttClient myMqttClient;
MyMqttClient::MyMqttClient()
: mqttClient(wifiClient)
: pubSubClient(wifiClient)
, lastConnectAttemptMs(0)
, lastWifiReconnectMs(0)
{
mqttClient.setServer(MQTT_BROKER_IP, MQTT_BROKER_PORT);
mqttClient.setKeepAlive(300);
pubSubClient.setServer(MQTT_BROKER_IP, MQTT_BROKER_PORT);
pubSubClient.setKeepAlive(600);
}
/**
@@ -29,7 +30,7 @@ MyMqttClient::MyMqttClient()
*/
bool MyMqttClient::ensureConnected()
{
if (mqttClient.connected())
if (pubSubClient.connected())
{
return true;
}
@@ -51,22 +52,24 @@ bool MyMqttClient::ensureConnected()
bool ok;
if (strlen(MQTT_USER) > 0)
{
ok = mqttClient.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD);
ok = pubSubClient.connect(MQTT_CLIENT_ID, MQTT_USER, MQTT_PASSWORD,
MQTT_TEMP_RH, 0, true, "{\"T\":0,\"rh\":0,\"t\":0}");
}
else
{
ok = mqttClient.connect(MQTT_CLIENT_ID);
ok = pubSubClient.connect(MQTT_CLIENT_ID, nullptr, nullptr,
MQTT_TEMP_RH, 0, true, "{\"T\":0,\"rh\":0,\"t\":0}");
}
if (ok)
{
Serial.println("[MQTT] Connected");
mqttClient.publish(MQTT_TOPIC_STATUS,
pubSubClient.publish(MQTT_TOPIC_SYSTEM,
"{\"e\":\"hello\",\"client\":\"" MQTT_CLIENT_ID VERSION_STR "\"}");
}
else
{
Serial.printf("[MQTT] Connect failed, rc=%d\n", mqttClient.state());
Serial.printf("[MQTT] Connect failed, rc=%d\n", pubSubClient.state());
}
return ok;
@@ -75,13 +78,28 @@ bool MyMqttClient::ensureConnected()
/**
* Publishes an arbitrary status payload to MQTT_TOPIC_STATUS.
*/
void MyMqttClient::publishStatus(const char* payload)
void MyMqttClient::publishStatus(const char* payload, bool retain)
{
if (!ensureConnected())
{
return;
}
mqttClient.publish(MQTT_TOPIC_STATUS , payload);
pubSubClient.publish(MQTT_TOPIC_STATUS, payload, retain);
}
/**
* Publishes temperature and humidity data to MQTT_TEMP_RH topic.
*/
void MyMqttClient::publishTemperatureAndHumidity(int temperature, uint8_t humidity, uint32_t rawData)
{
if (!ensureConnected())
{
return;
}
char payload[80];
snprintf(payload, sizeof(payload),
"{\"T\":%d,\"rh\":%u,\"t\":%lu, \"raw\":%lu}", temperature, humidity, (unsigned long)time(nullptr), (unsigned long)rawData);
pubSubClient.publish(MQTT_TEMP_RH, payload, true);
}
/**
@@ -104,18 +122,18 @@ void MyMqttClient::onLoop()
if (WiFi.isConnected())
{
ensureConnected();
mqttClient.loop();
pubSubClient.loop();
static uint32_t tNextRssiMs = 0u;
if (millis() >= tNextRssiMs)
{
tNextRssiMs = millis() + 600000u;
if (mqttClient.connected())
if (pubSubClient.connected())
{
char payload[48];
snprintf(payload, sizeof(payload),
"{\"rssi\":%d }", (int)WiFi.RSSI());
mqttClient.publish(MQTT_TOPIC_RSSI, payload);
pubSubClient.publish(MQTT_TOPIC_RSSI, payload);
}
}
}
+6 -2
View File
@@ -16,8 +16,10 @@
#define MQTT_BROKER_IP "flokke.de"
#define MQTT_BROKER_PORT 1883
#define MQTT_CLIENT_ID "Fensterpiepser" PROJECT_VARIANT
#define MQTT_TOPIC_SYSTEM "fenster/system/" PROJECT_VARIANT
#define MQTT_TOPIC_STATUS "fenster/status/" PROJECT_VARIANT
#define MQTT_TOPIC_RSSI "fenster/rssi/" PROJECT_VARIANT
#define MQTT_TEMP_RH "fenster/temprh/" PROJECT_VARIANT
// Optional: set to "" if no authentication required
#define MQTT_USER "lightcontrol"
#define MQTT_PASSWORD "mR9o3OYpAzUZvS"
@@ -27,7 +29,7 @@ class MyMqttClient
{
private:
WiFiClient wifiClient;
PubSubClient mqttClient;
PubSubClient pubSubClient;
uint32_t lastConnectAttemptMs;
uint32_t lastWifiReconnectMs;
@@ -38,7 +40,9 @@ public:
MyMqttClient();
void onLoop();
void publishStatus(const char* payload);
void publishStatus(const char* payload, bool retain = false);
void publishTemperatureAndHumidity(int temperature, uint8_t humidity, uint32_t rawData);
void closeConnection() { pubSubClient.disconnect(); }
};
extern MyMqttClient myMqttClient;
+68 -50
View File
@@ -5,12 +5,12 @@
* Author: flori
*/
#include "main.h"
#include "DataSender.h"
#include "ReceiverFunkThermometer.h"
#include <MyMqttClient.h>
#define DEBUG_LEVEL 0
#define DEBUG_LEVEL 2
#define MonitorPrint(x) // Serial.print(x)
#define MonitorPrint(x) Serial.print(x)
ReceiverFunkThermometer receiverThermo;
@@ -57,11 +57,11 @@ IRAM_ATTR void ReceiverFunkThermometer::Isr(uint32_t dtMicros, bool pinValue)
SignalDurationThermometer_t thisDuration = FUNK_THERMO_INVALID;
if (dtMicros > 350 && dtMicros < 600)
if (dtMicros > 400 && dtMicros < 600)
{
thisDuration = MS_0_5;
}
else if (dtMicros > 800 && dtMicros < 1200)
else if (dtMicros > 900 && dtMicros < 1100)
{
thisDuration = MS_1_0;
}
@@ -89,23 +89,9 @@ IRAM_ATTR void ReceiverFunkThermometer::Isr(uint32_t dtMicros, bool pinValue)
}
else if (pinValue == HIGH )
{
#if DEBUG_LEVEL > 1
bool bprint = (rByteIndex > 0 || rBitIndex<7);
#else
bool bprint = false;
#endif
if (bprint)
{
sprintf(textBuf, "\n%d %d : ", rByteIndex, rBitIndex );
MonitorPrint(textBuf);
}
if (thisDuration==MS_2_0 && lastDuration == MS_0_5)
{
if (bprint)
{
MonitorPrint(F("1"));
}
/* bit 1 received */
rBytes[rByteIndex] |= (1 << rBitIndex);
if (rBitIndex == 0)
@@ -126,10 +112,6 @@ IRAM_ATTR void ReceiverFunkThermometer::Isr(uint32_t dtMicros, bool pinValue)
}
else if (thisDuration==MS_1_0 &&lastDuration == MS_0_5)
{
if (bprint)
{
MonitorPrint(F("0"));
}
/* bit 0 received */
if (rBitIndex == 0)
{
@@ -147,14 +129,9 @@ IRAM_ATTR void ReceiverFunkThermometer::Isr(uint32_t dtMicros, bool pinValue)
rBytes[0] = 0;
}
}
}
}
lastDuration = thisDuration;
}
/**
@@ -247,8 +224,53 @@ bytes received from woolworth temp
69
6
111
93
102
10
96
6
111
93
102
10
*
*/
IRAM_ATTR void ReceiverFunkThermometer::printBits(void)
{
Serial.println("");
Serial.println("T_RH");
for (int i = 0; i < THERMO_KEY_NUMBYTES_PER_KEY; i++)
{
for (int j = 7; j >= 0; j--)
{
Serial.print((rBytes[i] >> j) & 0x01);
}
Serial.print(" ");
}
}
/*
Fehler: (anderer Sensor?)
01100000 00000110 10011111 01011101 T_RH
01100000 00000110 10011111 01011101 105 / 93
Korrekt:
01011000 00000111 10001111 00110110 T_RH
01011000 00000111 10001111 00110110 120 / 54
iiiiiiii tttttttt ttttffff hhhhhhhh
*/
IRAM_ATTR void ReceiverFunkThermometer::OnTempReceived(void)
{
@@ -258,24 +280,13 @@ IRAM_ATTR void ReceiverFunkThermometer::OnTempReceived(void)
value : id id t t t 0xf h h
*/
#define PRINT_ON_TEMP_RECEIVED 0
#if 0
/* testdaten */
rBytes[0] = 112u;
rBytes[1] = 255u;
rBytes[2] = 191u;
rBytes[3] = 89u;
#endif
#if PRINT_ON_TEMP_RECEIVED
Serial.println(rBytes[0]);
Serial.println(rBytes[1]);
Serial.println(rBytes[2]);
Serial.println(rBytes[3]);
printBits();
#endif
if ((rBytes[2]&0xF) == 0xF) /* these 4 bits must be 1 */
if ( ((rBytes[0]&0xF0)==0x50) /* id bits are 0101 */
&& (rBytes[2]&0xF) == 0xF)
{
int16_t tempInt = 0;
int16_t tempNow = 0;
uint8_t rhNow = rBytes[3];
@@ -291,20 +302,17 @@ IRAM_ATTR void ReceiverFunkThermometer::OnTempReceived(void)
tempInt = (~tempInt) & 0xFFFu;
tempInt += 1;
}
#if PRINT_ON_TEMP_RECEIVED
Serial.println(tempInt);
#endif
/* do the rounding with positive number */
tempNow = (tempInt + 5) / 10;
dataLast.tempDeciCelsius = tempInt;
if (isNegative)
{
/* set to negative */
tempNow = -tempNow;
dataLast.tempDeciCelsius = -dataLast.tempDeciCelsius;
}
#if PRINT_ON_TEMP_RECEIVED
Serial.println(tempNow);
#endif
int16_t dTempAbs = (tempNow >= dataLast.tempC) ? (tempNow - dataLast.tempC) : (dataLast.tempC - tempNow);
uint8_t dRHAbs = (rhNow >= dataLast.rhPercent) ? (rhNow - dataLast.rhPercent) : (dataLast.rhPercent - rhNow);
@@ -317,8 +325,18 @@ IRAM_ATTR void ReceiverFunkThermometer::OnTempReceived(void)
(dRHAbs <= 2u) )
#endif
{
bNewData = true;
data = dataLast;
if (data.tempDeciCelsius != dataLast.tempDeciCelsius || data.rhPercent != dataLast.rhPercent)
{
bNewData = true;
data = dataLast;
data.rawData = ((uint32_t)rBytes[0] << 24) | ((uint32_t)rBytes[1] << 16) | ((uint32_t)rBytes[2] << 8) | rBytes[3];
#if PRINT_ON_TEMP_RECEIVED
Serial.print(data.tempDeciCelsius);
Serial.print(" / ");
Serial.println(data.rhPercent);
#endif
}
}
}
+3 -1
View File
@@ -23,8 +23,10 @@ typedef enum
typedef struct
{
int16_t tempDeciCelsius;
int16_t tempC;
uint8_t rhPercent;
uint32_t rawData;
} ReceiverFunkThermometerData_t;
@@ -45,7 +47,7 @@ private:
void OnTempReceived(void);
void ResetBuffer(void);
void NextByte(void);
void printBits(void);
uint8_t rBytes[THERMO_KEY_NUMBYTES_PER_KEY];
uint8_t rByteIndex = 0;
-1
View File
@@ -76,7 +76,6 @@ void UpdateHandler()
{
webServer.sendHeader("Connection", "close");
webServer.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
myMqttClient.publishStatus("{\"event\":\"reset_update\", \"variant\": \"" PROJECT_VARIANT "\" }");
ESP.restart();
}, []()
{
+1 -1
View File
@@ -17,7 +17,7 @@
#endif
#define PROJECT_NAME "FENSTER_PIEPSER_NODEMCU_32_S_" PROJECT_VARIANT
#define VERSION_STR "_v2.0.3"
#define VERSION_STR "_v2.0.8"
#endif /* VERSION_H_ */
+42 -13
View File
@@ -11,7 +11,6 @@
#include "Display.h"
#include "Display_SSD1306.h"
#include "Seconds.h"
#include "DataSender.h"
#include "InterruptHandler.h"
#include "xcp/XcpPort.h"
#include "UpdateHandler.h"
@@ -61,9 +60,10 @@
#define TONE_FREQUENCY_HZ 2000
#define TIMEOUT_WIFI_CONNECTION_MS 30000u
#define USE_XCP (1u)
#define USE_WIFI (1u) /* WARNING, no OTA update without wifi ! */
#define USE_DATASENDER (0u)
/*---------------- GLOBAL VARIABLES ------------- */
uint32_t gtMillis;
@@ -156,7 +156,7 @@ static void handleDispUpdate(void);
static void handleKeyReceived(void);
static void updateIsNighttime();
static void updatePiepPattern(void);
static void handleWifiConnection(void);
/**
*
@@ -174,8 +174,6 @@ void setup()
WiFi.mode(WIFI_STA);
WiFi.begin(ssidElektro, password);
dataSender.onSetup();
const char* ntpServer = "ptbtime3.ptb.de";
const long gmtOffset_sec = 3600;
const int daylightOffset_sec = 3600;
@@ -254,11 +252,7 @@ void loop()
#if USE_WIFI
//updateIsNighttime();
#if USE_DATASENDER
dataSender.onLoop();
#endif
handleWifiConnection();
myMqttClient.onLoop();
UpdateHandler();
#endif
@@ -280,6 +274,40 @@ void loop()
loopCountSincePause++;
}
/* don't call from interrupt, set gbRestartRequest to true instead */
static void myEspRestart()
{
myMqttClient.closeConnection();
delay(100);
esp_restart();
}
/**
*
*/
static void handleWifiConnection(void)
{
static uint32_t tDoSoftResetMs = 0;
if (true == WiFi.isConnected())
{
tDoSoftResetMs = 0;
}
else
{
if (tDoSoftResetMs == 0u)
{
tDoSoftResetMs = millis() + TIMEOUT_WIFI_CONNECTION_MS;
WiFi.reconnect();
}
else if (millis() > tDoSoftResetMs)
{
myMqttClient.publishStatus("{\"reset\":\"reset due to WiFi connection timeout\"}");
myEspRestart();
}
}
}
static void handleDispUpdate(void)
{
/* cyclically request display update */
@@ -443,6 +471,8 @@ static void handleKeyReceived(void)
/* update wait time according to temperature */
updateWaittime();
myMqttClient.publishTemperatureAndHumidity(thermoData.tempC, thermoData.rhPercent, thermoData.rawData);
}
@@ -460,7 +490,6 @@ static void handleKeyReceived(void)
if (bWindowChanged)
{
bUpdateDisp = true;
dataSender.requestSend();
bRequestShortBeep = true;
publishAllFensterStatus("move");
if (lastKeyDirection == DIRECTION_CLOSE)
@@ -520,7 +549,7 @@ static void testWaitTime()
static void publishAllFensterStatus(const char *event)
{
char payload[256];
sprintf(payload, "{ \"e\": \"%s\", \"n\": %d, \"f\": [", event, NUM_FENSTER);
sprintf(payload, "{ \"t\": %lu, \"e\": \"%s\", \"n\": %d, \"f\": [", (unsigned long)time(nullptr), event, NUM_FENSTER);
for (uint8_t i = 0; i < NUM_FENSTER; i++)
{
if (i>0) strcat(payload, ",");
@@ -542,7 +571,7 @@ static void publishAllFensterStatus(const char *event)
}
strcat(payload, "] }");
myMqttClient.publishStatus(payload);
myMqttClient.publishStatus(payload, true);
}
/**