dodane logowanie wysyłanych danych do InfluxDB (przez --log)

wysylanie U_A, U_B, U_C do MQTT w formacie JSON podobnie jak dla innych pomiarów (np. Hz)
wysylanie U_A, U_B, U_C do InfluxDB w batchu razem z innymi pomiarami (nie osobno)
This commit is contained in:
ms
2026-02-14 22:47:13 +01:00
parent 0524e7284d
commit 8f3756b1fe
2 changed files with 136 additions and 7 deletions

68
kimi_analyse2.md Normal file
View File

@@ -0,0 +1,68 @@
frequency of reports of orno measuring is very rare , value not changes. try to analyse this problem
● I'll analyze the code to understand the ORNO measuring report frequency issue. Let me first read the relevant file.
● Read 1 file (ctrl+o to expand)
● I analyzed the code and found two critical bugs that explain the rare reports and stuck values:
Problem 1: Spike Detection Logic Bug (Causes "Values Not Changing")
Lines 618-624, 632-638, 644-650, 656-662, and 668-674 have a logic error. When a spike is detected, the code sends previous
values but never updates the stored previous value. This means once a spike is detected, the system reports old values forever.
Example from voltage check:
if(spike_U) {
send_voltage = prev_voltage; // Send old value
printf("ORNO: Voltage spike detected. Sending previous values.\n");
// BUG: prev_voltage is NOT updated here!
} else {
send_voltage = current_voltage;
prev_voltage = current_voltage; // Only updated when NO spike
}
Impact: If your voltage/current/power changes by more than 80% (or frequency by 5%), the system will get stuck reporting the
old values indefinitely.
Problem 2: SUN2K Retry Loop (Causes "Rare Reports")
Lines 796-799 show SUN2K has a retry loop with up to 10 attempts per register:
do {
num = modbus_read_timed(ctx, mbReg[i].ireg, mbReg[i].num_reg, reg);
} while ((num != mbReg[i].num_reg) && (proba++ < 10));
With a 0.9s timeout (line 766) and ~19 registers to read, if SUN2K is unresponsive this can delay each loop iteration by up to
~3 minutes (19 registers × 10 retries × 0.9s = 171s).
Since ORNO is read before SUN2K in the same loop, ORNO reports become rare when SUN2K has communication issues.
Recommendations
1. Fix spike detection - Update prev_* values even when spikes are detected, or the values will never update after any
significant change:
// Current buggy code:
if(spike_U) {
send_voltage = prev_voltage;
} else {
send_voltage = current_voltage;
prev_voltage = current_voltage; // Missing in spike branch!
}
// Fixed version:
if(spike_U) {
printf("ORNO: Voltage spike detected. Using previous values.\n");
}
send_voltage = current_voltage; // Always use current
prev_voltage = current_voltage; // Always update prev
2. Reduce SUN2K impact - Either:
- Reduce proba limit from 10 to 2-3 attempts
- Reduce response timeout from 900ms to 300ms
- Run SUN2K in a separate thread or process
- Disable SUN2K if not needed (#define READ_SUN2K false)
3. Add debugging - The code already has good logging. Check if you see "spike detected" messages or SUN2K timeout errors in
your logs.
The combination of these bugs explains why values appear stuck (spike detection) and reports are infrequent (SUN2K delays).
✻ Sautéed for 3m 13s

View File

@@ -13,6 +13,9 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
// sterowanie logiem wysyłanych danych do InfluxDB (przez --log)
int log_influx_data = 0; /* Set to 1 when --log parameter is provided */
/* ============================================ */ /* ============================================ */
/* STRUCTS FOR MEASUREMENTS */ /* STRUCTS FOR MEASUREMENTS */
/* ============================================ */ /* ============================================ */
@@ -249,10 +252,22 @@ int mqtt_send_Hz(float Hz)
return mosquitto_publish(mosq, NULL, "/energy/orno/Hz", strlen(buf), buf, 0, 0); return mosquitto_publish(mosq, NULL, "/energy/orno/Hz", strlen(buf), buf, 0, 0);
} }
int mqtt_send_SUN2K_U(float U_A, float U_B, float U_C)
{
if (DISABLE_MQTT) return 0;
char buf[128];
snprintf(buf, sizeof(buf), "{\"U_A\":%f,\"U_B\":%f,\"U_C\":%f}", U_A, U_B, U_C);
return mosquitto_publish(mosq, NULL, "/energy/sun2k/U", strlen(buf), buf, 0, 0);
}
/* InfluxDB Functions */ /* InfluxDB Functions */
int influx_send_post(char *data) int influx_send_post(char *data)
{ {
if (DISABLE_INFLUX) return 0; if (DISABLE_INFLUX) return 0;
/* Log data to screen if --log parameter was provided */
if (log_influx_data) {
printf("INFLUX: Sending data: %s\n", data);
}
int sock; int sock;
struct sockaddr_in server; struct sockaddr_in server;
@@ -351,7 +366,7 @@ int influx_send_orno_batch(s_voltage *v, int v_ok, s_current *i, int i_ok,
} }
if (f_ok) { if (f_ok) {
offset += snprintf(batch + offset, sizeof(batch) - offset, offset += snprintf(batch + offset, sizeof(batch) - offset,
"orno,device=orno,pomiar=frequency value=%.4f\n", f->Freq); "orno,device=orno,pomiar=frequency frequency=%.4f\n", f->Freq);
} }
if (offset == 0) return 0; if (offset == 0) return 0;
@@ -365,10 +380,18 @@ int influx_send_SUN2K(t_mb_reg *reg_to_send, char *_str_buf) {
if (!_str_buf || strlen(_str_buf) == 0) return 0; if (!_str_buf || strlen(_str_buf) == 0) return 0;
char line[256]; char line[256];
/* reg_id used as tag, value as field */ /* reg_id used as tag, value as field */
snprintf(line, sizeof(line), "sun2k,device=sun2k,pomiar=%s value=%s", reg_to_send->reg_id, _str_buf); snprintf(line, sizeof(line), "sun2k,device=sun2k %s=%s", reg_to_send->reg_id, _str_buf);
return influx_send_post(line); return influx_send_post(line);
} }
int influx_send_SUN2K_U_batch(float U_A, float U_B, float U_C, int valid) {
if (DISABLE_INFLUX) return 0;
if (!valid) return 0;
char batch[256];
snprintf(batch, sizeof(batch), "sun2k,device=sun2k,pomiar=voltage U_A=%.2f,U_B=%.2f,U_C=%.2f", U_A, U_B, U_C);
return influx_send_post(batch);
}
/* Validate float value - check if not NaN, Inf, or out of reasonable range */ /* Validate float value - check if not NaN, Inf, or out of reasonable range */
int is_valid_float(float value, float min_val, float max_val) int is_valid_float(float value, float min_val, float max_val)
{ {
@@ -421,6 +444,13 @@ int mosq_test()
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
/* Parse command line arguments */
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "--log") == 0) {
log_influx_data = 1;
printf("CFG: InfluxDB data logging enabled (--log)\n");
}
}
/* Użyj wartości z #define, token z env lub fallback */ /* Użyj wartości z #define, token z env lub fallback */
influx_token = getenv("INFLUX_TOKEN"); influx_token = getenv("INFLUX_TOKEN");
if (!influx_token || strlen(influx_token) == 0) { if (!influx_token || strlen(influx_token) == 0) {
@@ -587,7 +617,7 @@ int main(int argc, char *argv[])
fabs(current_voltage.U3 - avg_L3) > avg_L3 * VOLTAGE_FLUCTUATION_THRESHOLD) { fabs(current_voltage.U3 - avg_L3) > avg_L3 * VOLTAGE_FLUCTUATION_THRESHOLD) {
printf("ORNO: Voltage fluctuation detected! Switching to high frequency polling for %d seconds.\n", HIGH_FREQ_MODE_DURATION); printf("ORNO: Voltage fluctuation detected! Switching to high frequency polling for %d seconds.\n", HIGH_FREQ_MODE_DURATION);
mqtt_send("/energy/orno/fluct", "on"); mqtt_send("/energy/orno/fluct", "on");
influx_send_post("orno,device=orno,highfluct=start value=true"); influx_send_post("orno,device=orno,highfluct=start highfluct=true");
high_frequency_mode_end_time = time(NULL) + HIGH_FREQ_MODE_DURATION; high_frequency_mode_end_time = time(NULL) + HIGH_FREQ_MODE_DURATION;
} }
@@ -661,9 +691,8 @@ int main(int argc, char *argv[])
printf("ORNO: Energy spike/drop detected. Sending previous values.\n"); printf("ORNO: Energy spike/drop detected. Sending previous values.\n");
} else { } else {
send_energy = current_energy; send_energy = current_energy;
}
// Always update prev_energy to prevent getting stuck on old values
prev_energy = current_energy; prev_energy = current_energy;
}
// FREQUENCY check (5% threshold) // FREQUENCY check (5% threshold)
int spike_F = 0; int spike_F = 0;
@@ -674,9 +703,8 @@ int main(int argc, char *argv[])
printf("ORNO: Frequency spike detected. Sending previous values.\n"); printf("ORNO: Frequency spike detected. Sending previous values.\n");
} else { } else {
send_freq = current_freq; send_freq = current_freq;
}
// Always update prev_freq to prevent getting stuck on old values
prev_freq = current_freq; prev_freq = current_freq;
}
// --- Now send the selected values --- // --- Now send the selected values ---
@@ -794,8 +822,41 @@ int main(int argc, char *argv[])
int proba = 0; int proba = 0;
char str_buf[32]; char str_buf[32];
/* Read SUN2K voltages (U_A, U_B, U_C) in one batch - registers 32069-32071 */
float sun2k_U_A = 0, sun2k_U_B = 0, sun2k_U_C = 0;
int sun2k_voltage_ok = 0;
proba = 0;
do {
num = modbus_read_timed(ctx, 32069, 3, reg);
} while ((num != 3) && (proba++ < 10));
if (num == 3) {
sun2k_U_A = (float)reg[0] / 10.0;
sun2k_U_B = (float)reg[1] / 10.0;
sun2k_U_C = (float)reg[2] / 10.0;
printf("SUN2K: Voltages: U_A=%.1f V, U_B=%.1f V, U_C=%.1f V\n", sun2k_U_A, sun2k_U_B, sun2k_U_C);
if (is_valid_float(sun2k_U_A, 150.0, 280.0) &&
is_valid_float(sun2k_U_B, 150.0, 280.0) &&
is_valid_float(sun2k_U_C, 150.0, 280.0)) {
mqtt_send_SUN2K_U(sun2k_U_A, sun2k_U_B, sun2k_U_C);
sun2k_voltage_ok = 1;
printf("SUN2K: MQTT: Published voltages\n");
} else {
printf("SUN2K: MQTT: Skipping voltages - invalid values\n");
}
influx_send_SUN2K_U_batch(sun2k_U_A, sun2k_U_B, sun2k_U_C, sun2k_voltage_ok);
} else {
printf("SUN2K: Failed to read voltages: %s\n", modbus_strerror(errno));
}
usleep(10000); /* 10ms delay before continuing */
for (int i = 0; i < sizeof(mbReg) / sizeof(t_mb_reg); i++) for (int i = 0; i < sizeof(mbReg) / sizeof(t_mb_reg); i++)
{ {
/* Skip U_A, U_B, U_C - already read and sent in batch */
if (mbReg[i].ireg == 32069 || mbReg[i].ireg == 32070 || mbReg[i].ireg == 32071) {
continue;
}
memset(str_buf, 0, sizeof(str_buf)); memset(str_buf, 0, sizeof(str_buf));
proba = 0; proba = 0;
do do