|
@@ -0,0 +1,346 @@
|
|
|
|
|
+#include <stdio.h>
|
|
|
|
|
+#include <unistd.h>
|
|
|
|
|
+#include <modbus.h>
|
|
|
|
|
+#include <string.h>
|
|
|
|
|
+#include <errno.h>
|
|
|
|
|
+#include <stdlib.h>
|
|
|
|
|
+#include <math.h>
|
|
|
|
|
+#include <sys/select.h>
|
|
|
|
|
+#include <sys/socket.h>
|
|
|
|
|
+#include <arpa/inet.h>
|
|
|
|
|
+#include <netinet/in.h>
|
|
|
|
|
+#include <time.h>
|
|
|
|
|
+
|
|
|
|
|
+#define NB_REGS 120
|
|
|
|
|
+#define NB_CONNECTION 5
|
|
|
|
|
+#define IEM3155_ADDRESS 1 // Modbus RTU slave address for iEM3155
|
|
|
|
|
+#define METER_OR_GATEWAY_PORT "502"
|
|
|
|
|
+#define TRANSLATOR_IP_ADDRESS "10.0.1.2"
|
|
|
|
|
+#define SYMO_IP_ADDRESS "10.0.1.3"
|
|
|
|
|
+
|
|
|
|
|
+#define MODBUS_SET_INT32_TO_INT16_FRONIUS(tab_int16, index, value) \
|
|
|
|
|
+ do { \
|
|
|
|
|
+ ((int16_t *) (tab_int16))[(index) + 1] = (int16_t) ((value) >> 16); \
|
|
|
|
|
+ ((int16_t *) (tab_int16))[(index)] = (int16_t) (value); \
|
|
|
|
|
+ } while (0)
|
|
|
|
|
+
|
|
|
|
|
+int stringModbusCopy(char * destination,char * source, int n){ // Custom method to write string in the right format for Modbus
|
|
|
|
|
+ // Copy even characters
|
|
|
|
|
+ for(int i = 0; i < n; i+=2){
|
|
|
|
|
+ destination[i + 1] = source[i];
|
|
|
|
|
+ }
|
|
|
|
|
+ // Copy odd characters
|
|
|
|
|
+ for(int i = 1; i < n; i+=2){
|
|
|
|
|
+ destination[i - 1] = source[i];
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int server_socket = -1;
|
|
|
|
|
+static modbus_mapping_t *mb_mapping_sunspec_snap;
|
|
|
|
|
+
|
|
|
|
|
+static modbus_t *ctx; // Context for requests to Symo
|
|
|
|
|
+static modbus_t *ctx2; // Context for requests from GEN24
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+static void close_sigint(int dummy)
|
|
|
|
|
+{
|
|
|
|
|
+ if (server_socket != -1) {
|
|
|
|
|
+ close(server_socket);
|
|
|
|
|
+ }
|
|
|
|
|
+ modbus_free(ctx);
|
|
|
|
|
+ modbus_free(ctx2);
|
|
|
|
|
+ //modbus_free(ctx4);
|
|
|
|
|
+ modbus_mapping_free(mb_mapping_sunspec_snap);
|
|
|
|
|
+
|
|
|
|
|
+ exit(dummy);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int snapUpdate(modbus_mapping_t *mapping, modbus_t *ctxbis){
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ uint16_t dest [NB_REGS];
|
|
|
|
|
+ struct timespec ts;
|
|
|
|
|
+ float v1, v2, v3;
|
|
|
|
|
+
|
|
|
|
|
+ ts.tv_sec = 0;
|
|
|
|
|
+ ts.tv_nsec = 500000000;
|
|
|
|
|
+ //printf("Debut update symo\n");
|
|
|
|
|
+ ret = modbus_read_registers(ctxbis, 40069, 40, dest); // Request sunspec model
|
|
|
|
|
+ if(ret < 0){
|
|
|
|
|
+ perror("Unable to update\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ //memcpy(&mapping->tab_registers[71], &dest[2], 2); // AC Total Current
|
|
|
|
|
+ /*printf("Test float abcd : %f\n",modbus_get_float_abcd(&dest[2]));
|
|
|
|
|
+ printf("Test float badc : %f\n",modbus_get_float_badc(&dest[2]));
|
|
|
|
|
+ printf("Test float cdab : %f\n",modbus_get_float_cdab(&dest[2]));
|
|
|
|
|
+ printf("Test float dcba : %f\n",modbus_get_float_dcba(&dest[2]));*/
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[2]), &mapping->tab_registers[71]); // AC Total Current
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[4]), &mapping->tab_registers[73]); // AC Ph1 Current
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[6]), &mapping->tab_registers[75]); // AC Ph2 Current
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[8]), &mapping->tab_registers[77]); // AC Ph3 Current
|
|
|
|
|
+ v1 = modbus_get_float_abcd(&dest[16]); // L1-N Voltage
|
|
|
|
|
+ modbus_set_float_badc(v1, &mapping->tab_registers[81]);
|
|
|
|
|
+ v2 = modbus_get_float_abcd(&dest[18]); // L2-N Voltage
|
|
|
|
|
+ modbus_set_float_badc(v2, &mapping->tab_registers[83]);
|
|
|
|
|
+ v3 = modbus_get_float_abcd(&dest[20]); // L3-N Voltage
|
|
|
|
|
+ modbus_set_float_badc(v3, &mapping->tab_registers[85]);
|
|
|
|
|
+ modbus_set_float_badc((v1 + v2 + v3)/3.0, &mapping->tab_registers[79]); // L-N Voltage avg
|
|
|
|
|
+ v1 = modbus_get_float_abcd(&dest[10]); // L1-L2 Voltage
|
|
|
|
|
+ modbus_set_float_badc(v1, &mapping->tab_registers[89]);
|
|
|
|
|
+ v2 = modbus_get_float_abcd(&dest[12]); // L2-L3 Voltage
|
|
|
|
|
+ modbus_set_float_badc(v2, &mapping->tab_registers[91]);
|
|
|
|
|
+ v3 = modbus_get_float_abcd(&dest[14]); // L3-L1 Voltage
|
|
|
|
|
+ modbus_set_float_badc(v3, &mapping->tab_registers[93]);
|
|
|
|
|
+ modbus_set_float_badc((v1 + v2 + v3)/3.0, &mapping->tab_registers[87]); // L-L Voltage avg
|
|
|
|
|
+ memcpy(&mapping->tab_registers[95], &dest[24], 2); // Frequency
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[22]), &mapping->tab_registers[97]); // AC Real power
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[26]), &mapping->tab_registers[105]); // AC Apparent power
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[28]), &mapping->tab_registers[113]); // AC Reactive power
|
|
|
|
|
+ modbus_set_float_badc(-1.0 * modbus_get_float_abcd(&dest[30]), &mapping->tab_registers[121]); // Power factor
|
|
|
|
|
+ memcpy(&mapping->tab_registers[129], &dest[32], 2); // Energy exported
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+int main()
|
|
|
|
|
+{
|
|
|
|
|
+ printf("Begin\n");
|
|
|
|
|
+ int ret;
|
|
|
|
|
+ int rc;
|
|
|
|
|
+ int header_length;
|
|
|
|
|
+ uint8_t *query;
|
|
|
|
|
+ uint8_t nb_retry = 0;
|
|
|
|
|
+ uint8_t slaveAddress;
|
|
|
|
|
+ uint16_t dest [NB_REGS];
|
|
|
|
|
+ uint16_t reg_address;
|
|
|
|
|
+ uint16_t nb_registers;
|
|
|
|
|
+ uint16_t tempTab [2];
|
|
|
|
|
+ fd_set refset;
|
|
|
|
|
+ fd_set rdset;
|
|
|
|
|
+ /* Maximum file descriptor number */
|
|
|
|
|
+ int fdmax;
|
|
|
|
|
+ int master_socket;
|
|
|
|
|
+ time_t update_snap;
|
|
|
|
|
+
|
|
|
|
|
+ //Reader preparation - Symo
|
|
|
|
|
+ ctx = modbus_new_tcp_pi(SYMO_IP_ADDRESS, "502");
|
|
|
|
|
+ if (ctx == NULL) {
|
|
|
|
|
+ perror("Unable to create the libmodbus context\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ ret = modbus_set_slave(ctx, 1);
|
|
|
|
|
+ if(ret < 0){
|
|
|
|
|
+ perror("modbus_set_slave error\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ modbus_set_response_timeout(ctx, 10, 0);
|
|
|
|
|
+ modbus_set_error_recovery(ctx, MODBUS_ERROR_RECOVERY_LINK);
|
|
|
|
|
+
|
|
|
|
|
+ ret = modbus_connect(ctx);
|
|
|
|
|
+ if(ret < 0){
|
|
|
|
|
+ perror("modbus_connect error\n");
|
|
|
|
|
+ //return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // Receiver preparation
|
|
|
|
|
+ ctx2 = modbus_new_tcp_pi(TRANSLATOR_IP_ADDRESS, "502"); // You have to use port TCP/502 here, because the GEN24 doesn't appreciate otherwise
|
|
|
|
|
+ if (ctx2 == NULL) {
|
|
|
|
|
+ perror("Unable to create the libmodbus context\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ server_socket = modbus_tcp_pi_listen(ctx2, NB_CONNECTION);
|
|
|
|
|
+ if (server_socket == -1) {
|
|
|
|
|
+ perror("Unable to listen\n");
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+ signal(SIGINT, close_sigint);
|
|
|
|
|
+
|
|
|
|
|
+ /* Clear the reference set of socket */
|
|
|
|
|
+ FD_ZERO(&refset);
|
|
|
|
|
+ /* Add the server socket */
|
|
|
|
|
+ FD_SET(server_socket, &refset);
|
|
|
|
|
+
|
|
|
|
|
+ /* Keep track of the max file descriptor */
|
|
|
|
|
+ fdmax = server_socket;
|
|
|
|
|
+
|
|
|
|
|
+ mb_mapping_sunspec_snap = modbus_mapping_new_start_address(0,0,0,0,40000,197,0,0);
|
|
|
|
|
+
|
|
|
|
|
+ // Static Sunspec Values - Symo
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[0] = 0x5375; // Sunspec ID
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[1] = 0x6e53; // Sunspec ID
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[2] = 1; // Sunspec ID
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[3] = 65; // Length of Sunspec model meter common
|
|
|
|
|
+ stringModbusCopy((char *) &mb_mapping_sunspec_snap->tab_registers[4], "Fronius", 7); // Manufacturer name
|
|
|
|
|
+ stringModbusCopy((char *) &mb_mapping_sunspec_snap->tab_registers[20], "Symo 6", 6); // Meter product name
|
|
|
|
|
+ stringModbusCopy((char *) &mb_mapping_sunspec_snap->tab_registers[36], "custom", 6); // Meter name (test)
|
|
|
|
|
+ stringModbusCopy((char *) &mb_mapping_sunspec_snap->tab_registers[44], "1.0", 3); // SW version
|
|
|
|
|
+ stringModbusCopy((char *) &mb_mapping_sunspec_snap->tab_registers[52], "0123456789", 10); // Serial number
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[68] = 5; // Modbus address
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[69] = 213; // Meter type (213 = Three phases + Neutral float)
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[70] = 124; // Length of Sunspec model ac_meter
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[195] = 0xFFFF; // End of model ac_meter
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[196] = 0; // End of model ac_meter
|
|
|
|
|
+
|
|
|
|
|
+ // Not implemented registers - Symo
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[99] = 0x7FC0; // Active power phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[101] = 0x7FC0; // Active power phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[103] = 0x7FC0; // Active power phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[107] = 0x7FC0; // Apparent power phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[109] = 0x7FC0; // Apparent power phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[111] = 0x7FC0; // Apparent power phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[115] = 0x7FC0; // Reactive power phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[117] = 0x7FC0; // Reactive power phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[119] = 0x7FC0; // Reactive power phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[123] = 0x7FC0; // Power factor phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[125] = 0x7FC0; // Power factor phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[127] = 0x7FC0; // Power factor phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[131] = 0x7FC0; // Active energy exported phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[133] = 0x7FC0; // Active energy exported phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[135] = 0x7FC0; // Active energy exported phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[139] = 0x7FC0; // Active energy imported phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[141] = 0x7FC0; // Active energy imported phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[143] = 0x7FC0; // Active energy imported phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[145] = 0x7FC0; // Apparent energy exported total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[147] = 0x7FC0; // Apparent energy exported phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[149] = 0x7FC0; // Apparent energy exported phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[151] = 0x7FC0; // Apparent energy exported phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[153] = 0x7FC0; // Apparent energy imported total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[155] = 0x7FC0; // Apparent energy imported phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[157] = 0x7FC0; // Apparent energy imported phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[159] = 0x7FC0; // Apparent energy imported phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[161] = 0x7FC0; // Reactive energy imported Q1 total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[163] = 0x7FC0; // Reactive energy imported Q1 phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[165] = 0x7FC0; // Reactive energy imported Q1 phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[167] = 0x7FC0; // Reactive energy imported Q1 phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[169] = 0x7FC0; // Reactive energy imported Q2 total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[171] = 0x7FC0; // Reactive energy imported Q2 phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[173] = 0x7FC0; // Reactive energy imported Q2 phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[175] = 0x7FC0; // Reactive energy imported Q2 phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[177] = 0x7FC0; // Reactive energy exported Q3 total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[179] = 0x7FC0; // Reactive energy exported Q3 phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[181] = 0x7FC0; // Reactive energy exported Q3 phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[183] = 0x7FC0; // Reactive energy exported Q3 phase 3
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[185] = 0x7FC0; // Reactive energy exported Q4 total
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[187] = 0x7FC0; // Reactive energy exported Q4 phase 1
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[189] = 0x7FC0; // Reactive energy exported Q4 phase 2
|
|
|
|
|
+ mb_mapping_sunspec_snap->tab_registers[191] = 0x7FC0; // Reactive energy exported Q4 phase 3
|
|
|
|
|
+
|
|
|
|
|
+ // Test data for Symo
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[71]); // AC Total Current
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[73]); // AC Ph1 Current
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[75]); // AC Ph2 Current
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[77]); // AC Ph3 Current
|
|
|
|
|
+ modbus_set_float_badc(230.0, &mb_mapping_sunspec_snap->tab_registers[81]);
|
|
|
|
|
+ modbus_set_float_badc(230.0, &mb_mapping_sunspec_snap->tab_registers[83]);
|
|
|
|
|
+ modbus_set_float_badc(230.0, &mb_mapping_sunspec_snap->tab_registers[85]);
|
|
|
|
|
+ modbus_set_float_badc(230.0, &mb_mapping_sunspec_snap->tab_registers[79]); // L-N Voltage avg
|
|
|
|
|
+ modbus_set_float_badc(400.0, &mb_mapping_sunspec_snap->tab_registers[89]);
|
|
|
|
|
+ modbus_set_float_badc(400.0, &mb_mapping_sunspec_snap->tab_registers[91]);
|
|
|
|
|
+ modbus_set_float_badc(400.0, &mb_mapping_sunspec_snap->tab_registers[93]);
|
|
|
|
|
+ modbus_set_float_badc(400.0, &mb_mapping_sunspec_snap->tab_registers[87]); // L-L Voltage avg
|
|
|
|
|
+ modbus_set_float_badc(50.0, &mb_mapping_sunspec_snap->tab_registers[95]); // Frequency
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[97]); // AC Real power
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[105]); // AC Apparent power
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[113]); // AC Reactive power
|
|
|
|
|
+ modbus_set_float_badc(100.0, &mb_mapping_sunspec_snap->tab_registers[121]); // Power factor
|
|
|
|
|
+ modbus_set_float_badc(0.0, &mb_mapping_sunspec_snap->tab_registers[129]); // Energy exported
|
|
|
|
|
+
|
|
|
|
|
+ if(snapUpdate(mb_mapping_sunspec_snap, ctx) == 0){
|
|
|
|
|
+ update_snap = time( NULL );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ update_snap = 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ header_length = modbus_get_header_length(ctx2);
|
|
|
|
|
+
|
|
|
|
|
+ for (;;) {
|
|
|
|
|
+ rdset = refset;
|
|
|
|
|
+ if (select(fdmax + 1, &rdset, NULL, NULL, NULL) == -1) {
|
|
|
|
|
+ perror("Server select() failure.");
|
|
|
|
|
+ close_sigint(1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Run through the existing connections looking for data to be
|
|
|
|
|
+ * read */
|
|
|
|
|
+ for (master_socket = 0; master_socket <= fdmax; master_socket++) {
|
|
|
|
|
+ if (!FD_ISSET(master_socket, &rdset)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (master_socket == server_socket) {
|
|
|
|
|
+ /* A client is asking a new connection */
|
|
|
|
|
+ socklen_t addrlen;
|
|
|
|
|
+ struct sockaddr_in clientaddr;
|
|
|
|
|
+ int newfd;
|
|
|
|
|
+
|
|
|
|
|
+ /* Handle new connections */
|
|
|
|
|
+ addrlen = sizeof(clientaddr);
|
|
|
|
|
+ memset(&clientaddr, 0, sizeof(clientaddr));
|
|
|
|
|
+ newfd = accept(server_socket, (struct sockaddr *) &clientaddr, &addrlen);
|
|
|
|
|
+ if (newfd == -1) {
|
|
|
|
|
+ perror("Server accept() error");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ FD_SET(newfd, &refset);
|
|
|
|
|
+
|
|
|
|
|
+ if (newfd > fdmax) {
|
|
|
|
|
+ /* Keep track of the maximum */
|
|
|
|
|
+ fdmax = newfd;
|
|
|
|
|
+ }
|
|
|
|
|
+ printf("New connection from %s:%d on socket %d\n",
|
|
|
|
|
+ inet_ntoa(clientaddr.sin_addr),
|
|
|
|
|
+ clientaddr.sin_port,
|
|
|
|
|
+ newfd);
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ modbus_set_socket(ctx2, master_socket);
|
|
|
|
|
+ rc = modbus_receive(ctx2, query);
|
|
|
|
|
+ if (rc > 0) {
|
|
|
|
|
+ if (query[header_length] == 0x03) {
|
|
|
|
|
+ //Read holding registers
|
|
|
|
|
+ reg_address = (uint16_t) MODBUS_GET_INT16_FROM_INT8(query, header_length + 1);
|
|
|
|
|
+ nb_registers = (uint16_t) MODBUS_GET_INT16_FROM_INT8(query, header_length + 3);
|
|
|
|
|
+ slaveAddress = query[header_length - 1];
|
|
|
|
|
+ //printf("Request received. Slave address : %d, register address : %d, nb registers : %d\n", slaveAddress, reg_address, nb_registers);
|
|
|
|
|
+ if(slaveAddress == 5) { // Symo snap meter
|
|
|
|
|
+ if(difftime(time(NULL), update_snap) > 9){
|
|
|
|
|
+ if(snapUpdate(mb_mapping_sunspec_snap, ctx) == 0){
|
|
|
|
|
+ update_snap = time( NULL);
|
|
|
|
|
+ //printf("Update symo\n");
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ //printf("Reply Symo\n");
|
|
|
|
|
+ rc = modbus_reply(ctx2, query, rc, mb_mapping_sunspec_snap);
|
|
|
|
|
+ if (rc == -1) {
|
|
|
|
|
+ perror("Error during reply");
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ printf("Slave not found : %d\n", slaveAddress);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ } else if (rc == -1) {
|
|
|
|
|
+ /* This example server in ended on connection closing or
|
|
|
|
|
+ * any errors. */
|
|
|
|
|
+ printf("Connection closed on socket %d\n", master_socket);
|
|
|
|
|
+ close(master_socket);
|
|
|
|
|
+
|
|
|
|
|
+ /* Remove from reference set */
|
|
|
|
|
+ FD_CLR(master_socket, &refset);
|
|
|
|
|
+
|
|
|
|
|
+ if (master_socket == fdmax) {
|
|
|
|
|
+ fdmax--;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //modbus_close(ctx);
|
|
|
|
|
+ //modbus_free(ctx);
|
|
|
|
|
+ free(query);
|
|
|
|
|
+ modbus_close(ctx2);
|
|
|
|
|
+ modbus_free(ctx2);
|