]> git.webhop.me Git - lcd4linux.git/commitdiff
[lcd4linux @ 2006-08-13 18:14:03 by harbaum]
authorharbaum <harbaum@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 13 Aug 2006 18:14:03 +0000 (18:14 +0000)
committerharbaum <harbaum@3ae390bd-cb1e-0410-b409-cd5a39f66f1f>
Sun, 13 Aug 2006 18:14:03 +0000 (18:14 +0000)
Added KVV plugin

git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@692 3ae390bd-cb1e-0410-b409-cd5a39f66f1f

13 files changed:
Makefile.am
Makefile.in
config.h.in
configure
drv_LEDMatrix.c
font_6x8_bold.h
lcd4linux.conf.sample
plugin.c
plugin_kvv.c [new file with mode: 0644]
plugins.m4
property.c
widget_text.c
widget_text.h

index 96be71f21f9c2aa8b2b72d6f3758d9d18a63f2db..c4d286aea58386ef8109e94644ffc036f4bf515c 100644 (file)
@@ -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                 \
index 0339fc16dbbede58eb67da2ccabdcd1075890983..89c7472a7fdb5b3fc5469dc46f241f63084b378c 100644 (file)
@@ -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@
index c0df0ef149330f7a65d0d5e0deec8494a7f1314d..625293b8cb4832fbd287b0f6e453dffc95070ec4 100644 (file)
 /* ISDN plugin */
 #undef PLUGIN_ISDN
 
+/* kvv plugin */
+#undef PLUGIN_KVV
+
 /* loadavg plugin */
 #undef PLUGIN_LOADAVG
 
index d110d26f357ad825742e8607e02e284ee61b1720..2ecb2caf6d7ffc35699c6fad1eb62448905fd000 100755 (executable)
--- 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
          ;;
@@ -8770,6 +8774,14 @@ cat >>confdefs.h <<\_ACEOF
 #define PLUGIN_ISDN 1
 _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"
index 38e10ca07aa5c748817d92175c4d887b7f5ab1e1..f6fdee390bf5389d15b5bb7cece34a016574261a 100644 (file)
@@ -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') {
index 0fb37fcc31125447b1fe18aef03b5ac93786a8bc..d8dbb15f347b756e440503100b33bd9750d777a3 100644 (file)
@@ -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__,
index 6b15dc15bb53e197eac30ae2e6bf73944610ca00..c55f33baa33c75de24b6ded59c96013aaffff1c2 100644 (file)
@@ -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'
index 00f26ee2569e88d02c2a8fe17b663a8e628413e2..5618f4ec75c769a2930e55699480c3fee794cf96 100644 (file)
--- 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 (file)
index 0000000..9db6674
--- /dev/null
@@ -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);
+}
index e829e8dd693be07e09ccf13db330319df7027e0b..632f70d2067c4f7377fab680b8bb79d2b0a47f64 100644 (file)
@@ -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])
index d46527564226d0beff7496044f464649f16f5324..8e1e081d7a417be60ff7ed2d76a43932a60dfeff 100644 (file)
@@ -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;
 }
index 033d6f82a283e59f6d15b8c1a37d142e851a16e8..d5435343235d916e3c6e908f0347fca43925c227 100644 (file)
@@ -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 */
index 61e5b358067f19d9ecb406d7e8e3e2036fc526ce..bd9a18d4860a8b5eac5c1e9867575ddaa419fd1c 100644 (file)
@@ -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 */