The first ideas of the brewpanel simulation are in place.

Sat, 14 Nov 2015 16:52:33 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Sat, 14 Nov 2015 16:52:33 +0100
changeset 420
644a6106d712
parent 419
8a7f8272516c
child 421
0258107a9e72

The first ideas of the brewpanel simulation are in place.

brewpanel/Makefile file | annotate | diff | comparison | revisions
brewpanel/README file | annotate | diff | comparison | revisions
brewpanel/brewpanel.h file | annotate | diff | comparison | revisions
brewpanel/dlgBrew.c file | annotate | diff | comparison | revisions
brewpanel/futil.c file | annotate | diff | comparison | revisions
brewpanel/futil.h file | annotate | diff | comparison | revisions
brewpanel/sdlgui.c file | annotate | diff | comparison | revisions
brewpanel/sockio.c file | annotate | diff | comparison | revisions
brewpanel/sockio.h file | annotate | diff | comparison | revisions
thermferm/Makefile file | annotate | diff | comparison | revisions
thermferm/futil.c file | annotate | diff | comparison | revisions
thermferm/futil.h file | annotate | diff | comparison | revisions
thermferm/lcd-buffer.c file | annotate | diff | comparison | revisions
thermferm/lcd-pcf8574.c file | annotate | diff | comparison | revisions
thermferm/lcd-pcf8574.h file | annotate | diff | comparison | revisions
thermferm/slcd.c file | annotate | diff | comparison | revisions
thermferm/slcd.h file | annotate | diff | comparison | revisions
thermferm/thermferm.c file | annotate | diff | comparison | revisions
thermferm/thermferm.h file | annotate | diff | comparison | revisions
--- a/brewpanel/Makefile	Sun Nov 08 22:20:42 2015 +0100
+++ b/brewpanel/Makefile	Sat Nov 14 16:52:33 2015 +0100
@@ -55,7 +55,9 @@
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
 slcd.o: brewpanel.h slcd.h sdlgui.h
-sdlgui.o: brewpanel.h sdlgui.h lcdfont10x16.h
-dlgBrew.o: brewpanel.h dlgBrew.h sdlgui.h slcd.h
+futil.o: brewpanel.h futil.h
+sockio.o: brewpanel.h slcd.h futil.h sockio.h
+dlgBrew.o: brewpanel.h sockio.h dlgBrew.h sdlgui.h slcd.h
 brewpanel.o: brewpanel.h sdlgui.h dlgBrew.h
+sdlgui.o: brewpanel.h sdlgui.h sockio.h lcdfont10x16.h
 # End of generated dependencies
--- a/brewpanel/README	Sun Nov 08 22:20:42 2015 +0100
+++ b/brewpanel/README	Sat Nov 14 16:52:33 2015 +0100
@@ -4,20 +4,32 @@
 All commands are 16 bits unsigned integers.
 
      D15 D14 D13 D12 D11 D10 RS  R/W DB7 DB6 DB5 DB4 DB3 DB2 DB1 DB0
-      0   0   0  LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   1	Screen clear, home
-      0   0   0  LC2 LC1 LC0  0   0   0   0   0   0   0   0   1   .	DDRAM AD=0, return
-      0   0   0  LC2 LC1 LC0  0   0   0   0   0   0   0   1  I/D  S	Set moving direction of cursor
-      0   0   0  LC2 LC1 LC0  0   0   0   0   0   0   1   D   C   B	Display Cursor Blink on/off
-      0   0   0  LC2 LC1 LC0  0   0   0   0   0   1  S/C R/L  .   .	Remove cursor and display
-      0   0   0  LC2 LC1 LC0  0   0   0   0   1   DL  N   F   .   .	Set DL display line font
-      0   0   0  LC2 LC1 LC0  0   0   0   1				Set CGRAM send/receive data
-      0   0   0  LC2 LC1 LC0  0   0   1					Set DDRAM sebd/receive data
-      0   0   0  LC2 LC1 LC0  0   1   BF				Busy Flag
-      0   0   0  LC2 LC1 LC0  1   0					Write data to CGRAM or DDRAM
-      0   0   0  LC2 LC1 LC0  1   1					Read data from CGRAM or DDRAM
-      0   0   1  LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   .	LED on/off
-      0   1   0  LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   .	Buzzer on/off
+      0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0	Null command to get keys state.
+     LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   0   0   0   1	Screen clear, home
+     LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   0   0   1   .	DDRAM AD=0, return
+     LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   0   1  I/D  S	Set moving direction of cursor
+     LC2 LC1 LC0  0   0   0   0   0   0   0   0   0   1   D   C   B	Display Cursor Blink on/off
+     LC2 LC1 LC0  0   0   0   0   0   0   0   0   1  S/C R/L  .   .	Remove cursor and display
+     LC2 LC1 LC0  0   0   0   0   0   0   0   1   DL  N   F   .   .	Set DL display line font
+     LC2 LC1 LC0  0   0   0   0   0   0   1				Set CGRAM send/receive data
+     LC2 LC1 LC0  0   0   0   0   0   1					Set DDRAM sebd/receive data
+     LC2 LC1 LC0  0   0   0   0   1   BF				Busy Flag
+     LC2 LC1 LC0  0   0   0   1   0					Write data to CGRAM or DDRAM
+     LC2 LC1 LC0  0   0   0   1   1					Read data from CGRAM or DDRAM
+     LC2 LC1 LC0  0   0   1   0   0   .   .   .   .   .   .   .   .	LEDs, buzzer on/off
+     LC2 LC1 LC0  0   1   0   0   1   0   0   0   0  Up  Dwn Ret Ent	Keys pressed
  
 
 LC2 LC1 LC0 are the device index, 0..7
+LEDs:	DB0	Control LED on thermferm panels
+	DB1	HLT heater
+	DB2	MLT heater
+	DB3	MLT pump/mixer
+	DB7	Buzzer
 
+The thermferm or brewco units are leading, they send data and get a reply.
+The sending data will mostly be display data mixed with LEDs. The replies
+will mostly be the current key states, even if not changed. If the leading
+program just wants key states, it should send a 0 to the brewpanel.
+
+
--- a/brewpanel/brewpanel.h	Sun Nov 08 22:20:42 2015 +0100
+++ b/brewpanel/brewpanel.h	Sat Nov 14 16:52:33 2015 +0100
@@ -15,6 +15,9 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
 #include <time.h>
 #include <fcntl.h>
 #include <syslog.h>
--- a/brewpanel/dlgBrew.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/brewpanel/dlgBrew.c	Sat Nov 14 16:52:33 2015 +0100
@@ -24,6 +24,7 @@
  *****************************************************************************/
 
 #include "brewpanel.h"
+#include "sockio.h"
 #include "dlgBrew.h"
 #include "sdlgui.h"
 #include "slcd.h"
@@ -97,12 +98,11 @@
     SDLGui_DoDialogInit(maindlg);
     fd = Dialog_LCDinit(&x, &y, &w, &h, &cols, &rows, 0);
     fprintf(stdout, "Dialog_LCDinit(%d, %d, %d, %d, %d, %d, 0) = %d\n", x, y, w, h, cols, rows, fd);
+    socket_connect();
     slcdInit(fd, x, y, w, h, cols, rows);
 
     do {
 	retbut = SDLGui_DoDialogLoop(maindlg);
-	slcdPuts(0, (char *)"Hello");
-
 	fprintf(stdout, "SDLGui_DoDialog retbut=%d\n", retbut);
 
 	switch (retbut) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewpanel/futil.c	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,78 @@
+/*****************************************************************************
+ * Copyright (C) 2014
+ *   
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of the mbsePi-apps
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * mbsePi-apps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with ThermFerm; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *****************************************************************************/
+
+#include "brewpanel.h"
+#include "futil.h"
+
+
+/*
+ * Make directory tree, the name must end with a /
+ */
+int mkdirs(char *name, mode_t mode)
+{
+    char	buf[PATH_MAX], *p, *q;
+    int		last = 0, oldmask;
+
+    memset(&buf, 0, sizeof(buf));
+    strncpy(buf, name, sizeof(buf)-1);
+    buf[sizeof(buf)-1] = '\0';
+
+    p = buf+1;
+
+    oldmask = umask(000);
+    while ((q = strchr(p, '/'))) {
+	*q = '\0';
+	mkdir(buf, mode);
+	last = errno;
+	*q = '/';
+	p = q+1;
+    }
+
+    umask(oldmask);
+											
+    if ((last == 0) || (last == EEXIST)) {
+	return TRUE;
+    } else {
+	syslog(LOG_NOTICE, "mkdirs(%s)", name);
+	return FALSE;
+    }
+}
+
+
+
+/*
+ * Test if the given file exists. The second option is:
+ * R_OK - test for Read rights 
+ * W_OK - test for Write rights
+ * X_OK - test for eXecute rights
+ * F_OK - test file presence only
+ */ 
+int file_exist(char *path, int mode)
+{
+    if (access(path, mode) != 0)
+	return errno;
+
+    return 0;
+}
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewpanel/futil.h	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,8 @@
+#ifndef	FUTIL_H
+#define	FUTIL_H
+
+
+int  mkdirs(char *, mode_t);
+int  file_exist(char *, int);
+
+#endif
--- a/brewpanel/sdlgui.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/brewpanel/sdlgui.c	Sat Nov 14 16:52:33 2015 +0100
@@ -25,6 +25,7 @@
 
 #include "brewpanel.h"
 #include "sdlgui.h"
+#include "sockio.h"
 
 #ifdef HAVE_SDL_SDL_H
 
@@ -635,7 +636,10 @@
 
     /* The main loop */
     while (retbutton == 0 && !my_shutdown) {
-	if (SDL_WaitEvent(&sdlEvent) == 1)  /* Wait for events */
+
+	socket_recv();
+
+	if (SDL_PollEvent(&sdlEvent) == 1) { /* Wait for events */
 	    switch (sdlEvent.type) {
 		case SDL_QUIT:
 				retbutton = SDLGUI_QUIT;
@@ -699,6 +703,9 @@
 				}
 				break;
 	    }
+	} else {
+	    SDL_Delay(1);
+	}
     }
 
     if (retbutton == SDLGUI_QUIT)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewpanel/sockio.c	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,121 @@
+/*****************************************************************************
+ * Copyright (C) 2015
+ *   
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of the mbsePi-apps
+ *
+ * mbsePi-apps is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * mbsePi-apps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with mbsePi-apps; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *****************************************************************************/
+
+#include "brewpanel.h"
+#include "slcd.h"
+#include "futil.h"
+#include "sockio.h"
+
+#ifdef HAVE_SDL_SDL_H
+
+#define SLCD_NULL       0x0000
+#define SLCD_CLEAR      0x0001
+#define SLCD_MCLEAR     0x1fff
+#define SLCD_HOME       0x0002
+#define SLCD_MHOME      0x1ffe
+#define SLCD_DGRAM      0x0080
+#define SLCD_MDGRAM     0x1f80
+#define SLCD_DATA       0x0200
+#define SLCD_MDATA      0x1e00
+#define SLCD_LEDS       0x0400
+#define SLCD_MLEDS      0x1c00
+#define SLCD_KEYS       0x0800
+#define SLCD_MKEYS      0x1800
+#define SLCD_MDEV       0xe000
+
+
+int			sock = -1;	/* Unix datagram socket		*/
+struct sockaddr_in	servaddr;	/* Server socket address	*/
+
+
+
+void socket_recv(void)
+{
+    uint16_t		data;
+    struct sockaddr_in	clntaddr;
+    socklen_t		clntlen = sizeof(clntaddr);
+    ssize_t		recv_len;
+    int			fd, my_error;
+
+    recv_len = recvfrom(sock, &data, sizeof(uint16_t), MSG_DONTWAIT, (struct sockaddr *)&clntaddr, &clntlen);
+    if (recv_len == sizeof(uint16_t)) {
+	/*
+	 * Get device from data
+	 */
+	fd = data & SLCD_MDEV >> 13;
+	if (fd)
+	    fprintf(stdout, "Device %d ", fd);
+	if ((data & SLCD_MCLEAR) == SLCD_CLEAR) {
+	    slcdClear(fd);
+	} else if ((data & SLCD_MHOME) == SLCD_HOME) {
+	    slcdHome(fd);
+	} else if ((data & SLCD_MDGRAM) == SLCD_DGRAM) {
+	    fprintf(stdout, "slcdPosition(%d, %d, %d)\n", fd, data & 0x001f, (data & 0x0060) >> 5);
+	    slcdPosition(fd, data & 0x001f, (data & 0x0060) >> 5);
+	} else if ((data & 0xfe00) == SLCD_DATA) {
+	    slcdPutchar(fd, data & 0x00ff);
+	} else {
+	    fprintf(stdout, "socket_recv got %04x\n", data);
+	}
+    } else if (recv_len < 0) {
+	my_error = errno;
+	if (my_error != EAGAIN) {
+	    fprintf(stdout, "socket_recv error: %s", strerror(my_error));
+	}
+    } else {
+	fprintf(stdout, "socket_recv unknown len=%d\n", (int)recv_len);
+    }
+}
+
+
+
+int socket_connect(void)
+{
+    int		s;
+
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s == -1) {
+	syslog(LOG_NOTICE, "socket_connect() can't create: %s", strerror(errno));
+	return -1;
+    }
+
+    /*
+     * Setup address structure for the server socket.
+     */
+    memset(&servaddr, 0, sizeof(servaddr));
+    servaddr.sin_family = AF_INET;
+    servaddr.sin_port = htons(6554);
+    servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+
+    if (bind(s, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
+	close(s);
+	syslog(LOG_NOTICE, "socket_connect() can't bind socket: %s", strerror(errno));
+	return -1;
+    }
+
+    syslog(LOG_NOTICE, "socket_connect() using socket %d", s);
+    sock = s;
+    return sock;
+}
+
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/brewpanel/sockio.h	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,11 @@
+#ifndef _SOCKIO_H
+#define	_SOCKIO_H
+#ifdef	HAVE_SDL_SDL_H
+
+
+void socket_recv(void);
+int  socket_connect(void);
+
+
+#endif
+#endif
--- a/thermferm/Makefile	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/Makefile	Sat Nov 14 16:52:33 2015 +0100
@@ -55,14 +55,15 @@
 # DO NOT DELETE THIS LINE - MAKE DEPEND RELIES ON IT
 # Dependencies generated by make depend
 rc-switch.o: thermferm.h xutil.h rc-switch.h
+slcd.o: thermferm.h slcd.h
 panel.o: thermferm.h lcd-pcf8574.h panel.h
 devices.o: thermferm.h devices.h rc-switch.h panel.h xutil.h
-lcd-buffer.o: thermferm.h lcd-buffer.h lcd-pcf8574.h panel.h
+lcd-buffer.o: thermferm.h lcd-buffer.h lcd-pcf8574.h slcd.h panel.h
 futil.o: thermferm.h futil.h
+thermferm.o: lock.h logger.h rdconfig.h devices.h server.h thermferm.h simulator.h lcd-pcf8574.h lcd-buffer.h slcd.h panel.h futil.h xutil.h pid.h
 lock.o: lock.h thermferm.h
 logger.o: logger.h thermferm.h futil.h xutil.h
-lcd-pcf8574.o: thermferm.h lcd-pcf8574.h
-thermferm.o: lock.h logger.h rdconfig.h devices.h server.h thermferm.h simulator.h lcd-pcf8574.h lcd-buffer.h panel.h futil.h xutil.h pid.h
+lcd-pcf8574.o: thermferm.h lcd-pcf8574.h slcd.h
 pid.o: thermferm.h pid.h
 xutil.o: thermferm.h xutil.h
 server.o: rdconfig.h thermferm.h logger.h devices.h server.h lcd-buffer.h xutil.h
--- a/thermferm/futil.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/futil.c	Sat Nov 14 16:52:33 2015 +0100
@@ -58,3 +58,21 @@
 }
 
 
+
+/*
+ * Test if the given file exists. The second option is:
+ * R_OK - test for Read rights 
+ * W_OK - test for Write rights
+ * X_OK - test for eXecute rights
+ * F_OK - test file presence only
+ */ 
+int file_exist(char *path, int mode)
+{
+    if (access(path, mode) != 0)
+	return errno;
+
+    return 0;
+}
+
+
+
--- a/thermferm/futil.h	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/futil.h	Sat Nov 14 16:52:33 2015 +0100
@@ -3,5 +3,6 @@
 
 
 int  mkdirs(char *, mode_t);
+int  file_exist(char *, int);
 
 #endif
--- a/thermferm/lcd-buffer.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/lcd-buffer.c	Sat Nov 14 16:52:33 2015 +0100
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Copyright (C) 2014
+ * Copyright (C) 2014-2015
  *   
  * Michiel Broek <mbroek at mbse dot eu>
  *
@@ -23,6 +23,7 @@
 #include "thermferm.h"
 #include "lcd-buffer.h"
 #include "lcd-pcf8574.h"
+#include "slcd.h"
 #include "panel.h"
 
 
@@ -31,6 +32,7 @@
 lcd_rows		*my_lcd_rows = NULL;
 
 extern int		lcdHandle;
+extern int		slcdHandle;
 extern sys_config	Config;
 
 
@@ -151,6 +153,8 @@
     lcdPosition(lcdHandle, 0, r);
     lcdPuts(lcdHandle, tmp->row);
 #endif
+    slcdPosition(slcdHandle, 0, r);
+    slcdPuts(slcdHandle, tmp->row);
 
     r++;
     if (r < Config.lcd_rows) {
@@ -162,6 +166,8 @@
 	lcdPosition(lcdHandle, 0, r);
 	lcdPuts(lcdHandle, tmp->row);
 #endif
+	slcdPosition(slcdHandle, 0, r);
+	slcdPuts(slcdHandle, tmp->row);
     }
 }
 
--- a/thermferm/lcd-pcf8574.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/lcd-pcf8574.c	Sat Nov 14 16:52:33 2015 +0100
@@ -25,12 +25,14 @@
 
 #include "thermferm.h"
 #include "lcd-pcf8574.h"
+#include "slcd.h"
+
+
+int			lcdHandle;
+int			slcdHandle;
 
 
 #ifdef HAVE_WIRINGPI_H
-
-int			lcdHandle;
-
 struct lcdDataStruct
 {
     int bits, rows, cols ;
@@ -40,6 +42,7 @@
 };
 
 extern struct lcdDataStruct	*lcds [MAX_LCDS];
+#endif
 extern sys_config       	Config;
 
 
@@ -48,13 +51,13 @@
  * setBacklight:
  *********************************************************************************
  */
-
+#ifdef HAVE_WIRINGPI_H
 void setBacklight (int value)
 {
   pinMode (AF_BACKLIGHT, OUTPUT) ;
   digitalWrite (AF_BACKLIGHT, (value & 1)) ;
 }
-
+#endif
 
 
 /*
@@ -74,6 +77,7 @@
     	return EXIT_FAILURE ;
     }
 
+#ifdef HAVE_WIRINGPI_H
     pcf8574Setup(AF_BASE, 0x27) ;
     pinMode (AF_RW, OUTPUT) ;
     digitalWrite (AF_RW, LOW) ;        // Not used with wiringPi - always in write mode
@@ -89,9 +93,16 @@
 
     lcdClear (lcdHandle) ;
     setBacklight (1) ;
+#endif
+
+    slcdHandle = slcdInit(0, rows, cols);
+    if (slcdHandle < 0) {
+	fprintf (stderr, "slcdInit failed\n") ;
+	return -1;
+    }
+    slcdClear(slcdHandle);
 
     return 0 ;
 }
 
 
-#endif
--- a/thermferm/lcd-pcf8574.h	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/lcd-pcf8574.h	Sat Nov 14 16:52:33 2015 +0100
@@ -17,8 +17,9 @@
 #define AF_DB7          (AF_BASE + 7)
 
 void setBacklight (int);
+#endif
+
 int  initLCD (int, int);
 
+
 #endif
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/slcd.c	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,180 @@
+/*****************************************************************************
+ * Copyright (C) 2015
+ *   
+ * Michiel Broek <mbroek at mbse dot eu>
+ *
+ * This file is part of the mbsePi-apps
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * mbsePi-apps is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with ThermFerm; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *****************************************************************************/
+
+#include "thermferm.h"
+#include "slcd.h"
+#include "futil.h"
+#include "xutil.h"
+
+
+#define	SLCD_NULL	0x0000
+#define	SLCD_CLEAR	0x0001
+#define	SLCD_MCLEAR	0x1fff
+#define	SLCD_HOME	0x0002
+#define	SLCD_MHOME	0x1ffe
+#define	SLCD_DGRAM	0x0080
+#define	SLCD_MDGRAM	0x1f80
+#define	SLCD_DATA	0x0200
+#define	SLCD_MDATA	0x1e00
+#define	SLCD_LEDS	0x0400
+#define	SLCD_MLEDS	0x1c00
+#define	SLCD_KEYS	0x0800
+#define	SLCD_MKEYS	0x1800
+#define	SLCD_MDEV	0xe000
+
+#define	SEND_PORT	6554
+
+
+struct sockaddr_in	sendaddr;	/* Server send socket		*/
+int			sock = -1;
+
+extern int		debug;
+
+
+void putLCDsocket(int fd, uint16_t data)
+{
+    if (sock == -1)
+	return;
+
+    if (sendto(sock, &data, sizeof(uint16_t), 0, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) != sizeof(uint16_t)) {
+	syslog(LOG_NOTICE, "Socket send failed, closing socket: %s", strerror(errno));
+	if (shutdown(sock, SHUT_RDWR)) {
+	    syslog(LOG_NOTICE, "Can't shutdown socket: %s", strerror(errno));
+	}
+	sock = -1;
+//    } else {
+    }
+}
+
+
+
+//void slcdHome(int fd)
+//{
+//}
+
+
+
+void slcdClear(int fd)
+{
+    putLCDsocket(fd, SLCD_CLEAR);
+    putLCDsocket(fd, SLCD_HOME);
+}
+
+
+
+//void slcdDisplay(int fd, int state)
+//{
+//}
+
+
+
+//void slcdCursor(int fd, int state)
+//{
+//}
+
+
+
+//void slcdCursorBlink(int fd, int state)
+//{
+//}
+
+
+
+//void slcdSendCommand(int fd, unsigned char command)
+//{
+//}
+
+
+
+void slcdPosition(int fd, int x, int y)
+{
+    uint16_t	data = SLCD_DGRAM;
+
+    data += (x & 0x1f) + ((y & 0x03) << 5);
+    putLCDsocket(fd, data);
+}
+
+
+
+//void slcdCharDef(int fd, int index, unsigned char data[8])
+//{
+//}
+
+
+
+void slcdPutchar(int fd, unsigned char c)
+{
+    uint16_t	data = SLCD_DATA;
+
+    data += c & 0x0ff;
+    putLCDsocket(fd, data);
+}
+
+
+
+void slcdPuts(int fd, const char *string)
+{
+    while (*string)
+	slcdPutchar(fd, *string++);
+}
+
+
+
+//void slcdPrintf(int fd, const char *message, ...)
+//{
+//}
+
+
+
+/*
+ * Try to setup a udp connection to 127.0.0.1 so we duplicate the panel
+ * display and keys of the real panel. This should fail on a production
+ * system because there should no brewpanel program be running. If it
+ * succeeds, all io will be duplicated over the network.
+ */
+int slcdInit(int fd, int cols, int rows)
+{
+    if ((sock = socket(AF_INET, SOCK_DGRAM /*| SOCK_NONBLOCK */, 0)) < 0) {
+	syslog(LOG_NOTICE, "slcdInit() can't create socket: %s", strerror(errno));
+	return -1;
+    }
+
+    /*
+     * Setup address structure for the server socket.
+     */
+    memset(&sendaddr, 0, sizeof(struct sockaddr_in));
+    sendaddr.sin_family = AF_INET;
+    sendaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+    sendaddr.sin_port = htons(SEND_PORT);
+
+    if (connect(sock, (struct sockaddr *)&sendaddr, sizeof(sendaddr)) < 0) {
+	close(sock);
+	sock = -1;
+	syslog(LOG_NOTICE, "slcdInit() can't bind sendsock %s", strerror(errno));
+	return -1;
+    }
+
+    syslog(LOG_NOTICE, "slcdInit() socket %d to brewpanel is active", sock);
+    return 0;
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thermferm/slcd.h	Sat Nov 14 16:52:33 2015 +0100
@@ -0,0 +1,12 @@
+#ifndef	_SLCD_H
+#define	_SLCD_H
+
+
+void slcdClear(int fd);
+void slcdPosition(int fd, int x, int y);
+void slcdPutchar(int fd, unsigned char c);
+void slcdPuts(int fd, const char *string);
+int  slcdInit(int fd, int cols, int rows);
+
+
+#endif
--- a/thermferm/thermferm.c	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/thermferm.c	Sat Nov 14 16:52:33 2015 +0100
@@ -29,6 +29,7 @@
 #include "simulator.h"
 #include "lcd-pcf8574.h"
 #include "lcd-buffer.h"
+#include "slcd.h"
 #include "panel.h"
 #include "futil.h"
 #include "xutil.h"
@@ -43,6 +44,7 @@
 extern int		debug;
 extern sys_config	Config;
 extern int		lcdHandle;
+extern int		slcdHandle;
 int			setupmenu = MENU_NONE;
 units_list		*current_unit = NULL;		/* In panel editor this points to the current unit. */
 profiles_list		*current_profile = NULL;
@@ -54,6 +56,8 @@
 extern const char       UNITMODE[5][8];
 extern const char	PROFSTATE[4][6];
 
+extern int		sock;
+
 
 int  server(void);
 void help(void);
@@ -106,6 +110,8 @@
     lcdPuts(lcdHandle, buf);
     lcdPosition(lcdHandle, 0, 1);
 #endif
+    slcdPuts(slcdHandle, buf);
+    slcdPosition(slcdHandle, 0, 1);
 }
 
 
@@ -120,14 +126,15 @@
     lcdClear(lcdHandle);
     lcdPosition(lcdHandle, 0, 0);
 #endif
+    slcdClear(slcdHandle);
+    slcdPosition(slcdHandle, 0, 0);
+
     syslog(LOG_NOTICE, "from menu %d to menu %d", setupmenu, menu);
     setupmenu = menu;
 
     switch (menu) {
 	case MENU_NONE:		
-#ifdef HAVE_WIRINGPI_H
 				lcd_buf_show();
-#endif
 				break;
 
 	case MENU_TOP_DEFAULT:	
@@ -136,12 +143,16 @@
 				lcdPosition(lcdHandle, 0, 1);
 				lcdPuts(lcdHandle, "Up&Down = Escape");
 #endif
+				slcdPuts(slcdHandle, "Setup mode.");
+				slcdPosition(slcdHandle, 0, 1);
+				slcdPuts(slcdHandle, "Up&Down = Escape");
 				break;
 
 	case MENU_TOP_UNITS:	
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "Select units");
 #endif
+				slcdPuts(slcdHandle, "Select units");
 				break;
 
 	case MENU_UNITS:	
@@ -150,42 +161,51 @@
 				lcdPosition(lcdHandle, 0, 1);
 				lcdPuts(lcdHandle, current_unit->name);
 #endif
+				slcdPuts(slcdHandle, "Choose unit:");
+				slcdPosition(slcdHandle, 0, 1);
+				slcdPuts(slcdHandle, current_unit->name);
 				break;
 
 	case MENU_MODE_OFF:	show_mode();
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "New mode OFF");
 #endif
+				slcdPuts(slcdHandle, "New mode OFF");
 				break;
 
 	case MENU_MODE_NONE:	show_mode();
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "New mode NONE");
 #endif
+				slcdPuts(slcdHandle, "New mode NONE");
 				break;
 
 	case MENU_NONE_HEAT:	snprintf(buf, Config.lcd_cols, "Set heater %s", current_unit->heater_state ? "OFF":"ON");
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, buf);
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_NONE_COOL:	snprintf(buf, Config.lcd_cols, "Set cooler %s", current_unit->cooler_state ? "OFF":"ON");
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, buf);
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_NONE_FAN:	snprintf(buf, Config.lcd_cols, "Set fan %s", current_unit->fan_state ? "OFF":"ON");
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, buf);
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_MODE_BEER:	show_mode();
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "New mode BEER");
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_BEER_TEMP:	
@@ -193,16 +213,21 @@
 				lcdPuts(lcdHandle, "Set beer temp");
 				lcdPosition(lcdHandle, 0, 1);
 #endif
+				slcdPuts(slcdHandle, "Set beer temp");
+				slcdPosition(slcdHandle, 0, 1);
+
 				snprintf(buf, Config.lcd_cols, "Set %.1f", temp_temp);
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, buf);
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_MODE_FRIDGE:	show_mode();
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "New mode FRIDGE");
 #endif
+				slcdPuts(slcdHandle, "New mode FRIDGE");
 				break;
 
 	case MENU_FRIDGE_TEMP:	
@@ -210,16 +235,20 @@
 				lcdPuts(lcdHandle, "Set fridge temp");
 				lcdPosition(lcdHandle, 0, 1);
 #endif
+				slcdPuts(slcdHandle, "Set fridge temp");
+				slcdPosition(slcdHandle, 0, 1);
 				snprintf(buf, Config.lcd_cols, "Set %.1f", temp_temp);
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, buf);
 #endif
+				slcdPuts(slcdHandle, buf);
 				break;
 
 	case MENU_MODE_PROFILE:	show_mode();
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "New mode PROFILE");
 #endif
+				slcdPuts(slcdHandle, "New mode PROFILE");
 				break;
 
 	case MENU_PROFILE_SELECT:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -228,6 +257,9 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Select profile");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Select profile");
 					break;
 	
 	case MENU_PROFILE_START:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -236,6 +268,9 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Start profile");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Start profile");
 					break;
 	
 	case MENU_PROFILE_PAUSE:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -244,6 +279,9 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Pause profile");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Pause profile");
 					break;
 
 	case MENU_PROFILE_ABORT:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -252,6 +290,9 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Abort profile");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Abort profile");
 					break;
 
 	case MENU_PROFILE_RESUME:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -260,6 +301,9 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Resume profile");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Resume profile");
 					break;
 
 	case MENU_PROFILE_GOOFF:	snprintf(buf, Config.lcd_cols, "%s", current_profile->name);
@@ -268,24 +312,30 @@
 					lcdPosition(lcdHandle, 0, 1);
 					lcdPuts(lcdHandle, "Set profile OFF");
 #endif
+					slcdPuts(slcdHandle, buf);
+					slcdPosition(slcdHandle, 0, 1);
+					slcdPuts(slcdHandle, "Set profile OFF");
 					break;
 
 	case MENU_TOP_SYS:	
 #ifdef HAVE_WIRINGPI_H
 				lcdPuts(lcdHandle, "System menu");
 #endif
+				slcdPuts(slcdHandle, "System menu");
 				break;
 
 	case MENU_SYS_HALT:	
 #ifdef HAVE_WIRINGPI_H				
 				lcdPuts(lcdHandle, "Halt system");
 #endif
+				slcdPuts(slcdHandle, "Halt system");
 				break;
 
 	case MENU_SYS_REBOOT:	
 #ifdef HAVE_WIRINGPI_H				
 				lcdPuts(lcdHandle, "Reboot system");
 #endif
+				slcdPuts(slcdHandle, "Reboot system");
 				break;
     }
 
@@ -303,6 +353,9 @@
     piLock(LOCK_LCD);
     lcdClear(lcdHandle);
     setBacklight(0);
+#endif
+    slcdClear(slcdHandle);
+#ifdef HAVE_WIRINGPI_H
     piUnlock(LOCK_LCD);
 #endif
 }
@@ -800,12 +853,12 @@
 #ifdef HAVE_WIRINGPI_H
     if (wiringPiSetup () )
 	return 1;
+#endif
 
     if ((rc = initLCD (Config.lcd_cols, Config.lcd_rows))) {
 	fprintf(stderr, "Cannot initialize LCD display, rc=%d\n", rc);
 	return 1;
     }
-#endif
 
     if (debug) {
 	/*
@@ -1757,6 +1810,7 @@
 	syslog(LOG_NOTICE, "Unit `%s' stopped in mode %s", unit->name, UNITMODE[unit->mode]);
     }
 
+    syslog(LOG_NOTICE, "Out of loop");
     if (debug)
 	fprintf(stdout, (char *)"Out of loop\n");
 
@@ -1766,6 +1820,12 @@
     usleep(1500000);
 
     stopLCD();
+    if (sock != -1) {
+	if (shutdown(sock, SHUT_RDWR)) {
+	    syslog(LOG_NOTICE, "Can't shutdown socket: %s", strerror(errno));
+	}
+	sock = -1;
+    }
     wrconfig();
     ulockprog((char *)"thermferm");
     return 0;
--- a/thermferm/thermferm.h	Sun Nov 08 22:20:42 2015 +0100
+++ b/thermferm/thermferm.h	Sat Nov 14 16:52:33 2015 +0100
@@ -15,8 +15,10 @@
 #include <string.h>
 #include <ctype.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 #include <sys/stat.h>
 #include <sys/time.h>
+#include <sys/un.h>
 #include <time.h>
 #include <fcntl.h>
 #include <syslog.h>

mercurial