aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorharbaum <>2006-08-13 18:14:03 +0000
committerharbaum <>2006-08-13 18:14:03 +0000
commit2e871a2380f375f81b137a659e6ffa0d8199cb83 (patch)
tree553a469c55802d218cae6c2f62db3f3ccd4e1927
parent1133451dceeed7160bad057f77c263fb98c25214 (diff)
downloadlcd4linux-2e871a2380f375f81b137a659e6ffa0d8199cb83.tar.gz
[lcd4linux @ 2006-08-13 18:14:03 by harbaum]
Added KVV plugin
-rw-r--r--Makefile.am1
-rw-r--r--Makefile.in2
-rw-r--r--config.h.in3
-rwxr-xr-xconfigure12
-rw-r--r--drv_LEDMatrix.c52
-rw-r--r--font_6x8_bold.h21
-rw-r--r--lcd4linux.conf.sample30
-rw-r--r--plugin.c13
-rw-r--r--plugin_kvv.c714
-rw-r--r--plugins.m48
-rw-r--r--property.c24
-rw-r--r--widget_text.c9
-rw-r--r--widget_text.h9
13 files changed, 866 insertions, 32 deletions
diff --git a/Makefile.am b/Makefile.am
index 96be71f..c4d286a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -104,6 +104,7 @@ plugin_file.c \
plugin_i2c_sensors.c \
plugin_imon.c \
plugin_isdn.c \
+plugin_kvv.c \
plugin_loadavg.c \
plugin_meminfo.c \
plugin_mpd.c \
diff --git a/Makefile.in b/Makefile.in
index 0339fc1..89c7472 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -279,6 +279,7 @@ plugin_file.c \
plugin_i2c_sensors.c \
plugin_imon.c \
plugin_isdn.c \
+plugin_kvv.c \
plugin_loadavg.c \
plugin_meminfo.c \
plugin_mpd.c \
@@ -458,6 +459,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_i2c_sensors.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_imon.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_isdn.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_kvv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_loadavg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_math.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plugin_meminfo.Po@am__quote@
diff --git a/config.h.in b/config.h.in
index c0df0ef..625293b 100644
--- a/config.h.in
+++ b/config.h.in
@@ -281,6 +281,9 @@
/* ISDN plugin */
#undef PLUGIN_ISDN
+/* kvv plugin */
+#undef PLUGIN_KVV
+
/* loadavg plugin */
#undef PLUGIN_LOADAVG
diff --git a/configure b/configure
index d110d26..2ecb2ca 100755
--- a/configure
+++ b/configure
@@ -8245,6 +8245,7 @@ echo "$as_me: error: run ./configure --with-plugins=..." >&2;}
PLUGIN_I2C_SENSORS="yes"
PLUGIN_IMON="yes"
PLUGIN_ISDN="yes"
+ PLUGIN_KVV="yes"
PLUGIN_LOADAVG="yes"
PLUGIN_MEMINFO="yes"
PLUGIN_MPD="yes"
@@ -8289,6 +8290,9 @@ echo "$as_me: error: run ./configure --with-plugins=..." >&2;}
isdn)
PLUGIN_ISDN=$val
;;
+ kvv)
+ PLUGIN_KVV=$val
+ ;;
loadavg)
PLUGIN_LOADAVG=$val
;;
@@ -8771,6 +8775,14 @@ cat >>confdefs.h <<\_ACEOF
_ACEOF
fi
+if test "$PLUGIN_KVV" = "yes"; then
+ PLUGINS="$PLUGINS plugin_kvv.o"
+
+cat >>confdefs.h <<\_ACEOF
+#define PLUGIN_KVV 1
+_ACEOF
+
+fi
if test "$PLUGIN_LOADAVG" = "yes"; then
PLUGINS="$PLUGINS plugin_loadavg.o"
diff --git a/drv_LEDMatrix.c b/drv_LEDMatrix.c
index 38e10ca..f6fdee3 100644
--- a/drv_LEDMatrix.c
+++ b/drv_LEDMatrix.c
@@ -1,4 +1,4 @@
-/* $Id: drv_LEDMatrix.c,v 1.5 2006/08/13 09:53:10 reinelt Exp $
+/* $Id: drv_LEDMatrix.c,v 1.6 2006/08/13 18:14:03 harbaum Exp $
*
* LED matrix driver for LCD4Linux
* (see http://www.harbaum.org/till/ledmatrix for hardware)
@@ -23,6 +23,9 @@
*
*
* $Log: drv_LEDMatrix.c,v $
+ * Revision 1.6 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.5 2006/08/13 09:53:10 reinelt
* dynamic properties added (used by 'style' of text widget)
*
@@ -106,7 +109,13 @@ static int port = DSP_DEFAULT_PORT;
static void drv_LEDMatrix_blit(const int row, const int col, const int height, const int width)
{
- int r, c;
+ int r, c, i;
+ fd_set rfds;
+ struct timeval tv;
+ unsigned char reply[256];
+ struct sockaddr_in cli_addr;
+ int fromlen, ack = 0;
+ int timeout = 10;
for (r = row; r < row + height; r++) {
for (c = col; c < col + width; c++) {
@@ -127,8 +136,42 @@ static void drv_LEDMatrix_blit(const int row, const int col, const int height, c
// scan entire display
tx_buffer[0] = DSP_CMD_IMAGE;
- if ((sendto(sock, tx_buffer, DSP_MEM + 1, 0, (struct sockaddr *) &dsp_addr, sizeof(dsp_addr))) != DSP_MEM + 1)
- error("%s: sendto error on socket", Name);
+
+ do {
+
+ if ((sendto(sock, tx_buffer, DSP_MEM + 1, 0, (struct sockaddr *) &dsp_addr, sizeof(dsp_addr))) != DSP_MEM + 1)
+ error("%s: sendto error on socket", Name);
+
+ /* now wait for reply */
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+
+ // wait 1 sec for ack
+ if ((i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv)) < 0) {
+ perror("select");
+ }
+
+ if (FD_ISSET(sock, &rfds)) {
+ // wait for ack
+ fromlen = sizeof(dsp_addr);
+ i = recvfrom(sock, reply, sizeof(reply), 0, (struct sockaddr *) &cli_addr, &fromlen);
+ if (i < 0) {
+ perror("recvfrom");
+ } else {
+ if ((i == 2) && (reply[0] == DSP_CMD_ACK) && (reply[1] == DSP_CMD_IMAGE)) {
+ ack = 1;
+// } else if((i > 1) && (reply[0] == DSP_CMD_IR)) {
+// ir_receive(reply+1, i-1);
+ } else {
+ fprintf(stderr, "Unexpected reply message\n");
+ }
+ }
+ }
+ timeout--;
+ } while ((!ack) && (timeout > 0));
}
static int drv_LEDMatrix_start(const char *section)
@@ -137,7 +180,6 @@ static int drv_LEDMatrix_start(const char *section)
struct sockaddr_in cli_addr;
struct hostent *hp;
int val;
- char *attr;
IPAddress = cfg_get(section, "IPAddress", NULL);
if (IPAddress == NULL || *IPAddress == '\0') {
diff --git a/font_6x8_bold.h b/font_6x8_bold.h
index 0fb37fc..d8dbb15 100644
--- a/font_6x8_bold.h
+++ b/font_6x8_bold.h
@@ -1,4 +1,4 @@
-/* $Id: font_6x8_bold.h,v 1.1 2006/08/09 17:25:34 harbaum Exp $
+/* $Id: font_6x8_bold.h,v 1.2 2006/08/13 18:14:03 harbaum Exp $
*
* 6x8 bold font
*
@@ -23,6 +23,9 @@
*
*
* $Log: font_6x8_bold.h,v $
+ * Revision 1.2 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.1 2006/08/09 17:25:34 harbaum
* Better bar color support and new bold font
*
@@ -175,11 +178,11 @@ unsigned char Font_6x8_bold[256][8] = {
_OO___,
______},
[0x2a] {______,
- __OO__,
- O_OO_O,
- _OOOO_,
- O_OO_O,
- __OO__,
+ ___O__,
+ _O_O_O,
+ __OOO_,
+ _O_O_O,
+ ___O__,
______,
______},
[0x2b] {______,
@@ -230,12 +233,12 @@ unsigned char Font_6x8_bold[256][8] = {
_OO_OO,
__OOO_,
______},
- [0x31] {____O_,
- ___OO_,
+ [0x31] {___OO_,
__OOO_,
___OO_,
___OO_,
___OO_,
+ ___OO_,
__OOOO,
______},
[0x32] {__OOO_,
@@ -767,8 +770,8 @@ unsigned char Font_6x8_bold[256][8] = {
_OOOO_,
______},
[0x74] {__OO__,
- _OOOO_,
__OO__,
+ _OOOO_,
__OO__,
__OO__,
__OO__,
diff --git a/lcd4linux.conf.sample b/lcd4linux.conf.sample
index 6b15dc1..c55f33b 100644
--- a/lcd4linux.conf.sample
+++ b/lcd4linux.conf.sample
@@ -420,6 +420,14 @@ Display Image {
Basecolor '80d000'
}
+Plugin KVV {
+ StationID '12_701'
+ Refresh 30
+
+ Proxy 'igate'
+ Port 8080;
+}
+
Plugin Seti {
Directory '/root/setiathome-3.08.i686-pc-linux-gnu'
}
@@ -877,6 +885,28 @@ Widget ImageTest {
inverted 0
}
+Widget KVV {
+ class 'Text'
+ expression kvv::line(0).' '.kvv::station(0)
+ width 11
+
+ align 'L'
+ update tick
+ Foreground 'ffff00'
+ style 'bold'
+}
+
+Widget KVV_TIME {
+ class 'Text'
+ expression kvv::time_str(0)
+ width 2
+
+ align 'R'
+ update tick
+ foreground kvv::time(0) < 2 ? 'FF0000' : ( kvv::time(0) < 5 ? 'FFFF00' : '00FF00' )
+ style 'bold'
+}
+
Layout Default {
Row1 {
Col1 'OS'
diff --git a/plugin.c b/plugin.c
index 00f26ee..5618f4e 100644
--- a/plugin.c
+++ b/plugin.c
@@ -1,4 +1,4 @@
-/* $Id: plugin.c,v 1.44 2006/07/31 03:48:09 reinelt Exp $
+/* $Id: plugin.c,v 1.45 2006/08/13 18:14:03 harbaum Exp $
*
* plugin handler for the Evaluator
*
@@ -23,6 +23,9 @@
*
*
* $Log: plugin.c,v $
+ * Revision 1.45 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.44 2006/07/31 03:48:09 reinelt
* preparations for scrolling
*
@@ -250,6 +253,8 @@ int plugin_init_imon(void);
void plugin_exit_imon(void);
int plugin_init_isdn(void);
void plugin_exit_isdn(void);
+int plugin_init_kvv(void);
+void plugin_exit_kvv(void);
int plugin_init_loadavg(void);
void plugin_exit_loadavg(void);
int plugin_init_meminfo(void);
@@ -319,6 +324,9 @@ int plugin_init(void)
#ifdef PLUGIN_ISDN
plugin_init_isdn();
#endif
+#ifdef PLUGIN_KVV
+ plugin_init_kvv();
+#endif
#ifdef PLUGIN_LOADAVG
plugin_init_loadavg();
#endif
@@ -402,6 +410,9 @@ void plugin_exit(void)
#ifdef PLUGIN_ISDN
plugin_exit_isdn();
#endif
+#ifdef PLUGIN_KVV
+ plugin_exit_kvv();
+#endif
#ifdef PLUGIN_LOADAVG
plugin_exit_loadavg();
#endif
diff --git a/plugin_kvv.c b/plugin_kvv.c
new file mode 100644
index 0000000..9db6674
--- /dev/null
+++ b/plugin_kvv.c
@@ -0,0 +1,714 @@
+/* $Id: plugin_kvv.c,v 1.1 2006/08/13 18:14:03 harbaum Exp $
+ *
+ * plugin kvv (karlsruher verkehrsverbund)
+ *
+ * Copyright (C) 2006 Till Harbaum <till@harbaum.org>
+ * Copyright (C) 2006 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net>
+ *
+ * This file is part of LCD4Linux.
+ *
+ * LCD4Linux 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.
+ *
+ * LCD4Linux 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ * $Log: plugin_kvv.c,v $
+ * Revision 1.1 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
+ *
+ */
+
+/*
+ * exported functions:
+ *
+ * int plugin_init_kvv (void)
+ * adds various functions
+ * void plugin_exit_kvv (void)
+ *
+ */
+
+/* define the include files you need */
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <signal.h>
+
+/* network specific includes */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+
+/* these should always be included */
+#include "debug.h"
+#include "plugin.h"
+#include "cfg.h"
+#include "thread.h"
+
+/* these can't be configured as it doesn't make sense to change them */
+#define HTTP_SERVER "www.init-ka.de"
+#define HTTP_REQUEST "/webfgi/StopInfoInplace.aspx?ID=%s"
+
+#define DEFAULT_STATION_ID "89" // Hauptbahnhof
+
+/* example ids:
+ * 89 = Hauptbahnhof
+ * 12_701 = Berufsakademie
+ */
+
+/* total max values to calculate shm size */
+#define MAX_LINES 4
+#define MAX_LINE_LENGTH 8
+#define MAX_STATION_LENGTH 32
+
+typedef struct {
+ char line[MAX_LINE_LENGTH + 1];
+ char station[MAX_STATION_LENGTH + 1];
+ int time;
+} kvv_entry_t;
+
+typedef struct {
+ int entries;
+ kvv_entry_t entry[MAX_LINES];
+} kvv_shm_t;
+
+static char *station_id = NULL;
+static char *proxy_name = NULL;
+static int port = 80;
+static pid_t pid = -1;
+static int refresh = 60;
+static int stringlen = 16;
+
+static int mutex = 0;
+static int shmid;
+static kvv_shm_t *shm;
+
+#define SECTION "Plugin:KVV"
+
+#define TIMEOUT_SHORT 1 /* wait this long for additional data */
+#define TIMEOUT_LONG 10 /* wait this long for initial data */
+
+/* search an element in the result string */
+static int get_element(char *input, char *name, char **data)
+{
+ int skip = 0;
+ int len = 0;
+ int state = 0; // nothing found yet
+
+ // search entire string
+ while (*input) {
+ if (skip == 0) {
+ switch (state) {
+ case 0:
+ if (*input == '<')
+ state = 1;
+ else
+ state = 0;
+ break;
+
+ case 1:
+ // ignore white spaces
+ if (*input != ' ') {
+ if (strncasecmp(input, name, strlen(name)) == 0) {
+ state = 2;
+ skip = strlen(name) - 1;
+ } else
+ state = 0;
+ }
+ break;
+
+ case 2:
+ if (*input == ' ') {
+ *data = ++input;
+ while (*input++ != '>')
+ len++;
+
+ return len;
+ } else
+ state = 0;
+ break;
+ }
+ } else if (skip)
+ skip--;
+
+ input++;
+ }
+ return -1;
+}
+
+/* serach an attribute within an element */
+static int get_attrib(char *input, char *name, char **data)
+{
+ int skip = 0;
+ int len = 0;
+ int state = 0; // nothing found
+
+ // search in this element
+ while (*input != '>') {
+ // ignore white spaces
+ if (((*input != ' ') && (*input != '\t')) && (skip == 0)) {
+ switch (state) {
+ case 0:
+ if (strncasecmp(input, name, strlen(name)) == 0) {
+ state = 1;
+ skip = strlen(name) - 1;
+ }
+ break;
+
+ case 1:
+ if (*input == '=')
+ state = 2;
+ else
+ state = 0;
+ break;
+
+ case 2:
+ if (*input == '\"') {
+ *data = ++input;
+ while (*input++ != '\"')
+ len++;
+
+ return len;
+ } else
+ state = 0;
+
+ break;
+ }
+ } else if (skip)
+ skip--;
+
+ input++;
+ }
+ return -1;
+}
+
+static int http_open(char *name)
+{
+ struct sockaddr_in server;
+ struct hostent *host_info;
+ unsigned long addr;
+ int sock;
+
+ /* create socket */
+ sock = socket(PF_INET, SOCK_STREAM, 0);
+ if (sock < 0) {
+ perror("failed to create socket");
+ return -1;
+ }
+
+ /* Erzeuge die Socketadresse des Servers
+ * Sie besteht aus Typ, IP-Adresse und Portnummer */
+ memset(&server, 0, sizeof(server));
+ if ((addr = inet_addr(name)) != INADDR_NONE) {
+ memcpy((char *) &server.sin_addr, &addr, sizeof(addr));
+ } else {
+ /* Wandle den Servernamen in eine IP-Adresse um */
+ host_info = gethostbyname(name);
+ if (NULL == host_info) {
+ error("[KVV] Unknown server: %s", name);
+ return -1;
+ }
+ memcpy((char *) &server.sin_addr, host_info->h_addr, host_info->h_length);
+ }
+
+ server.sin_family = AF_INET;
+ server.sin_port = htons(port);
+
+ /* Baue die Verbindung zum Server auf */
+ if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
+ perror("can't connect to server");
+ return -1;
+ }
+
+ return sock;
+}
+
+static void get_text(char *input, char *end, char *dest, int dlen)
+{
+ int state = 0; // nothing yet, outside any element
+ int cnt = 0;
+
+ while (*input) {
+ switch (state) {
+ case 0:
+ if (*input == '<')
+ state = 1;
+ else {
+ if (cnt < (dlen - 1))
+ dest[cnt++] = *input;
+ }
+ break;
+
+ case 1:
+ if (*input == '/')
+ state = 2;
+ else if (*input == '>')
+ state = 0;
+ break;
+
+ case 2:
+ if (strncasecmp(input, end, strlen(end)) == 0) {
+ dest[cnt++] = 0;
+ return;
+ }
+ break;
+ }
+
+ input++;
+ }
+
+}
+
+static void process_station_string(char *str)
+{
+ char *p, *q;
+ int last, i;
+ char *repl[] = {
+ "Hauptbahnhof", "Hbf.",
+ "Bahnhof", "Bhf.",
+ "Karlsruhe", "KA",
+ "Schienenersatzverkehr", "Ersatzv.",
+ "Marktplatz", "Marktpl.",
+ };
+
+ /* erase multiple spaces */
+ p = q = str;
+ last = 1; // no leading spaces
+ while (*p) {
+ if ((!last) || (*p != ' '))
+ *q++ = *p;
+
+ last = (*p == ' ');
+ p++;
+ }
+ *q++ = 0;
+
+ /* decode utf8 */
+ p = q = str;
+ last = 0;
+ while (*p) {
+ if (last) {
+ *q++ = (last << 6) | (*p & 0x3f);
+ last = 0;
+ } else if ((*p & 0xe0) == 0xc0) {
+ last = *p & 3;
+ } else
+ *q++ = *p;
+
+ p++;
+ }
+ *q++ = 0;
+
+ /* replace certain (long) words with e.g. abbreviations */
+ for (i = 0; i < (int) (sizeof(repl) / (2 * sizeof(char *))); i++) {
+ if ((p = strstr(str, repl[2 * i])) != NULL) {
+
+ /* move new string */
+ memcpy(p, repl[2 * i + 1], strlen(repl[2 * i + 1]));
+ /* move rest of string down */
+ memmove(p + strlen(repl[2 * i + 1]),
+ p + strlen(repl[2 * i]), strlen(str) - (p - str) - strlen(repl[2 * i]) + 1);
+ }
+ }
+}
+
+static void kvv_client(void)
+{
+ char ibuffer[8192];
+ char obuffer[8192];
+ int count, i, sock;
+
+ char server_name[] = HTTP_SERVER;
+ char *connect_to;
+
+ /* connect to proxy if given, to server otherwise */
+ if ((proxy_name != NULL) && (strlen(proxy_name) != 0))
+ connect_to = proxy_name;
+ else
+ connect_to = server_name;
+
+ info("[KVV] Connecting to %s", connect_to);
+
+ while (1) {
+
+ sock = http_open(connect_to);
+ if (sock < 0) {
+ error("[KVV] Error accessing server/proxy: %s", strerror(errno));
+ return;
+ }
+ // create and set get request
+ sprintf(obuffer, "GET http://%s" HTTP_REQUEST " HTTP/1.1\n" "Host: %s\n\n", server_name, station_id,
+ server_name);
+
+ info("[KVV] Sending first (GET) request ...");
+ send(sock, obuffer, strlen(obuffer), 0);
+
+ count = 0;
+ do {
+ fd_set rfds;
+ struct timeval tv;
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+
+ tv.tv_sec = count ? TIMEOUT_SHORT : TIMEOUT_LONG;
+ tv.tv_usec = 0;
+
+ i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ if (i < 0) {
+ perror("select");
+ exit(1);
+ }
+
+ if (i != 0) {
+ i = recv(sock, ibuffer + count, sizeof(ibuffer) - count, 0);
+ count += i;
+ }
+ }
+ while (i > 0);
+
+ ibuffer[count] = 0; // terminate string
+ close(sock);
+
+ if (count > 0) {
+ char *input, *cookie, *name, *value;
+ int input_len, cookie_len, name_len, value_len;
+
+ // buffer to html encode value
+ char value_enc[512];
+ int value_enc_len;
+
+ // find cookie
+ cookie_len = 0;
+ cookie = strstr(ibuffer, "Set-Cookie:");
+ if (cookie) {
+ cookie += strlen("Set-Cookie:");
+
+ while (*cookie == ' ')
+ cookie++;
+
+ while (cookie[cookie_len] != ';')
+ cookie_len++;
+ }
+ // find input element
+ input_len = get_element(ibuffer, "input", &input);
+
+
+ if (input_len > 0) {
+ char *input_end = input;
+ while (*input_end != '>')
+ input_end++;
+ while (*input_end != '\"')
+ input_end--;
+ *(input_end + 1) = 0;
+
+ name_len = get_attrib(input, "name", &name);
+ value_len = get_attrib(input, "value", &value);
+
+ for (value_enc_len = 0, i = 0; i < value_len; i++) {
+ if (isalnum(value[i]))
+ value_enc[value_enc_len++] = value[i];
+ else {
+ sprintf(value_enc + value_enc_len, "%%%02X", 0xff & value[i]);
+ value_enc_len += 3;
+ }
+ }
+
+ if (cookie_len >= 0)
+ cookie[cookie_len] = 0;
+ if (name_len >= 0)
+ name[name_len] = 0;
+ if (value_len >= 0)
+ value[value_len] = 0;
+ if (value_enc_len >= 0)
+ value_enc[value_enc_len] = 0;
+
+ sock = http_open(connect_to);
+
+ // send POST
+ sprintf(obuffer,
+ "POST http://%s" HTTP_REQUEST " HTTP/1.1\n"
+ "Host: %s\n"
+ "Cookie: %s\n"
+ "Content-Type: application/x-www-form-urlencoded\n"
+ "Content-Length: %d\n"
+ "\n%s=%s",
+ server_name, station_id, server_name, cookie, name_len + value_enc_len + 1, name, value_enc);
+
+ info("[KVV] Sending second (POST) request ...");
+ send(sock, obuffer, strlen(obuffer), 0);
+
+ count = 0;
+ do {
+ fd_set rfds;
+ struct timeval tv;
+
+ FD_ZERO(&rfds);
+ FD_SET(sock, &rfds);
+
+ tv.tv_sec = count ? TIMEOUT_SHORT : TIMEOUT_LONG;
+ tv.tv_usec = 0;
+
+ i = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ if (i > 0) {
+ i = recv(sock, ibuffer + count, sizeof(ibuffer) - count, 0);
+ count += i;
+ }
+ }
+ while (i > 0); /* leave on select or read error */
+
+ ibuffer[count] = 0;
+
+ /* close connection */
+ close(sock);
+
+ if (count > 0) {
+ int last_was_stop = 0;
+ char *td = ibuffer;
+ char str[32];
+ int td_len, i, overflow = 0;
+
+ /* lock shared memory */
+ mutex_lock(mutex);
+
+ /* free allocated memory */
+ shm->entries = 0;
+
+ /* scan through all <td> entries and search the line nums */
+ do {
+ if ((td_len = get_element(td, "td", &td)) > 0) {
+ char *attr, *p;
+ int attr_len;
+
+ /* time does not have a class but comes immediately after stop :-( */
+ if (last_was_stop) {
+ td += td_len + 1;
+ get_text(td, "td", str, sizeof(str));
+
+ /* time needs special treatment */
+ if (strncasecmp(str, "sofort", strlen("sofort")) == 0)
+ i = 0;
+ else {
+ /* skip everything that is not a number */
+ p = str;
+ while (!isdigit(*p))
+ p++;
+
+ /* and convert remaining to number */
+ i = atoi(p);
+ }
+
+ /* save time */
+ if (!overflow)
+ shm->entry[shm->entries - 1].time = i;
+
+ last_was_stop = 0;
+ }
+
+ /* linenum and stopname fields have proper classes */
+ if ((attr_len = get_attrib(td, "class", &attr)) > 0) {
+
+ if (strncasecmp(attr, "lineNum", strlen("lineNum")) == 0) {
+ td += td_len + 1;
+ get_text(td, "td", str, sizeof(str));
+
+ if (shm->entries < MAX_LINES) {
+ // allocate a new slot
+ shm->entries++;
+ shm->entry[shm->entries - 1].time = -1;
+ memset(shm->entry[shm->entries - 1].line, 0, MAX_LINE_LENGTH + 1);
+ memset(shm->entry[shm->entries - 1].station, 0, MAX_STATION_LENGTH + 1);
+
+ // add new lines entry
+ strncpy(shm->entry[shm->entries - 1].line, str, MAX_LINE_LENGTH);
+ } else
+ overflow = 1; /* don't add further entries */
+ }
+
+ if (strncasecmp(attr, "stopname", strlen("stopname")) == 0) {
+ td += td_len + 1;
+ get_text(td, "td", str, sizeof(str));
+
+ /* stopname may need further tuning */
+ process_station_string(str);
+
+ if (!overflow)
+ strncpy(shm->entry[shm->entries - 1].station, str, MAX_STATION_LENGTH);
+
+ last_was_stop = 1;
+ }
+ }
+ }
+ } while (td_len >= 0);
+
+ mutex_unlock(mutex);
+ }
+ }
+ }
+
+ sleep(refresh);
+ }
+}
+
+static void kvv_line(RESULT * result, RESULT * arg1)
+{
+ int index = (int) R2N(arg1);
+
+ mutex_lock(mutex);
+
+ if (index < shm->entries) {
+ SetResult(&result, R_STRING, shm->entry[index].line);
+ } else
+ SetResult(&result, R_STRING, "---");
+
+ mutex_unlock(mutex);
+}
+
+static void kvv_station(RESULT * result, RESULT * arg1)
+{
+ int index = (int) R2N(arg1);
+
+ mutex_lock(mutex);
+
+ if (index < shm->entries)
+ SetResult(&result, R_STRING, shm->entry[index].station);
+ else
+ SetResult(&result, R_STRING, "---");
+
+ mutex_unlock(mutex);
+}
+
+static void kvv_time(RESULT * result, RESULT * arg1)
+{
+ int index = (int) R2N(arg1);
+ double value = -1.0;
+
+ mutex_lock(mutex);
+
+ if (index < shm->entries)
+ value = shm->entry[index].time;
+
+ SetResult(&result, R_NUMBER, &value);
+
+ mutex_unlock(mutex);
+}
+
+static void kvv_time_str(RESULT * result, RESULT * arg1)
+{
+ int index = (int) R2N(arg1);
+
+ mutex_lock(mutex);
+
+ if (index < shm->entries) {
+ char str[8];
+ sprintf(str, "%d", shm->entry[index].time);
+ SetResult(&result, R_STRING, str);
+ } else
+ SetResult(&result, R_STRING, "---");
+
+ mutex_unlock(mutex);
+}
+
+/* plugin initialization */
+int plugin_init_kvv(void)
+{
+ int val;
+ char *p;
+
+ /* register all our cool functions */
+ AddFunction("kvv::line", 1, kvv_line);
+ AddFunction("kvv::station", 1, kvv_station);
+ AddFunction("kvv::time", 1, kvv_time);
+ AddFunction("kvv::time_str", 1, kvv_time_str);
+
+ /* parse parameter */
+ if ((p = cfg_get(SECTION, "StationID", DEFAULT_STATION_ID)) != NULL) {
+ station_id = malloc(strlen(p) + 1);
+ strcpy(station_id, p);
+ }
+ info("[KVV] Using station %s", station_id);
+
+ if ((p = cfg_get(SECTION, "Proxy", NULL)) != NULL) {
+ proxy_name = malloc(strlen(p) + 1);
+ strcpy(proxy_name, p);
+ info("[KVV] Using proxy \"%s\"", proxy_name);
+ }
+
+ if (cfg_number(SECTION, "Port", 0, 0, 65535, &val) > 0) {
+ port = val;
+ info("[KVV] Using port %d", port);
+ } else {
+ info("[KVV] Using default port %d", port);
+ }
+
+ if (cfg_number(SECTION, "Refresh", 0, 0, 65535, &val) > 0) {
+ refresh = val;
+ info("[KVV] Using %d seconds refresh interval", refresh);
+ } else {
+ info("[KVV] Using default refresh interval of %d seconds", refresh);
+ }
+
+ if (cfg_number(SECTION, "Stringlen", 0, 0, 65535, &val) > 0) {
+ stringlen = val;
+ info("[KVV] Using %d character string length", stringlen);
+ } else {
+ info("[KVV] Using %d characters default string length", stringlen);
+ }
+
+ /* create communication buffer */
+ shmid = shm_create((void **) &shm, sizeof(kvv_shm_t));
+
+ /* catch error */
+ if (shmid < 0) {
+ error("[KVV] Shared memory allocation failed!");
+ return -1;
+ }
+
+ /* attach client thread */
+ mutex = mutex_create();
+ pid = fork();
+ if (pid < 0) {
+ error("[KVV] Unable to fork client: %s", strerror(errno));
+ return -1;
+ }
+
+ if (pid == 0)
+ kvv_client();
+ else
+ info("[KVV] forked client with pid %d", pid);
+
+ return 0;
+}
+
+void plugin_exit_kvv(void)
+{
+ if (pid != -1)
+ kill(pid, SIGTERM);
+
+ if (station_id)
+ free(station_id);
+ if (proxy_name)
+ free(proxy_name);
+
+ mutex_destroy(mutex);
+
+ if (shm)
+ shm_destroy(shmid, shm);
+}
diff --git a/plugins.m4 b/plugins.m4
index e829e8d..632f70d 100644
--- a/plugins.m4
+++ b/plugins.m4
@@ -58,6 +58,7 @@ for plugin in $plugins; do
PLUGIN_I2C_SENSORS="yes"
PLUGIN_IMON="yes"
PLUGIN_ISDN="yes"
+ PLUGIN_KVV="yes"
PLUGIN_LOADAVG="yes"
PLUGIN_MEMINFO="yes"
PLUGIN_MPD="yes"
@@ -102,6 +103,9 @@ for plugin in $plugins; do
isdn)
PLUGIN_ISDN=$val
;;
+ kvv)
+ PLUGIN_KVV=$val
+ ;;
loadavg)
PLUGIN_LOADAVG=$val
;;
@@ -203,6 +207,10 @@ if test "$PLUGIN_ISDN" = "yes"; then
PLUGINS="$PLUGINS plugin_isdn.o"
AC_DEFINE(PLUGIN_ISDN,1,[ISDN plugin])
fi
+if test "$PLUGIN_KVV" = "yes"; then
+ PLUGINS="$PLUGINS plugin_kvv.o"
+ AC_DEFINE(PLUGIN_KVV,1,[kvv plugin])
+fi
if test "$PLUGIN_LOADAVG" = "yes"; then
PLUGINS="$PLUGINS plugin_loadavg.o"
AC_DEFINE(PLUGIN_LOADAVG,1,[loadavg plugin])
diff --git a/property.c b/property.c
index d465275..8e1e081 100644
--- a/property.c
+++ b/property.c
@@ -1,4 +1,4 @@
-/* $Id: property.c,v 1.2 2006/08/13 11:38:20 reinelt Exp $
+/* $Id: property.c,v 1.3 2006/08/13 18:14:03 harbaum Exp $
*
* dynamic properties
*
@@ -23,6 +23,9 @@
*
*
* $Log: property.c,v $
+ * Revision 1.3 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.2 2006/08/13 11:38:20 reinelt
* text widget uses dynamic properties
*
@@ -93,32 +96,31 @@ int property_eval(PROPERTY * prop)
{
RESULT old;
int update = 1;
-
+
/* this is a bit ugly: we need to remember the old value */
-
+
old.type = prop->result.type;
old.size = prop->result.size;
old.number = prop->result.number;
- old.string = prop->result.string != NULL ? strdup(prop->result.string) : NULL;
-
+ old.string = prop->result.string != NULL ? strdup(prop->result.string) : NULL;
+
DelResult(&prop->result);
Eval(prop->compiled, &prop->result);
-
+
if (prop->result.type & R_NUMBER && old.type & R_NUMBER && prop->result.number == old.number) {
update = 0;
}
-
+
if (prop->result.type & R_STRING && old.type & R_STRING && prop->result.size == old.size) {
if (prop->result.string == NULL && old.string == NULL) {
update = 0;
- }
- else if (prop->result.string != NULL && old.string != NULL && strcmp(prop->result.string, old.string) == 0) {
+ } else if (prop->result.string != NULL && old.string != NULL && strcmp(prop->result.string, old.string) == 0) {
update = 0;
}
}
-
+
if (old.string)
- free (old.string);
+ free(old.string);
return update;
}
diff --git a/widget_text.c b/widget_text.c
index 033d6f8..d543534 100644
--- a/widget_text.c
+++ b/widget_text.c
@@ -1,4 +1,4 @@
-/* $Id: widget_text.c,v 1.26 2006/08/13 11:38:20 reinelt Exp $
+/* $Id: widget_text.c,v 1.27 2006/08/13 18:14:03 harbaum Exp $
*
* simple text widget handling
*
@@ -21,6 +21,9 @@
*
*
* $Log: widget_text.c,v $
+ * Revision 1.27 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.26 2006/08/13 11:38:20 reinelt
* text widget uses dynamic properties
*
@@ -172,7 +175,7 @@ void widget_text_scroll(void *Self)
char *postfix = P2S(&T->postfix);
char *string = T->string;
-
+
int num, len, width, pad;
char *src, *dst;
@@ -325,7 +328,7 @@ void widget_text_update(void *Self)
/* text style */
update += property_eval(&T->style);
-
+
/* something has changed and should be updated */
if (update) {
/* reset marquee counter if content has changed */
diff --git a/widget_text.h b/widget_text.h
index 61e5b35..bd9a18d 100644
--- a/widget_text.h
+++ b/widget_text.h
@@ -1,4 +1,4 @@
-/* $Id: widget_text.h,v 1.9 2006/08/13 11:38:20 reinelt Exp $
+/* $Id: widget_text.h,v 1.10 2006/08/13 18:14:03 harbaum Exp $
*
* simple text widget handling
*
@@ -23,6 +23,9 @@
*
*
* $Log: widget_text.h,v $
+ * Revision 1.10 2006/08/13 18:14:03 harbaum
+ * Added KVV plugin
+ *
* Revision 1.9 2006/08/13 11:38:20 reinelt
* text widget uses dynamic properties
*
@@ -77,9 +80,9 @@ typedef enum { ALIGN_LEFT, ALIGN_CENTER, ALIGN_RIGHT, ALIGN_MARQUEE } TEXT_ALIGN
typedef struct WIDGET_TEXT {
PROPERTY prefix; /* label on the left side */
PROPERTY postfix; /* label on the right side */
- PROPERTY value; /* value of text widget */
+ PROPERTY value; /* value of text widget */
PROPERTY style; /* text style (plain/bold/slant) */
- char *string; /* formatted value */
+ char *string; /* formatted value */
char *buffer; /* string with 'width+1' bytes allocated */
int width; /* field width */
int precision; /* number of digits after the decimal point */