diff --git a/apps/gtk-discover/BACnet-Icon.svg b/apps/gtk-discover/BACnet-Icon.svg
new file mode 100644
index 00000000..f4fcbc4e
--- /dev/null
+++ b/apps/gtk-discover/BACnet-Icon.svg
@@ -0,0 +1,193 @@
+
+
+
+
diff --git a/apps/gtk-discover/bacdiscover-gtk.desktop b/apps/gtk-discover/bacdiscover-gtk.desktop
new file mode 100644
index 00000000..63571ed1
--- /dev/null
+++ b/apps/gtk-discover/bacdiscover-gtk.desktop
@@ -0,0 +1,16 @@
+[Desktop Entry]
+Name=BACnet GTK Discovery
+Comment=Graphical discovery for BACnet devices, objects, and properties
+Exec=/usr/local/bin/bacdiscover-gtk
+Icon=network-workgroup
+Terminal=false
+Type=Application
+Categories=Network;Development;Utility;
+Keywords=BACnet;Building Automation;HVAC;Industrial;Network;Protocol;
+StartupNotify=true
+MimeType=application/x-bacnet;
+
+# Additional metadata
+GenericName=BACnet Device Discovery
+StartupWMClass=bacnet-gtk-discovery
+X-GNOME-UsesNotifications=true
diff --git a/apps/gtk-discover/bacnet-icon.xpm b/apps/gtk-discover/bacnet-icon.xpm
new file mode 100644
index 00000000..b01b095f
--- /dev/null
+++ b/apps/gtk-discover/bacnet-icon.xpm
@@ -0,0 +1,140 @@
+/* XPM */
+static const char *bacnet_icon[] = {
+/* columns rows colors chars-per-pixel */
+"81 70 64 1 ",
+" c black",
+". c #060906090609",
+"X c gray3",
+"o c #0D150D150D15",
+"O c #111B111B111B",
+"+ c #173C173C173C",
+"@ c #1B0F1B0F1B0F",
+"# c #1EFB1EFB1EFB",
+"$ c #203320332033",
+"% c #242524252425",
+"& c #294429442944",
+"* c #2D412D412D41",
+"= c gray20",
+"- c #351035103510",
+"; c #3A333A333A33",
+": c #3D623D623D62",
+"> c #414141414141",
+", c #477347734773",
+"< c #4A4C4A4C4A4C",
+"1 c #4E3E4E3E4E3E",
+"2 c #503E503E503E",
+"3 c #54C054C054C0",
+"4 c #5A665A665A66",
+"5 c #5F825F825F82",
+"6 c #606060606060",
+"7 c #653F653F653F",
+"8 c #6A6A6A6A6A6A",
+"9 c #6FC46FC46FC4",
+"0 c #72B272B272B2",
+"q c #767376737673",
+"w c #799279927992",
+"e c #7DA67DA67DA6",
+"r c #805B805B805B",
+"t c #857585758575",
+"y c #888888888888",
+"u c #8E968E968E96",
+"i c #927E927E927E",
+"p c #946794679467",
+"a c #9B659B659B65",
+"s c #9D9E9D9E9D9E",
+"d c #A0D9A0D9A0D9",
+"f c #A569A569A569",
+"g c #ABE1ABE1ABE1",
+"h c #AEDFAEDFAEDF",
+"j c #B2C9B2C9B2C9",
+"k c #B799B799B799",
+"l c #B97EB97EB97E",
+"z c gray",
+"x c #C3ECC3ECC3EC",
+"c c #C5A4C5A4C5A4",
+"v c #CBCBCBCBCBCB",
+"b c #CFB6CFB6CFB6",
+"n c #D1C2D1C2D1C2",
+"m c gray83",
+"M c #DBBFDBBFDBBF",
+"N c gainsboro",
+"B c #E0F7E0F7E0F7",
+"V c #E841E841E841",
+"C c #EA2BEA2BEA2B",
+"Z c #EF17EF17EF17",
+"A c #F200F200F200",
+"S c #F4EEF4EEF4EE",
+"D c #FC4BFC4BFC4B",
+"F c white",
+/* pixels */
+"FFFFFFFFFFFFFFFFFFFFx9999999999999999999999999999999999999999xFFFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFFD DFFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFFu vFFFFFFFFFFFFFFF* rFFFFFFFFFFFFFFFFFFv uFFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFV 2FFFFFFFFFFFFFFFm *FFFFFFFFFFFFFFFFFFF1 VFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFF4 VFFFFFFFFFFFFFFFe o mFFFFFFFFFFFFFFFFFFB 4FFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFb tFFFFFFFFFFFFFFFF% Xt rFFFFFFFFFFFFFFFFFFFt bFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFF# SFFFFFFFFFFFFFFFb 2B &FFFFFFFFFFFFFFFFFFFS #FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFg jFFFFFFFFFFFFFFFFq fF- nFFFFFFFFFFFFFFFFFFFj gFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFS %FFFFFFFFFFFFFFFFF# .AFt eFFFFFFFFFFFFFFFFFFFF% SFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFe nFFFFFFFFFFFFFFFFx BFFFFFFFFFFFFFFj >FFFFFFv $FFFFFFFFFFFV1 e; ZFFFFFFFFFF",
+"FFFFFFFFFFF4 $ZFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFm@ *,% i 9FFFFFFFFFF",
+"FFFFFFFFFFn *+ aFZZFFFFFFFFzzzzzzzzzzzzzzzzzzzzvFFFFZ# 6mFFFh. +9 MFFFFFFFFF",
+"FFFFFFFFFF@ eFS: >- -mFFFFFz ZFFF9 OkFFFFFFi a -FFFFFFFFF",
+"FFFFFFFFFf *FFFy OnFFFF. oX o. 2FFDo lFFFFFFFS. 7d lFFFFFFFF",
+"FFFFFFFFD zFFF: 2r% 1FFFu df m0 nFn 1FFFFFFFFDX 2Fo DFFFFFFF",
+"FFFFFFFF9 ,FFFj 4FFA# FFZ @F= % Fe. .NFFFFFFFFFFh hFFFF",
+"FFFFS %FFFFFFFAq. 7Fq OX ks @5F, by OX vFM01 4Fx$ lFFFFFFFFFw *BF, aFFFFFFFFFFFFFFFFFF5 BFF",
+"FFF< CFFFFFFFFFFFFFFdDc OpFwlFFFFFFFFFFF0iFeX SFFFFFFFFFFFFFFFFFC 2 zFFF; otct :FFFFF3o o@FFFFFFFFFFFF; ZFFFFFFFFFF",
+"FFFFFFFFFFFFs zFFFFFFFF> X8w$ 1FFx yFFF> bFFFFFg uFFFFFFFFFFFFz sFFFFFFFFFFF",
+"FFFFFFFFFFFFD. DFFFFFFF> gFFm %FFp #***+ aFFFFFg uFFFFFFFFFFFD XFFFFFFFFFFFF",
+"FFFFFFFFFFFFFx pFFFFFFF> ZFFFO @FFw yFFFFFg uFFFFFFFFFFFi xFFFFFFFFFFFF",
+"FFFFFFFFFFFFFF, CFFFFFF> SFFF@ @FFp kFFFFFFFFFFFFg uFFFFFFFFFFC SFFF@ @FFx tFFFkttBFFFFFg uFFFFFFFFFF6 BFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFe nFFFFF> SFFF@ @FFF= Xani. $FFFFFFg yFFFFFFFFFn eFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFA %FFFFF> SFFF@ @FFFcO +nFFFFFFh 1MFFFFFFFF% SFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFg jFFFF> SFFF@ @FFFFB5&X&0VFFFFFFFM FFFFFFFj gFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFF# SFFF> SFFF@ @FFFFFFFFFFFFFFFFFFFp#X%FFFFFFS #FFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFb tFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFt bFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFF4 BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB 4FFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFV 2FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 VFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFFu vFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFv uFFFFFFFFFFFFFFFFFF",
+"FFFFFFFFFFFFFFFFFFFD DFFFFFFFFFFFFFFFFFF"
+};
diff --git a/apps/gtk-discover/install.sh b/apps/gtk-discover/install.sh
new file mode 100755
index 00000000..87253696
--- /dev/null
+++ b/apps/gtk-discover/install.sh
@@ -0,0 +1,143 @@
+#!/bin/bash
+
+# Install script for BACnet GTK Discovery
+# This script helps install the necessary dependencies and build the application
+
+set -e
+
+echo "BACnet GTK Discovery - Installation Script"
+echo "========================================="
+
+# Function to detect the Linux distribution
+detect_distro() {
+ if [ -f /etc/os-release ]; then
+ . /etc/os-release
+ echo $ID
+ elif [ -f /etc/debian_version ]; then
+ echo "debian"
+ elif [ -f /etc/redhat-release ]; then
+ echo "rhel"
+ else
+ echo "unknown"
+ fi
+}
+
+# Function to install GTK dependencies
+install_gtk_deps() {
+ local distro=$(detect_distro)
+
+ echo "Detected distribution: $distro"
+ echo "Installing GTK+ 3.0 development libraries..."
+
+ case $distro in
+ ubuntu|debian|linuxmint)
+ sudo apt-get update
+ sudo apt-get install -y libgtk-3-dev pkg-config build-essential
+ ;;
+ fedora)
+ sudo dnf install -y gtk3-devel pkgconfig gcc make
+ ;;
+ rhel|centos)
+ sudo yum install -y gtk3-devel pkgconfig gcc make
+ ;;
+ opensuse|suse)
+ sudo zypper install -y gtk3-devel pkg-config gcc make
+ ;;
+ arch|manjaro)
+ sudo pacman -S --needed gtk3 pkgconfig gcc make
+ ;;
+ *)
+ echo "Unknown distribution. Please install GTK+ 3.0 development libraries manually."
+ echo "Required packages: gtk3-devel (or libgtk-3-dev), pkgconfig, gcc, make"
+ exit 1
+ ;;
+ esac
+}
+
+# Function to check if GTK is available
+check_gtk() {
+ if pkg-config --exists gtk+-3.0; then
+ echo "GTK+ 3.0 development libraries are available."
+ echo "Version: $(pkg-config --modversion gtk+-3.0)"
+ return 0
+ else
+ echo "GTK+ 3.0 development libraries are not available."
+ return 1
+ fi
+}
+
+# Function to build the GTK application
+build_gtk_app() {
+ echo "Building BACnet GTK Discovery..."
+
+ # Default to BACnet/IP
+ DATALINK=${1:-bip}
+
+ make -C ../../ clean || true
+ make -C ../../ gtk-discover BACDL=$DATALINK
+
+ if [ -f "./bacdiscover-gtk" ]; then
+ echo "BACnet GTK Discovery built successfully!"
+ echo "Run with: ./bacdiscover-gtk"
+ else
+ echo "Build failed. Please check the error messages above."
+ exit 1
+ fi
+}
+
+# Main installation process
+main() {
+ echo "Checking for GTK+ 3.0 development libraries..."
+
+ if ! check_gtk; then
+ echo "GTK+ 3.0 development libraries not found."
+ read -p "Do you want to install them automatically? (y/n): " -n 1 -r
+ echo
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ install_gtk_deps
+ if ! check_gtk; then
+ echo "Failed to install GTK+ 3.0 development libraries."
+ exit 1
+ fi
+ else
+ echo "Please install GTK+ 3.0 development libraries manually and run this script again."
+ exit 1
+ fi
+ fi
+
+ # Ask user for datalink type
+ echo ""
+ echo "Choose BACnet datalink type:"
+ echo "1) BACnet/IP (default)"
+ echo "2) MS/TP (Master-Slave/Token-Passing)"
+ echo "3) Ethernet"
+ echo ""
+ read -p "Enter choice (1-3) [default: 1]: " choice
+
+ case $choice in
+ 2)
+ DATALINK="mstp"
+ ;;
+ 3)
+ DATALINK="ethernet"
+ ;;
+ *)
+ DATALINK="bip"
+ ;;
+ esac
+
+ echo "Building with datalink: $DATALINK"
+ build_gtk_app $DATALINK
+
+ echo ""
+ echo "Installation completed successfully!"
+ echo ""
+ echo "To run the application:"
+ echo " ./bacdiscover-gtk"
+ echo ""
+ echo "To install system-wide:"
+ echo " sudo make install"
+}
+
+# Run main function
+main "$@"
diff --git a/apps/gtk-discover/main.c b/apps/gtk-discover/main.c
index 5ca72fa8..5f6ba16c 100644
--- a/apps/gtk-discover/main.c
+++ b/apps/gtk-discover/main.c
@@ -36,6 +36,8 @@
#include "bacnet/basic/tsm/tsm.h"
#include "bacnet/datalink/datalink.h"
#include "bacnet/datalink/dlenv.h"
+/* Used ImageMagick: convert BACnet-Icon.svg bacnet-icon.xpm */
+#include "bacnet-icon.xpm"
/* Global variables */
static GtkWidget *main_window;
@@ -372,6 +374,8 @@ static void on_refresh_clicked(GtkButton *button, gpointer data)
(void)data; /* unused parameter */
gtk_list_store_clear(device_store);
+ gtk_list_store_clear(object_store);
+ gtk_list_store_clear(property_store);
process_discovered_devices();
}
@@ -517,6 +521,7 @@ static void create_main_window(void)
GtkWidget *scrolled_window;
GtkWidget *discover_button, *refresh_button;
GtkToolItem *tool_item;
+ GdkPixbuf *icon_pixbuf;
/* Create main window */
main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -524,6 +529,12 @@ static void create_main_window(void)
gtk_window_set_default_size(GTK_WINDOW(main_window), 1200, 800);
gtk_container_set_border_width(GTK_CONTAINER(main_window), 5);
+ /* set the icon */
+ icon_pixbuf = gdk_pixbuf_new_from_xpm_data(bacnet_icon);
+ if (icon_pixbuf) {
+ gtk_window_set_icon(GTK_WINDOW(main_window), icon_pixbuf);
+ }
+
/* Connect destroy signal */
g_signal_connect(main_window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
@@ -670,7 +681,7 @@ static void bacnet_server_init(void)
mstimer_set(&BACnet_TSM_Timer, 50);
/* Start BACnet background processing */
- bacnet_timeout_id = g_timeout_add(100, bacnet_task_timeout, NULL);
+ bacnet_timeout_id = g_timeout_add(10, bacnet_task_timeout, NULL);
bacnet_initialized = true;
printf("BACnet Stack initialized\n");