|
|
|
|
@@ -12,6 +12,15 @@
|
|
|
|
|
#include <netinet/in.h>
|
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
|
|
|
|
|
|
/* ============================================ */
|
|
|
|
|
/* STRUCTS FOR MEASUREMENTS */
|
|
|
|
|
/* ============================================ */
|
|
|
|
|
typedef struct { float U1, U2, U3; } s_voltage;
|
|
|
|
|
typedef struct { float I1, I2, I3; } s_current;
|
|
|
|
|
typedef struct { float P_Tot, P1, P2, P3; } s_power;
|
|
|
|
|
typedef struct { float W_Tot, W1, W2, W3; } s_energy;
|
|
|
|
|
typedef struct { float Freq; } s_frequency;
|
|
|
|
|
|
|
|
|
|
/* ============================================ */
|
|
|
|
|
/* KONFIGURACJA PROGRAMU - EDYTUJ TU */
|
|
|
|
|
/* ============================================ */
|
|
|
|
|
@@ -406,6 +415,13 @@ int main(int argc, char *argv[])
|
|
|
|
|
int do_orno = READ_ORNO;
|
|
|
|
|
int do_sun2k = READ_SUN2K;
|
|
|
|
|
|
|
|
|
|
s_voltage prev_voltage = {0}, current_voltage = {0};
|
|
|
|
|
s_current prev_current = {0}, current_current = {0};
|
|
|
|
|
s_power prev_power = {0}, current_power = {0};
|
|
|
|
|
s_energy prev_energy = {0}, current_energy = {0};
|
|
|
|
|
s_frequency prev_freq = {0}, current_freq = {0};
|
|
|
|
|
int first_run = 1;
|
|
|
|
|
|
|
|
|
|
float voltage_buffer_L1[VOLTAGE_BUFFER_SIZE] = {0};
|
|
|
|
|
float voltage_buffer_L2[VOLTAGE_BUFFER_SIZE] = {0};
|
|
|
|
|
float voltage_buffer_L3[VOLTAGE_BUFFER_SIZE] = {0};
|
|
|
|
|
@@ -437,10 +453,9 @@ int main(int argc, char *argv[])
|
|
|
|
|
{
|
|
|
|
|
if (do_orno)
|
|
|
|
|
{
|
|
|
|
|
//Create a new RTU context with proper serial parameters (in this example,
|
|
|
|
|
//device name /dev/ttyS0, baud rate 9600, no parity bit, 8 data bits, 1 stop bit)
|
|
|
|
|
//Create a new RTU context
|
|
|
|
|
modbus_t *ctx = modbus_new_rtu(USB_DEV, 9600, 'E', 8, 1);
|
|
|
|
|
//Set the Modbus address of the remote slave (to 2)
|
|
|
|
|
//Set the Modbus address of the remote slave
|
|
|
|
|
modbus_set_slave(ctx, ORNO_SLAVE);
|
|
|
|
|
if (!ctx)
|
|
|
|
|
{
|
|
|
|
|
@@ -455,61 +470,83 @@ int main(int argc, char *argv[])
|
|
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Enable libmodbus debug to print raw frames */
|
|
|
|
|
/* modbus_set_debug(ctx, TRUE); */ /* Disabled - causes timing issues */
|
|
|
|
|
/* Configure RTS delay and timeouts from #define */
|
|
|
|
|
modbus_rtu_set_rts_delay(ctx, ORNO_RTS_DELAY);
|
|
|
|
|
modbus_set_response_timeout(ctx, 0, 900000); /* 0.9s */
|
|
|
|
|
modbus_set_byte_timeout(ctx, 0, ORNO_BYTE_TIMEOUT);
|
|
|
|
|
|
|
|
|
|
/* Display current configuration */
|
|
|
|
|
int rts_delay = modbus_rtu_get_rts_delay(ctx);
|
|
|
|
|
uint32_t response_timeout_sec, response_timeout_usec;
|
|
|
|
|
uint32_t byte_timeout_sec, byte_timeout_usec;
|
|
|
|
|
modbus_get_response_timeout(ctx, &response_timeout_sec, &response_timeout_usec);
|
|
|
|
|
modbus_get_byte_timeout(ctx, &byte_timeout_sec, &byte_timeout_usec);
|
|
|
|
|
printf("ORNO: RTS Delay %u us\n", rts_delay);
|
|
|
|
|
printf("ORNO: Response Timeout %u,%06u s\n", response_timeout_sec, response_timeout_usec);
|
|
|
|
|
printf("ORNO: Byte Timeout %u,%06u s\n", byte_timeout_sec, byte_timeout_usec);
|
|
|
|
|
printf("ORNO: RTS Delay and Timeouts configured.\n");
|
|
|
|
|
|
|
|
|
|
uint16_t reg[32]; // will store read registers values
|
|
|
|
|
uint16_t reg2[2]; // will store read registers values
|
|
|
|
|
float d = 0.0;
|
|
|
|
|
uint16_t reg[32];
|
|
|
|
|
int num;
|
|
|
|
|
|
|
|
|
|
int num = 0;
|
|
|
|
|
int proba = 0;
|
|
|
|
|
float U1, U2, U3;
|
|
|
|
|
float I1, I2, I3;
|
|
|
|
|
float P_Tot, P1, P2, P3;
|
|
|
|
|
float W_Tot, W1, W2, W3;
|
|
|
|
|
float Freq;
|
|
|
|
|
// ---- READ ALL ORNO VALUES ----
|
|
|
|
|
|
|
|
|
|
long l = 0;
|
|
|
|
|
|
|
|
|
|
/* Flush serial buffer and wait for device to be ready */
|
|
|
|
|
modbus_flush(ctx);
|
|
|
|
|
usleep(100000); /* 100ms delay before first read */
|
|
|
|
|
|
|
|
|
|
memset((char *)reg, 0, sizeof(reg));
|
|
|
|
|
//NAPIECIA
|
|
|
|
|
num = modbus_read_timed(ctx, 0xe, 6, reg); // ORNO
|
|
|
|
|
// num = modbus_read_registers(ctx, 32072, 2, reg); // SUN2000
|
|
|
|
|
if (num != 6)
|
|
|
|
|
{ // number of read registers is not the one expected
|
|
|
|
|
printf("ORNO: %x \t\n", 0xe);
|
|
|
|
|
printf("ORNO: Failed to read: %s\n", modbus_strerror(errno));
|
|
|
|
|
// VOLTAGES
|
|
|
|
|
num = modbus_read_timed(ctx, 0xe, 6, reg);
|
|
|
|
|
if (num == 6) {
|
|
|
|
|
current_voltage.U1 = modbus_get_float_abcd(®[0]);
|
|
|
|
|
current_voltage.U2 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
current_voltage.U3 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: Failed to read voltages: %s\n", modbus_strerror(errno));
|
|
|
|
|
current_voltage = prev_voltage; // On error, use previous values
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
U1 = modbus_get_float_abcd(®[0]);
|
|
|
|
|
U2 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
U3 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
printf("ORNO: Voltages: L1=%.1f V, L2=%.1f V, L3=%.1f V\n", U1, U2, U3);
|
|
|
|
|
usleep(100000);
|
|
|
|
|
|
|
|
|
|
// Add to circular buffer
|
|
|
|
|
voltage_buffer_L1[voltage_buffer_index] = U1;
|
|
|
|
|
voltage_buffer_L2[voltage_buffer_index] = U2;
|
|
|
|
|
voltage_buffer_L3[voltage_buffer_index] = U3;
|
|
|
|
|
// CURRENTS
|
|
|
|
|
num = modbus_read_timed(ctx, 0x16, 6, reg);
|
|
|
|
|
if (num == 6) {
|
|
|
|
|
current_current.I1 = modbus_get_float_abcd(®[0]);
|
|
|
|
|
current_current.I2 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
current_current.I3 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: Failed to read currents: %s\n", modbus_strerror(errno));
|
|
|
|
|
current_current = prev_current;
|
|
|
|
|
}
|
|
|
|
|
usleep(100000);
|
|
|
|
|
|
|
|
|
|
// POWER
|
|
|
|
|
num = modbus_read_timed(ctx, 0x1c, 8, reg);
|
|
|
|
|
if (num == 8) {
|
|
|
|
|
current_power.P_Tot = modbus_get_float_abcd(®[0]);
|
|
|
|
|
current_power.P1 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
current_power.P2 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
current_power.P3 = modbus_get_float_abcd(®[6]);
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: Failed to read power: %s\n", modbus_strerror(errno));
|
|
|
|
|
current_power = prev_power;
|
|
|
|
|
}
|
|
|
|
|
usleep(100000);
|
|
|
|
|
|
|
|
|
|
// ENERGY
|
|
|
|
|
num = modbus_read_timed(ctx, 0x100, 8, reg);
|
|
|
|
|
if (num == 8) {
|
|
|
|
|
current_energy.W_Tot = modbus_get_float_abcd(®[0]);
|
|
|
|
|
current_energy.W1 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
current_energy.W2 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
current_energy.W3 = modbus_get_float_abcd(®[6]);
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: Failed to read energy: %s\n", modbus_strerror(errno));
|
|
|
|
|
current_energy = prev_energy;
|
|
|
|
|
}
|
|
|
|
|
usleep(10000);
|
|
|
|
|
|
|
|
|
|
// FREQUENCY
|
|
|
|
|
num = modbus_read_timed(ctx, 0x14, 2, reg);
|
|
|
|
|
if (num == 2) {
|
|
|
|
|
current_freq.Freq = modbus_get_float_abcd(®[0]);
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: Failed to read frequency: %s\n", modbus_strerror(errno));
|
|
|
|
|
current_freq = prev_freq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modbus_close(ctx);
|
|
|
|
|
modbus_free(ctx);
|
|
|
|
|
|
|
|
|
|
// --- VOLTAGE FLUCTUATION DETECTION (uses fresh, unfiltered values) ---
|
|
|
|
|
voltage_buffer_L1[voltage_buffer_index] = current_voltage.U1;
|
|
|
|
|
voltage_buffer_L2[voltage_buffer_index] = current_voltage.U2;
|
|
|
|
|
voltage_buffer_L3[voltage_buffer_index] = current_voltage.U3;
|
|
|
|
|
voltage_buffer_index = (voltage_buffer_index + 1) % VOLTAGE_BUFFER_SIZE;
|
|
|
|
|
if (voltage_buffer_items < VOLTAGE_BUFFER_SIZE) {
|
|
|
|
|
voltage_buffer_items++;
|
|
|
|
|
@@ -525,140 +562,137 @@ int main(int argc, char *argv[])
|
|
|
|
|
avg_L2 /= voltage_buffer_items;
|
|
|
|
|
avg_L3 /= voltage_buffer_items;
|
|
|
|
|
|
|
|
|
|
if (fabs(U1 - avg_L1) > avg_L1 * VOLTAGE_FLUCTUATION_THRESHOLD ||
|
|
|
|
|
fabs(U2 - avg_L2) > avg_L2 * VOLTAGE_FLUCTUATION_THRESHOLD ||
|
|
|
|
|
fabs(U3 - avg_L3) > avg_L3 * VOLTAGE_FLUCTUATION_THRESHOLD) {
|
|
|
|
|
if (fabs(current_voltage.U1 - avg_L1) > avg_L1 * VOLTAGE_FLUCTUATION_THRESHOLD ||
|
|
|
|
|
fabs(current_voltage.U2 - avg_L2) > avg_L2 * 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);
|
|
|
|
|
mqtt_send("fluct/start", "on");
|
|
|
|
|
influx_send_post("orno,device=orno,highfluct=start value=true");
|
|
|
|
|
high_frequency_mode_end_time = time(NULL) + HIGH_FREQ_MODE_DURATION;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Validate voltages (150V - 280V is reasonable range for EU grid) */
|
|
|
|
|
if (is_valid_float(U1, 150.0, 280.0) &&
|
|
|
|
|
is_valid_float(U2, 150.0, 280.0) &&
|
|
|
|
|
is_valid_float(U3, 150.0, 280.0)) {
|
|
|
|
|
mqtt_send_U(U1, U2, U3);
|
|
|
|
|
influx_send_U(U1, U2, U3);
|
|
|
|
|
|
|
|
|
|
// --- DATA VALIDATION AND SENDING ---
|
|
|
|
|
|
|
|
|
|
if (first_run) {
|
|
|
|
|
prev_voltage = current_voltage;
|
|
|
|
|
prev_current = current_current;
|
|
|
|
|
prev_power = current_power;
|
|
|
|
|
prev_energy = current_energy;
|
|
|
|
|
prev_freq = current_freq;
|
|
|
|
|
first_run = 0;
|
|
|
|
|
printf("ORNO: First run, buffering initial measurements.\n");
|
|
|
|
|
} else {
|
|
|
|
|
s_voltage send_voltage;
|
|
|
|
|
s_current send_current;
|
|
|
|
|
s_power send_power;
|
|
|
|
|
s_energy send_energy;
|
|
|
|
|
s_frequency send_freq;
|
|
|
|
|
|
|
|
|
|
int spike_U = 0;
|
|
|
|
|
if (prev_voltage.U1 != 0 && (current_voltage.U1 > prev_voltage.U1 * 1.8 || current_voltage.U1 < prev_voltage.U1 * 0.2)) spike_U = 1;
|
|
|
|
|
if (prev_voltage.U2 != 0 && (current_voltage.U2 > prev_voltage.U2 * 1.8 || current_voltage.U2 < prev_voltage.U2 * 0.2)) spike_U = 1;
|
|
|
|
|
if (prev_voltage.U3 != 0 && (current_voltage.U3 > prev_voltage.U3 * 1.8 || current_voltage.U3 < prev_voltage.U3 * 0.2)) spike_U = 1;
|
|
|
|
|
|
|
|
|
|
if(spike_U) {
|
|
|
|
|
send_voltage = prev_voltage;
|
|
|
|
|
printf("ORNO: Voltage spike detected. Sending previous values.\n");
|
|
|
|
|
} else {
|
|
|
|
|
send_voltage = current_voltage;
|
|
|
|
|
prev_voltage = current_voltage;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int spike_I = 0;
|
|
|
|
|
if (prev_current.I1 != 0 && (current_current.I1 > prev_current.I1 * 1.8 || current_current.I1 < prev_current.I1 * 0.2)) spike_I = 1;
|
|
|
|
|
if (prev_current.I2 != 0 && (current_current.I2 > prev_current.I2 * 1.8 || current_current.I2 < prev_current.I2 * 0.2)) spike_I = 1;
|
|
|
|
|
if (prev_current.I3 != 0 && (current_current.I3 > prev_current.I3 * 1.8 || current_current.I3 < prev_current.I3 * 0.2)) spike_I = 1;
|
|
|
|
|
|
|
|
|
|
if(spike_I) {
|
|
|
|
|
send_current = prev_current;
|
|
|
|
|
printf("ORNO: Current spike detected. Sending previous values.\n");
|
|
|
|
|
} else {
|
|
|
|
|
send_current = current_current;
|
|
|
|
|
prev_current = current_current;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int spike_P = 0;
|
|
|
|
|
if (prev_power.P_Tot != 0 && (current_power.P_Tot > prev_power.P_Tot * 1.8 || current_power.P_Tot < prev_power.P_Tot * 0.2)) spike_P = 1;
|
|
|
|
|
|
|
|
|
|
if(spike_P) {
|
|
|
|
|
send_power = prev_power;
|
|
|
|
|
printf("ORNO: Power spike detected. Sending previous values.\n");
|
|
|
|
|
} else {
|
|
|
|
|
send_power = current_power;
|
|
|
|
|
prev_power = current_power;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int spike_W = 0;
|
|
|
|
|
if (prev_energy.W_Tot != 0 && (current_energy.W_Tot > prev_energy.W_Tot * 1.8 || current_energy.W_Tot < prev_energy.W_Tot)) spike_W = 1;
|
|
|
|
|
|
|
|
|
|
if(spike_W) {
|
|
|
|
|
send_energy = prev_energy;
|
|
|
|
|
printf("ORNO: Energy spike/drop detected. Sending previous values.\n");
|
|
|
|
|
} else {
|
|
|
|
|
send_energy = current_energy;
|
|
|
|
|
prev_energy = current_energy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int spike_F = 0;
|
|
|
|
|
if (prev_freq.Freq != 0 && (current_freq.Freq > prev_freq.Freq * 1.05 || current_freq.Freq < prev_freq.Freq * 0.95)) spike_F = 1; // 5% for frequency
|
|
|
|
|
|
|
|
|
|
if(spike_F) {
|
|
|
|
|
send_freq = prev_freq;
|
|
|
|
|
printf("ORNO: Frequency spike detected. Sending previous values.\n");
|
|
|
|
|
} else {
|
|
|
|
|
send_freq = current_freq;
|
|
|
|
|
prev_freq = current_freq;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("ORNO: Voltages: L1=%.1f V, L2=%.1f V, L3=%.1f V\n", send_voltage.U1, send_voltage.U2, send_voltage.U3);
|
|
|
|
|
if (is_valid_float(send_voltage.U1, 150.0, 280.0) && is_valid_float(send_voltage.U2, 150.0, 280.0) && is_valid_float(send_voltage.U3, 150.0, 280.0)) {
|
|
|
|
|
mqtt_send_U(send_voltage.U1, send_voltage.U2, send_voltage.U3);
|
|
|
|
|
influx_send_U(send_voltage.U1, send_voltage.U2, send_voltage.U3);
|
|
|
|
|
printf("ORNO: MQTT: Published voltages\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: MQTT: Skipping voltages - invalid values\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usleep(100000); /* 100ms delay between queries */
|
|
|
|
|
|
|
|
|
|
// PRADY (Currents)
|
|
|
|
|
memset((char *)reg, 0, sizeof(reg));
|
|
|
|
|
num = modbus_read_timed(ctx, 0x16, 6, reg); // ORNO
|
|
|
|
|
if (num != 6)
|
|
|
|
|
{
|
|
|
|
|
printf("ORNO: %x \t\n", 0x16);
|
|
|
|
|
printf("ORNO: Failed to read currents: %s\n", modbus_strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
I1 = modbus_get_float_abcd(®[0]);
|
|
|
|
|
I2 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
I3 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
printf("ORNO: Currents: L1=%.2f A, L2=%.2f A, L3=%.2f A\n", I1, I2, I3);
|
|
|
|
|
|
|
|
|
|
/* Validate currents (0-100A is reasonable range for home use) */
|
|
|
|
|
if (is_valid_float(I1, 0.0, 100.0) &&
|
|
|
|
|
is_valid_float(I2, 0.0, 100.0) &&
|
|
|
|
|
is_valid_float(I3, 0.0, 100.0)) {
|
|
|
|
|
mqtt_send_I(I1, I2, I3);
|
|
|
|
|
influx_send_I(I1, I2, I3);
|
|
|
|
|
printf("ORNO: Currents: L1=%.2f A, L2=%.2f A, L3=%.2f A\n", send_current.I1, send_current.I2, send_current.I3);
|
|
|
|
|
if (is_valid_float(send_current.I1, 0.0, 100.0) && is_valid_float(send_current.I2, 0.0, 100.0) && is_valid_float(send_current.I3, 0.0, 100.0)) {
|
|
|
|
|
mqtt_send_I(send_current.I1, send_current.I2, send_current.I3);
|
|
|
|
|
influx_send_I(send_current.I1, send_current.I2, send_current.I3);
|
|
|
|
|
printf("ORNO: MQTT: Published currents\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: MQTT: Skipping currents - invalid values\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usleep(100000); /* 100ms delay between queries */
|
|
|
|
|
|
|
|
|
|
memset((char *)reg, 0, sizeof(reg));
|
|
|
|
|
num = modbus_read_timed(ctx, 0x1c, 8, reg);
|
|
|
|
|
if (num != 8)
|
|
|
|
|
{ // number of read registers is not the one expected
|
|
|
|
|
printf("ORNO: %x \t\n", 0x1c);
|
|
|
|
|
printf("ORNO: Failed to read: %s\n", modbus_strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
P_Tot = modbus_get_float_abcd(®[0]);
|
|
|
|
|
P1 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
P2 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
P3 = modbus_get_float_abcd(®[6]);
|
|
|
|
|
printf("ORNO: Power: Total=%.3f W, L1=%.3f W, L2=%.3f W, L3=%.3f W\n", P_Tot, P1, P2, P3);
|
|
|
|
|
|
|
|
|
|
/* Validate power (-25000W to +25000W, allows negative for generation) */
|
|
|
|
|
if (is_valid_float(P_Tot, -25000.0, 25000.0) &&
|
|
|
|
|
is_valid_float(P1, -10000.0, 10000.0) &&
|
|
|
|
|
is_valid_float(P2, -10000.0, 10000.0) &&
|
|
|
|
|
is_valid_float(P3, -10000.0, 10000.0)) {
|
|
|
|
|
mqtt_send_P(P_Tot, P1, P2, P3);
|
|
|
|
|
influx_send_P(P_Tot, P1, P2, P3);
|
|
|
|
|
printf("ORNO: Power: Total=%.3f W, L1=%.3f W, L2=%.3f W, L3=%.3f W\n", send_power.P_Tot, send_power.P1, send_power.P2, send_power.P3);
|
|
|
|
|
if (is_valid_float(send_power.P_Tot, -25000.0, 25000.0) && is_valid_float(send_power.P1, -10000.0, 10000.0) && is_valid_float(send_power.P2, -10000.0, 10000.0) && is_valid_float(send_power.P3, -10000.0, 10000.0)) {
|
|
|
|
|
mqtt_send_P(send_power.P_Tot, send_power.P1, send_power.P2, send_power.P3);
|
|
|
|
|
influx_send_P(send_power.P_Tot, send_power.P1, send_power.P2, send_power.P3);
|
|
|
|
|
printf("ORNO: MQTT: Published power\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: MQTT: Skipping power - invalid values\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
usleep(100000); /* 100ms delay between queries */
|
|
|
|
|
|
|
|
|
|
memset((char *)reg, 0, sizeof(reg));
|
|
|
|
|
num = modbus_read_timed(ctx, 0x100, 8, reg);
|
|
|
|
|
if (num != 8)
|
|
|
|
|
{ // number of read registers is not the one expected
|
|
|
|
|
printf("ORNO: %x \t\n", 0x100);
|
|
|
|
|
printf("ORNO: Failed to read: %s\n", modbus_strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
W_Tot = modbus_get_float_abcd(®[0]);
|
|
|
|
|
W1 = modbus_get_float_abcd(®[2]);
|
|
|
|
|
W2 = modbus_get_float_abcd(®[4]);
|
|
|
|
|
W3 = modbus_get_float_abcd(®[6]);
|
|
|
|
|
printf("ORNO: Energy: Total=%.3f kWh, L1=%.3f kWh, L2=%.3f kWh, L3=%.3f kWh\n", W_Tot, W1, W2, W3);
|
|
|
|
|
|
|
|
|
|
/* Validate energy (0-1000000 kWh is reasonable range) */
|
|
|
|
|
if (is_valid_float(W_Tot, 0.0, 1000000.0) &&
|
|
|
|
|
is_valid_float(W1, 0.0, 1000000.0) &&
|
|
|
|
|
is_valid_float(W2, 0.0, 1000000.0) &&
|
|
|
|
|
is_valid_float(W3, 0.0, 1000000.0)) {
|
|
|
|
|
mqtt_send_W(W_Tot, W1, W2, W3);
|
|
|
|
|
influx_send_W(W_Tot, W1, W2, W3);
|
|
|
|
|
printf("ORNO: Energy: Total=%.3f kWh, L1=%.3f kWh, L2=%.3f kWh, L3=%.3f kWh\n", send_energy.W_Tot, send_energy.W1, send_energy.W2, send_energy.W3);
|
|
|
|
|
if (is_valid_float(send_energy.W_Tot, 0.0, 1000000.0) && is_valid_float(send_energy.W1, 0.0, 1000000.0) && is_valid_float(send_energy.W2, 0.0, 1000000.0) && is_valid_float(send_energy.W3, 0.0, 1000000.0)) {
|
|
|
|
|
mqtt_send_W(send_energy.W_Tot, send_energy.W1, send_energy.W2, send_energy.W3);
|
|
|
|
|
influx_send_W(send_energy.W_Tot, send_energy.W1, send_energy.W2, send_energy.W3);
|
|
|
|
|
printf("ORNO: MQTT: Published energy\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: MQTT: Skipping energy - invalid values\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usleep(10000); /* 10ms delay between queries */
|
|
|
|
|
|
|
|
|
|
// CZESTOTLIWOSC (Frequency)
|
|
|
|
|
memset((char *)reg, 0, sizeof(reg));
|
|
|
|
|
num = modbus_read_timed(ctx, 0x14, 2, reg); // ORNO
|
|
|
|
|
if (num != 2)
|
|
|
|
|
{
|
|
|
|
|
printf("ORNO: %x \t\n", 0x14);
|
|
|
|
|
printf("ORNO: Failed to read frequency: %s\n", modbus_strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Freq = modbus_get_float_abcd(®[0]);
|
|
|
|
|
printf("ORNO: Frequency: %.4f Hz\n", Freq);
|
|
|
|
|
|
|
|
|
|
/* Validate frequency (47-53 Hz is reasonable range for EU/US grid) */
|
|
|
|
|
if (is_valid_float(Freq, 47.0, 53.0)) {
|
|
|
|
|
mqtt_send_Hz(Freq);
|
|
|
|
|
influx_send_Hz(Freq);
|
|
|
|
|
printf("ORNO: Frequency: %.4f Hz\n", send_freq.Freq);
|
|
|
|
|
if (is_valid_float(send_freq.Freq, 47.0, 53.0)) {
|
|
|
|
|
mqtt_send_Hz(send_freq.Freq);
|
|
|
|
|
influx_send_Hz(send_freq.Freq);
|
|
|
|
|
printf("ORNO: MQTT: Published frequency\n");
|
|
|
|
|
} else {
|
|
|
|
|
printf("ORNO: MQTT: Skipping frequency - invalid value\n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
modbus_close(ctx);
|
|
|
|
|
modbus_free(ctx);
|
|
|
|
|
}
|
|
|
|
|
if (do_sun2k)
|
|
|
|
|
{
|
|
|
|
|
|