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 <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;
|
||||||
|
prev_energy = current_energy;
|
||||||
}
|
}
|
||||||
// Always update prev_energy to prevent getting stuck on old values
|
|
||||||
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;
|
||||||
|
prev_freq = current_freq;
|
||||||
}
|
}
|
||||||
// Always update prev_freq to prevent getting stuck on old values
|
|
||||||
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
|
||||||
|
|||||||
Reference in New Issue
Block a user