connect and close is working

main
Steffen Pohle 2 years ago
parent 36879aa9c5
commit 8ca01af2d1

2
.gitignore vendored

@ -1,4 +1,6 @@
.project .project
testmodbus-client.ui~
*.oo
# ---> Autotools # ---> Autotools
# http://www.gnu.org/software/automake # http://www.gnu.org/software/automake

@ -1,15 +1,28 @@
/////////////////////////////////////////////////////////////////////////////////
//
// client.cc is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#include <sys/time.h> #include <sys/time.h>
#include "config.h" #include "config.h"
#include "client.h" #include "client.h"
#include "nwthread.h"
#define BUILDER_FILE "testmodbus-client.ui" #define BUILDER_FILE "testmodbus-client.ui"
/************************************************************************************ /************************************************************************************
* Global Variables * Global Variables
*/ */
GtkBuilder *_builder_ = NULL; // work around for the thread situation GtkBuilder *_builder_ = NULL; // work around for the thread situation
gboolean modbuscli_callback(gpointer data); // callback for threads 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
NetworkThread netthread;
int main (int argc, char **argv) { int main (int argc, char **argv) {
GtkBuilder *builder; GtkBuilder *builder;
@ -35,7 +48,6 @@ int main (int argc, char **argv) {
// #endif // #endif
// //
// modbuscli.SetCallback(&modbus_callback);
window = gtk_builder_get_object (builder, "testmodbus-client"); window = gtk_builder_get_object (builder, "testmodbus-client");
gtk_widget_show_all (GTK_WIDGET(window)); gtk_widget_show_all (GTK_WIDGET(window));
gtk_main (); gtk_main ();
@ -44,9 +56,76 @@ int main (int argc, char **argv) {
} }
gboolean modbuscli_callback(gpointer data) {
void *mdata = data; /*
free (mdata); * display error if somethin happened within a thread
*/
gboolean mbcli_thread_cb_error(gpointer data) {
if (data == NULL) {
displayerror ("unknown error");
}
else {
std::string text = (char*)data;
free (data);
displayerror (text);
}
return FALSE; return FALSE;
}; };
void displayerror (std::string error) {
GtkWidget *dialog;
GtkWidget *window = GTK_WIDGET (gtk_builder_get_object (_builder_, "testmodbus-client"));
dialog = gtk_message_dialog_new(GTK_WINDOW(window),
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
error.c_str());
gtk_window_set_title(GTK_WINDOW(dialog), "Error");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
/*
* network thread callback
*/
gboolean mbcli_thread_cb_status(gpointer data) {
GtkWidget *statusbar = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_statusbar"));
mbcli_connect_btn_sensitive (netthread.GetState() == NWT_nothing);
if (data) {
gtk_label_set_label(GTK_LABEL(statusbar), (char*)data);
free (data);
}
return FALSE;
};
void mbcli_connect_btn_sensitive (bool enable) {
GtkWidget *txthost = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_host"));
GtkWidget *txtport = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_port"));
GtkWidget *btnconnect = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_btnConnect"));
GtkWidget *btndisconnect = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_btnDisconnect"));
gtk_widget_set_sensitive(txthost, enable);
gtk_widget_set_sensitive(txtport, enable);
gtk_widget_set_sensitive(btnconnect, enable);
gtk_widget_set_sensitive(btndisconnect, !enable);
};
void mbcli_cb_connect (GtkWidget *widget, gpointer data) {
GtkWidget *txthost = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_host"));
GtkWidget *txtport = GTK_WIDGET (gtk_builder_get_object (_builder_, "cli_port"));
mbcli_connect_btn_sensitive(false);
netthread.Connect(gtk_entry_get_text(GTK_ENTRY(txthost)), gtk_entry_get_text(GTK_ENTRY(txtport)));
};
void mbcli_cb_disconnect (GtkWidget *widget, gpointer data) {
netthread.Disconnect();
};

@ -19,13 +19,20 @@
extern "C" { extern "C" {
#endif #endif
#define LEN_STATUSTEXT 255
void displayerror (std::string error);
// *********************************************************************** // ***********************************************************************
// //
// main windows call backs // main windows call backs
// //
gboolean mbcli_thread_cb_error(gpointer data);
gboolean mbcli_thread_cb_status(gpointer data);
G_MODULE_EXPORT gboolean modbus_callback (gpointer data); G_MODULE_EXPORT void mbcli_cb_connect (GtkWidget *widget, gpointer data);
G_MODULE_EXPORT void mbcli_cb_disconnect (GtkWidget *widget, gpointer data);
#ifdef __cplusplus #ifdef __cplusplus
} }

@ -0,0 +1,148 @@
/////////////////////////////////////////////////////////////////////////////////
//
// nwthread.cc is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#include <errno.h>
#include <glib.h>
#include <sys/time.h>
#include <string>
#include <string.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#else
#include <unistd.h> /* close() */
#endif
#include "tcp.h"
#include "nwthread.h"
#include "client.h"
extern NetworkThread netthread;
// c / C++ wrapper
gpointer _Thread (gpointer data) {
netthread.Thread ();
return NULL;
};
NetworkThread::NetworkThread() {
g_mutex_init (&mutex);
thread = NULL;
state = 0;
host = "";
port = "";
};
NetworkThread::~NetworkThread() {
Disconnect();
g_mutex_clear(&mutex);
};
void NetworkThread::Lock() {
g_mutex_lock(&mutex);
};
void NetworkThread::UnLock() {
g_mutex_unlock(&mutex);
};
/*
* start network thread and connect
*/
int NetworkThread::Connect(std::string dest_host, std::string dest_port) {
printf ("%s:%d NetworkThread::Connect to %s:%s\n", __FILE__, __LINE__, dest_host.c_str(), dest_port.c_str());
//
// if there is an open connection close this one first
if (GetState() != NWT_nothing) Disconnect();
host = dest_host;
port = dest_port;
thread = g_thread_new("network thread", _Thread, NULL);
return -1;
};
/*
* stop network connection
*/
int NetworkThread::Disconnect() {
printf ("%s:%d NetworkThread::Disconnect\n", __FILE__, __LINE__);
Lock();
if (state != NWT_nothing) state = NWT_close;
UnLock();
while (GetState() != NWT_nothing) { usleep(1000); };
if (thread != NULL) g_thread_unref(thread);
thread = NULL;
return 0;
};
void NetworkThread::SetState(int s) {
Lock();
state = s;
UnLock();
};
int NetworkThread::GetState() {
int s;
Lock();
s = state;
UnLock();
return s;
};
void NetworkThread::ClientSendStatustext(char *txt) {
char *msg = NULL;
if (txt) {
int l = strlen (txt)+1;
msg = (char*) malloc(l+1);
memset (msg, 0x0, l+1);
strncpy (msg, txt, strlen (txt));
}
gdk_threads_add_idle(mbcli_thread_cb_status, msg);
}
void NetworkThread::Thread() {
printf ("%s:%d NetworkThread::Thread Started\n", __FILE__, __LINE__);
TCP tcp;
ClientSendStatustext((char*)"connecting");
SetState (NWT_connect);
if (tcp.Connect(host, port) != 1) {
ClientSendStatustext(strerror(errno));
}
else {
//
// destination host and port should be set already
SetState(NWT_running);
while (GetState() == NWT_running) {
ClientSendStatustext((char*)"connected");
usleep (1000);
}
if(GetState() == NWT_close) {
ClientSendStatustext((char*)"");
}
}
SetState(NWT_nothing);
ClientSendStatustext(NULL);
printf ("%s:%d NetworkThread::Thread Finished\n", __FILE__, __LINE__);
};

@ -0,0 +1,49 @@
/////////////////////////////////////////////////////////////////////////////////
//
// nwthread.h is part of TestModbus-Client.
//
/////////////////////////////////////////////////////////////////////////////////
#ifndef _NWTHREAD_H_
#define _NWTHREAD_H_
#include <string>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <glib.h>
enum {
NWT_nothing,
NWT_connect,
NWT_running,
NWT_close
};
class NetworkThread {
private:
GMutex mutex;
GThread *thread;
int state;
std::string host, port;
void SetState(int s);
void ClientSendStatustext(char* txt);
public:
NetworkThread();
~NetworkThread();
void Lock();
void UnLock();
int Connect(std::string dest_host, std::string dest_port);
int Disconnect();
int GetState();
void Thread();
};
#endif

@ -1,6 +1,6 @@
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////
// //
// tcp.h is part of TestModbus-Server. // tcp.h is part of TestModbus-Client.
// //
///////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////

@ -9,6 +9,10 @@
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkFrame"> <object class="GtkFrame">
@ -16,8 +20,6 @@
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="margin-start">4</property> <property name="margin-start">4</property>
<property name="margin-end">4</property> <property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="label-xalign">0</property> <property name="label-xalign">0</property>
<child> <child>
<object class="GtkAlignment"> <object class="GtkAlignment">
@ -28,29 +30,76 @@
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="spacing">4</property> <property name="orientation">vertical</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property> <property name="spacing">4</property>
<child> <child>
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property> <property name="spacing">4</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">Host:</property> <property name="spacing">4</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Host:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="cli_host">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="text" translatable="yes">localhost</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="label" translatable="yes">Port:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="cli_port">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="width-chars">6</property>
<property name="text" translatable="yes">1502</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -59,40 +108,40 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry" id="cli_host"> <object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="text" translatable="yes">localhost</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">Port:</property> <property name="spacing">4</property>
</object> <child>
<packing> <object class="GtkLabel">
<property name="expand">False</property> <property name="visible">True</property>
<property name="fill">True</property> <property name="can-focus">False</property>
<property name="position">2</property> <property name="label" translatable="yes">Refresh [ms]:</property>
</packing> </object>
</child> <packing>
<child> <property name="expand">False</property>
<object class="GtkEntry" id="cli_port"> <property name="fill">True</property>
<property name="visible">True</property> <property name="position">0</property>
<property name="can-focus">True</property> </packing>
<property name="width-chars">6</property> </child>
<property name="text" translatable="yes">502</property> <child>
<object class="GtkEntry">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="width-chars">4</property>
<property name="text" translatable="yes">1000</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">True</property> <property name="fill">True</property>
<property name="position">3</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
</object> </object>
@ -106,12 +155,17 @@
<object class="GtkBox"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="spacing">4</property> <property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="orientation">vertical</property>
<child> <child>
<object class="GtkLabel"> <object class="GtkCheckButton" id="cli_cb_reconnect">
<property name="label" translatable="yes">Auto Reconnect</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">True</property>
<property name="label" translatable="yes">Refresh [ms]:</property> <property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -120,11 +174,13 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkEntry"> <object class="GtkCheckButton" id="cli_cb_readonly">
<property name="label" translatable="yes">Read Only</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">True</property> <property name="can-focus">True</property>
<property name="width-chars">4</property> <property name="receives-default">False</property>
<property name="text" translatable="yes">1000</property> <property name="active">True</property>
<property name="draw-indicator">True</property>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -132,6 +188,9 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<placeholder/>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -147,43 +206,19 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkBox"> <object class="GtkLabel" id="cli_statusbar">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="orientation">vertical</property> <property name="margin-left">8</property>
<child> <property name="margin-right">8</property>
<object class="GtkCheckButton" id="cli_cb_reconnect"> <property name="margin-start">8</property>
<property name="label" translatable="yes">Auto Reconnect</property> <property name="margin-end">8</property>
<property name="visible">True</property> <property name="margin-top">8</property>
<property name="can-focus">True</property> <property name="margin-bottom">8</property>
<property name="receives-default">False</property> <attributes>
<property name="active">True</property> <attribute name="style" value="normal"/>
<property name="draw-indicator">True</property> <attribute name="weight" value="bold"/>
</object> </attributes>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="cli_cb_readonly">
<property name="label" translatable="yes">Read Only</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">False</property>
<property name="active">True</property>
<property name="draw-indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<placeholder/>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -191,51 +226,6 @@
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">3</property>
<child>
<object class="GtkButton" id="cli_btnConnect">
<property name="label">gtk-connect</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cli_btnClose">
<property name="label">gtk-disconnect</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">2</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
@ -244,14 +234,55 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkLabel"> <object class="GtkBox">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can-focus">False</property> <property name="can-focus">False</property>
<property name="label" translatable="yes">last error | status</property> <property name="halign">center</property>
<property name="valign">center</property>
<property name="margin-start">4</property>
<property name="margin-end">4</property>
<property name="margin-top">4</property>
<property name="margin-bottom">4</property>
<property name="orientation">vertical</property>
<property name="spacing">4</property>
<child>
<object class="GtkButton" id="cli_btnConnect">
<property name="label">gtk-connect</property>
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="mbcli_cb_connect" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="cli_btnDisconnect">
<property name="label">gtk-disconnect</property>
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="can-focus">True</property>
<property name="receives-default">True</property>
<property name="use-stock">True</property>
<property name="always-show-image">True</property>
<signal name="clicked" handler="mbcli_cb_disconnect" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object> </object>
<packing> <packing>
<property name="expand">False</property> <property name="expand">False</property>
<property name="fill">False</property> <property name="fill">True</property>
<property name="pack-type">end</property>
<property name="position">1</property> <property name="position">1</property>
</packing> </packing>
</child> </child>

Loading…
Cancel
Save