linux
monitoring
raspberry-pi
automation
raspberrypi
mqtt
iot
internet-of-things
smarthome
dashboard
mqtt-hyperdash
control-systems
rule-engines
cockpit
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
477 lines
18 KiB
477 lines
18 KiB
/* HDDASHGEN.C (c) Markus Hoffmann */ |
|
|
|
/* This file is part of MQTT-Hyperdash, the MQTT Dashboard |
|
* ============================================================ |
|
* MQTT-Hyperdash is free software and comes with NO WARRANTY - read the file |
|
* COPYING for details |
|
*/ |
|
|
|
/* This tool makes a series of generic .dash files out of a (sorted) list |
|
of topics, like the list created by mqtt-list-topics. |
|
|
|
A common way to create such a parameter tree is by excecuting |
|
mqtt-list-topics --broker localhost | sort | hddashgen --broker localhost |
|
|
|
*/ |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <stdint.h> |
|
#include <unistd.h> |
|
#include <ctype.h> |
|
#include <fnmatch.h> |
|
#include <dirent.h> |
|
#include <string.h> |
|
#include <sys/stat.h> |
|
#if defined WINDOWS |
|
size_t getline(char **lineptr, size_t *n, FILE *stream); |
|
#define EX_OK 0 |
|
#else |
|
#include <sysexits.h> |
|
#endif |
|
|
|
#include "file.h" |
|
#include "hddashgen.h" |
|
#include "element_groups.h" |
|
|
|
|
|
/* Global variables and defaults */ |
|
|
|
|
|
int verbose=0; /* Verbosity level */ |
|
char *broker_url=DEFAULT_BROKER; |
|
char *broker_user=NULL; |
|
char *broker_passwd=NULL; |
|
char *dashboard_prefix=""; |
|
char *dashboarddir="."; /* by default use current dir.*/ |
|
|
|
static void hddashgen_set_defaults() { |
|
/* Set the default path where the .dash files are searched for. |
|
* The path can be overridden by a commandline parameter. |
|
*/ |
|
char *envptr; |
|
static char path[256]; |
|
envptr=getenv("HOME"); |
|
if(envptr) { |
|
snprintf(path,sizeof(path),"%s/.hyperdash/dashboards",envptr); |
|
if(exist(path)) { /* It does exist! */ |
|
dashboarddir=path; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
static void intro() { |
|
puts("hddashgen " HDDASHGEN_VERSION " (c) 2020 by Markus Hoffmann\n" |
|
"This tool is part of MQTT-Hyperdash, the universal MQTT Dashboard for linux."); |
|
} |
|
static void usage() { |
|
printf( |
|
"\nUsage: %s [-hvq] ---\tcreate dashboards from topic lists.\n\n" |
|
" -h --help\t\t---\tusage\n" |
|
" --broker <url>\t---\tdefine the broker url used [%s]\n" |
|
" --user <user>\t\t---\tuse this username for broker.\n" |
|
" --passwd <passwd>\t---\tuse this password for broker.\n" |
|
" --dashpath <path>\t---\tset path for dash files [%s]\n" |
|
" --prefix <name>\t---\tset prefix for dashboard file names [%s]\n" |
|
" -v\t\t\t---\tbe more verbose\n" |
|
" -q\t\t\t---\tbe more quiet\n" |
|
,"hddashgen",broker_url,dashboarddir,dashboard_prefix); |
|
} |
|
static void kommandozeile(int anzahl, char *argumente[]) { |
|
int count,quitflag=0; |
|
/* process command line parameters */ |
|
for(count=1;count<anzahl;count++) { |
|
if(!strcmp(argumente[count],"-h") || !strcmp(argumente[count],"--help")) { |
|
intro(); |
|
usage(); |
|
quitflag=1; |
|
} |
|
else if(!strcmp(argumente[count],"--version")) { |
|
intro(); |
|
quitflag=1; |
|
} |
|
else if(!strcmp(argumente[count],"--broker")) broker_url=argumente[++count]; |
|
else if(!strcmp(argumente[count],"--user")) broker_user=argumente[++count]; |
|
else if(!strcmp(argumente[count],"--passwd")) broker_passwd=argumente[++count]; |
|
else if(!strcmp(argumente[count],"--dashpath")) dashboarddir=argumente[++count]; |
|
else if(!strcmp(argumente[count],"--prefix")) dashboard_prefix=argumente[++count]; |
|
else if(!strcmp(argumente[count],"-v")) verbose++; |
|
else if(!strcmp(argumente[count],"-q")) verbose--; |
|
else if(*(argumente[count])=='-') ; /* do nothing, these could be options for the rule itself */ |
|
else { |
|
/* do nothing, these could be options for rule itself */ |
|
} |
|
} |
|
if(quitflag) exit(EX_OK); |
|
} |
|
|
|
typedef struct { |
|
char *name; |
|
char *typ; |
|
int anz; |
|
char *inhalt; |
|
} TOPIC; |
|
|
|
TOPIC topics[MAX_ANZ_TOPICS]; |
|
int anztopics=0; |
|
|
|
static void free_topics() { |
|
int i; |
|
for(i=0;i<anztopics;i++) { |
|
free(topics[i].name); |
|
free(topics[i].typ); |
|
free(topics[i].inhalt); |
|
} |
|
anztopics=0; |
|
} |
|
|
|
|
|
#define advance() y+=ADVANCE_Y; \ |
|
if(y>MAX_Y) {y=FIELD_START_Y;x+=ADVANCE_X;} \ |
|
if(h<y+ADVANCE_Y) h=y+ADVANCE_Y; \ |
|
if(w<x+ADVANCE_X) w=x+ADVANCE_X |
|
|
|
|
|
int do_level(int level,char *match, char *filename) { |
|
int i,offset=0,x=5,y; |
|
char filenameprefix[256]; |
|
char fullfilename[256]; |
|
char buffer[128]; |
|
char old[128]="/"; /* start with something impossible */ |
|
char *p1,*p2; |
|
int sublevel; |
|
int w=200; |
|
int h=100; |
|
/* Open/create file */ |
|
snprintf(filenameprefix, sizeof(filenameprefix),"%s%s",dashboard_prefix,filename); |
|
snprintf(fullfilename, sizeof(fullfilename),"%s/%s%s",dashboarddir,dashboard_prefix,filename); |
|
printf("--> %s [%s]\n",fullfilename,match); |
|
FILE *fp=fopen(fullfilename,"w"); |
|
if(fp==NULL) { |
|
printf("ERROR: could not create %s\n",fullfilename); |
|
return(-1); |
|
} |
|
/* Write Header information |
|
*/ |
|
fprintf(fp,"PANEL: TITLE=\"%s\" W=%d H=%d " WHITE BGBLACK "\n#####################################\n",filename,w,h); |
|
fprintf(fp,"# generated by hddasghen V." HDDASHGEN_VERSION "\n"); |
|
fprintf(fp,"# \n"); |
|
if(broker_user) { |
|
fprintf(fp,"BROKER: URL=\"%s\" USER=\"%s\" PASSWD=\"%s\"\n",broker_url,broker_user,broker_passwd); |
|
} else fprintf(fp,"BROKER: URL=\"%s\"\n",broker_url); |
|
y=FIELD_START_Y; |
|
fprintf(fp,"# HEADER\n"); |
|
if(match) { |
|
offset=strlen(match); |
|
fprintf(fp,"TEXT: X=10 Y=30 FGC=$FFFF00FF h=40 TEXT=\"%s\" FONT=\"Arial_Bold\" FONTSIZE=20\n",match); |
|
if(w<10+strlen(match)*14) w=10+strlen(match)*14; |
|
} else { |
|
fprintf(fp,"TEXT: X=10 Y=10 FGC=$FFFFFFFF h=20 TEXT=\"%s\" FONT=\"Arial_Bold\" FONTSIZE=20\n","Root of Broker"); |
|
fprintf(fp,"TEXT: X=10 Y=30 FGC=$FFFFFFFF h=20 TEXT=\"%s\" FONT=\"Arial_Bold\" FONTSIZE=16\n",dashboard_prefix); |
|
fprintf(fp,"\n"); |
|
|
|
|
|
/* Create a button for each *mainroot_hd.dash it finds. */ |
|
|
|
DIR *dp; |
|
struct dirent *entry; |
|
struct stat statbuf; |
|
|
|
if((dp = opendir(dashboarddir)) == NULL) { |
|
fprintf(stderr,"cannot open directory: %s\n",dashboarddir); |
|
} else { |
|
|
|
while((entry = readdir(dp)) != NULL) { |
|
stat(entry->d_name,&statbuf); |
|
if(S_ISDIR(statbuf.st_mode)) { |
|
/* Found a directory, but ignore . and .. */ |
|
if(strcmp(".",entry->d_name) == 0 || |
|
strcmp("..",entry->d_name) == 0) |
|
continue; |
|
} else { |
|
if(!fnmatch("*mainroot_hd.dash",entry->d_name,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
if(strcmp(entry->d_name,filenameprefix)) { |
|
printf("%s\n",entry->d_name); |
|
char buf[256]; |
|
char buf2[256]; |
|
strncpy(buf,entry->d_name,256); |
|
strncpy(buf2,entry->d_name,256); |
|
int l=strlen(buf); |
|
if(l>=5) buf[l-5]=0; |
|
if(l>16) buf2[l-16]=0; |
|
fprintf(fp,"# LINK TO MAINROOT DASHBOARD\n"); |
|
fprintf(fp,"PBOX: " XYWH BGGRAY2 GRAY "\n", x+5, y,180,20); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_BUTTON "\n",x+10,y, 20,buf2); |
|
fprintf(fp,"DASH: " XYWH "DASH=\"%s\"\n", x+5, y,180,20,buf); |
|
fprintf(fp,"FRAMETOGGLE: " XYWH "\n", x+5, y,180,20); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} |
|
} |
|
} |
|
} |
|
closedir(dp); |
|
y+=10; /* a little extra space */ |
|
} |
|
} |
|
|
|
|
|
for(i=0;i<anztopics;i++) { |
|
if(match==NULL || !strncmp(topics[i].name,match,strlen(match))) { |
|
p1=&(topics[i].name[offset]); |
|
p2=buffer; |
|
sublevel=0; |
|
while(*p1 && *p1!='/') *p2++=*p1++; |
|
if(*p1=='/') sublevel=1; |
|
*p2=0; |
|
if(!((*old==0 && *buffer==0) || !strncmp(old,buffer,128))) { |
|
if(sublevel) { |
|
/* Make a Button to follow the tree */ |
|
/* Process new branch*/ |
|
char newmatch[128]; |
|
if(match) snprintf(newmatch,sizeof(newmatch),"%s%s/",match,buffer); |
|
else snprintf(newmatch,sizeof(newmatch),"%s/",buffer); |
|
char nfilename[128]; |
|
p1=nfilename; |
|
p2=newmatch; |
|
while(*p2) { |
|
if(*p2=='/') *p1='_'; |
|
else if(*p2=='$') *p1='_'; |
|
else *p1=tolower(*p2); |
|
p1++; |
|
p2++; |
|
} |
|
*p1=0; |
|
strcat(nfilename,"hd"); |
|
char text[256]; |
|
p1=text; |
|
p2=newmatch; |
|
while(*p2) { |
|
if(*p2=='/' && p2[1]) p1=text; |
|
else *p1++=*p2; |
|
p2++; |
|
} |
|
if(p1>text) --p1; |
|
*p1=0; |
|
|
|
char buf[256]; |
|
snprintf(buf,sizeof(buf),"%s%s",dashboard_prefix,nfilename); |
|
fprintf(fp,"# LINK to next TREE LEVEL\n"); |
|
fprintf(fp,"PBOX: " XYWH GRAY BGGRAY "\n",x+5,y,180,20); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_BUTTON "\n",x+10,y,20,text); |
|
fprintf(fp,"DASH: " XYWH "DASH=\"%s\"\n",x+5,y,180,20,buf); |
|
fprintf(fp,"FRAMETOGGLE: " XYWH "\n",x+5,y,180,20); |
|
fprintf(fp,"\n"); |
|
|
|
strcat(nfilename,".dash"); |
|
do_level(level+1,newmatch,nfilename); |
|
|
|
advance(); |
|
strncpy(old,buffer,128); /* Ignore all topics here which are in the Subtree. */ |
|
} else { |
|
if(!strcmp(buffer,"ACTIVITY_DM")) { |
|
fprintf(fp,"# ACTIVITY indicator\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"BITMAPLABEL: " XY BGBLUE "TOPIC=\"%s\" " |
|
" BITMAP[0]=\"0|Disc1|$FFFFFFFF\" \\\n" |
|
" BITMAP[1]=\"1|Disc2|$FFFFFFFF\" \\\n" |
|
" BITMAP[2]=\"2|Disc3|$FFFFFFFF\" \\\n" |
|
" BITMAP[3]=\"3|Disc4|$FFFFFFFF\" \n",x+160,y,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!strcmp(buffer,"STATUS_DM")) { |
|
fprintf(fp,"# STATUS indicator\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"BITMAPLABEL: " XY BGBLUE "TOPIC=\"%s\" " |
|
" BITMAP[0]=\"0|SmallCircle|$00FF00FF\" \\\n" |
|
" BITMAP[1]=\"1|SmallCircle|$FF0000FF\" \\\n" |
|
" BITMAP[2]=\"2|SmallCircle|$FFFF00FF\" \\\n" |
|
" BITMAP[3]=\"3|SmallCircle|$FF00FFFF\" \n",x+160,y,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*ONOFF_DC",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# ON/OFF button group\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"PBOX: " XYWH GRAY BGDARKGRAY "\n",x+150,y,45,20); |
|
fprintf(fp,"PBOX: " XYWH GRAY BGDARKGRAY "\n",x+205,y,45,20); |
|
fprintf(fp,"TEXT: " XYHT GREEN FONT_BUTTON "\n",x+160,y+1,20,"ON"); |
|
fprintf(fp,"TEXT: " XYHT RED FONT_BUTTON "\n",x+210,y+1,20,"OFF"); |
|
fprintf(fp,"FRAMELABEL: " XYWHT "MATCH=\"1\"\n",x+150,y,45,20,topics[i].name); |
|
fprintf(fp,"FRAMELABEL: " XYWHT "MATCH=\"0\"\n",x+205,y,45,20,topics[i].name); |
|
fprintf(fp,"TOPICINAREA: " XYWHT "VALUE=\"1\"\n",x+150,y,45,20,topics[i].name); |
|
fprintf(fp,"TOPICINAREA: " XYWHT "VALUE=\"0\"\n",x+205,y,45,20,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!strcmp(buffer,"STATUS_SM")) { |
|
fprintf(fp,"# STATUS string\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICSTRING: " XYWHT BGBLACK YELLOW FONT_PAR "\n",x+130,y,110,20,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+130-2,y-2,110+4,20+4); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_AM",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# ANALOG MEASURED parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLUE YELLOW FONT_PAR ANAFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_AD",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# ANALOG DATA parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLACK ORANGE FONT_PAR ANAFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"TOPICINNUMBER: " XYWHT ANAFORMAT "MIN=0 MAX=1000\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+150-2,y-2,100+4,20+4); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_AC",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# ANALOG CONTROL parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLUE CYAN FONT_PAR ANAFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
advance(); |
|
fprintf(fp,"PBOX: " XYWH BGGRAY GRAY "\n",x+7,y,240,20); |
|
fprintf(fp,"FRAME: " XYWH "\n",x+7-2,y-2,240+4,20+4); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+7-2+20,y+2,240+4-40,20-4-1); |
|
fprintf(fp,"BITMAP: " XY WHITE "BITMAP=\"TickLeft\"\n",x+7,y+2); |
|
fprintf(fp,"BITMAP: " XY WHITE "BITMAP=\"TickRight\"\n",x+7+220+2,y+2); |
|
fprintf(fp,"HSCALER: " XYWHT ANAMM BGBLACK GRAY "TIC=0.05 AGC=$0\n",x+7+20,y+2,240-40,20-4-2,topics[i].name); |
|
fprintf(fp,"TICKER: " XYWHT ANAMM "TIC=-0.05\n",x+7, y+2,16,16,topics[i].name); |
|
fprintf(fp,"TICKER: " XYWHT ANAMM "TIC=0.05\n", x+7+220+2,y+2,16,16,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_DM",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# DIGITAL MEASURED parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLUE YELLOW FONT_PAR DIGIFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_DD",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# DIGITAL DATA parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLACK ORANGE FONT_PAR DIGIFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"TOPICINNUMBER: " XYWHT DIGIFORMAT DIGIMM "\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+150-2,y-2,100+4,20+4); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_DC",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# DIGITAL CONTROL parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICNUMBER: " XYWHT BGBLACK CYAN FONT_PAR DIGIFORMAT "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"TOPICINNUMBER: " XYWHT DIGIFORMAT DIGIMM "\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+150-2,y-2,100+4,20+4); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_SM",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# MEASURED STRING parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICSTRING: " XYWHT BGBLUE YELLOW FONT_PAR "\n",x+130,y,110,20,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_SC",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# CONTROL STRING parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICSTRING: " XYWHT BGBLACK WHITE FONT_PAR "\n",x+130,y,110,20,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+130-2,y-2,110+4,20+4); |
|
fprintf(fp,"TOPICINSTRING: " XYWHT "\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else if(!fnmatch("*_SD",buffer,FNM_NOESCAPE|FNM_PATHNAME)) { |
|
fprintf(fp,"# generic STRING parameter\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
fprintf(fp,"TOPICSTRING: " XYWHT BGBLACK ORANGE FONT_PAR "\n",x+130,y,110,20,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+130-2,y-2,110+4,20+4); |
|
fprintf(fp,"TOPICINSTRING: " XYWHT "\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} else { |
|
fprintf(fp,"# unknown parameter type\n"); |
|
fprintf(fp,"TEXT: " XYHT WHITE FONT_PARNAME "\n",x+10,y,20,buffer); |
|
if(!strcmp(topics[i].typ,"binary")) { |
|
fprintf(fp,"TEXTAREA: " XYWHT BGBLACK MAGENTA FONT_SMALL "\n",x+150,y,100,20,topics[i].name); |
|
} else if(!strcmp(topics[i].typ,"IMAGE")) { |
|
fprintf(fp,"TOPICIMAGE: " XYWHT "\n",x+150,y,100,90,topics[i].name); |
|
advance(); |
|
advance(); |
|
advance(); |
|
} else if(!strcmp(topics[i].typ,"JSON")) { |
|
fprintf(fp,"TEXTAREA: " XYWHT BGBLACK WHITE FONT_SMALL "\n",x+150,y,100,50,topics[i].name); |
|
fprintf(fp,"TOPICINSTRING: " XYWHT "\n",x+150-2,y-2,100+4,50+4,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+150-2,y-2,100+4,50+4); |
|
advance(); |
|
} else { |
|
fprintf(fp,"TEXTAREA: " XYWHT BGBLACK WHITE FONT_SMALL "\n",x+150,y,100,20,topics[i].name); |
|
fprintf(fp,"TOPICINSTRING: " XYWHT "\n",x+150-2,y-2,100+4,20+4,topics[i].name); |
|
fprintf(fp,"FRAME: " XYWHR "\n",x+150-2,y-2,100+4,20+4); |
|
} |
|
fprintf(fp,"\n"); |
|
advance(); |
|
} |
|
} |
|
} |
|
} else { |
|
/* doesnt match */ |
|
old[0]='/'; |
|
old[1]=0; |
|
} |
|
} |
|
fprintf(fp,"# FOOTER\n"); |
|
fprintf(fp,"TEXT: " XYHT YELLOW FONT_TINY "\n",x+5,y+5,20,"generated by hddashgen V." HDDASHGEN_VERSION); |
|
fprintf(fp,"\n"); |
|
/* |
|
* Now write the PANEL element. It must be the first visible element. |
|
* therefore we have to rewind the file and insert this line. |
|
*/ |
|
rewind(fp); |
|
fprintf(fp,"PANEL: TITLE=\"%s\" W=%d H=%d" WHITE BGBLUE "\n",filename,w,h); |
|
|
|
fclose(fp); /* close file */ |
|
// printf("} leave level <%s>\n",match); |
|
return(1); |
|
} |
|
|
|
|
|
#define next_column() p1=p2; \ |
|
while(*p1 && isspace(*p1)) p1++; \ |
|
p2=p1; \ |
|
while(*p2 && !isspace(*p2)) p2++; \ |
|
*p2++=0 |
|
|
|
|
|
int main(int argc, char* argv[]) { |
|
char *line = NULL; |
|
char *p1,*p2; |
|
size_t size; |
|
|
|
hddashgen_set_defaults(); /* Set default dashboard directory. */ |
|
kommandozeile(argc, argv); /* process command line */ |
|
|
|
/* Read from stdin */ |
|
|
|
while(getline(&line,&size,stdin)!=-1) { |
|
p1=line; |
|
if(*p1==0) continue; |
|
while(*p1 && isspace(*p1)) p1++; |
|
if(*p1==0) continue; |
|
if(*p1=='#') continue; |
|
p2=p1; |
|
while(*p2 && !isspace(*p2)) p2++; |
|
*p2++=0; |
|
topics[anztopics].name=strdup(p1); |
|
|
|
next_column(); topics[anztopics].anz=atoi(p1); |
|
next_column(); topics[anztopics].typ=strdup(p1); |
|
next_column(); topics[anztopics].inhalt=strdup(p1); |
|
anztopics++; |
|
if(anztopics>=MAX_ANZ_TOPICS) { |
|
printf("ERROR: Maximum number of topics reached. Cannot handle more than %d.",MAX_ANZ_TOPICS); |
|
break; |
|
} |
|
} |
|
free(line); |
|
printf("hddashgen: Have %d topics from list.\n",anztopics); |
|
do_level(0,NULL,"mainroot_hd.dash"); |
|
free_topics(); |
|
return(EX_OK); |
|
}
|
|
|