Compare commits

...

2 Commits

3
.gitignore vendored

@ -1,3 +1,6 @@
Makefile.rules
config.h
testmodbus-client
.project
testmodbus-client.ui~
*.oo

@ -3,7 +3,7 @@ VERSION = 1.0.1
-include Makefile.rules
OBJECTSCLI = client.oo tcp.oo nwthread.oo
OBJECTSCLI = client.oo tcp.oo nwthread.oo modbus.oo
DISTNAME=testmodbus-client-$(VERSION)

@ -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
};

@ -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);

@ -0,0 +1,155 @@
/////////////////////////////////////////////////////////////////////////////////
//
// modbus.cc is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include "modbus.h"
#define PACK_INT8(__dstptr, __srci8) \
memcpy(__dstptr, &__srci8, 1); \
__dstptr += 1
#define UNPACK_INT8(__dsti8, __srcptr) \
memcpy(&__dsti8, __srcptr, 1); \
__srcptr += 1
#define PACK_INT16(__tmpi16, __dstptr, __srci16) \
__tmpi16 = htons((uint16_t)__srci16); \
memcpy(__dstptr, &__tmpi16, 2); \
__dstptr += 2
#define UNPACK_INT16(__tmpi16, __dsti16, __srcptr) \
memcpy(&__tmpi16, __srcptr, 2); \
__srcptr += 2; \
__dsti16 = ntohs((uint16_t)__tmpi16)
/*
* 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_headerrq (char *destbuffer, int bufsize, modbustcp_rq_header *srcmbh) {
uint16_t tmp;
// destination memory valid
if (destbuffer == NULL) {
errno = EFAULT;
return NULL;
}
if (bufsize < 12) {
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_INT16(tmp, pos, srcmbh->offset);
PACK_INT16(tmp, pos, srcmbh->number);
return pos;
}
/*
* unpacks the buffer into the header request
* returns NULL on error or points to end of data
*/
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;
return NULL;
}
if (bufsize < 12) {
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_INT16(tmp, destmbh->offset, src);
UNPACK_INT16(tmp, destmbh->number, src);
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;
}

@ -0,0 +1,45 @@
/////////////////////////////////////////////////////////////////////////////////
//
// modbus.h is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _MODBUS_H_
#define _MODBUS_H_
#include <stdint.h>
#include <stdlib.h>
#include <arpa/inet.h>
/*
* this file will only contain the encoding and decoding functions
*/
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
uint16_t offset; // first register to read
uint16_t number; // number of registers to read
} typedef modbustcp_rq_header;
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

@ -36,6 +36,10 @@ NetworkThread::NetworkThread() {
state = 0;
host = "";
port = "";
memset (&req_mbh, 0x0, sizeof(modbustcp_rq_header));
req_new = 0;
memset (&req_time, 0x0, sizeof (req_time));
req_timeout = 0;
};
NetworkThread::~NetworkThread() {
@ -106,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;
@ -118,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();
//
@ -141,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);
@ -157,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;
@ -168,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;
@ -184,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();
}
@ -195,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;
}

@ -13,6 +13,9 @@
#include <glib.h>
#include <sys/time.h>
#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();
};

@ -2,9 +2,17 @@
<!-- Generated with glade 3.40.0 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkEntryBuffer" id="entrybuffer_numbers">
<property name="text" translatable="yes">16</property>
</object>
<object class="GtkEntryBuffer" id="entrybuffer_offset"/>
<object class="GtkEntryBuffer" id="entrybuffer_unitid">
<property name="text" translatable="yes">255</property>
</object>
<object class="GtkWindow" id="testmodbus-client">
<property name="can-focus">False</property>
<signal name="destroy" handler="gtk_main_quit" swapped="no"/>
<signal name="show" handler="mbcli_cb_show" swapped="no"/>
<child>
<object class="GtkBox">
<property name="visible">True</property>
@ -128,7 +136,7 @@
</packing>
</child>
<child>
<object class="GtkEntry">
<object class="GtkEntry" id="cli_refreshtime">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="width-chars">4</property>
@ -209,19 +217,64 @@
</packing>
</child>
<child>
<object class="GtkLabel" id="cli_statusbar">
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">8</property>
<property name="margin-right">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<attributes>
<attribute name="style" value="normal"/>
<attribute name="weight" value="bold"/>
</attributes>
<child>
<object class="GtkLabel" id="cli_statusbar">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="margin-left">8</property>
<property name="margin-right">8</property>
<property name="margin-start">8</property>
<property name="margin-end">8</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<attributes>
<attribute name="style" value="normal"/>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="cli_rate">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">0 / 0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="pack-type">end</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="Error / Requests:">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">end</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Rate
Errors / Requests:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="padding">5</property>
<property name="pack-type">end</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
@ -340,6 +393,7 @@
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="draw-indicator">True</property>
<signal name="toggled" handler="mbcli_cb_updateread" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
@ -355,6 +409,7 @@
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
<property name="group">cli_FC1</property>
</object>
<packing>
<property name="expand">False</property>
@ -371,6 +426,7 @@
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
<property name="group">cli_FC1</property>
</object>
<packing>
<property name="expand">False</property>
@ -387,6 +443,7 @@
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
<property name="group">cli_FC1</property>
</object>
<packing>
<property name="expand">False</property>
@ -420,7 +477,7 @@
</packing>
</child>
<child>
<!-- n-columns=4 n-rows=2 -->
<!-- n-columns=7 n-rows=2 -->
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can-focus">False</property>
@ -430,14 +487,17 @@
<property name="row-spacing">4</property>
<property name="column-spacing">4</property>
<child>
<object class="GtkLabel">
<object class="GtkEntry" id="cli_number">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Register / Flag:</property>
<property name="can-focus">True</property>
<property name="buffer">entrybuffer_numbers</property>
<property name="max-length">5</property>
<property name="width-chars">5</property>
<property name="placeholder-text" translatable="yes">16</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
<property name="left-attach">4</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
@ -447,32 +507,33 @@
<property name="label" translatable="yes">Numbers:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="left-attach">3</property>
<property name="top-attach">1</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="max-length">5</property>
<property name="width-chars">5</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Register / Flag:</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="left-attach">3</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry">
<object class="GtkEntry" id="cli_register">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="buffer">entrybuffer_offset</property>
<property name="max-length">5</property>
<property name="width-chars">5</property>
<property name="placeholder-text" translatable="yes">0</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">1</property>
<property name="left-attach">4</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
@ -485,10 +546,47 @@
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="left-attach">3</property>
<property name="left-attach">6</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Unit:</property>
</object>
<packing>
<property name="left-attach">0</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="cli_unitid">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="buffer">entrybuffer_unitid</property>
<property name="max-length">5</property>
<property name="width-chars">5</property>
<property name="placeholder-text" translatable="yes">255</property>
</object>
<packing>
<property name="left-attach">1</property>
<property name="top-attach">0</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>

Loading…
Cancel
Save