// https://libmodbus.org/getting_started/
/*
 *cd /home/olegk/qt/modbus_1
 *gcc main.cpp -o modbus_1 $(pkg-config --libs --cflags libmodbus)
 *
 *
 */

#include "dlfcn.h"
#include <stdio.h>
#include "modbus.h"
#include <iostream>
#include <cstring>

typedef modbus_t* modbus_tp;

typedef const char* (*p_modbus_strerror)(int);
typedef modbus_tp (*p_modbus_new_tcp)(const char*,int);
typedef void (*p_modbus_free)(modbus_t*);
typedef int (*p_modbus_connect)(modbus_t*);
typedef void (*p_modbus_close)(modbus_t*);
typedef int (*p_modbus_flush)(modbus_t*);
typedef int (*p_modbus_set_slave)(modbus_t*, int);
typedef int (*p_modbus_read_registers)(modbus_t*, int, int, uint16_t*);

p_modbus_strerror pmodbus_strerror;
p_modbus_new_tcp pmodbus_new_tcp;
p_modbus_free pmodbus_free;
p_modbus_connect pmodbus_connect;
p_modbus_close pmodbus_close;
p_modbus_flush pmodbus_flush;
p_modbus_set_slave pmodbus_set_slave;
p_modbus_read_registers pmodbus_read_registers;

using namespace std;

int main(void)
{
    void* handle=dlopen("libmodbus.so.5",RTLD_NOW);   //.5.1.0
    pmodbus_new_tcp=(p_modbus_new_tcp)dlsym(handle,"modbus_new_tcp");
    pmodbus_free=(p_modbus_free)dlsym(handle,"modbus_free");
    pmodbus_connect=(p_modbus_connect)dlsym(handle,"modbus_connect");
    pmodbus_close=(p_modbus_close)dlsym(handle,"modbus_close");
    pmodbus_flush=(p_modbus_flush)dlsym(handle,"modbus_flush");
    pmodbus_set_slave=(p_modbus_set_slave)dlsym(handle,"modbus_set_slave");
    pmodbus_strerror=(p_modbus_strerror)dlsym(handle,"modbus_strerror");
    pmodbus_read_registers=(p_modbus_read_registers)dlsym(handle,"modbus_read_registers");
//    const int REMOTE_ID = 1;
    modbus_t *ctx;
    uint16_t tab_reg[100];
    memset(tab_reg,0,sizeof(tab_reg));

//    ctx = modbus_new_rtu("/dev/ttyr00", 9600, 'N', 8, 1); //"/dev/ttyUSB0"
    ctx = (*pmodbus_new_tcp)("192.168.13.11", 502);
    if (ctx == NULL) {
        fprintf(stderr, "Unable to create the libmodbus context\n");
        dlclose(handle);
        return -1;
    }

    int iRes;
    iRes=(*pmodbus_connect)(ctx);
    cout << "connect: iRes=" << iRes << " errno=" << errno << endl;
    if (iRes == -1) {
        fprintf(stderr, "Connection failed: %s\n", (*pmodbus_strerror)(errno));
        (*pmodbus_free)(ctx);
        dlclose(handle);
        return -1;
    }
    const int REMOTE_ID = 1;
    (*pmodbus_set_slave)(ctx, REMOTE_ID);
    for(int j=0;j<5;j++){
        iRes=(*pmodbus_read_registers)(ctx,40000,12,tab_reg);
        cout << "read_registers: iRes=" << iRes << " errno=" << errno << " " <<
                (*pmodbus_strerror)(errno) << endl;
        float z=*(float*)&(tab_reg[0]);
        cout << z << " ";
        z=*(float*)&(tab_reg[3]);
        cout << z << endl;
        for(int i=0;i<4;i++)
            printf("%.4X ",tab_reg[i]);
        cout << endl;

    }

//    (*pmodbus_flush)(ctx);
    (*pmodbus_close)(ctx);
    (*pmodbus_free)(ctx);

    dlclose(handle);

    return 0;

}

