/** * @brief Help function. FC15, FC16 request handler * * @fc Function code 15 and 16 only. * @param handle Mbtcp handle. * @param req cJSON request object. * @return Modbus response string in JSON format. */ static char * mbtcp_multi_write_req(int fc, mbtcp_handle_s *handle, cJSON *req) { BEGIN(enable_syslog); int addr = json_get_int(req, "addr"); int len = json_get_int(req, "len"); int tid = json_get_int(req, "tid"); uint8_t *bits; // FC15 uint16_t *regs; // FC16 cJSON * data = NULL; int ret = 0; switch (fc) { case 15: // memory reset for variable length array bits = (uint8_t *) malloc(len * sizeof(uint8_t)); memset(bits, 0, len * sizeof(uint8_t)); // handle uint8_t array data = cJSON_GetObjectItem(req, "data"); for (int i = 0 ; i < cJSON_GetArraySize(data) ; i++) { uint8_t subitem = cJSON_GetArrayItem(data, i)->valueint; bits[i] = subitem; LOG(enable_syslog, "[%d]=%d", i, bits[i]); } ret = modbus_write_bits(handle->ctx, addr, len, bits); free(bits); break; case 16: // memory reset for variable length array regs = (uint16_t *) malloc(len * sizeof(uint16_t)); memset(regs, 0, len * sizeof(uint16_t)); // handle uint16_t array data = cJSON_GetObjectItem(req, "data"); for (int i = 0 ; i < cJSON_GetArraySize(data) ; i++) { uint16_t subitem = cJSON_GetArrayItem(data, i)->valueint; regs[i] = subitem; LOG(enable_syslog, "[%d]=%d", i, regs[i]); } ret = modbus_write_registers(handle->ctx, addr, len, regs); free(regs); break; default: return set_modbus_error_resp(tid, "Wrong function code"); } if (ret < 0) { return set_modbus_errno_resp(tid, handle, errno); } else { return set_modbus_no_data_ok_resp(tid); } }
static int ctx_write_bits(lua_State *L) { ctx_t *ctx = ctx_check(L, 1); int addr = luaL_checknumber(L, 2); int rc; int rcount; /* * TODO - could allow just a series of arguments too? easier for * smaller sets?"?) */ luaL_checktype(L, 3, LUA_TTABLE); /* array style table only! */ int count = lua_objlen(L, 3); if (count > MODBUS_MAX_WRITE_BITS) { return luaL_argerror(L, 3, "requested too many bits"); } /* Convert table to uint8_t array */ uint8_t *buf = malloc(count * sizeof(uint8_t)); assert(buf); for (int i = 1; i <= count; i++) { bool ok = false; lua_rawgeti(L, 3, i); if (lua_type(L, -1) == LUA_TNUMBER) { buf[i-1] = lua_tonumber(L, -1); ok = true; } if (lua_type(L, -1) == LUA_TBOOLEAN) { buf[i-1] = lua_toboolean(L, -1); ok = true; } if (ok) { lua_pop(L, 1); } else { free(buf); return luaL_argerror(L, 3, "table values must be numeric or bool"); } } rc = modbus_write_bits(ctx->modbus, addr, count, buf); if (rc == count) { rcount = 1; lua_pushboolean(L, true); } else { rcount = libmodbus_rc_to_nil_error(L, rc, count); } free(buf); return rcount; }
int write_coils(int address, int length, uint8_t data[]){ int retries = 3; do { if (modbus_write_bits(ctx,address,length,data)==length){ qWarning() << "Successful Write"; return 1; }else{ retries--; qWarning() << "Failed to Write, re-attempting"; } } while( retries >= 0); qWarning() << "Failed to Write, reached retry limit!"; return 0; }
void ModBusTCP::WriteMultipleCoils(quint16 slave, quint16 addr, quint16 num, quint8 *data) { quint16 repeat = NumberOfRepeat; qDebug() << "Write multiCoils from slave: " << slave << "Addr: " << addr << " number: " << num; while(repeat) { if (modbus_set_slave(ctx, slave) == -1) { if (--repeat == 0) { qDebug() << "Error set slave: " << errno; emit ModBusError(errno); return; } } else { repeat = 0; } } repeat = NumberOfRepeat; while (repeat) { qDebug() << Q_FUNC_INFO << repeat; if (modbus_write_bits(ctx, addr, num, data) == -1) { if (--repeat == 0) { qDebug() << "Error write MultiCoils: " << errno; emit ModBusError(errno); return; } } else { repeat = 0; } } qDebug() << "Write OK" << repeat; emit ModBusOK(); }
/* * This Function sends modbus request and returns the response * Arguments: * unsigned char * fn :- Modbus request array. 1st byte is function code, next 2 bytes is address of register * 4th 5th byte is no. of register. 6th 7th byte is data. Modbus response is sent back on * 6th and 7th byte * Return Value :- 0 : On successful * -1 : on error */ int MBSendRequest(unsigned char *fn) { uint16_t address,NIitem,*data,data1 ; int ret=0; address = *(fn+1); address = address<<8; // This is done so that data recieved is in big indian format. address = address | (*(fn+2)); //It should be converted to little indian format NIitem = *(fn+3); NIitem = NIitem<<8; NIitem = NIitem | *(fn+4); data1 = *(fn+5); data1 = data1<<8; data1 = data1 | *(fn+6); data = &data1; printf("Function code = %d \n",*fn); printf("register address = %x \n",address); printf("NIitem = %x \n",NIitem); printf("Data=%d\n",*data); switch(*fn) { case 1:ret = modbus_read_bits(ctx,address,NIitem,(uint8_t*) data); break; case 2:ret = modbus_read_input_bits(ctx,address,NIitem,(uint8_t*) data); break; case 3:ret = modbus_read_registers(ctx,address,NIitem,data); break; case 4:ret = modbus_read_input_registers(ctx,address,NIitem,data); break; case 5:ret = modbus_write_bit(ctx,address,*data); break; case 6:ret = modbus_write_register(ctx,address,*data); break; case 15:ret = modbus_write_bits(ctx,address,NIitem,(uint8_t*) data); break; case 16:ret = modbus_write_registers(ctx,address,NIitem,data); break; } *(fn+6)=((*data) >> 8)& 0x00ff; *(fn+5)= (*data) & 0x00ff; return ret; }
int main( int argc, char **argv ) { int a, rc; int ec = 0; options_t options; modbus_t *ctx; uint8_t *tab_bit; uint16_t *tab_reg; if(argc > 1) { options_init(&options); for (a = 1; a < argc; a++) { options_execute(&options, argv[a], strlen(argv[a])+1); rc = options_finish(&options); DEBUG("argument: '%s' end state: %d\n",argv[a], rc); if (rc == -1) { options_err_disp(&options,argv[a]); ec = 1; goto exit; } } if(rc == 0) { fprintf(stderr, "Missing action argument\n"); ec = 1; goto exit; } if(options.action == _UNDEF) goto exit; // Options are valid options_dump(&options); ctx = modbus_init_con(&options); modbus_set_debug(ctx, options.debug); modbus_set_response_timeout(ctx, &options.timeout); if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); ec = 1; goto destroy; } switch(options.action) { case _RC: case _RD: tab_bit = (uint8_t *) malloc(options.count * sizeof(uint8_t)); DBG_ASSERT(tab_bit != NULL, "Unable to allocate tab_bit!"); memset(tab_bit, 0, options.count * sizeof(uint8_t)); switch(options.action) { case _RC: rc = modbus_read_bits(ctx, options.address, options.count, tab_bit); break; case _RD: rc = modbus_read_input_bits(ctx, options.address, options.count, tab_bit); break; } if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); ec = 1; } else { display_8bit(&options, tab_bit); } free(tab_bit); break; case _RH: case _RI: tab_reg = (uint16_t *) malloc(options.count * sizeof(uint16_t)); DBG_ASSERT(tab_reg != NULL, "Unable to allocate tab_reg!"); switch(options.action) { case _RH: rc = modbus_read_registers(ctx, options.address, options.count, tab_reg); break; case _RI: rc = modbus_read_input_registers(ctx, options.address, options.count, tab_reg); break; } if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); ec = 1; } else { display_16bit(&options, tab_reg); } free(tab_reg); break; case _WC: if(options.count == 1) rc = modbus_write_bit(ctx, options.address, options.coil_values[0]); else { rc = modbus_write_bits(ctx, options.address, options.count, options.coil_values); } if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); ec = 1; } else { printf("Success\n"); } break; case _WH: if(options.count == 1) rc = modbus_write_register(ctx, options.address, options.reg_values[0]); else { rc = modbus_write_registers(ctx, options.address, options.count, options.reg_values); } if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); ec = 1; } else { printf("Success\n"); } break; default: DBG_ASSERT(0,"Unhandled action enum constant!"); } } else { options_help(); ec = 1; goto exit; } close: modbus_close(ctx); destroy: modbus_free(ctx); exit: return ec; }
int main(int argc, char **argv) { int c; int ok; int debug = 0; BackendParams *backend = 0; int slaveAddr = 1; int startAddr = 100; int startReferenceAt0 = 0; int readWriteNo = 1; int fType = FuncNone; int timeout_ms = 1000; int hasDevice = 0; int isWriteFunction = 0; enum WriteDataType { DataInt, Data8Array, Data16Array } wDataType = DataInt; union Data { int dataInt; uint8_t *data8; uint16_t *data16; } data; while (1) { int option_index = 0; static struct option long_options[] = { {DebugOpt, no_argument, 0, 0}, {0, 0, 0, 0} }; c = getopt_long(argc, argv, "a:b:d:c:m:r:s:t:p:o:0", long_options, &option_index); if (c == -1) { break; } switch (c) { case 0: if (0 == strcmp(long_options[option_index].name, DebugOpt)) { debug = 1; } break; case 'a': { slaveAddr = getInt(optarg, &ok); if (0 == ok) { printf("Slave address (%s) is not integer!\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } } break; case 'c': { readWriteNo = getInt(optarg, &ok); if (0 == ok) { printf("# elements to read/write (%s) is not integer!\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } } break; case 'm': if (0 == strcmp(optarg, TcpOptVal)) { backend = createTcpBackend((TcpBackend*)malloc(sizeof(TcpBackend))); } else if (0 == strcmp(optarg, RtuOptVal)) backend = createRtuBackend((RtuBackend*)malloc(sizeof(RtuBackend))); else { printf("Unrecognized connection type %s\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } break; case 'r': { startAddr = getInt(optarg, &ok); if (0 == ok) { printf("Start address (%s) is not integer!\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } } break; case 't': { fType = getInt(optarg, &ok); if (0 == ok) { printf("Function type (%s) is not integer!\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } } break; case 'o': { timeout_ms = getInt(optarg, &ok); if (0 == ok) { printf("Timeout (%s) is not integer!\n\n", optarg); printUsage(argv[0]); exit(EXIT_FAILURE); } printf("Timeout set to %d\r\n", timeout_ms); } break; case '0': startReferenceAt0 = 1; break; //tcp/rtu params case 'p': case 'b': case 'd': case 's': if (0 == backend) { printf("Connection type (-m switch) has to be set before its params are provided!\n"); printUsage(argv[0]); exit(EXIT_FAILURE); } else { if (0 == backend->setParam(backend, c, optarg)) { printUsage(argv[0]); exit(EXIT_FAILURE); } } break; case '?': break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (0 == backend) { printf("No connection type was specified!\n"); printUsage(argv[0]); exit(EXIT_FAILURE); } if (1 == startReferenceAt0) { startAddr--; } //choose write data type switch (fType) { case(ReadCoils): wDataType = Data8Array; break; case(ReadDiscreteInput): wDataType = DataInt; break; case(ReadHoldingRegisters): case(ReadInputRegisters): wDataType = Data16Array; break; case(WriteSingleCoil): case(WriteSingleRegister): wDataType = DataInt; isWriteFunction = 1; break; case(WriteMultipleCoils): wDataType = Data8Array; isWriteFunction = 1; break; case(WriteMultipleRegisters): wDataType = Data16Array; isWriteFunction = 1; break; default: printf("No correct function type chosen"); printUsage(argv[0]); exit(EXIT_FAILURE); } if (isWriteFunction) { int dataNo = argc - optind - 1; /*if (-1 != readWriteNo && dataNo != readWriteNo) { printf("Write count specified, not equal to data values count!"); printUsage(argv[0]); exit(EXIT_FAILURE); } else*/ readWriteNo = dataNo; } //allocate buffer for data switch (wDataType) { case (DataInt): //no need to alloc anything break; case (Data8Array): data.data8 = malloc(readWriteNo * sizeof(uint8_t)); break; case (Data16Array): data.data16 = malloc(readWriteNo * sizeof(uint16_t)); break; default: printf("Data alloc error!\n"); exit(EXIT_FAILURE); } int wDataIdx = 0; if (1 == debug && 1 == isWriteFunction) printf("Data to write: "); if (optind < argc) { while (optind < argc) { if (0 == hasDevice) { if (0 != backend) { if (Rtu == backend->type) { RtuBackend *rtuP = (RtuBackend*)backend; strcpy(rtuP->devName, argv[optind]); hasDevice = 1; } else if (Tcp == backend->type) { TcpBackend *tcpP = (TcpBackend*)backend; strcpy(tcpP->ip, argv[optind]); hasDevice = 1; } } } else {//setting write data buffer switch (wDataType) { case (DataInt): data.dataInt = getInt(argv[optind], 0); if (debug) printf("0x%x", data.dataInt); break; case (Data8Array): { data.data8[wDataIdx] = getInt(argv[optind], 0); if (debug) printf("0x%02x ", data.data8[wDataIdx]); } break; case (Data16Array): { data.data16[wDataIdx] = getInt(argv[optind], 0); if (debug) printf("0x%04x ", data.data16[wDataIdx]); } break; } wDataIdx++; } optind++; } } if (1 == debug && 1 == isWriteFunction) printf("\n"); //create modbus context, and preapare it modbus_t *ctx = backend->createCtxt(backend); modbus_set_debug(ctx, debug); modbus_set_slave(ctx, slaveAddr); //issue the request int ret = -1; if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } else { switch (fType) { case(ReadCoils): ret = modbus_read_bits(ctx, startAddr, readWriteNo, data.data8); break; case(ReadDiscreteInput): printf("ReadDiscreteInput: not implemented yet!\n"); wDataType = DataInt; break; case(ReadHoldingRegisters): ret = modbus_read_registers(ctx, startAddr, readWriteNo, data.data16); break; case(ReadInputRegisters): ret = modbus_read_input_registers(ctx, startAddr, readWriteNo, data.data16); break; case(WriteSingleCoil): ret = modbus_write_bit(ctx, startAddr, data.dataInt); break; case(WriteSingleRegister): ret = modbus_write_register(ctx, startAddr, data.dataInt); break; case(WriteMultipleCoils): ret = modbus_write_bits(ctx, startAddr, readWriteNo, data.data8); break; case(WriteMultipleRegisters): ret = modbus_write_registers(ctx, startAddr, readWriteNo, data.data16); break; default: printf("No correct function type chosen"); printUsage(argv[0]); exit(EXIT_FAILURE); } } if (ret == readWriteNo) {//success if (isWriteFunction) printf("SUCCESS: written %d elements!\n", readWriteNo); else { printf("SUCCESS: read %d of elements:\n\tData: ", readWriteNo); int i = 0; if (DataInt == wDataType) { printf("0x%04x\n", data.dataInt); } else { const char Format8[] = "0x%02x "; const char Format16[] = "0x%04x "; const char *format = ((Data8Array == wDataType) ? Format8 : Format16); for (; i < readWriteNo; ++i) { printf(format, (Data8Array == wDataType) ? data.data8[i] : data.data16[i]); } printf("\n"); } } } else { printf("ERROR occured!\n"); modbus_strerror(errno); } //cleanup modbus_close(ctx); modbus_free(ctx); backend->del(backend); switch (wDataType) { case (DataInt): //nothing to be done break; case (Data8Array): free(data.data8); break; case (Data16Array): free(data.data16); break; } exit(EXIT_SUCCESS); }
/* At each loop, the program works in the range ADDRESS_START to * ADDRESS_END then ADDRESS_START + 1 to ADDRESS_END and so on. */ int main(void) { modbus_t *ctx; int rc; int nb_fail; int nb_loop; int addr; int nb; uint8_t *tab_rq_bits; uint8_t *tab_rp_bits; uint16_t *tab_rq_registers; uint16_t *tab_rw_rq_registers; uint16_t *tab_rp_registers; /* RTU */ /* ctx = modbus_new_rtu("/dev/ttyUSB0", 19200, 'N', 8, 1); modbus_set_slave(ctx, SERVER_ID); */ /* TCP */ ctx = modbus_new_tcp("127.0.0.1", 1502); modbus_set_debug(ctx, TRUE); if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } /* Allocate and initialize the different memory spaces */ nb = ADDRESS_END - ADDRESS_START; tab_rq_bits = (uint8_t *) malloc(nb * sizeof(uint8_t)); memset(tab_rq_bits, 0, nb * sizeof(uint8_t)); tab_rp_bits = (uint8_t *) malloc(nb * sizeof(uint8_t)); memset(tab_rp_bits, 0, nb * sizeof(uint8_t)); tab_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t)); memset(tab_rq_registers, 0, nb * sizeof(uint16_t)); tab_rp_registers = (uint16_t *) malloc(nb * sizeof(uint16_t)); memset(tab_rp_registers, 0, nb * sizeof(uint16_t)); tab_rw_rq_registers = (uint16_t *) malloc(nb * sizeof(uint16_t)); memset(tab_rw_rq_registers, 0, nb * sizeof(uint16_t)); nb_loop = nb_fail = 0; while (nb_loop++ < LOOP) { for (addr = ADDRESS_START; addr <= ADDRESS_END; addr++) { int i; /* Random numbers (short) */ for (i=0; i<nb; i++) { tab_rq_registers[i] = (uint16_t) (65535.0*rand() / (RAND_MAX + 1.0)); tab_rw_rq_registers[i] = ~tab_rq_registers[i]; tab_rq_bits[i] = tab_rq_registers[i] % 2; } nb = ADDRESS_END - addr; /* WRITE BIT */ rc = modbus_write_bit(ctx, addr, tab_rq_bits[0]); if (rc != 1) { printf("ERROR modbus_write_bit (%d)\n", rc); printf("Address = %d, value = %d\n", addr, tab_rq_bits[0]); nb_fail++; } else { rc = modbus_read_bits(ctx, addr, 1, tab_rp_bits); if (rc != 1 || tab_rq_bits[0] != tab_rp_bits[0]) { printf("ERROR modbus_read_bits single (%d)\n", rc); printf("address = %d\n", addr); nb_fail++; } } /* MULTIPLE BITS */ rc = modbus_write_bits(ctx, addr, nb, tab_rq_bits); if (rc != nb) { printf("ERROR modbus_write_bits (%d)\n", rc); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { rc = modbus_read_bits(ctx, addr, nb, tab_rp_bits); if (rc != nb) { printf("ERROR modbus_read_bits\n"); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { for (i=0; i<nb; i++) { if (tab_rp_bits[i] != tab_rq_bits[i]) { printf("ERROR modbus_read_bits\n"); printf("Address = %d, value %d (0x%X) != %d (0x%X)\n", addr, tab_rq_bits[i], tab_rq_bits[i], tab_rp_bits[i], tab_rp_bits[i]); nb_fail++; } } } } /* SINGLE REGISTER */ rc = modbus_write_register(ctx, addr, tab_rq_registers[0]); if (rc != 1) { printf("ERROR modbus_write_register (%d)\n", rc); printf("Address = %d, value = %d (0x%X)\n", addr, tab_rq_registers[0], tab_rq_registers[0]); nb_fail++; } else { rc = modbus_read_registers(ctx, addr, 1, tab_rp_registers); if (rc != 1) { printf("ERROR modbus_read_registers single (%d)\n", rc); printf("Address = %d\n", addr); nb_fail++; } else { if (tab_rq_registers[0] != tab_rp_registers[0]) { printf("ERROR modbus_read_registers single\n"); printf("Address = %d, value = %d (0x%X) != %d (0x%X)\n", addr, tab_rq_registers[0], tab_rq_registers[0], tab_rp_registers[0], tab_rp_registers[0]); nb_fail++; } } } /* MULTIPLE REGISTERS */ rc = modbus_write_registers(ctx, addr, nb, tab_rq_registers); if (rc != nb) { printf("ERROR modbus_write_registers (%d)\n", rc); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { rc = modbus_read_registers(ctx, addr, nb, tab_rp_registers); if (rc != nb) { printf("ERROR modbus_read_registers (%d)\n", rc); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { for (i=0; i<nb; i++) { if (tab_rq_registers[i] != tab_rp_registers[i]) { printf("ERROR modbus_read_registers\n"); printf("Address = %d, value %d (0x%X) != %d (0x%X)\n", addr, tab_rq_registers[i], tab_rq_registers[i], tab_rp_registers[i], tab_rp_registers[i]); nb_fail++; } } } } /* R/W MULTIPLE REGISTERS */ rc = modbus_write_and_read_registers(ctx, addr, nb, tab_rw_rq_registers, addr, nb, tab_rp_registers); if (rc != nb) { printf("ERROR modbus_read_and_write_registers (%d)\n", rc); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { for (i=0; i<nb; i++) { if (tab_rp_registers[i] != tab_rw_rq_registers[i]) { printf("ERROR modbus_read_and_write_registers READ\n"); printf("Address = %d, value %d (0x%X) != %d (0x%X)\n", addr, tab_rp_registers[i], tab_rw_rq_registers[i], tab_rp_registers[i], tab_rw_rq_registers[i]); nb_fail++; } } rc = modbus_read_registers(ctx, addr, nb, tab_rp_registers); if (rc != nb) { printf("ERROR modbus_read_registers (%d)\n", rc); printf("Address = %d, nb = %d\n", addr, nb); nb_fail++; } else { for (i=0; i<nb; i++) { if (tab_rw_rq_registers[i] != tab_rp_registers[i]) { printf("ERROR modbus_read_and_write_registers WRITE\n"); printf("Address = %d, value %d (0x%X) != %d (0x%X)\n", addr, tab_rw_rq_registers[i], tab_rw_rq_registers[i], tab_rp_registers[i], tab_rp_registers[i]); nb_fail++; } } } } } printf("Test: "); if (nb_fail) printf("%d FAILS\n", nb_fail); else printf("SUCCESS\n"); } /* Free the memory */ free(tab_rq_bits); free(tab_rp_bits); free(tab_rq_registers); free(tab_rp_registers); /* Close the connection */ modbus_close(ctx); modbus_free(ctx); return 0; }
int main(int argc, char **argv) { uint8_t *tab_bit; uint16_t *tab_reg; /* Allocate and initialize the memory to store the status */ tab_bit = (uint8_t *)malloc(MODBUS_MAX_READ_BITS * sizeof(uint8_t)); memset(tab_bit, 0, MODBUS_MAX_READ_BITS * sizeof(uint8_t)); /* Allocate and initialize the memory to store the registers */ tab_reg = (uint16_t *)malloc(MODBUS_MAX_READ_REGISTERS * sizeof(uint16_t)); memset(tab_reg, 0, MODBUS_MAX_READ_REGISTERS * sizeof(uint16_t)); /* Defaults */ char host[1024] = "127.0.0.1"; size_t port = 502; enum mb_operations operation = read_registers; size_t base_addr = 0; // read from address 0 by deafult size_t n_addrs = 10; // read forst 10 addressxes by default. size_t n_times = 1; // one times by default. size_t interval = 0; // no waiting by default. bool quiet = false; // Do not suppress output by default. size_t n_data = 0; // The number of data items from the command line. char **data_items; // Array of data items from the command line. int c; int rc; while (1) { c = getopt(argc, argv, "h:p:o:b:a:n:i:q"); if (c == -1) break; switch (c) { case 'h': printf("Connect to host: '%s'\n", optarg); strncpy(host, optarg, 1024); // Made host str 1024. Should define a constant. break; case 'p': printf("Connect on port: '%s'\n", optarg); port = strtoul(optarg, (void *)0, 10); break; case 'o': printf("Option o with value '%s'\n", optarg); if (!strcmp("read_bits", optarg)) operation = read_bits; if (!strcmp("read_input_bits", optarg)) operation = read_input_bits; if (!strcmp("read_registers", optarg)) operation = read_registers; if (!strcmp("read_input_registers", optarg))operation = read_input_registers; if (!strcmp("write_bit", optarg)) operation = write_bit; if (!strcmp("write_register", optarg)) operation = write_register; if (!strcmp("write_bits", optarg)) operation = write_bits; if (!strcmp("write_registers",optarg)) operation = write_registers; break; case 'b': printf("Base address set to: '%s'\n", optarg); base_addr = strtoul(optarg, (void *)0, 10);; break; case 'a': printf("Number of addresses to read: '%s'\n", optarg); n_addrs = strtoul(optarg, (void *)0, 10); if (n_addrs > MODBUS_MAX_READ_REGISTERS) { printf("Number of addresses to read adjusted to maximum: '%i'\n", MODBUS_MAX_READ_REGISTERS); n_addrs = MODBUS_MAX_READ_REGISTERS; } break; case 'n': printf("Repeat this many times: '%s'\n", optarg); n_times = strtoul(optarg, (void *)0, 10); break; case 'i': printf("Repeat at this interval: '%s'\n", optarg); interval = strtoul(optarg, (void *)0, 10); break; case 'q': printf("option q: supressing output.\n"); quiet = true; break; case '?': printf("option ?: There is not doc only source codes.\n"); break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { n_data = argc - optind; data_items = (char **)malloc(n_data * sizeof(char *)); printf("There are %i non-option ARGV-elements: ", (argc-optind)); size_t n = 0; while (optind < argc) { printf("%s ", argv[optind]); data_items[n] = argv[optind]; ++optind; ++n; } printf("\n"); } /* Get show on the road. */ modbus_t *ctx; ctx = modbus_new_tcp(host, port); if (modbus_connect(ctx) == -1) { fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno)); modbus_free(ctx); return -1; } for (size_t i = 0; i<n_times; i++) { switch (operation) { case read_bits: printf("READ BITS:\n"); rc = modbus_read_bits(ctx, base_addr, n_addrs, tab_bit); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } if (!quiet) { /* What did we read?*/ for (uint8_t *reg_ptr = tab_bit; reg_ptr < tab_bit + n_addrs; reg_ptr++) { printf("%i ", *reg_ptr); } printf("\n"); } break; case read_input_bits: printf("READ INPUT BITS:\n"); rc = modbus_read_input_bits(ctx, base_addr, n_addrs, tab_bit); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } if (!quiet) { /* What did we read?*/ for (uint8_t *reg_ptr = tab_bit; reg_ptr < tab_bit + n_addrs; reg_ptr++) { printf("%i ", *reg_ptr); } printf("\n"); } break; case read_registers: printf("READ REGISTERS:\n"); rc = modbus_read_registers(ctx, base_addr, n_addrs, tab_reg); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } if (!quiet) { /* What did we read?*/ for (uint16_t *reg_ptr = tab_reg; reg_ptr < tab_reg + n_addrs; reg_ptr++) { printf("%i ", *reg_ptr); } printf("\n"); } break; case read_input_registers: printf("READ INPUT REGISTERS\n\n"); rc = modbus_read_input_registers(ctx, base_addr, n_addrs, tab_reg); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } if (!quiet) { /* What did we read?*/ for (uint16_t *reg_ptr = tab_reg; reg_ptr < tab_reg + n_addrs; reg_ptr++) { printf("%i ", *reg_ptr); } printf("\n"); } break; case write_bit: printf("WRITE BIT\n"); n_addrs = 1; if (n_addrs > n_data) { fprintf(stderr, "Not enough data items on command line to write to requested address.\n"); return(EXIT_FAILURE); } for (uint8_t *reg_ptr = tab_bit; reg_ptr < tab_bit + n_addrs; reg_ptr++) { *reg_ptr = strtoul(*data_items++, (void *)0, 10); } rc = modbus_write_bit(ctx, base_addr, tab_bit); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } break; case write_register: printf("WRITE REGISTER\n"); // There is only one register. Almost everything else stays the same as write_registers. n_addrs = 1; if (n_addrs > n_data) { fprintf(stderr, "Not enough data items on command line to write to requested address.\n"); return(EXIT_FAILURE); } for (uint16_t *reg_ptr = tab_reg; reg_ptr < tab_reg + n_addrs; reg_ptr++) { *reg_ptr = strtoul(*data_items++, (void *)0, 10); } rc = modbus_write_register(ctx, base_addr, tab_reg); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } break; case write_bits: printf("WRITE BITS\n"); if (n_addrs > n_data) { fprintf(stderr, "Not enough data items on command line to write to requested addresses.\n"); return(EXIT_FAILURE); } for (uint8_t *reg_ptr = tab_bit; reg_ptr < tab_bit + n_addrs; reg_ptr++) { *reg_ptr = strtoul(*data_items++, (void *)0, 10); } rc = modbus_write_bits(ctx, base_addr, n_addrs, tab_bit); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } break; case write_registers: printf("WRITE REGISTERS\n"); if (n_addrs > n_data) { fprintf(stderr, "Not enough data items on command line to write to requested addresses.\n"); return(EXIT_FAILURE); } for (uint16_t *reg_ptr = tab_reg; reg_ptr < tab_reg + n_addrs; reg_ptr++) { *reg_ptr = strtoul(*data_items++, (void *)0, 10); } rc = modbus_write_registers(ctx, base_addr, n_addrs, tab_reg); if (rc == -1) { fprintf(stderr, "%s\n", modbus_strerror(errno)); return(EXIT_FAILURE); } break; default: break; } sleep(interval); } /* Free the memory */ free(tab_bit); free(tab_reg); //free(data_items); /* Close the connection */ modbus_close(ctx); modbus_free(ctx); exit(EXIT_SUCCESS); }
int main(int argc, char *argv[]) { uint16_t regs[1]; float heaterTemp; float heaterSetPoint; char * heaterEnableState; char * heaterElementState; char * modbusClientIP = DEFAULT_CLIENT_IP; int modbusPort = DEFAULT_PORT; int packet_counter = 0; uint8_t *tab_bits; uint16_t *tab_input_value_registers; tab_bits = (uint8_t *)malloc(NO_BITS * sizeof(uint8_t)); memset(tab_bits, 0, NO_BITS * sizeof(uint8_t)); tab_input_value_registers = (uint16_t *)malloc(NO_REGS* sizeof(uint16_t)); memset(tab_input_value_registers, 0, NO_REGS * sizeof(uint16_t)); bool sts; int rc; uint8_t coils[2]; ctx = modbus_new_tcp(modbusClientIP, modbusPort); if (ctx == NULL) { fprintf(stderr, "Unable to allocate libmodbus context\n"); return -1; } if (modbus_connect(ctx) == -1) { sts = false; } rc = modbus_read_input_registers(ctx,0,1, regs); packet_counter++; printf(" Value of current:%d\n", regs[0]); modbus_close(ctx); ctx = modbus_new_tcp(modbusClientIP, modbusPort); if (ctx == NULL) { fprintf(stderr, "Unable to allocate libmodbus context\n"); return -1; } if (modbus_connect(ctx) == -1) { sts = false; } coils[0] = false; coils[1] = false; rc = modbus_write_bits(ctx,0,2,coils); printf("Status of circuit breakers to be written: CB1 = %d, CB2 = %d\n", coils[0],coils[1]); /* Close the connection */ modbus_close(ctx); modbus_free(ctx); sleep(5); return 0; }