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:
68
kimi_analyse2.md
Normal file
68
kimi_analyse2.md
Normal 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
|
||||
75
modb_orno3.c
75
modb_orno3.c
@@ -13,6 +13,9 @@
|
||||
#include <netinet/in.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 */
|
||||
/* ============================================ */
|
||||
@@ -249,10 +252,22 @@ int mqtt_send_Hz(float Hz)
|
||||
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 */
|
||||
int influx_send_post(char *data)
|
||||
{
|
||||
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;
|
||||
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) {
|
||||
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;
|
||||
@@ -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;
|
||||
char line[256];
|
||||
/* 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);
|
||||
}
|
||||
|
||||
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 */
|
||||
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[])
|
||||
{
|
||||
/* 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 */
|
||||
influx_token = getenv("INFLUX_TOKEN");
|
||||
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) {
|
||||
printf("ORNO: Voltage fluctuation detected! Switching to high frequency polling for %d seconds.\n", HIGH_FREQ_MODE_DURATION);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -661,9 +691,8 @@ int main(int argc, char *argv[])
|
||||
printf("ORNO: Energy spike/drop detected. Sending previous values.\n");
|
||||
} else {
|
||||
send_energy = current_energy;
|
||||
prev_energy = current_energy;
|
||||
}
|
||||
// Always update prev_energy to prevent getting stuck on old values
|
||||
prev_energy = current_energy;
|
||||
|
||||
// FREQUENCY check (5% threshold)
|
||||
int spike_F = 0;
|
||||
@@ -674,9 +703,8 @@ int main(int argc, char *argv[])
|
||||
printf("ORNO: Frequency spike detected. Sending previous values.\n");
|
||||
} else {
|
||||
send_freq = current_freq;
|
||||
prev_freq = current_freq;
|
||||
}
|
||||
// Always update prev_freq to prevent getting stuck on old values
|
||||
prev_freq = current_freq;
|
||||
|
||||
// --- Now send the selected values ---
|
||||
|
||||
@@ -794,8 +822,41 @@ int main(int argc, char *argv[])
|
||||
int proba = 0;
|
||||
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++)
|
||||
{
|
||||
/* 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));
|
||||
proba = 0;
|
||||
do
|
||||
|
||||
Reference in New Issue
Block a user