int main(int argc, char *argv[])
{
    int socket;
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;
    int rc;
    int use_backend;

     /* TCP */
    if (argc > 1) {
        if (strcmp(argv[1], "tcp") == 0) {
            use_backend = TCP;
        } else if (strcmp(argv[1], "rtu") == 0) {
            use_backend = RTU;
        } else {
            printf("Usage:\n  %s [tcp|rtu] - Modbus client to measure data bandwith\n\n", argv[0]);
            exit(1);
        }
    } else {
        /* By default */
        use_backend = TCP;
    }

    if (use_backend == TCP) {
        ctx = modbus_new_tcp("127.0.0.1", 1502);
        socket = modbus_tcp_listen(ctx, 1);
        modbus_tcp_accept(ctx, &socket);

    } else {
        ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
        modbus_set_slave(ctx, 1);
        modbus_connect(ctx);
    }

    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                    MODBUS_MAX_READ_REGISTERS, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    for(;;) {
        uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];

        rc = modbus_receive(ctx, query);
        if (rc >= 0) {
            modbus_reply(ctx, query, rc, mb_mapping);
        } else {
            /* Connection closed by the client or server */
            break;
        }
    }

    printf("Quit the loop: %s\n", modbus_strerror(errno));

    modbus_mapping_free(mb_mapping);
    close(socket);
    modbus_free(ctx);

    return 0;
}
int main(int argc, char *argv[]) {
    modbus_t       *ctx_tcp;
    modbus_t    *ctx_serial;

    uint8_t        *query;
    uint8_t         *raw_query;
    uint8_t        *raw_reply;
    int             header_length;
    int             socket;
    int rc;

    modbus_mapping_t *mb_mapping;
    modbus_mapping_t *local_mb_mapping;

    const int RAW_REQ_LENGTH = 10;
    int RTU;
    int exitFlag = 0; // Set to non-zero to exit.
    //    int opt=1;
    int cnt=1;

    //    int tty_len=0;

    int baud_rate=9600;
    char parity='N';
    int length=8;
    int stop_bits=2;
    char *tty=(char *)NULL;
    char *ip=(char *)NULL;
    int port=1502;
    int verbose=1;
    int io_address=0;
    int tmp_address=0;

    uint16_t *localInputRegisters;
    int localInputRegistersSize;

    uint16_t *localHoldingRegisters;
    int localHoldingRegistersSize;

    int holdingShmKey=0;
    int holdingShmId=0;

    int holdingSemKey=0;
    int holdingSemId=0;


    int inputShmKey=0;
    int inputShmId=0;

    int inputSemKey=0;
    int inputSemId=0;

    int i;
    unsigned char *tmp;
    int ch;    // for getopt
    char *iniFile=(char *)NULL;
    char *ptr;

    int useSharedInput=0;
    int useSharedHolding=0;
    int modbusDebug = 0;
    int localRTU = 0;
    int serialRTUenabled = 0;

    char *iniFileName[] = {
        "/etc/newServer.ini",
        "/usr/local/etc/newServer.ini",
        "./newServer.ini"
    };

    while ((ch = getopt(argc,argv,"b:c:h?i:p:P:t:v")) != -1) {
        switch (ch) {
            case 'c':
                if ( iniFile != (char *)NULL) {
                    free(iniFile);
                }
                iniFile = strsave( optarg );

                if(verbose)
                    printf("Set ini file to %s\n",iniFile);
                break;
            case 'n':   // baud rate
                baud_rate=atoi(optarg);
                break;
            case 'h':
            case '?':
                usage();
                exit(0);
                break;
            case 'i':
                if ( ip != (char *)NULL) {
                    free(ip);
                }
                ip=strsave( optarg );
                break;
            case 'p':
                port=atoi( optarg );
                break;
            case 'P':
                parity=optarg[0];

                if ('E' != parity && 'O' != parity && 'N' != parity) {
                    fprintf(stderr,"Invalid parity %c, exiting.\n",parity);
                    exit(-1);
                }
                break;
            case 't':   // serial port
                if ( tty != (char *)NULL) {
                    free( tty );
                }
                tty=strsave( optarg );
                break;
            case 'v':
                verbose=1;
                break;
            default:
                break;
        }
    }

    if (iniFile == (char *)NULL) {
        for(i=0;(i<3 && (iniFile == (char *)NULL))  ;i++) {

            if ( verbose) {
                printf("%d:%s\n",i, iniFileName[i]);
            }

            if( 0 == access( iniFileName[i],R_OK)) {
                if(verbose ) {
                    printf("\tFile exists\n");
                }
                iniFile = strsave( iniFileName[i]);
            }
        }
    }    

    if (iniFile == (char *)NULL ) {
        printf("No existing ini file.\n");
        // Create an default file

        iniFile=strsave("./newServer.ini");
        printf("\tCreating new ini file %s\n", iniFile);

        createIni( iniFile );
        //        exit(0);
    }

    ini = iniparser_load( iniFile );
    ptr= iniparser_getstring(ini,"network:IP","127.0.0.1");

    if((char *)NULL == ip) {
        ip=strsave(ptr);
    }

    if (0 == port) {
        port = iniparser_getint(ini,"network:port",1502);
    }

    if (-1 == verbose) {
        verbose = iniparser_getboolean(ini,"system:verbose",0);
    }

    localHoldingRegistersSize = iniparser_getint(ini,"system:holding_reg_size", LOCAL_HOLDING_REGISTERS);

    localInputRegistersSize = iniparser_getint(ini,"system:input_reg_size", LOCAL_INPUT_REGISTERS);

    useSharedInput = iniparser_getboolean(ini,"system:share_input",0);
    useSharedHolding = iniparser_getboolean(ini,"system:share_holding",0);

    modbusDebug = iniparser_getboolean(ini,"modbus:debug",0);

    localRTU = iniparser_getint(ini,"modbus:LOCAL_RTU",255);

    serialRTUenabled = iniparser_getboolean(ini,"modbus:RTU",0);

    if( serialRTUenabled ) {
        if( (char *) NULL == tty) {
            tty = iniparser_getstring(ini,"modbus:tty","/dev/ttyUSB0");
        }
    } else {
        tty = (char *)NULL;
    }


    if(verbose) {
        printf("\n\t\tSettings\n");
        printf(  "\t\t========\n\n");
        printf("\tBuild Date\t:%s\n",__DATE__);
        printf("\tAddress\t\t:%s\n",ip);
        printf("\tNetwork port\t:%d\n",port);
        printf("\tSerial port\t:%s\n",tty);
        printf("\tBaud rate\t:%d\n",baud_rate);
        printf("\tParity\t\t:%c\n",parity);
    } else {
        printf("\nStarted.\n");
    }

    if (serialRTUenabled ) {
        if(access(tty,F_OK) == 0) {
            printf("Serial port %s exists.....\n",tty);
            // 
            // Now test that it is readable, writable.
            //
        } else {
            printf("Serial port %s does NOT exist\n",tty);
            printf("Disabling serial RTU.\n");
            free( tty );
            tty = (char *)NULL;
            serialRTUenabled=0;
        }
    }

    query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
    raw_query = malloc(RAW_REQ_LENGTH);
    raw_reply = malloc(MODBUS_TCP_MAX_ADU_LENGTH);

    mb_mapping = modbus_mapping_new(
            MODBUS_MAX_BITS,   // Coils
            MODBUS_MAX_BITS,   // Discrete inputs
            MODBUS_MAX_REGISTERS,   // Holding registers
            MODBUS_MAX_REGISTERS);  // Input registers

    local_mb_mapping = modbus_mapping_new(
            NULL,   // Coils
            NULL,   // Discrete inputs
            LOCAL_HOLDING_REGISTERS,   // Holding registers
            LOCAL_INPUT_REGISTERS);  // Input registers

    // 
    // Setup the memory for the holding registers.
    //
    if ( useSharedHolding ) {
        if (verbose)
            printf("Share the Holding regsisters R/W\n");

        localHoldingRegisters = local_mb_mapping->tab_registers;

        holdingShmKey = iniparser_getint(ini, "system:holding_reg_key",110);
        holdingSemKey = iniparser_getint(ini, "system:holding_reg_sema",111);

        holdingShmId = shmget(holdingShmKey, localHoldingRegistersSize, IPC_CREAT | 0600 );  // change to 0400

        if (holdingShmId < 0) {
            perror("Holding Reg shmget");
            exit(3);
        }
        local_mb_mapping->tab_registers = (uint16_t *)shmat(holdingShmId,NULL,0);
        if (local_mb_mapping->tab_registers < 0) {
            perror("Holding Reg shmat");
            exit(4);
        }

        /* 
         * Create the seamphore 
         */
        holdingSemId = semget( holdingSemKey, 1, IPC_CREAT | 0600 );
        if (-1 == holdingSemId) {
            perror("Input reg semaphore");
            exit(2);
        }
        /*
         *         Shared memory created, semaphore created (default is locked)
         *         release the seamphore !
         */
        rc = semctl(holdingSemId, 0, SETVAL, 1);

    }
    // 
    // Setup the memory for the shared input registers.
    // 
    if ( useSharedInput ) {
        if (verbose)
            printf("Share the Input regsisters R/W\n");

        localInputRegisters = local_mb_mapping->tab_input_registers; // Save the current pointer

        inputShmKey = iniparser_getint(ini, "system:input_reg_key",110);
        inputSemKey = iniparser_getint(ini, "system:input_reg_sema",111);

        inputShmId = shmget(inputShmKey, localInputRegistersSize, IPC_CREAT | 0600 );  // change to 0400

        if (inputShmId < 0) {
            perror("Input Reg shmget");
            exit(3);
        }
        local_mb_mapping->tab_input_registers = (uint16_t *)shmat(inputShmId,NULL,0);

        if ( local_mb_mapping->tab_input_registers < 0) {
            perror("Input Reg shmat");
            exit(1);
        }

        /* 
         * create the seamphore 
         */
        inputSemId = semget( inputSemKey, 1, IPC_CREAT | 0600 );
        if (-1 == inputSemId) {
            perror("Input reg semaphore");
            exit(2);
        }
        /*
         *         Shared memory created, semaphore created (default is locked)
         *         release the seamphore !
         */
        rc = semctl(inputSemId, 0, SETVAL, 1);

    }

    memset( localInputRegisters,0x00, LOCAL_INPUT_REGISTERS);
    memset( localHoldingRegisters,0x00, LOCAL_HOLDING_REGISTERS);

    local_mb_mapping->tab_input_registers[0]=0xaa55;

    ctx_tcp = modbus_new_tcp(ip, port);

    if ( tty != (char *)NULL ) {
        ctx_serial = modbus_new_rtu(tty, baud_rate, parity, length, stop_bits);
    }

    while ( !exitFlag ) {
        header_length = modbus_get_header_length(ctx_tcp);

        if(verbose) {
            modbus_set_debug(ctx_tcp, TRUE);
            //            modbus_set_debug(ctx_serial, TRUE);
        }

        do {
            socket = modbus_tcp_listen(ctx_tcp, 5);
            if (socket < 0) {
                printf("%04d: Socket in use.\n",cnt++);
                sleep(1);
            }
        } while(socket < 0);
        //        printf("modbus_tcp_listen   =%d\n",socket);
        if (socket == -1) {
            printf("\t: %s\n", modbus_strerror(errno));
        }

        rc=modbus_tcp_accept(ctx_tcp, &socket);

        //        printf("modbus_tcp_accept rc=%d\n",rc);
        if (rc == -1) {
            fprintf(stderr,"FATAL ERROR: %s\n", modbus_strerror(errno));
            exit(-1);
        }

        while ( 1 ) {
            do {
                if(verbose) {
                    printf("Recieve.\n");
                }
                rc = modbus_receive(ctx_tcp, query);
                //                printf("rc=%d\n",rc);
                /* Filtered queries return 0 */
            } while (rc == 0);

            if (-1 == rc) {
                if( verbose ) {
                    printf("Client disconnected.\n");
                }
                break;
            }
            RTU=query[header_length - 1];
            io_address= ( query[header_length+1] << 8) + (query[header_length+2] & 0xff);

            printf("IO Address=%04x\n",io_address);

            if (verbose) {
                if( localRTU == RTU ) {
                    printf("It's for me !\n");
                } else {
                    printf("RTU Id: %02d\n",RTU);
                }

                printf("IO Address=0x%04x\n",io_address);
                printf("Seq Number=0x%04x\n", query[1]);
            }   

            if( localRTU == RTU ) {
                //
                // Local mapping
                //
                int len;
                uint16_t data;
                int cnt=0;

                // Need to add address range checks, and return an error 
                // for an invalid function.

                switch (query[header_length]) {
                    case 0x03:  // read holding registers
                    case 0x04:  // read input registers
                        rc = modbus_reply(ctx_tcp, query, rc, local_mb_mapping);
                        break;
                    case 0x06: //write single register
                        swab(&query[8],&len,2);
                        swab(&query[10],&data,2);
                        printf("Data=%02d\n",data);

                        local_mb_mapping->tab_registers[io_address]=data;
                        rc = modbus_reply(ctx_tcp, query, rc, local_mb_mapping);
                        break;
                    case 0x10: // Write multiple registers
                        //                        len=query[7];
                        swab(&query[10],&len,2);
                        printf("Length=%02d\n",len);

                        for (i=13; i< (13 + len ); i +=2) {
                            data= (query[i] << 8) + (query[i+1] & 0xff);
                            printf("%04x\n",data);

                            local_mb_mapping->tab_registers[ io_address + cnt++ ] = data;
                        }
                        rc = modbus_reply(ctx_tcp, query, rc, local_mb_mapping);
                        break;

                    default:
                        break;
                }
            } else {
                if(serialRTUenabled)  {

                    modbus_set_slave( ctx_serial,RTU);
                    if( -1 == modbus_connect( ctx_serial)) {
                        fprintf(stderr, "Connection failed: %s\n",modbus_strerror(errno));
                    }
                    switch( query[header_length] ) {
                        case 0x06:
                            printf("Write Single Register %d\n",RTU);
                            memcpy(raw_query,&query[header_length-1], 6);
                            rc=modbus_send_raw_request( ctx_serial,raw_query,6);
                            modbus_receive_confirmation(ctx_serial, raw_reply);
                            rc = modbus_reply(ctx_tcp, query, rc, mb_mapping);

                            break;
                        case 0x03:
                        case 0x04:
                            printf("Read Registers %d\n",RTU);
                            break;
                        case 0x10:
                            {
                                int len=0;
                                //	      modbus_set_debug(ctx_serial, TRUE);

                                printf("Write multiple registers %d\n",RTU);
                                len=query[header_length - 2];
                                printf("Length %d\n",len);
                                memcpy(raw_query,&query[header_length-1], len);

                                rc=modbus_send_raw_request( ctx_serial,raw_query,len);
                                if( -1 == rc) {
                                    printf("modbus_send_raw_request: %s\n",modbus_strerror(errno));
                                } else {
                                    modbus_receive_confirmation(ctx_serial, raw_reply);
                                    rc = modbus_reply(ctx_tcp, query, rc, mb_mapping);
                                    printf("rc =  %d\n",rc);
                                    //		modbus_set_debug(ctx_serial, FALSE);
                                }
                            } 
                            break;
                    }

                    if( (0x03 == query[header_length]) || (0x04 == query[header_length])) {
                        int len;

                        if(verbose) {
                            switch (query[header_length]) {
                                case 0x03:
                                    printf("Read Holding Registers.\n");
                                    break;
                                case 0x04:
                                    printf("Read Input Registers.\n");
                                    break;
                                default:
                                    break;
                            }
                        }

                        memcpy(raw_query,&query[header_length-1], 6);

                        modbus_set_slave( ctx_serial, query[header_length-1]);

                        if( -1 == modbus_connect( ctx_serial)) {
                            fprintf(stderr, "Connection failed: %s\n",modbus_strerror(errno));
                        }

                        rc=modbus_send_raw_request( ctx_serial,raw_query,6);

                        if( -1 == rc ) {
                            printf("modbus_send_raw_request: %s\n",modbus_strerror(errno));
                        }

                        modbus_receive_confirmation(ctx_serial, raw_reply);
                        /*
                         * This next loop swaps bytes in words.
                         * If this is built and running on a little endian 
                         * machine (most machines are these days)
                         * Then this needs to be done.  
                         * If on a big endian machine (M68000 family) just 
                         * comment this out.
                         *                     
                         * It might be worth having a command line switch,
                         * detect endianness.
                         *                     
                         */

                        switch (query[header_length]) {
                            case 0x03:
                                printf("Read Holding Registers.\n");
                                tmp=(unsigned char *)mb_mapping->tab_registers;
                                break;
                            case 0x04:
                                printf("Read Input Registers.\n");
                                tmp=(unsigned char *)mb_mapping->tab_input_registers;
                                break;
                            default:
                                break;
                        }

                        tmp_address = (io_address*2);

                        for(i=0;i<raw_reply[2];i=i+2 ) {
                            tmp[tmp_address+i]=raw_reply[i+4];
                            tmp[tmp_address+i+1]=raw_reply[i+3];
                        }

                        for(i=0;i<10;i++) {
                            if (verbose) {
                                printf("!%02x!",raw_reply[i]);
                            }
                        }
                        printf("\n");

                        for(i=0;i<10;i++) {
                            if (verbose) {
                                printf("+%02x+",tmp[i]);
                            }
                        }
                        printf("\n");

                        //
                        // compute packet length by getting the data length 
                        // and then add 2.
                        // Then overwrite the outbound data.
                        //
                        len=raw_reply[2] + 3;
                        rc = modbus_reply(ctx_tcp, query, rc, mb_mapping);

                        //    memcpy(  mb_mapping->tab_input_registers, &raw_reply[3], raw_reply[2]);

                        //    MODBUS_SET_INT16_TO_INT8(query, header_length + 3, UT_REGISTERS_NB_SPECIAL - 1);

                    }
                }
            }

            //    printf("Reply with an invalid TID or slave\n");
            //    rc=modbus_reply_exception(ctx_tcp, query, 1);
            //    rc=modbus_send_raw_request(ctx_tcp, raw_reply, 10 * sizeof(uint8_t));


            //      rc = modbus_reply(ctx_tcp, query, rc, mb_mapping);
        }

        if( verbose ) {
            printf("Tidying up\n");
        }
        close(socket);

        usleep( 1000 ); // wait 1 ms

    }
    printf("simpleServer exiting.\n");
    modbus_close(ctx_tcp);
    modbus_free(ctx_tcp);
    free(query);
    modbus_mapping_free(mb_mapping);
    return(0);
}
int main(int argc, char*argv[])
{
    int s = -1;
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;
    int rc;
    int i;
    int use_backend;
    uint8_t *query;
    int header_length;

    if (argc > 1) {
        if (strcmp(argv[1], "tcp") == 0) {
            use_backend = TCP;
        } else if (strcmp(argv[1], "tcppi") == 0) {
            use_backend = TCP_PI;
        } else if (strcmp(argv[1], "rtu") == 0) {
            use_backend = RTU;
		} else if (strcmp(argv[1], "rtuASCII") == 0) {
			use_backend = RTU_ASCII;
        } else {
            printf("Usage:\n  %s [tcp|tcppi|rtu] - Modbus server for unit testing\n\n", argv[0]);
            return -1;
        }
    } else {
        /* By default */
        use_backend = TCP;
    }

    if (use_backend == TCP) {
        ctx = modbus_new_tcp("127.0.0.1", 1502);
        query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
    } else if (use_backend == TCP_PI) {
        ctx = modbus_new_tcp_pi("::0", "1502");
        query = malloc(MODBUS_TCP_MAX_ADU_LENGTH);
	} else if (use_backend == RTU_ASCII) {
		// NOTE: In Client and server you can use any serial port
		// in your system here.  (see server) I had a double
		// serial port USB device so I used port 1 in server
		// and 2 in client
		ctx = modbus_new_rtu_ascii("/dev/cu.USA28X1a123P1.2", 115200, 'N', 8, 1);
    } else {
        ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
        modbus_set_slave(ctx, SERVER_ID);
        query = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
    }
    header_length = modbus_get_header_length(ctx);

    modbus_set_debug(ctx, TRUE);

    mb_mapping = modbus_mapping_new(
        UT_BITS_ADDRESS + UT_BITS_NB,
        UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
        UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /* Unit tests of modbus_mapping_new (tests would not be sufficient if two
       nb_* were identical) */
    if (mb_mapping->nb_bits != UT_BITS_ADDRESS + UT_BITS_NB) {
        printf("Invalid nb bits (%d != %d)\n", UT_BITS_ADDRESS + UT_BITS_NB, mb_mapping->nb_bits);
        modbus_free(ctx);
        return -1;
    }

    if (mb_mapping->nb_input_bits != UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB) {
        printf("Invalid nb input bits: %d\n", UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB);
        modbus_free(ctx);
        return -1;
    }

    if (mb_mapping->nb_registers != UT_REGISTERS_ADDRESS + UT_REGISTERS_NB) {
        printf("Invalid nb registers: %d\n", UT_REGISTERS_ADDRESS + UT_REGISTERS_NB);
        modbus_free(ctx);
        return -1;
    }

    if (mb_mapping->nb_input_registers != UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB) {
        printf("Invalid nb input registers: %d\n", UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);
        modbus_free(ctx);
        return -1;
    }

    /* Examples from PI_MODBUS_300.pdf.
       Only the read-only input values are assigned. */

    /** INPUT STATUS **/
    modbus_set_bits_from_bytes(mb_mapping->tab_input_bits,
                               UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
                               UT_INPUT_BITS_TAB);

    /** INPUT REGISTERS **/
    for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
        mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
            UT_INPUT_REGISTERS_TAB[i];;
    }

    if (use_backend == TCP) {
        s = modbus_tcp_listen(ctx, 1);
        modbus_tcp_accept(ctx, &s);
    } else if (use_backend == TCP_PI) {
        s = modbus_tcp_pi_listen(ctx, 1);
        modbus_tcp_pi_accept(ctx, &s);
    } else {
        rc = modbus_connect(ctx);
        if (rc == -1) {
            fprintf(stderr, "Unable to connect %s\n", modbus_strerror(errno));
            modbus_free(ctx);
            return -1;
        }
    }

    for (;;) {
        do {
            rc = modbus_receive(ctx, query);
            /* Filtered queries return 0 */
        } while (rc == 0);

        /* The connection is not closed on errors which require on reply such as
           bad CRC in RTU. */
        if (rc == -1 && errno != EMBBADCRC) {
            /* Quit */
            break;
        }

        /* Special server behavior to test client */
        if (query[header_length] == 0x03) {
            /* Read holding registers */

            if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3)
                == UT_REGISTERS_NB_SPECIAL) {
                printf("Set an incorrect number of values\n");
                MODBUS_SET_INT16_TO_INT8(query, header_length + 3,
                                         UT_REGISTERS_NB_SPECIAL - 1);
            } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
                       == UT_REGISTERS_ADDRESS_SPECIAL) {
                printf("Reply to this special register address by an exception\n");
                modbus_reply_exception(ctx, query,
                                       MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY);
                continue;
            } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
                       == UT_REGISTERS_ADDRESS_INVALID_TID_OR_SLAVE) {
                const int RAW_REQ_LENGTH = 5;
                uint8_t raw_req[] = {
                    (use_backend == RTU || use_backend == RTU_ASCII) ? INVALID_SERVER_ID : 0xFF,
                    0x03,
                    0x02, 0x00, 0x00
                };

                printf("Reply with an invalid TID or slave\n");
                modbus_send_raw_request(ctx, raw_req, RAW_REQ_LENGTH * sizeof(uint8_t));
                continue;
            } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
                       == UT_REGISTERS_ADDRESS_SLEEP_500_MS) {
                printf("Sleep 0.5 s before replying\n");
                usleep(500000);
            } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
                       == UT_REGISTERS_ADDRESS_BYTE_SLEEP_5_MS) {
                /* Test low level only available in TCP mode */
                /* Catch the reply and send reply byte a byte */
                uint8_t req[] = "\x00\x1C\x00\x00\x00\x05\xFF\x03\x02\x00\x00";
                int req_length = 11;
                int w_s = modbus_get_socket(ctx);

                /* Copy TID */
                req[1] = query[1];
                for (i=0; i < req_length; i++) {
                    printf("(%.2X)", req[i]);
                    usleep(5000);
                    send(w_s, (const char*)(req + i), 1, MSG_NOSIGNAL);
                }
                continue;
            }
        }

        rc = modbus_reply(ctx, query, rc, mb_mapping);
        if (rc == -1) {
            break;
        }
    }

    printf("Quit the loop: %s\n", modbus_strerror(errno));

    if (use_backend == TCP) {
        if (s != -1) {
            close(s);
        }
    }
    modbus_mapping_free(mb_mapping);
    free(query);
    /* For RTU */
    modbus_close(ctx);
    modbus_free(ctx);

    return 0;
}
int main(void)
{
    int master_socket;
    int rc;
    fd_set refset;
    fd_set rdset;

    /* Maximum file descriptor number */
    int fdmax;

    ctx = modbus_new_tcp("127.0.0.1", 1502);

    mb_mapping = modbus_mapping_new(MODBUS_MAX_READ_BITS, 0,
                                    MODBUS_MAX_READ_REGISTERS, 0);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    server_socket = modbus_listen(ctx, NB_CONNECTION);

    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;

    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)) {
                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 {
                    /* An already connected master has sent a new query */
                    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];

                    rc = modbus_receive(ctx, master_socket, query);
                    if (rc != -1) {
                        modbus_reply(ctx, query, rc, mb_mapping);
                    } else {
                        /* Connection closed by the client, end of server */
                        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--;
                        }
                    }
                }
            }
        }
    }

    return 0;
}
int main(int argc, char*argv[])
{
    int socket;
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;
    int rc;
    int i;
    int use_backend;
    uint8_t *query;
    int header_length;

    if (argc > 1) {
        if (strcmp(argv[1], "tcp") == 0) {
            use_backend = TCP;
        } else if (strcmp(argv[1], "tcppi") == 0) {
            use_backend = TCP_PI;
        } else if (strcmp(argv[1], "rtu") == 0) {
            use_backend = RTU;
        } else {
            printf("Usage:\n  %s [tcp|tcppi|rtu] - Modbus server for unit testing\n\n", argv[0]);
            return -1;
        }
    } else {
        /* By default */
        use_backend = TCP;
    }

    if (use_backend == TCP) {
        printf("Modbus TCP server for unit testing.\n");
        ctx = modbus_new_tcp("127.0.0.1", 1502);
        query = (uint8_t *)malloc(MODBUS_TCP_MAX_ADU_LENGTH);
    } else if (use_backend == TCP_PI) {
        ctx = modbus_new_tcp_pi("::0", "1502");
        query = (uint8_t *)malloc(MODBUS_TCP_MAX_ADU_LENGTH);
    } else {
        printf("Modbus RTU server for unit testing.\n");
        ctx = modbus_new_rtu("/dev/ttyUSB0", 115200, 'N', 8, 1);
        modbus_set_slave(ctx, SERVER_ID);
        query = (uint8_t *)malloc(MODBUS_RTU_MAX_ADU_LENGTH);
    }
    header_length = modbus_get_header_length(ctx);

    modbus_set_debug(ctx, TRUE);

    mb_mapping = modbus_mapping_new(
        UT_BITS_ADDRESS + UT_BITS_NB,
        UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
        UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    /* Examples from PI_MODBUS_300.pdf.
       Only the read-only input values are assigned. */

    /** INPUT STATUS **/
    modbus_set_bits_from_bytes(mb_mapping->tab_input_bits,
                               UT_INPUT_BITS_ADDRESS, UT_INPUT_BITS_NB,
                               UT_INPUT_BITS_TAB);

    /** INPUT REGISTERS **/
    for (i=0; i < UT_INPUT_REGISTERS_NB; i++) {
        mb_mapping->tab_input_registers[UT_INPUT_REGISTERS_ADDRESS+i] =
            UT_INPUT_REGISTERS_TAB[i];;
    }

    if (use_backend == TCP) {
        socket = modbus_tcp_listen(ctx, 1);
        modbus_tcp_accept(ctx, &socket);
    } else if (use_backend == TCP_PI) {
        socket = modbus_tcp_pi_listen(ctx, 1);
        modbus_tcp_pi_accept(ctx, &socket);
    } else {
        rc = modbus_connect(ctx);
        if (rc == -1) {
            fprintf(stderr, "Unable to connect %s\n", modbus_strerror(errno));
            modbus_free(ctx);
            return -1;
        }
    }

    for (;;) {
        rc = modbus_receive(ctx, query);
        if (rc == -1) {
            printf("Connection closed by the client or error.\n");
            break;
        }

        /* Read holding registers */
        if (query[header_length] == 0x03) {
            if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 3)
                == UT_REGISTERS_NB_SPECIAL) {
                printf("Set an incorrect number of values\n");
                MODBUS_SET_INT16_TO_INT8(query, header_length + 3,
                                         UT_REGISTERS_NB_SPECIAL - 1);
            } else if (MODBUS_GET_INT16_FROM_INT8(query, header_length + 1)
                == UT_REGISTERS_ADDRESS_SPECIAL) {
                printf("Reply to this special register address by an exception\n");
                modbus_reply_exception(ctx, query,
                                       MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY);
                continue;
            }
        }

        rc = modbus_reply(ctx, query, rc, mb_mapping);
        if (rc == -1) {
            break;
        }
    }

    printf("Quit the loop: %s\n", modbus_strerror(errno));

    if (use_backend == TCP) {
        close(socket);
    }
    modbus_mapping_free(mb_mapping);
    free(query);
    modbus_free(ctx);

    return 0;
}
Exemple #6
0
int main(void)
{
	int rc;
	iolib_init();
	iolib_setdir(9,12, DIR_OUT);

    int socket;
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;

    ctx = modbus_new_tcp("192.168.1.100", 502);
    modbus_set_debug(ctx, TRUE);

    mb_mapping = modbus_mapping_new(10, 10, 10, 10);
    if (mb_mapping == NULL) {
        fprintf(stderr, "Failed to allocate the mapping: %s\n",
                modbus_strerror(errno));
        modbus_free(ctx);
        return -1;
    }

    socket = modbus_tcp_listen(ctx, 1);
    modbus_tcp_accept(ctx, &socket);

    for (;;) {
        uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
        int rc;

        rc = modbus_receive(ctx, query);



	if (rc != -1) {
            /* rc is the query size */
            modbus_reply(ctx, query, rc, mb_mapping);

    if((*mb_mapping).tab_bits[1] == 1) {
		 pin_high(9,12);
    }

    else if((*mb_mapping).tab_bits[1] == 0) {
		 pin_low(9,12);
   }





	} else {
            /* Connection closed by the client or error */
            break;
        }
    }



    printf("Quit the loop: %s\n", modbus_strerror(errno));

    modbus_mapping_free(mb_mapping);
    close(socket);
    modbus_free(ctx);

    return 0;
}
Exemple #7
0
int main(int argc, char *argv[])
{
	int addr;
	modbus_mapping_t *mb_mapping;
	modbus_t *ctx;
	int s;
	int ret;

	/*
	 * Check command line
	 */

	optind = check_common_opts(argc, argv);
	if (argc - optind < 1)
		usage();

	addr = parse_addr(argv[optind + 0]);
	if (addr < 1) {
		err("invalid address \"%s\"", argv[optind + 0]);
		exit(-1);
	}

	/*
	 * Modbus stuff
	 */

	mb_mapping = modbus_mapping_new(10, 10, 10, 10);
	if (mb_mapping == NULL) {
		err("failed to allocate the mapping: %s\n",
			modbus_strerror(errno));
		exit(-1);
	}

	ctx = modbus_server_new(addr, &s);
	if (!ctx) {
		err("cannot create server: %s", modbus_strerror(errno));
		exit(1);
	}

	for (;;) {
		ret = modbus_server_connect(ctx, &s);
		if (ret < 0) {
			err("connection failed: %s", modbus_strerror(errno));
			exit(1);
		}
		dbg("got new connection");

		for (;;) {
			uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
	
			ret = modbus_receive(ctx, query);
			dbg("got new query");
			if (ret >= 0) {
				modbus_reply(ctx, query, ret, mb_mapping);
				dbg("query answered");
			} else {
				/* Connection closed by the client or server */
				break;
			}
		}
	}

	printf("Quit the loop: %s\n", modbus_strerror(errno));

	modbus_mapping_free(mb_mapping);

	modbus_close(ctx);
	modbus_free(ctx);

	return 0;
}
Exemple #8
0
int slave()
{
    modbus_t *ctx;
    modbus_mapping_t *mb_mapping;
    int rc;
    uint8_t *query;
	uint8_t *raw_rsp;
	uint8_t *con_rsp;
	uint16_t *raw_rd_rsp;
	uint16_t *rd_rsp;
    int header_length;
	int year,month,day,hour,minute,second;
	int i,j;
	int rsp_length;
	int set_date[6];
	mb_mapping = modbus_mapping_new(
        UT_BITS_ADDRESS + UT_BITS_NB,
        UT_INPUT_BITS_ADDRESS + UT_INPUT_BITS_NB,
        UT_REGISTERS_ADDRESS + UT_REGISTERS_NB,
        UT_INPUT_REGISTERS_ADDRESS + UT_INPUT_REGISTERS_NB);
    if (mb_mapping == NULL) 
	{
        modbus_free(ctx);
        return -1;
    }
    ctx = modbus_new_rtu("/dev/ttyS2", 9600, 'N', 8, 1);
    modbus_set_slave(ctx, 1);
    query = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
	raw_rsp = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
	con_rsp = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
	raw_rd_rsp = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
	rd_rsp = malloc(MODBUS_RTU_MAX_ADU_LENGTH);
    header_length = modbus_get_header_length(ctx);

    modbus_set_debug(ctx, TRUE);
start:
    rc = modbus_connect(ctx);
    if (rc == -1) 
    {
		modbus_free(ctx);
		return -1;
    }
    for (;;) 
    {
        rc = modbus_receive(ctx, query);
        if (rc == -1) 
		{
            break;
   	    }
		//Send the raw message to SDL
		if(extend(query[2],query[3]) == 5152)
		{
			
			raw_rsp = raw_data_command(&rsp_length,rc,query);
			if(raw_rsp == NULL){printf("SDL is sleeping\n");goto close;}
			for(i=6;i<rsp_length;i++)
			{
				con_rsp[i-6]=raw_rsp[i];
			}
			modbus_send_raw_request(ctx, con_rsp, (rsp_length-6)*sizeof(uint8_t));
		}
		if(extend(query[2],query[3]) == 5168)
		{
			
			raw_rsp = raw_data_command(&rsp_length,rc,query);
			if(raw_rsp == NULL){printf("SDL is sleeping\n");goto close;}
			for(i=6;i<rsp_length;i++)
			{
				con_rsp[i-6]=raw_rsp[i];
			}
			modbus_send_raw_request(ctx, con_rsp, (rsp_length-6)*sizeof(uint8_t));
		}
		if(extend(query[2],query[3]) == 16384) 
		{	
			raw_rsp = sdl_read_buffsize(&rsp_length);
			if(raw_rsp == NULL){printf("SDL is sleeping\n");goto close;}
			for(i=0;i<2;i++)
			{
				con_rsp[i] = query[i];
			}
			con_rsp[2] = 0x4;
			for(i=0,j=3;i<rsp_length;i++)
			{
				con_rsp[j]=raw_rsp[i];
				j++;
			}
			modbus_send_raw_request(ctx, con_rsp, 7*sizeof(uint8_t));	
		}
		if(extend(query[2],query[3]) == 16386) 
		{	
			raw_rsp = sdl_read_data(&rsp_length,16);
			if(raw_rsp == NULL){printf("SDL is sleeping\n");goto close;}
			for(i=0;i<2;i++)
			{
				con_rsp[i] = query[i];
			}
			con_rsp[2] = 0x40;
			for(i=0,j=3;i<rsp_length;i++)
			{
				con_rsp[j]=raw_rsp[i];
				j++;
			}
			modbus_send_raw_request(ctx, con_rsp, 67*sizeof(uint8_t));	
		}
		
		if(extend(query[2],query[3]) == 1400) 
		{
			rc = modbus_reply(ctx, query, rc, mb_mapping);				
			set_date[0] = extend(query[7],query[8])+2000;
			set_date[1] = extend(query[9],query[10]);
			set_date[2]= extend(query[11],query[12]);
			set_date[3] = extend(query[13],query[14]);
			set_date[4] = extend(query[15],query[16]);
			set_date[5] = extend(query[17],query[18]);
			set_time(&set_date);
			//printf("%d %d %d %d %d %d\n",set_date[0],set_date[1],set_date[2],set_date[3],set_date[4],set_date[5]);
		}
		
    }
close:
	goto start;
    modbus_mapping_free(mb_mapping);
    free(query);
    modbus_free(ctx);
	

    return 0;
}