#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
 
#include <modbus.h>
 
#define MODBUS_SERVER_IP            "127.0.0.1"
#define MODBUS_SERVER_PORT          502
#define MODBUS_DEVICE_ID            100
#define MODBUS_TIMEOUT_SEC          3
#define MODBUS_TIMEOUT_USEC         0
#define MODBUS_DEBUG                ON
 
#define MODBUS_DISCRETE_ADDR        0
#define MODBUS_DISCRETE_LEN         32
#define MODBUS_COIL_ADDR            0
#define MODBUS_COIL_LEN             32
#define MODUBS_INPUT_ADDR           0
#define MODUBS_INPUT_LEN            64
#define MODUBS_HOLDING_ADDR         0
#define MODUBS_HOLDING_LEN          64
 
int main(int argc, char *argv[])
{
    modbus_t        *ctx;
    struct timeval  timeout;
    int             ret, ii;
    uint8_t         bits[MODBUS_MAX_READ_BITS] = {0};
    uint16_t        regs[MODBUS_MAX_READ_REGISTERS] = {0};
 
    ctx = modbus_new_tcp(MODBUS_SERVER_IP, MODBUS_SERVER_PORT);
 
    /* set device ID */
    modbus_set_slave(ctx, MODBUS_DEVICE_ID);
 
    /* Debug mode */
    modbus_set_debug(ctx, MODBUS_DEBUG);
 
    /* set timeout */
    timeout.tv_sec = MODBUS_TIMEOUT_SEC;
    timeout.tv_usec = MODBUS_TIMEOUT_USEC;
    modbus_get_byte_timeout(ctx, &timeout);
 
    timeout.tv_sec = MODBUS_TIMEOUT_SEC;
    timeout.tv_usec = MODBUS_TIMEOUT_USEC;
    modbus_set_response_timeout(ctx, &timeout);
 
    if (modbus_connect(ctx) == -1) {
        fprintf(stderr, "Connexion failed: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        exit(-1);
    }
 
    /* read discrete input (0x02 function code) */
    ret = modbus_read_input_bits(ctx,
            MODBUS_DISCRETE_ADDR, MODBUS_DISCRETE_LEN, bits);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    } else {
        printf("BITS DISCRETE:\n");
        for (ii=0; ii < ret; ii++) {
            printf("[%d]=%d\n", ii, bits[ii]);
        }
    }
 
    /* read coils (0x01 function code) */
    ret = modbus_read_bits(ctx, MODBUS_COIL_ADDR, MODBUS_COIL_LEN, bits);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    } else {
        printf("BITS COILS:\n");
        for (ii=0; ii < ret; ii++) {
            printf("[%d]=%d\n", ii, bits[ii]);
        }
    }
 
    /* read input registers (0x04 function code) */
    ret = modbus_read_input_registers(ctx,
            MODUBS_INPUT_ADDR, MODUBS_INPUT_LEN, regs);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    } else {
        printf("INPUT REGISTERS:\n");
        for (ii=0; ii < ret; ii++) {
            printf("[%d]=%d\n", ii, regs[ii]);
        }
    }
 
    /* read holding registers (0x03 function code) */
    ret = modbus_read_registers(ctx,
            MODUBS_HOLDING_ADDR, MODUBS_HOLDING_LEN, regs);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    } else {
        printf("HOLDING REGISTERS:\n");
        for (ii=0; ii < ret; ii++) {
            printf("[%d]=%d\n", ii, regs[ii]);
        }
    }
 
    /* write single coil (0x05 function code) */
    ret = modbus_write_bit(ctx, 1, TRUE);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    }
 
    /* write single register (0x06 function code) */
    ret = modbus_write_register(ctx, 1, 0x1234);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    }
 
    /* write multi coil (0x0F function code) */
    bits[1] = TRUE;
    bits[2] = FALSE;
    ret = modbus_write_bits(ctx, 1, 2, &bits[1]);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    }
 
    /* write multi registers (0x10 function code) */
    regs[1] = 0x1234;
    regs[2] = 0x5678;
    ret = modbus_write_registers(ctx, 1, 2, &regs[1]);
    if (ret < 0) {
        fprintf(stderr, "%s\n", modbus_strerror(errno));
    }
 
    /* Close the connection */
    modbus_close(ctx);
    modbus_free(ctx);
 
    exit(0);
}