From 1e24cc5dd0c7051b707405f606bc6e7dd1bedaa3 Mon Sep 17 00:00:00 2001 From: Steffen Pohle Date: Sun, 17 Sep 2023 23:42:07 +0200 Subject: [PATCH] request of first values is working now. --- client.cc | 254 +++++++++++++++++++++++++++++++++++++++++++ client.h | 19 +++- modbus.cc | 75 ++++++++++++- modbus.h | 18 ++- nwthread.cc | 138 +++++++++++++++++++---- nwthread.h | 25 ++++- testmodbus-client.ui | 153 ++++++++++++++++++++------ 7 files changed, 615 insertions(+), 67 deletions(-) diff --git a/client.cc b/client.cc index a288b89..078d176 100644 --- a/client.cc +++ b/client.cc @@ -10,6 +10,7 @@ #include "config.h" #include "client.h" #include "nwthread.h" +#include "modbus.h" #define BUILDER_FILE "testmodbus-client.ui" @@ -20,10 +21,28 @@ GtkBuilder *_builder_ = NULL; // work around for the thread situation gboolean mbcli_thread_cb_net(gpointer data); // callback thread network data gboolean mbcli_thread_cb_error(gpointer data); // callback thread error void mbcli_connect_btn_sensitive (bool enable); // enable/disable connect buttons +int old_refreshtime = -1; +int num_errors = 0; // error counter +int num_requests = 0; // request counter NetworkThread netthread; +std::string to_hex16 (int v) { + char HEX[] = "0123456789ABCDEF"; + int i = v; + int n; + std::string txt = ""; + + for (n = 0; n < 4; n++) { + txt = HEX[i%16]+ txt; + i = i / 16; + } + + return txt; +} + + int main (int argc, char **argv) { GtkBuilder *builder; GObject *window; @@ -57,6 +76,89 @@ int main (int argc, char **argv) { +void mbcli_cb_show(GtkWidget *widget, gpointer data) { + GtkTextTag *tag_addr; + GtkTextTag *tag_values; + GtkTextTag *tag_head; + GtkWidget *textview = GTK_WIDGET(gtk_builder_get_object (_builder_, "cli_RawResult")); + GtkTextBuffer *textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + + tag_head = gtk_text_buffer_create_tag (textbuffer, "Head", + "foreground", "green", "style", PANGO_WEIGHT_HEAVY, "family", "Monospace", NULL); + tag_addr = gtk_text_buffer_create_tag (textbuffer, "Addr", + "foreground", "blue", "style", PANGO_WEIGHT_BOLD, "family", "Monospace", NULL); + tag_values = gtk_text_buffer_create_tag (textbuffer, "Data", + "foreground", "black", "style", PANGO_WEIGHT_NORMAL, "family", "Monospace", NULL); +} + + +/* + * got some data + */ +gboolean mbcli_thread_cb_net(gpointer data) { + NWTReqResult *res = (NWTReqResult*) data; + GtkWidget *textview = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_RawResult")); + GtkTextBuffer *textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + GtkTextIter start, end; + + std::string text; + float f1, f2; + char tmp[255]; + + printf ("%s:%d %s got some data\n", __FILE__, __LINE__, __FUNCTION__); + gtk_text_buffer_get_start_iter(textbuffer, &start); + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_delete(textbuffer, &start, &end); + + if (res->fc == 1 | res->fc == 2) { + text = "binary data"; + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_insert_with_tags_by_name(textbuffer, &end, text.c_str(), -1, "Addr", NULL); + } + else { + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_insert_with_tags_by_name(textbuffer, &end, " Addr RawData Integer Float Float(SW)\n", -1, "Head", NULL); + + for (int i = 0; i < res->cnt; i++) { + // add addr to textbuffer + snprintf (tmp, 255, "%5d ", res->reg + i); + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_insert_with_tags_by_name(textbuffer, &end, tmp, -1, "Addr", NULL); + + // add data to textbuffer + text = to_hex16((int) res->data[i]); + if ((res->reg + i)%2 == 0 && i < res->cnt-1) { + memcpy (((char*)&f1) + 0, &res->data[i], 2); + memcpy (((char*)&f1) + 2, &res->data[i+1], 2); + + memcpy (((char*)&f2) + 2, &res->data[i], 2); + memcpy (((char*)&f2) + 0, &res->data[i+1], 2); + + snprintf (tmp, 255, " | %6d | %9.3g | %9.5g", res->data[i], f1, f2); + text = text + tmp; + } + else { + snprintf (tmp, 255, " | %6d | | ", res->data[i]); + text = text + tmp; + } + + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_insert_with_tags_by_name(textbuffer, &end, text.c_str(), -1, "Data", NULL); + + gtk_text_buffer_get_end_iter(textbuffer, &end); + gtk_text_buffer_insert(textbuffer, &end, (char *) "\n", -1); + } + + } + + GtkWidget *statusbar = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_statusbar")); + gtk_label_set_label(GTK_LABEL(statusbar), (char*)"got data"); + + free (res); + return FALSE; +}; + + /* * display error if somethin happened within a thread */ @@ -74,6 +176,7 @@ gboolean mbcli_thread_cb_error(gpointer data) { }; + void displayerror (std::string error) { GtkWidget *dialog; GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (_builder_, "testmodbus-client")); @@ -129,3 +232,154 @@ void mbcli_cb_disconnect (GtkWidget *widget, gpointer data) { netthread.Disconnect(); }; + +/* + * returns the currently selected FC + */ +int mbcli_get_FC () { + GtkWidget *FC_n[4] = { NULL, NULL, NULL, NULL }; + int fc = 0, i = 0; + + FC_n[fc++] = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_FC1")); + FC_n[fc++] = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_FC2")); + FC_n[fc++] = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_FC3")); + FC_n[fc++] = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_FC4")); + + for (i = 0, fc = -1; i < 4; i++) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(FC_n[i]))) fc = i+1; + + return fc; +} + + +/* + * returns the refresh time + */ +int mbcli_get_refreshtime() { + GtkWidget *rd_refresh = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_refreshtime")); + return atoi(gtk_entry_get_text(GTK_ENTRY(rd_refresh))); +} + +/* + * returns the register + */ +int mbcli_get_register() { + GtkWidget *rd_refresh = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_register")); + return atoi(gtk_entry_get_text(GTK_ENTRY(rd_refresh))); +} + + +/* + * returns the number + */ +int mbcli_get_number() { + GtkWidget *rd_refresh = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_number")); + return atoi(gtk_entry_get_text(GTK_ENTRY(rd_refresh))); +} + + +/* + * returns the unitid + */ +int mbcli_get_unitid() { + GtkWidget *rd_refresh = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_unitid")); + return atoi(gtk_entry_get_text(GTK_ENTRY(rd_refresh))); +} + +/* + * returns status of the update button + */ +int mbcli_get_update () { + GtkWidget *tb_update = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_Update")); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb_update))) return 1; + return 0; +} + + +/* + * sets the active button + */ +void mbcli_set_update (int active) { + GtkWidget *tb_update = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_Update")); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tb_update), active); +} + + +/* + * returns status of the dont_use_FC1516 button + */ +int mbcli_get_FC1516 () { + GtkWidget *tb_update = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_dontuse_FC1516")); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb_update))) return 1; + return 0; +} + + +/* + * toglebutton to read some data is changed. + */ +void mbcli_cb_updateread (GtkToggleButton *togglebutton, gpointer user_data) { + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (mbcli_get_update()) { + num_requests = 0; + num_errors = 0; + + g_timeout_add(mbcli_get_refreshtime(), mbcli_refreshtimeout, NULL); + if (mbcli_get_FC1516()) mbcli_set_update(0); + } +} + + + +gboolean mbcli_refreshtimeout(gpointer data) { + int timeout = mbcli_get_refreshtime(); + int update = mbcli_get_update(); + int fc1516 = mbcli_get_FC1516(); + int fc = mbcli_get_FC(); + int reg = mbcli_get_register(); + int num = mbcli_get_number(); + int unitid = mbcli_get_unitid(); + int state = netthread.GetState(); + + GtkWidget *statusbar = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_statusbar")); + GtkWidget *rate = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_rate")); + char txt[255]; + + printf ("%s:%d %s\n", __FILE__, __LINE__, __FUNCTION__); + + if (state == NWT_running) { + num_requests++; + if (netthread.SendRequestRead(unitid, fc, reg, num) == 0) { + num_errors++; + gtk_label_set_label(GTK_LABEL(statusbar), "busy, another request in progress"); + } + else { + gtk_label_set_label(GTK_LABEL(statusbar), "request send"); + } + snprintf (txt, 255, "%d / %d", num_errors, num_requests); + gtk_label_set_label(GTK_LABEL(rate), txt); + } + else { + gtk_label_set_label(GTK_LABEL(rate), "- / -"); + } + + + // + // need to continue + if (fc1516) { + mbcli_set_update(0); + return FALSE; + } + if (!update) return FALSE; + + // + // refresh time changed? + if (timeout != old_refreshtime) { + old_refreshtime = timeout; + g_timeout_add(timeout, mbcli_refreshtimeout, NULL); + return FALSE; + } + return TRUE; // continue with timer +}; + diff --git a/client.h b/client.h index 2db7433..4c1c2a0 100644 --- a/client.h +++ b/client.h @@ -19,6 +19,8 @@ extern "C" { #endif +#include "modbus.h" + #define LEN_STATUSTEXT 255 void displayerror (std::string error); @@ -30,7 +32,22 @@ void displayerror (std::string error); // gboolean mbcli_thread_cb_error(gpointer data); gboolean mbcli_thread_cb_status(gpointer data); - +gboolean mbcli_thread_cb_net(gpointer data); + +int mbcli_get_FC (); +int mbcli_get_register (); +int mbcli_get_unitid (); +int mbcli_get_number (); +int mbcli_get_update (); +void mbcli_set_update (int active); +int mbcli_get_FC1516 (); +void mbcli_readdata(); +gboolean mbcli_refreshtimeout(gpointer data); + +std::string to_hex16 (int v); + +G_MODULE_EXPORT void mbcli_cb_show(GtkWidget *widget, gpointer data); +G_MODULE_EXPORT void mbcli_cb_updateread (GtkToggleButton *togglebutton, gpointer user_data); G_MODULE_EXPORT void mbcli_cb_connect (GtkWidget *widget, gpointer data); G_MODULE_EXPORT void mbcli_cb_disconnect (GtkWidget *widget, gpointer data); diff --git a/modbus.cc b/modbus.cc index dfc100a..12c127c 100644 --- a/modbus.cc +++ b/modbus.cc @@ -5,6 +5,8 @@ ///////////////////////////////////////////////////////////////////////////////// #include +#include +#include #include #include "modbus.h" @@ -27,10 +29,10 @@ __dsti16 = ntohs((uint16_t)__tmpi16) /* - * packs the header into the buffer data and returns the lenght of the header + * packs the request header into the buffer data and returns the lenght of the header * returns NULL on error or points to end of data */ -char * modbustcp_pkt_header (char *destbuffer, int bufsize, modbustcp_header *srcmbh) { +char * modbustcp_pkt_headerrq (char *destbuffer, int bufsize, modbustcp_rq_header *srcmbh) { uint16_t tmp; // destination memory valid @@ -58,12 +60,14 @@ char * modbustcp_pkt_header (char *destbuffer, int bufsize, modbustcp_header *sr /* - * unpacks the buffer into the header + * unpacks the buffer into the header request * returns NULL on error or points to end of data */ -char * modbustcp_unpkt_header (modbustcp_header *destmbh, char *srcbuffer, int bufsize) { +char * modbustcp_unpkt_headerrq (modbustcp_rq_header *destmbh, char *srcbuffer, int bufsize) { uint16_t tmp; + printf ("%s:%d %s bufsize:%d\n", __FILE__, __LINE__, __FUNCTION__, bufsize); + // source memory valid if (srcbuffer == NULL) { errno = EFAULT; @@ -86,3 +90,66 @@ char * modbustcp_unpkt_header (modbustcp_header *destmbh, char *srcbuffer, int b return src; } + + +/* + * packs the resonse header into the buffer data and returns the lenght of the header + * returns NULL on error or points to end of data + */ +char * modbustcp_pkt_headerres (char *destbuffer, int bufsize, modbustcp_res_header *srcmbh) { + uint16_t tmp; + + // destination memory valid + if (destbuffer == NULL) { + errno = EFAULT; + return NULL; + } + if (bufsize < 9) { + errno = EOVERFLOW; + return NULL; + } + + char *pos = destbuffer; + + PACK_INT16(tmp, pos, srcmbh->transid); + PACK_INT16(tmp, pos, srcmbh->protid); + PACK_INT16(tmp, pos, srcmbh->length); + PACK_INT8(pos, srcmbh->uid); + PACK_INT8(pos, srcmbh->fc); + PACK_INT8(pos, srcmbh->number); + + return pos; +} + + + +/* + * unpacks the buffer into the header modbustcp response + * returns NULL on error or points to end of data + */ +char * modbustcp_unpkt_headerres (modbustcp_res_header *destmbh, char *srcbuffer, int bufsize) { + uint16_t tmp; + + printf ("%s:%d %s bufsize:%d\n", __FILE__, __LINE__, __FUNCTION__, bufsize); + + // source memory valid + if (srcbuffer == NULL) { + errno = EFAULT; + return NULL; + } + if (bufsize < 10) { + errno = EOVERFLOW; + return NULL; + } + + char *src = srcbuffer; + + UNPACK_INT16(tmp, destmbh->transid, src); + UNPACK_INT16(tmp, destmbh->protid, src); + UNPACK_INT16(tmp, destmbh->length, src); + UNPACK_INT8(destmbh->uid, src); + UNPACK_INT8(destmbh->fc, src); + UNPACK_INT8(destmbh->number, src); + + return src; +} diff --git a/modbus.h b/modbus.h index 2b598f1..cbe776a 100644 --- a/modbus.h +++ b/modbus.h @@ -23,11 +23,23 @@ struct { uint8_t fc; // function code uint16_t offset; // first register to read uint16_t number; // number of registers to read -} typedef modbustcp_header; +} typedef modbustcp_rq_header; -char * modbustcp_pkt_header (char *destbuffer, int bufsize, modbustcp_header *srcmbh); -char * modbustcp_unpkt_header (modbustcp_header *destmbh, char *srcbuffer, int bufsize); +struct { + uint16_t transid; // transaction id + uint16_t protid; // protocol id + uint16_t length; // number of bytes followed + uint8_t uid; // unit/slave id + uint8_t fc; // function code + uint8_t number; // number of registers to read +} typedef modbustcp_res_header; + +char * modbustcp_pkt_headerrq (char *destbuffer, int bufsize, modbustcp_rq_header *srcmbh); +char * modbustcp_unpkt_headerrq (modbustcp_rq_header *destmbh, char *srcbuffer, int bufsize); + +char * modbustcp_pkt_headerres (char *destbuffer, int bufsize, modbustcp_res_header *srcmbh); +char * modbustcp_unpkt_headerres (modbustcp_res_header *destmbh, char *srcbuffer, int bufsize); #endif diff --git a/nwthread.cc b/nwthread.cc index c535392..c567668 100644 --- a/nwthread.cc +++ b/nwthread.cc @@ -36,9 +36,8 @@ NetworkThread::NetworkThread() { state = 0; host = ""; port = ""; - req_fc = -1; - req_offset = 0; - req_size = 0; + memset (&req_mbh, 0x0, sizeof(modbustcp_rq_header)); + req_new = 0; memset (&req_time, 0x0, sizeof (req_time)); req_timeout = 0; }; @@ -111,7 +110,30 @@ int NetworkThread::GetState() { }; -void NetworkThread::ClientSendStatustext(char *txt) { +int NetworkThread::SendRequestRead(int unitid, int fc, int reg, int num) { + Lock(); + if (req_mbh.fc != 0 || req_new != 0) { + printf ("%s%d %s req_new: %d req_mbh.fc: %d\n", __FILE__, __LINE__, __FUNCTION__, + req_new, req_mbh.fc); + UnLock(); + return 0; + } + + req_new = 1; + req_mbh.fc = fc; + req_mbh.offset = reg; + req_mbh.number = num; + req_mbh.uid = unitid; + + printf ("%s:%d build request fc:%d offset:%d number:%d\n", __FILE__, __LINE__, + req_mbh.fc, req_mbh.offset, req_mbh.number); + + UnLock(); + return 1; +} + + +void NetworkThread::GuiSendStatustext(char *txt) { char *msg = NULL; if (txt) { int l = strlen (txt)+1; @@ -123,19 +145,62 @@ void NetworkThread::ClientSendStatustext(char *txt) { } -#define BUFFER_SIZE 0x10000 +/* + * send response to the gui. + * the data block must be freed. + */ +void NetworkThread::GuiSendResult(char *buffer, int len, modbustcp_rq_header *mbh_rq) { + NWTReqResult *res = (NWTReqResult*) malloc(sizeof (NWTReqResult)); + int i, cnt; + uint16_t tmp; + + res->fc = mbh_rq->fc; + res->cnt = mbh_rq->number; + res->reg = mbh_rq->offset; + + if (res->fc == 1 || res->fc == 2) { + + } + else { + for (cnt = 0, i = 9; i < len && cnt < 0x100 && cnt < mbh_rq->number; cnt++) { + memcpy (&tmp, buffer+i, 2); + res->data[cnt] = ntohs(tmp); + i += 2; + } + } + + gdk_threads_add_idle(mbcli_thread_cb_net, (void *) res); +} + +/* + * data must be Thread Locked already + * request information must be set already + */ +void NetworkThread::BuildAndSendReadReq(char *buffer, int size) { + char *pos; + + req_mbh.length = 0; + req_mbh.transid++; + pos = modbustcp_pkt_headerrq(buffer, size, &req_mbh); + tcp.Write(buffer, (pos-buffer)); +}; + + +#define BUFFER_SIZE 0x10000 void NetworkThread::Thread() { int i; long int len; - TCP tcp; char buffer[BUFFER_SIZE]; + modbustcp_res_header in_mbh; // incomming mbh data + char *pos; printf ("%s:%d NetworkThread::Thread Started\n", __FILE__, __LINE__); - ClientSendStatustext((char*)"connecting"); + GuiSendStatustext((char*)"connecting"); Lock(); - req_fc = 0; + req_mbh.fc = 0; + req_mbh.transid = 0; UnLock(); // @@ -146,15 +211,15 @@ void NetworkThread::Thread() { if (i < 0) { // // error on connect, stop thread. - ClientSendStatustext(strerror(errno)); + GuiSendStatustext(strerror(errno)); SetState(NWT_nothing); - ClientSendStatustext(NULL); + GuiSendStatustext(NULL); printf ("%s:%d NetworkThread::Thread Finished on connect\n", __FILE__, __LINE__); return; } - if (i == 1) ClientSendStatustext((char*)"connected"); + if (i == 1) GuiSendStatustext((char*)"connected"); // FIXME: else: still connecting need some timeout and checks. SetState(NWT_running); @@ -162,9 +227,18 @@ void NetworkThread::Thread() { // connection established // go into the main loop while (GetState() == NWT_running) { + // + // new request? + Lock(); + if (req_new == 1) { + BuildAndSendReadReq(buffer, BUFFER_SIZE); + req_new = 0; + } + UnLock(); + // // check for new data - i = tcp.IsData(1000); + i = tcp.IsData(10); if (i < 0) { SetState(NWT_error); break; @@ -173,14 +247,14 @@ void NetworkThread::Thread() { // // we got some data + Lock(); printf ("read data\n"); len = tcp.Read(buffer, BUFFER_SIZE); - Lock(); if (len < 0) state = NWT_close; else { // // we could get some data, if busy reset connection - if (req_fc == 0) { + if (req_mbh.fc == 0) { // got data without request? - Protokol error errno = EPROTO; state = NWT_error; @@ -189,8 +263,34 @@ void NetworkThread::Thread() { // // return data - - + if ((pos = modbustcp_unpkt_headerres(&in_mbh, buffer, len)) == NULL) { + printf ("%s:%d error on reading modbus header (%s)\n", __FILE__, __LINE__, strerror(errno)); + errno = EPROTO; + GuiSendStatustext(strerror(errno)); + } + // + // process data is valid + if ((in_mbh.fc == 1 || in_mbh.fc == 2) && + (in_mbh.fc == req_mbh.fc && + in_mbh.number == (((req_mbh.number-1) / 8)+1) && + in_mbh.transid == req_mbh.transid)) { + GuiSendResult(buffer, len, &req_mbh); + req_mbh.fc = 0; + } + else if ((in_mbh.fc == 3 || in_mbh.fc == 4) && + (in_mbh.fc == req_mbh.fc && + in_mbh.number/2 == req_mbh.number && + in_mbh.transid == req_mbh.transid)) { + GuiSendResult(buffer, len, &req_mbh); + req_mbh.fc = 0; + } + else { + printf ("%s:%d incorrect data: fc: %d == %d number: %d == %d(%d) transid: %d == %d\n", __FILE__, __LINE__, + in_mbh.fc, req_mbh.fc, in_mbh.number, (((req_mbh.number-1) / 8)+1), req_mbh.number, in_mbh.transid, req_mbh.transid); + errno = EPROTO; + GuiSendStatustext(strerror(errno)); + } + req_mbh.fc = 0; } UnLock(); } @@ -200,15 +300,15 @@ void NetworkThread::Thread() { i = GetState(); switch (i) { case NWT_error: - ClientSendStatustext(strerror(errno)); + GuiSendStatustext(strerror(errno)); tcp.Close(); break; case NWT_close: - ClientSendStatustext((char*)"Connection Closed"); + GuiSendStatustext((char*)"Connection Closed"); tcp.Close(); break; default: - ClientSendStatustext((char*)"Unknown Error"); + GuiSendStatustext((char*)"Unknown Error"); tcp.Close(); break; } diff --git a/nwthread.h b/nwthread.h index 8df548f..782eb9d 100644 --- a/nwthread.h +++ b/nwthread.h @@ -13,6 +13,9 @@ #include #include +#include "modbus.h" +#include "tcp.h" + enum { NWT_nothing, NWT_connect, @@ -22,22 +25,32 @@ enum { }; +struct { + int fc; + int reg; + int cnt; + uint16_t data[0x100]; +} typedef NWTReqResult; + class NetworkThread { private: GMutex mutex; GThread *thread; int state; - int req_fc; // 0 .. is no request - int req_offset; - int req_size; + int req_new; // new request + + modbustcp_rq_header req_mbh; + // .fc == 0 no request int req_timeout; // timeout[ms] struct timeval req_time; - + TCP tcp; std::string host, port; void SetState(int s); - void ClientSendStatustext(char* txt); + void GuiSendStatustext(char* txt); + void GuiSendResult(char *buffer, int len, modbustcp_rq_header *mbh_in); + void BuildAndSendReadReq(char *buffer, int size); public: NetworkThread(); @@ -50,7 +63,7 @@ public: int Disconnect(); int GetState(); - int SendRequest(); + int SendRequestRead(int unitid, int fc, int reg, int num); void Thread(); }; diff --git a/testmodbus-client.ui b/testmodbus-client.ui index 51bbcd7..cc84261 100644 --- a/testmodbus-client.ui +++ b/testmodbus-client.ui @@ -5,12 +5,14 @@ 16 - - 0 + + + 255 False + True @@ -134,7 +136,7 @@ - + True True 4 @@ -215,19 +217,64 @@ - + True False - 8 - 8 - 8 - 8 - 8 - 8 - - - - + + + True + False + 8 + 8 + 8 + 8 + 8 + 8 + + + + + + + True + True + 0 + + + + + True + False + 0 / 0 + + + + + + False + True + 5 + end + 1 + + + + + True + False + end + center + Rate +Errors / Requests: + + + False + True + 5 + end + 2 + + False @@ -346,6 +393,7 @@ True False True + False @@ -429,7 +477,7 @@ - + True False @@ -439,14 +487,17 @@ 4 4 - + True - False - Register / Flag: + True + entrybuffer_numbers + 5 + 5 + 16 - 0 - 0 + 4 + 1 @@ -456,36 +507,33 @@ Numbers: - 0 + 3 1 - + True - True - entrybuffer_offset - 5 - 5 - 0 + False + Register / Flag: - 1 + 3 0 - + True True - entrybuffer_numbers + entrybuffer_offset 5 5 - 16 + 0 - 1 - 1 + 4 + 0 @@ -498,10 +546,47 @@ True - 3 + 6 + 0 + + + + + True + False + Unit: + + + 0 0 + + + True + True + entrybuffer_unitid + 5 + 5 + 255 + + + 1 + 0 + + + + + + + + + + + + + +