diff options
author | harbaum <harbaum@3ae390bd-cb1e-0410-b409-cd5a39f66f1f> | 2006-08-13 18:14:03 +0000 |
---|---|---|
committer | harbaum <harbaum@3ae390bd-cb1e-0410-b409-cd5a39f66f1f> | 2006-08-13 18:14:03 +0000 |
commit | 763788fd716a2c8f5064c913d35d10973c621ef9 (patch) | |
tree | 553a469c55802d218cae6c2f62db3f3ccd4e1927 | |
parent | 9e6804e49cac8d859b899ae49509ffdf347eda7f (diff) | |
download | lcd4linux-763788fd716a2c8f5064c913d35d10973c621ef9.tar.gz |
[lcd4linux @ 2006-08-13 18:14:03 by harbaum]
Added KVV plugin
git-svn-id: https://ssl.bulix.org/svn/lcd4linux/trunk@692 3ae390bd-cb1e-0410-b409-cd5a39f66f1f
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | config.h.in | 3 | ||||
-rwxr-xr-x | configure | 12 | ||||
-rw-r--r-- | drv_LEDMatrix.c | 52 | ||||
-rw-r--r-- | font_6x8_bold.h | 21 | ||||
-rw-r--r-- | lcd4linux.conf.sample | 30 | ||||
-rw-r--r-- | plugin.c | 13 | ||||
-rw-r--r-- | plugin_kvv.c | 714 | ||||
-rw-r--r-- | plugins.m4 | 8 | ||||
-rw-r--r-- | property.c | 24 | ||||
-rw-r--r-- | widget_text.c | 9 | ||||
-rw-r--r-- | widget_text.h | 9 |
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 @@ -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' @@ -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); +} @@ -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]) @@ -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 */ |