mirror of
https://github.com/eddyem/tsys01.git
synced 2025-12-06 10:35:14 +03:00
rebuild for using with libusefull_macros and run through serialsock
This commit is contained in:
parent
722645aa16
commit
2e4cc8c1fe
@ -1,4 +1,4 @@
|
|||||||
update=Чт 30 янв 2020 17:14:40
|
update=Сб 31 июл 2021 22:20:24
|
||||||
version=1
|
version=1
|
||||||
last_client=kicad
|
last_client=kicad
|
||||||
[pcbnew]
|
[pcbnew]
|
||||||
|
|||||||
26
src/netdaemon/Commands_list
Normal file
26
src/netdaemon/Commands_list
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
### Serial interface commands (ends with '\n'), small letter for only
|
||||||
|
local processing:
|
||||||
|
- **0...7** send message to Nth controller, not broadcast (after numb
|
||||||
|
er should be CAN command)
|
||||||
|
- **a** get raw ADC values
|
||||||
|
- **B** send dummy CAN messages to broadcast address
|
||||||
|
- **c** show coefficients for all thermosensors
|
||||||
|
- **D** send dummy CAN messages to master (0) address
|
||||||
|
- **Ee** end temperature scan
|
||||||
|
- **Ff** turn sensors off
|
||||||
|
- **g** get last CAN address
|
||||||
|
- **Hh** switch I2C to high speed (100kHz)
|
||||||
|
- **i** reinit CAN with new address (if changed)
|
||||||
|
- **Jj** get MCU temperature
|
||||||
|
- **Kk** get values of U and I
|
||||||
|
- **Ll** switch I2C to low speed (default, 10kHz)
|
||||||
|
- **Mm** change master id to 0 (**m**) / broadcast (**M**)
|
||||||
|
- **Oo** turn onboard diagnostic LEDs **O**n or **o**ff (both commands
|
||||||
|
are local!)
|
||||||
|
- **P** ping everyone over CAN
|
||||||
|
- **Rr** reinit I2C
|
||||||
|
- **Ss** start temperature scan
|
||||||
|
- **Tt** start single temperature measurement
|
||||||
|
- **u** check CAN bus status for errors
|
||||||
|
- **Vv** very low speed
|
||||||
|
- **Z** get sensors state over CAN
|
||||||
@ -1,13 +1,14 @@
|
|||||||
# run `make DEF=...` to add extra defines
|
# run `make DEF=...` to add extra defines
|
||||||
PROGRAM := netdaemon
|
PROGRAM := netdaemon
|
||||||
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -pthread
|
LDFLAGS := -fdata-sections -ffunction-sections -Wl,--gc-sections -Wl,--discard-all -pthread
|
||||||
|
LDFLAGS += -lusefull_macros -lm
|
||||||
SRCS := $(wildcard *.c)
|
SRCS := $(wildcard *.c)
|
||||||
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
|
DEFINES := $(DEF) -D_GNU_SOURCE -D_XOPEN_SOURCE=1111
|
||||||
#DEFINES += -DEBUG
|
#DEFINES += -DEBUG
|
||||||
# baudrate for USB<->UART converter
|
# baudrate for USB<->UART converter
|
||||||
DEFINES += -DBAUD_RATE=B115200
|
DEFINES += -DBAUD_RATE=B115200
|
||||||
OBJDIR := mk
|
OBJDIR := mk
|
||||||
CFLAGS += -O2 -Wall -Werror -Wextra -Wno-trampolines
|
CFLAGS += -O3 -Wall -Werror -Wextra -Wno-trampolines
|
||||||
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o))
|
OBJS := $(addprefix $(OBJDIR)/, $(SRCS:%.c=%.o))
|
||||||
DEPS := $(OBJS:.o=.d)
|
DEPS := $(OBJS:.o=.d)
|
||||||
CC = gcc
|
CC = gcc
|
||||||
@ -16,7 +17,7 @@ all : $(OBJDIR) $(PROGRAM)
|
|||||||
|
|
||||||
$(PROGRAM) : $(OBJS)
|
$(PROGRAM) : $(OBJS)
|
||||||
@echo -e "\t\tLD $(PROGRAM)"
|
@echo -e "\t\tLD $(PROGRAM)"
|
||||||
$(CC) $(LDFLAGS) $(OBJS) -o $(PROGRAM)
|
$(CC) $(OBJS) $(LDFLAGS) -o $(PROGRAM)
|
||||||
|
|
||||||
$(OBJDIR):
|
$(OBJDIR):
|
||||||
mkdir $(OBJDIR)
|
mkdir $(OBJDIR)
|
||||||
@ -27,7 +28,7 @@ endif
|
|||||||
|
|
||||||
$(OBJDIR)/%.o: %.c
|
$(OBJDIR)/%.o: %.c
|
||||||
@echo -e "\t\tCC $<"
|
@echo -e "\t\tCC $<"
|
||||||
$(CC) -MD -c $(LDFLAGS) $(CFLAGS) $(DEFINES) -o $@ $<
|
$(CC) $< -MD -c $(CFLAGS) $(DEFINES) -o $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
@echo -e "\t\tCLEAN"
|
@echo -e "\t\tCLEAN"
|
||||||
|
|||||||
@ -20,3 +20,9 @@ images storing directory, copy there script 'plot' and run service as
|
|||||||
|
|
||||||
Every 15 minutes it will calculate average values of thermal data and plot three graphs:
|
Every 15 minutes it will calculate average values of thermal data and plot three graphs:
|
||||||
T0.html with top temperatures, T1.html with bottom and Tgrad.html with their differences (T0-T1).
|
T0.html with top temperatures, T1.html with bottom and Tgrad.html with their differences (T0-T1).
|
||||||
|
|
||||||
|
** Signals
|
||||||
|
|
||||||
|
SIGUSR1 - reread temperatures adjustment file
|
||||||
|
|
||||||
|
SIGUSR2 - dump to logfile all current temperature values and turn sensors off until next reading
|
||||||
|
|||||||
@ -1,127 +0,0 @@
|
|||||||
/*
|
|
||||||
* daemon.c - functions for running in background like a daemon
|
|
||||||
*
|
|
||||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
*
|
|
||||||
* This program 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 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <dirent.h> // opendir
|
|
||||||
#include "checkfile.h"
|
|
||||||
#include "usefull_macros.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief readPSname - read process name from /proc/PID/cmdline
|
|
||||||
* @param pid - PID of interesting process
|
|
||||||
* @return filename or NULL if not found
|
|
||||||
* don't use this function twice for different names without copying
|
|
||||||
* its returning by strdup, because `name` contains in static array
|
|
||||||
*/
|
|
||||||
char *readPSname(pid_t pid){
|
|
||||||
static char name[PATH_MAX];
|
|
||||||
char *pp = name, byte, path[PATH_MAX];
|
|
||||||
FILE *file;
|
|
||||||
int cntr = 0;
|
|
||||||
size_t sz;
|
|
||||||
snprintf(path, PATH_MAX, PROC_BASE "/%d/cmdline", pid);
|
|
||||||
file = fopen(path, "r");
|
|
||||||
if(!file) return NULL; // there's no such file
|
|
||||||
do{ // read basename
|
|
||||||
sz = fread(&byte, 1, 1, file);
|
|
||||||
if(sz != 1) break;
|
|
||||||
if(byte != '/') *pp++ = byte;
|
|
||||||
else{
|
|
||||||
pp = name;
|
|
||||||
cntr = 0;
|
|
||||||
}
|
|
||||||
}while(byte && cntr++ < PATH_MAX-1);
|
|
||||||
name[cntr] = 0;
|
|
||||||
fclose(file);
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *pidfilename_ = NULL; // store the name of pidfile here
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check wether there is a same running process
|
|
||||||
* exit if there is a running process or error
|
|
||||||
* Checking have 3 steps:
|
|
||||||
* 1) lock executable file
|
|
||||||
* 2) check pidfile (if you run a copy?)
|
|
||||||
* 3) check /proc for executables with the same name (no/wrong pidfile)
|
|
||||||
* @param pidfilename - name of pidfile or NULL if none
|
|
||||||
* @return 0 if all OK or PID of first running process found
|
|
||||||
*/
|
|
||||||
pid_t check4running(char *pidfilename){
|
|
||||||
DIR *dir;
|
|
||||||
FILE *pidfile;
|
|
||||||
struct dirent *de;
|
|
||||||
struct stat s_buf;
|
|
||||||
pid_t pid = 0, self;
|
|
||||||
char *name, *myname;
|
|
||||||
self = getpid(); // get self PID
|
|
||||||
if(!(dir = opendir(PROC_BASE))){ // open /proc directory
|
|
||||||
ERR(PROC_BASE);
|
|
||||||
}
|
|
||||||
if(!(name = readPSname(self))){ // error reading self name
|
|
||||||
ERR("Can't read self name");
|
|
||||||
}
|
|
||||||
myname = strdup(name);
|
|
||||||
if(pidfilename && stat(pidfilename, &s_buf) == 0){ // pidfile exists
|
|
||||||
pidfile = fopen(pidfilename, "r");
|
|
||||||
if(pidfile){
|
|
||||||
if(fscanf(pidfile, "%d", &pid) > 0){ // read PID of (possibly) running process
|
|
||||||
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0){
|
|
||||||
fclose(pidfile);
|
|
||||||
goto procfound;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fclose(pidfile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// There is no pidfile or it consists a wrong record
|
|
||||||
while((de = readdir(dir))){ // scan /proc
|
|
||||||
if(!(pid = (pid_t)atoi(de->d_name)) || pid == self) // pass non-PID files and self
|
|
||||||
continue;
|
|
||||||
if((name = readPSname(pid)) && strncmp(name, myname, 255) == 0)
|
|
||||||
goto procfound;
|
|
||||||
}
|
|
||||||
pid = 0; // OK, not found -> create pid-file if need
|
|
||||||
if(pidfilename){
|
|
||||||
pidfile = fopen(pidfilename, "w");
|
|
||||||
if(!pidfile){
|
|
||||||
WARN("Can't open PID file");
|
|
||||||
}else{
|
|
||||||
fprintf(pidfile, "%d\n", self); // write self PID to pidfile
|
|
||||||
fclose(pidfile);
|
|
||||||
if(pidfilename_) FREE(pidfilename_);
|
|
||||||
pidfilename_ = strdup(pidfilename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
procfound:
|
|
||||||
closedir(dir);
|
|
||||||
free(myname);
|
|
||||||
return pid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief unlink_pidfile - remove pidfile @ exit
|
|
||||||
*/
|
|
||||||
void unlink_pidfile(){
|
|
||||||
if(!pidfilename_) return;
|
|
||||||
unlink(pidfilename_);
|
|
||||||
FREE(pidfilename_);
|
|
||||||
}
|
|
||||||
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Zphocus project.
|
|
||||||
* Copyright 2019 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
|
||||||
*
|
|
||||||
* This program 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef CHECKFILE_H__
|
|
||||||
#define CHECKFILE_H__
|
|
||||||
|
|
||||||
#include <unistd.h> // getpid, unlink
|
|
||||||
|
|
||||||
#ifndef PROC_BASE
|
|
||||||
#define PROC_BASE "/proc"
|
|
||||||
#endif
|
|
||||||
#ifndef WEAK
|
|
||||||
#define WEAK __attribute__ ((weak))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// check that our process is exclusive
|
|
||||||
pid_t check4running(char *pidfilename);
|
|
||||||
// read name of process by its PID
|
|
||||||
char *readPSname(pid_t pid);
|
|
||||||
void unlink_pidfile();
|
|
||||||
|
|
||||||
|
|
||||||
#endif // CHECKFILE_H__
|
|
||||||
@ -22,9 +22,10 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <strings.h>
|
#include <strings.h>
|
||||||
#include <math.h>
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "usefull_macros.h"
|
#include "term.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* here are global parameters initialisation
|
* here are global parameters initialisation
|
||||||
@ -33,20 +34,15 @@ int help;
|
|||||||
static glob_pars G;
|
static glob_pars G;
|
||||||
|
|
||||||
// default values for Gdefault & help
|
// default values for Gdefault & help
|
||||||
#define DEFAULT_COMDEV "/dev/ttyUSB0"
|
#define DEFAULT_SOCKPATH "\0canbus"
|
||||||
#define DEFAULT_PORT "4444"
|
#define DEFAULT_PORT "4444"
|
||||||
#define DEFAULT_PIDFILE "/tmp/TSYS01daemon.pid"
|
#define DEFAULT_PIDFILE "/tmp/TSYS01daemon.pid"
|
||||||
|
|
||||||
// DEFAULTS
|
// DEFAULTS
|
||||||
// default global parameters
|
// default global parameters
|
||||||
glob_pars const Gdefault = {
|
glob_pars const Gdefault = {
|
||||||
.device = DEFAULT_COMDEV,
|
.sockname = DEFAULT_SOCKPATH,
|
||||||
.port = DEFAULT_PORT,
|
.port = DEFAULT_PORT,
|
||||||
.terminal = 0,
|
|
||||||
.savepath = NULL,
|
|
||||||
.makegraphs = 0,
|
|
||||||
.rest_pars = NULL,
|
|
||||||
.rest_pars_num = 0,
|
|
||||||
.adjfilename = "tempadj.txt",
|
.adjfilename = "tempadj.txt",
|
||||||
.pidfilename = DEFAULT_PIDFILE
|
.pidfilename = DEFAULT_PIDFILE
|
||||||
};
|
};
|
||||||
@ -55,18 +51,18 @@ glob_pars const Gdefault = {
|
|||||||
* Define command line options by filling structure:
|
* Define command line options by filling structure:
|
||||||
* name has_arg flag val type argptr help
|
* name has_arg flag val type argptr help
|
||||||
*/
|
*/
|
||||||
myoption cmdlnopts[] = {
|
static myoption cmdlnopts[] = {
|
||||||
// common options
|
// common options
|
||||||
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
{"help", NO_ARGS, NULL, 'h', arg_int, APTR(&help), _("show this help")},
|
||||||
{"device", NEED_ARG, NULL, 'i', arg_string, APTR(&G.device), _("serial device name (default: " DEFAULT_COMDEV ")")},
|
{"name", NEED_ARG, NULL, 'n', arg_string, APTR(&G.sockname), _("server's UNIX socket name (default: \\0canbus)")},
|
||||||
{"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("network port to connect (default: " DEFAULT_PORT ")")},
|
{"port", NEED_ARG, NULL, 'p', arg_string, APTR(&G.port), _("network port to connect (default: " DEFAULT_PORT ")")},
|
||||||
{"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")},
|
//{"terminal",NO_ARGS, NULL, 't', arg_int, APTR(&G.terminal), _("run as terminal")},
|
||||||
{"savepath",NEED_ARG, NULL, 's', arg_string, APTR(&G.savepath), _("path where files would be saved (if none - don't save)")},
|
{"savepath",NEED_ARG, NULL, 's', arg_string, APTR(&G.savepath), _("path where files would be saved (if none - don't save)")},
|
||||||
{"graphplot",NO_ARGS, NULL, 'g', arg_int, APTR(&G.makegraphs),_("make graphics with gnuplot")},
|
{"graphplot",NO_ARGS, NULL, 'g', arg_int, APTR(&G.makegraphs),_("make graphics with gnuplot")},
|
||||||
{"testadjfile",NO_ARGS, NULL, 'T', arg_int, APTR(&G.testadjfile),_("test format of file with T adjustements and force running proces to re-read it")},
|
{"testadjfile",NO_ARGS, NULL, 'T', arg_int, APTR(&G.testadjfile),_("test format of file with T adjustements")},
|
||||||
{"adjname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.adjfilename),_("name of adjustements file (default: tempadj.txt)")},
|
{"adjname", NEED_ARG, NULL, 'N', arg_string, APTR(&G.adjfilename),_("name of adjustements file (default: tempadj.txt)")},
|
||||||
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfilename),_("name of PID file (default: " DEFAULT_PIDFILE ")")},
|
{"pidfile", NEED_ARG, NULL, 'P', arg_string, APTR(&G.pidfilename),_("name of PID file (default: " DEFAULT_PIDFILE ")")},
|
||||||
{"dumpoff", NO_ARGS, NULL, 'd', arg_string, APTR(&G.dumpoff), _("dump sensors data & turn all OFF until next request")},
|
//{"dumpoff", NO_ARGS, NULL, 'd', arg_string, APTR(&G.dumpoff), _("dump sensors data & turn all OFF until next request")},
|
||||||
end_option
|
end_option
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -23,16 +23,13 @@
|
|||||||
#ifndef __CMDLNOPTS_H__
|
#ifndef __CMDLNOPTS_H__
|
||||||
#define __CMDLNOPTS_H__
|
#define __CMDLNOPTS_H__
|
||||||
|
|
||||||
#include "parseargs.h"
|
|
||||||
#include "term.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* here are some typedef's for global data
|
* here are some typedef's for global data
|
||||||
*/
|
*/
|
||||||
typedef struct{
|
typedef struct{
|
||||||
char *device; // serial device name
|
char *sockname; // server's UNIX socket name
|
||||||
char *port; // port to connect
|
char *port; // port to connect
|
||||||
int terminal; // run as terminal
|
//int terminal; // run as terminal
|
||||||
char *savepath; // path where data & graphical files would be saved
|
char *savepath; // path where data & graphical files would be saved
|
||||||
int makegraphs; // ==1 to make graphics with gnuplot
|
int makegraphs; // ==1 to make graphics with gnuplot
|
||||||
int rest_pars_num; // number of rest parameters
|
int rest_pars_num; // number of rest parameters
|
||||||
@ -40,7 +37,7 @@ typedef struct{
|
|||||||
int testadjfile; // test format of file with adjustments
|
int testadjfile; // test format of file with adjustments
|
||||||
char *adjfilename; // name of adjustements file
|
char *adjfilename; // name of adjustements file
|
||||||
char *pidfilename; // name of PID file
|
char *pidfilename; // name of PID file
|
||||||
int dumpoff; // dump sensors data & turn all OFF until next request
|
//int dumpoff; // dump sensors data & turn all OFF until next request
|
||||||
} glob_pars;
|
} glob_pars;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -20,12 +20,15 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
#include <linux/limits.h> // PATH_MAX
|
||||||
#include <stdio.h> // file operations
|
#include <stdio.h> // file operations
|
||||||
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h> // access() to check file exists
|
#include <unistd.h> // access() to check file exists
|
||||||
#include <linux/limits.h> // PATH_MAX
|
#include <usefull_macros.h>
|
||||||
#include "usefull_macros.h"
|
|
||||||
#include "cmdlnopts.h" // glob_pars
|
#include "cmdlnopts.h" // glob_pars
|
||||||
|
#include "sens_place.h"
|
||||||
|
|
||||||
extern glob_pars *G;
|
extern glob_pars *G;
|
||||||
|
|
||||||
@ -94,7 +97,7 @@ static void gnuplot(char *path, char *fname){
|
|||||||
DBG("Run %s", buf);
|
DBG("Run %s", buf);
|
||||||
if(system(buf)){
|
if(system(buf)){
|
||||||
WARNX(_("Can't run `%s`"), buf);
|
WARNX(_("Can't run `%s`"), buf);
|
||||||
}else LOG("created chart %s", fname);
|
}else LOGMSG("created chart %s", fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void plot(double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], char *savepath){
|
void plot(double data[2][NCHANNEL_MAX+1][NCTRLR_MAX+1], char *savepath){
|
||||||
|
|||||||
@ -19,15 +19,17 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include <sys/prctl.h> //prctl
|
#include <sys/prctl.h> //prctl
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h> // wait
|
#include <sys/wait.h> // wait
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
#include "checkfile.h"
|
//#include "checkfile.h"
|
||||||
#include "cmdlnopts.h"
|
#include "cmdlnopts.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
#include "usefull_macros.h"
|
|
||||||
|
|
||||||
glob_pars *G; // non-static: some another files should know about it!
|
glob_pars *G; // non-static: some another files should know about it!
|
||||||
static pid_t childpid = 0; // PID of child - to kill it if need
|
static pid_t childpid = 0; // PID of child - to kill it if need
|
||||||
@ -35,29 +37,25 @@ static pid_t childpid = 0; // PID of child - to kill it if need
|
|||||||
// default signals handler
|
// default signals handler
|
||||||
void signals(int signo){
|
void signals(int signo){
|
||||||
restore_console();
|
restore_console();
|
||||||
restore_tty();
|
|
||||||
if(childpid){
|
if(childpid){
|
||||||
const char *s = signum_to_signame(signo);
|
LOGERR("Exit with status %d", signo);
|
||||||
if(s) LOG("exit with status %d (or by signal %s)", signo, s);
|
|
||||||
else LOG("exit with status %d", signo);
|
|
||||||
}
|
}
|
||||||
exit(signo);
|
exit(signo);
|
||||||
}
|
}
|
||||||
|
|
||||||
// report about some ignored signals
|
// report about some ignored signals
|
||||||
static void repsig(int signo){
|
static void repsig(int signo){
|
||||||
const char *s = signum_to_signame(signo);
|
WARNX("PID: %d, received signal %d (%s)", getpid(), signo, strsignal(signo));
|
||||||
WARNX("PID: %d, received signal %d, %s (%s)", getpid(), signo, s ? s : "", strsignal(signo));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIGUSR1 handler - re-read Tadj file
|
// SIGUSR1 handler - re-read Tadj file
|
||||||
static void refreshAdj(_U_ int signo){
|
static void refreshAdj(_U_ int signo){
|
||||||
DBG("refresh adj");
|
DBG("refresh adj");
|
||||||
if(childpid){ // I am a master
|
if(childpid){ // I am a master
|
||||||
LOG("Force child %d to re-read adj-file", childpid);
|
LOGMSG("Force child %d to re-read adj-file", childpid);
|
||||||
kill(childpid, SIGUSR1);
|
kill(childpid, SIGUSR1);
|
||||||
}else{ // I am a child
|
}else{ // I am a child
|
||||||
LOG("Re-read adj-file");
|
LOGMSG("Re-read adj-file");
|
||||||
read_adj_file(G->adjfilename);
|
read_adj_file(G->adjfilename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,38 +63,38 @@ static void refreshAdj(_U_ int signo){
|
|||||||
static void logT(_U_ int signo){
|
static void logT(_U_ int signo){
|
||||||
for(int i = 0; i < 3; ++i){
|
for(int i = 0; i < 3; ++i){
|
||||||
const char *s = gotstr(i);
|
const char *s = gotstr(i);
|
||||||
if(s && *s) LOG("Sensors group #%d:\n%s", i, s);
|
if(s && *s) LOGMSG("Sensors group #%d:\n%s", i, s);
|
||||||
}
|
}
|
||||||
LOG("Turn sensors off");
|
LOGMSG("Turn sensors off");
|
||||||
TurnOFF();
|
TurnOFF();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
initial_setup();
|
initial_setup();
|
||||||
|
char *self = strdup(argv[0]);
|
||||||
G = parse_args(argc, argv);
|
G = parse_args(argc, argv);
|
||||||
if(G->makegraphs && !G->savepath){
|
if(G->makegraphs && !G->savepath){
|
||||||
ERRX(_("Point the path to graphical files"));
|
ERRX(_("Point the path to graphical files"));
|
||||||
}
|
}
|
||||||
pid_t runningproc = check4running(G->pidfilename);
|
check4running(self, G->pidfilename);
|
||||||
if(G->dumpoff){
|
/*if(G->dumpoff){
|
||||||
if(runningproc) kill(runningproc, SIGUSR2);
|
if(runningproc) kill(runningproc, SIGUSR2);
|
||||||
else ERRX("There's no running daemon");
|
else ERRX("There's no running daemon");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}*/
|
||||||
int raf = read_adj_file(G->adjfilename);
|
int raf = read_adj_file(G->adjfilename);
|
||||||
if(G->testadjfile){
|
if(G->testadjfile){
|
||||||
if(raf == 0){
|
if(raf == 0){
|
||||||
green("Format of file %s is right\n", G->adjfilename);
|
green("Format of file %s is right\n", G->adjfilename);
|
||||||
if(runningproc){ // fore running process to re-read it
|
/*if(runningproc){ // fore running process to re-read it
|
||||||
kill(runningproc, SIGUSR1);
|
kill(runningproc, SIGUSR1);
|
||||||
}
|
}*/
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(runningproc) ERRX("Found running process, pid=%d.", runningproc);
|
|
||||||
if(G->rest_pars_num)
|
if(G->rest_pars_num)
|
||||||
Cl_createlog(G->rest_pars[0]);
|
OPENLOG(G->rest_pars[0], LOGLEVEL_DBG, 1);
|
||||||
// ignore almost all possible signals
|
// ignore almost all possible signals
|
||||||
for(int sig = 0; sig < 256; ++sig) signal(sig, repsig);
|
for(int sig = 0; sig < 256; ++sig) signal(sig, repsig);
|
||||||
signal(SIGTERM, signals); // kill (-15) - quit
|
signal(SIGTERM, signals); // kill (-15) - quit
|
||||||
@ -108,35 +106,34 @@ int main(int argc, char **argv){
|
|||||||
signal(SIGUSR1, refreshAdj); // refresh adjustements
|
signal(SIGUSR1, refreshAdj); // refresh adjustements
|
||||||
signal(SIGUSR2, logT); // print all current temperatures into logfile and turn off sensors
|
signal(SIGUSR2, logT); // print all current temperatures into logfile and turn off sensors
|
||||||
#ifndef EBUG
|
#ifndef EBUG
|
||||||
if(!G->terminal){
|
if(daemon(1, 0)){
|
||||||
if(daemon(1, 0)){
|
ERR("daemon()");
|
||||||
ERR("daemon()");
|
}
|
||||||
}
|
while(1){ // guard for dead processes
|
||||||
while(1){ // guard for dead processes
|
childpid = fork();
|
||||||
childpid = fork();
|
if(childpid){
|
||||||
if(childpid){
|
LOGMSG("create child with PID %d\n", childpid);
|
||||||
LOG("create child with PID %d\n", childpid);
|
DBG("Created child with PID %d\n", childpid);
|
||||||
DBG("Created child with PID %d\n", childpid);
|
while(childpid != waitpid(childpid, NULL, 0));
|
||||||
while(childpid != waitpid(childpid, NULL, 0));
|
WARNX("Child %d died\n", childpid);
|
||||||
WARNX("Child %d died\n", childpid);
|
sleep(10);
|
||||||
sleep(10);
|
}else{
|
||||||
}else{
|
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
|
||||||
prctl(PR_SET_PDEATHSIG, SIGTERM); // send SIGTERM to child when parent dies
|
break; // go out to normal functional
|
||||||
break; // go out to normal functional
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
DBG("dev: %s", G->device);
|
DBG("sockname: %s", G->sockname);
|
||||||
try_connect(G->device);
|
if(!try_connect(G->sockname)) ERR("Can't connect to UNIX socket");
|
||||||
if(check_sensors()){
|
if(check_sensors()){
|
||||||
LOG("No CAN-controllers detected");
|
LOGWARN("No CAN-controllers detected");
|
||||||
if(!poll_sensors(0)){ // there's not main controller connected to given terminal
|
if(!poll_sensors(0)){ // there's not main controller connected to given terminal
|
||||||
LOG("Opened device is not main controller");
|
LOGERR("Opened device is not main controller");
|
||||||
if(!G->terminal) signals(15);
|
ERRX("Opened device is not main controller");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(G->terminal) run_terminal();
|
//if(G->terminal) run_terminal();
|
||||||
else daemonize(G->port);
|
//else
|
||||||
|
daemonize(G->port);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,497 +0,0 @@
|
|||||||
/* geany_encoding=koi8-r
|
|
||||||
* parseargs.c - parsing command line arguments & print help
|
|
||||||
*
|
|
||||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
*
|
|
||||||
* This program 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 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h> // printf
|
|
||||||
#include <getopt.h> // getopt_long
|
|
||||||
#include <stdlib.h> // calloc, exit, strtoll
|
|
||||||
#include <assert.h> // assert
|
|
||||||
#include <string.h> // strdup, strchr, strlen
|
|
||||||
#include <strings.h>// strcasecmp
|
|
||||||
#include <limits.h> // INT_MAX & so on
|
|
||||||
#include <libintl.h>// gettext
|
|
||||||
#include <ctype.h> // isalpha
|
|
||||||
#include "parseargs.h"
|
|
||||||
#include "usefull_macros.h"
|
|
||||||
|
|
||||||
char *helpstring = "%s\n";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change standard help header
|
|
||||||
* MAY consist ONE "%s" for progname
|
|
||||||
* @param str (i) - new format
|
|
||||||
*/
|
|
||||||
void change_helpstring(char *s){
|
|
||||||
int pcount = 0, scount = 0;
|
|
||||||
char *str = s;
|
|
||||||
// check `helpstring` and set it to default in case of error
|
|
||||||
for(; pcount < 2; str += 2){
|
|
||||||
if(!(str = strchr(str, '%'))) break;
|
|
||||||
if(str[1] != '%') pcount++; // increment '%' counter if it isn't "%%"
|
|
||||||
else{
|
|
||||||
str += 2; // pass next '%'
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(str[1] == 's') scount++; // increment "%s" counter
|
|
||||||
};
|
|
||||||
if(pcount > 1 || pcount != scount){ // amount of pcount and/or scount wrong
|
|
||||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÓÔÒÏËÉ ÐÏÍÏÝÉ"
|
|
||||||
ERRX(_("Wrong helpstring!"));
|
|
||||||
}
|
|
||||||
helpstring = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Carefull atoll/atoi
|
|
||||||
* @param num (o) - returning value (or NULL if you wish only check number) - allocated by user
|
|
||||||
* @param str (i) - string with number must not be NULL
|
|
||||||
* @param t (i) - T_INT for integer or T_LLONG for long long (if argtype would be wided, may add more)
|
|
||||||
* @return TRUE if conversion sone without errors, FALSE otherwise
|
|
||||||
*/
|
|
||||||
static bool myatoll(void *num, char *str, argtype t){
|
|
||||||
long long tmp, *llptr;
|
|
||||||
int *iptr;
|
|
||||||
char *endptr;
|
|
||||||
assert(str);
|
|
||||||
assert(num);
|
|
||||||
tmp = strtoll(str, &endptr, 0);
|
|
||||||
if(endptr == str || *str == '\0' || *endptr != '\0')
|
|
||||||
return FALSE;
|
|
||||||
switch(t){
|
|
||||||
case arg_longlong:
|
|
||||||
llptr = (long long*) num;
|
|
||||||
*llptr = tmp;
|
|
||||||
break;
|
|
||||||
case arg_int:
|
|
||||||
default:
|
|
||||||
if(tmp < INT_MIN || tmp > INT_MAX){
|
|
||||||
/// "ãÅÌÏÅ ×ÎÅ ÄÏÐÕÓÔÉÍÏÇÏ ÄÉÁÐÁÚÏÎÁ"
|
|
||||||
WARNX(_("Integer out of range"));
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
iptr = (int*)num;
|
|
||||||
*iptr = (int)tmp;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// the same as myatoll but for double
|
|
||||||
// There's no NAN & INF checking here (what if they would be needed?)
|
|
||||||
static bool myatod(void *num, const char *str, argtype t){
|
|
||||||
double tmp, *dptr;
|
|
||||||
float *fptr;
|
|
||||||
char *endptr;
|
|
||||||
assert(str);
|
|
||||||
tmp = strtod(str, &endptr);
|
|
||||||
if(endptr == str || *str == '\0' || *endptr != '\0')
|
|
||||||
return FALSE;
|
|
||||||
switch(t){
|
|
||||||
case arg_double:
|
|
||||||
dptr = (double *) num;
|
|
||||||
*dptr = tmp;
|
|
||||||
break;
|
|
||||||
case arg_float:
|
|
||||||
default:
|
|
||||||
fptr = (float *) num;
|
|
||||||
*fptr = (float)tmp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get index of current option in array options
|
|
||||||
* @param opt (i) - returning val of getopt_long
|
|
||||||
* @param options (i) - array of options
|
|
||||||
* @return index in array
|
|
||||||
*/
|
|
||||||
static int get_optind(int opt, myoption *options){
|
|
||||||
int oind;
|
|
||||||
myoption *opts = options;
|
|
||||||
assert(opts);
|
|
||||||
for(oind = 0; opts->name && opts->val != opt; oind++, opts++);
|
|
||||||
if(!opts->name || opts->val != opt) // no such parameter
|
|
||||||
showhelp(-1, options);
|
|
||||||
return oind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* reallocate new value in array of multiple repeating arguments
|
|
||||||
* @arg paptr - address of pointer to array (**void)
|
|
||||||
* @arg type - its type (for realloc)
|
|
||||||
* @return pointer to new (next) value
|
|
||||||
*/
|
|
||||||
void *get_aptr(void *paptr, argtype type){
|
|
||||||
int i = 1;
|
|
||||||
void **aptr = *((void***)paptr);
|
|
||||||
if(aptr){ // there's something in array
|
|
||||||
void **p = aptr;
|
|
||||||
while(*p++) ++i;
|
|
||||||
}
|
|
||||||
size_t sz = 0;
|
|
||||||
switch(type){
|
|
||||||
default:
|
|
||||||
case arg_none:
|
|
||||||
/// "îÅ ÍÏÇÕ ÉÓÐÏÌØÚÏ×ÁÔØ ÎÅÓËÏÌØËÏ ÐÁÒÁÍÅÔÒÏ× ÂÅÚ ÁÒÇÕÍÅÎÔÏ×!"
|
|
||||||
ERRX("Can't use multiple args with arg_none!");
|
|
||||||
break;
|
|
||||||
case arg_int:
|
|
||||||
sz = sizeof(int);
|
|
||||||
break;
|
|
||||||
case arg_longlong:
|
|
||||||
sz = sizeof(long long);
|
|
||||||
break;
|
|
||||||
case arg_double:
|
|
||||||
sz = sizeof(double);
|
|
||||||
break;
|
|
||||||
case arg_float:
|
|
||||||
sz = sizeof(float);
|
|
||||||
break;
|
|
||||||
case arg_string:
|
|
||||||
sz = 0;
|
|
||||||
break;
|
|
||||||
/* case arg_function:
|
|
||||||
sz = sizeof(argfn *);
|
|
||||||
break;*/
|
|
||||||
}
|
|
||||||
aptr = realloc(aptr, (i + 1) * sizeof(void*));
|
|
||||||
*((void***)paptr) = aptr;
|
|
||||||
aptr[i] = NULL;
|
|
||||||
if(sz){
|
|
||||||
aptr[i - 1] = malloc(sz);
|
|
||||||
}else
|
|
||||||
aptr[i - 1] = &aptr[i - 1];
|
|
||||||
return aptr[i - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse command line arguments
|
|
||||||
* ! If arg is string, then value will be strdup'ed!
|
|
||||||
*
|
|
||||||
* @param argc (io) - address of argc of main(), return value of argc stay after `getopt`
|
|
||||||
* @param argv (io) - address of argv of main(), return pointer to argv stay after `getopt`
|
|
||||||
* BE CAREFUL! if you wanna use full argc & argv, save their original values before
|
|
||||||
* calling this function
|
|
||||||
* @param options (i) - array of `myoption` for arguments parcing
|
|
||||||
*
|
|
||||||
* @exit: in case of error this function show help & make `exit(-1)`
|
|
||||||
*/
|
|
||||||
void parseargs(int *argc, char ***argv, myoption *options){
|
|
||||||
char *short_options, *soptr;
|
|
||||||
struct option *long_options, *loptr;
|
|
||||||
size_t optsize, i;
|
|
||||||
myoption *opts = options;
|
|
||||||
// check whether there is at least one options
|
|
||||||
assert(opts);
|
|
||||||
assert(opts[0].name);
|
|
||||||
// first we count how much values are in opts
|
|
||||||
for(optsize = 0; opts->name; optsize++, opts++);
|
|
||||||
// now we can allocate memory
|
|
||||||
short_options = calloc(optsize * 3 + 1, 1); // multiply by three for '::' in case of args in opts
|
|
||||||
long_options = calloc(optsize + 1, sizeof(struct option));
|
|
||||||
opts = options; loptr = long_options; soptr = short_options;
|
|
||||||
// in debug mode check the parameters are not repeated
|
|
||||||
#ifdef EBUG
|
|
||||||
char **longlist = MALLOC(char*, optsize);
|
|
||||||
char *shortlist = MALLOC(char, optsize);
|
|
||||||
#endif
|
|
||||||
// fill short/long parameters and make a simple checking
|
|
||||||
for(i = 0; i < optsize; i++, loptr++, opts++){
|
|
||||||
// check
|
|
||||||
assert(opts->name); // check name
|
|
||||||
#ifdef EBUG
|
|
||||||
longlist[i] = strdup(opts->name);
|
|
||||||
#endif
|
|
||||||
if(opts->has_arg){
|
|
||||||
assert(opts->type != arg_none); // check error with arg type
|
|
||||||
assert(opts->argptr); // check pointer
|
|
||||||
}
|
|
||||||
if(opts->type != arg_none) // if there is a flag without arg, check its pointer
|
|
||||||
assert(opts->argptr);
|
|
||||||
// fill long_options
|
|
||||||
// don't do memcmp: what if there would be different alignment?
|
|
||||||
loptr->name = opts->name;
|
|
||||||
loptr->has_arg = (opts->has_arg < MULT_PAR) ? opts->has_arg : 1;
|
|
||||||
loptr->flag = opts->flag;
|
|
||||||
loptr->val = opts->val;
|
|
||||||
// fill short options if they are:
|
|
||||||
if(!opts->flag && opts->val){
|
|
||||||
#ifdef EBUG
|
|
||||||
shortlist[i] = (char) opts->val;
|
|
||||||
#endif
|
|
||||||
*soptr++ = opts->val;
|
|
||||||
if(loptr->has_arg) // add ':' if option has required argument
|
|
||||||
*soptr++ = ':';
|
|
||||||
if(loptr->has_arg == 2) // add '::' if option has optional argument
|
|
||||||
*soptr++ = ':';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// sort all lists & check for repeating
|
|
||||||
#ifdef EBUG
|
|
||||||
int cmpstringp(const void *p1, const void *p2){
|
|
||||||
return strcmp(* (char * const *) p1, * (char * const *) p2);
|
|
||||||
}
|
|
||||||
int cmpcharp(const void *p1, const void *p2){
|
|
||||||
return (int)(*(char * const)p1 - *(char *const)p2);
|
|
||||||
}
|
|
||||||
qsort(longlist, optsize, sizeof(char *), cmpstringp);
|
|
||||||
qsort(shortlist,optsize, sizeof(char), cmpcharp);
|
|
||||||
char *prevl = longlist[0], prevshrt = shortlist[0];
|
|
||||||
for(i = 1; i < optsize; ++i){
|
|
||||||
if(longlist[i]){
|
|
||||||
if(prevl){
|
|
||||||
if(strcmp(prevl, longlist[i]) == 0) ERRX("double long arguments: --%s", prevl);
|
|
||||||
}
|
|
||||||
prevl = longlist[i];
|
|
||||||
}
|
|
||||||
if(shortlist[i]){
|
|
||||||
if(prevshrt){
|
|
||||||
if(prevshrt == shortlist[i]) ERRX("double short arguments: -%c", prevshrt);
|
|
||||||
}
|
|
||||||
prevshrt = shortlist[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
// now we have both long_options & short_options and can parse `getopt_long`
|
|
||||||
while(1){
|
|
||||||
int opt;
|
|
||||||
int oindex = 0, optind = 0; // oindex - number of option in argv, optind - number in options[]
|
|
||||||
if((opt = getopt_long(*argc, *argv, short_options, long_options, &oindex)) == -1) break;
|
|
||||||
if(opt == '?'){
|
|
||||||
opt = optopt;
|
|
||||||
optind = get_optind(opt, options);
|
|
||||||
if(options[optind].has_arg == NEED_ARG || options[optind].has_arg == MULT_PAR)
|
|
||||||
showhelp(optind, options); // need argument
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
if(opt == 0 || oindex > 0) optind = oindex;
|
|
||||||
else optind = get_optind(opt, options);
|
|
||||||
}
|
|
||||||
opts = &options[optind];
|
|
||||||
// if(opt == 0 && opts->has_arg == NO_ARGS) continue; // only long option changing integer flag
|
|
||||||
// now check option
|
|
||||||
if(opts->has_arg == NEED_ARG || opts->has_arg == MULT_PAR)
|
|
||||||
if(!optarg) showhelp(optind, options); // need argument
|
|
||||||
void *aptr;
|
|
||||||
if(opts->has_arg == MULT_PAR){
|
|
||||||
aptr = get_aptr(opts->argptr, opts->type);
|
|
||||||
}else
|
|
||||||
aptr = opts->argptr;
|
|
||||||
bool result = TRUE;
|
|
||||||
// even if there is no argument, but argptr != NULL, think that optarg = "1"
|
|
||||||
if(!optarg) optarg = "1";
|
|
||||||
switch(opts->type){
|
|
||||||
default:
|
|
||||||
case arg_none:
|
|
||||||
if(opts->argptr) *((int*)aptr) += 1; // increment value
|
|
||||||
break;
|
|
||||||
case arg_int:
|
|
||||||
result = myatoll(aptr, optarg, arg_int);
|
|
||||||
break;
|
|
||||||
case arg_longlong:
|
|
||||||
result = myatoll(aptr, optarg, arg_longlong);
|
|
||||||
break;
|
|
||||||
case arg_double:
|
|
||||||
result = myatod(aptr, optarg, arg_double);
|
|
||||||
break;
|
|
||||||
case arg_float:
|
|
||||||
result = myatod(aptr, optarg, arg_float);
|
|
||||||
break;
|
|
||||||
case arg_string:
|
|
||||||
result = (*((void**)aptr) = (void*)strdup(optarg));
|
|
||||||
break;
|
|
||||||
case arg_function:
|
|
||||||
result = ((argfn)aptr)(optarg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(!result){
|
|
||||||
showhelp(optind, options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*argc -= optind;
|
|
||||||
*argv += optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* compare function for qsort
|
|
||||||
* first - sort by short options; second - sort arguments without sort opts (by long options)
|
|
||||||
*/
|
|
||||||
static int argsort(const void *a1, const void *a2){
|
|
||||||
const myoption *o1 = (myoption*)a1, *o2 = (myoption*)a2;
|
|
||||||
const char *l1 = o1->name, *l2 = o2->name;
|
|
||||||
int s1 = o1->val, s2 = o2->val;
|
|
||||||
int *f1 = o1->flag, *f2 = o2->flag;
|
|
||||||
// check if both options has short arg
|
|
||||||
if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg
|
|
||||||
return (s1 - s2);
|
|
||||||
}else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long
|
|
||||||
return strcmp(l1, l2);
|
|
||||||
}else{ // only one have short arg -- return it
|
|
||||||
if(f2 || !s2) return -1; // a1 have short - it is 'lesser'
|
|
||||||
else return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show help information based on myoption->help values
|
|
||||||
* @param oindex (i) - if non-negative, show only help by myoption[oindex].help
|
|
||||||
* @param options (i) - array of `myoption`
|
|
||||||
*
|
|
||||||
* @exit: run `exit(-1)` !!!
|
|
||||||
*/
|
|
||||||
void showhelp(int oindex, myoption *options){
|
|
||||||
int max_opt_len = 0; // max len of options substring - for right indentation
|
|
||||||
const int bufsz = 255;
|
|
||||||
char buf[bufsz+1];
|
|
||||||
myoption *opts = options;
|
|
||||||
assert(opts);
|
|
||||||
assert(opts[0].name); // check whether there is at least one options
|
|
||||||
if(oindex > -1){ // print only one message
|
|
||||||
opts = &options[oindex];
|
|
||||||
printf(" ");
|
|
||||||
if(!opts->flag && isalpha(opts->val)) printf("-%c, ", opts->val);
|
|
||||||
printf("--%s", opts->name);
|
|
||||||
if(opts->has_arg == 1) printf("=arg");
|
|
||||||
else if(opts->has_arg == 2) printf("[=arg]");
|
|
||||||
printf(" %s\n", _(opts->help));
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
// header, by default is just "progname\n"
|
|
||||||
printf("\n");
|
|
||||||
if(strstr(helpstring, "%s")) // print progname
|
|
||||||
printf(helpstring, __progname);
|
|
||||||
else // only text
|
|
||||||
printf("%s", helpstring);
|
|
||||||
printf("\n");
|
|
||||||
// count max_opt_len
|
|
||||||
do{
|
|
||||||
int L = strlen(opts->name);
|
|
||||||
if(max_opt_len < L) max_opt_len = L;
|
|
||||||
}while((++opts)->name);
|
|
||||||
max_opt_len += 14; // format: '-S , --long[=arg]' - get addition 13 symbols
|
|
||||||
opts = options;
|
|
||||||
// count amount of options
|
|
||||||
int N; for(N = 0; opts->name; ++N, ++opts);
|
|
||||||
if(N == 0) exit(-2);
|
|
||||||
// Now print all help (sorted)
|
|
||||||
opts = options;
|
|
||||||
qsort(opts, N, sizeof(myoption), argsort);
|
|
||||||
do{
|
|
||||||
int p = sprintf(buf, " "); // a little indent
|
|
||||||
if(!opts->flag && opts->val) // .val is short argument
|
|
||||||
p += snprintf(buf+p, bufsz-p, "-%c, ", opts->val);
|
|
||||||
p += snprintf(buf+p, bufsz-p, "--%s", opts->name);
|
|
||||||
if(opts->has_arg == 1) // required argument
|
|
||||||
p += snprintf(buf+p, bufsz-p, "=arg");
|
|
||||||
else if(opts->has_arg == 2) // optional argument
|
|
||||||
p += snprintf(buf+p, bufsz-p, "[=arg]");
|
|
||||||
assert(p < max_opt_len); // there would be magic if p >= max_opt_len
|
|
||||||
printf("%-*s%s\n", max_opt_len+1, buf, _(opts->help)); // write options & at least 2 spaces after
|
|
||||||
++opts;
|
|
||||||
}while(--N);
|
|
||||||
printf("\n\n");
|
|
||||||
exit(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get suboptions from parameter string
|
|
||||||
* @param str - parameter string
|
|
||||||
* @param opt - pointer to suboptions structure
|
|
||||||
* @return TRUE if all OK
|
|
||||||
*/
|
|
||||||
bool get_suboption(char *str, mysuboption *opt){
|
|
||||||
int findsubopt(char *par, mysuboption *so){
|
|
||||||
int idx = 0;
|
|
||||||
if(!par) return -1;
|
|
||||||
while(so[idx].name){
|
|
||||||
if(strcasecmp(par, so[idx].name) == 0) return idx;
|
|
||||||
++idx;
|
|
||||||
}
|
|
||||||
return -1; // badarg
|
|
||||||
}
|
|
||||||
bool opt_setarg(mysuboption *so, int idx, char *val){
|
|
||||||
mysuboption *soptr = &so[idx];
|
|
||||||
bool result = FALSE;
|
|
||||||
void *aptr = soptr->argptr;
|
|
||||||
switch(soptr->type){
|
|
||||||
default:
|
|
||||||
case arg_none:
|
|
||||||
if(soptr->argptr) *((int*)aptr) += 1; // increment value
|
|
||||||
result = TRUE;
|
|
||||||
break;
|
|
||||||
case arg_int:
|
|
||||||
result = myatoll(aptr, val, arg_int);
|
|
||||||
break;
|
|
||||||
case arg_longlong:
|
|
||||||
result = myatoll(aptr, val, arg_longlong);
|
|
||||||
break;
|
|
||||||
case arg_double:
|
|
||||||
result = myatod(aptr, val, arg_double);
|
|
||||||
break;
|
|
||||||
case arg_float:
|
|
||||||
result = myatod(aptr, val, arg_float);
|
|
||||||
break;
|
|
||||||
case arg_string:
|
|
||||||
result = (*((void**)aptr) = (void*)strdup(val));
|
|
||||||
break;
|
|
||||||
case arg_function:
|
|
||||||
result = ((argfn)aptr)(val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
char *tok;
|
|
||||||
bool ret = FALSE;
|
|
||||||
char *tmpbuf;
|
|
||||||
tok = strtok_r(str, ":,", &tmpbuf);
|
|
||||||
do{
|
|
||||||
char *val = strchr(tok, '=');
|
|
||||||
int noarg = 0;
|
|
||||||
if(val == NULL){ // no args
|
|
||||||
val = "1";
|
|
||||||
noarg = 1;
|
|
||||||
}else{
|
|
||||||
*val++ = '\0';
|
|
||||||
if(!*val || *val == ':' || *val == ','){ // no argument - delimeter after =
|
|
||||||
val = "1"; noarg = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
int idx = findsubopt(tok, opt);
|
|
||||||
if(idx < 0){
|
|
||||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÐÁÒÁÍÅÔÒ: %s"
|
|
||||||
WARNX(_("Wrong parameter: %s"), tok);
|
|
||||||
goto returning;
|
|
||||||
}
|
|
||||||
if(noarg && opt[idx].has_arg == NEED_ARG){
|
|
||||||
/// "%s: ÎÅÏÂÈÏÄÉÍ ÁÒÇÕÍÅÎÔ!"
|
|
||||||
WARNX(_("%s: argument needed!"), tok);
|
|
||||||
goto returning;
|
|
||||||
}
|
|
||||||
if(!opt_setarg(opt, idx, val)){
|
|
||||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÁÒÇÕÍÅÎÔ \"%s\" ÐÁÒÁÍÅÔÒÁ \"%s\""
|
|
||||||
WARNX(_("Wrong argument \"%s\" of parameter \"%s\""), val, tok);
|
|
||||||
goto returning;
|
|
||||||
}
|
|
||||||
}while((tok = strtok_r(NULL, ":,", &tmpbuf)));
|
|
||||||
ret = TRUE;
|
|
||||||
returning:
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@ -1,124 +0,0 @@
|
|||||||
/* geany_encoding=koi8-r
|
|
||||||
* parseargs.h - headers for parsing command line arguments
|
|
||||||
*
|
|
||||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
*
|
|
||||||
* This program 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 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
#pragma once
|
|
||||||
#ifndef __PARSEARGS_H__
|
|
||||||
#define __PARSEARGS_H__
|
|
||||||
|
|
||||||
#include <stdbool.h>// bool
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE true
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE false
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// macro for argptr
|
|
||||||
#define APTR(x) ((void*)x)
|
|
||||||
|
|
||||||
// if argptr is a function:
|
|
||||||
typedef bool(*argfn)(void *arg);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* type of getopt's argument
|
|
||||||
* WARNING!
|
|
||||||
* My function change value of flags by pointer, so if you want to use another type
|
|
||||||
* make a latter conversion, example:
|
|
||||||
* char charg;
|
|
||||||
* int iarg;
|
|
||||||
* myoption opts[] = {
|
|
||||||
* {"value", 1, NULL, 'v', arg_int, &iarg, "char val"}, ..., end_option};
|
|
||||||
* ..(parse args)..
|
|
||||||
* charg = (char) iarg;
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
arg_none = 0, // no arg
|
|
||||||
arg_int, // integer
|
|
||||||
arg_longlong, // long long
|
|
||||||
arg_double, // double
|
|
||||||
arg_float, // float
|
|
||||||
arg_string, // char *
|
|
||||||
arg_function // parse_args will run function `bool (*fn)(char *optarg, int N)`
|
|
||||||
} argtype;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Structure for getopt_long & help
|
|
||||||
* BE CAREFUL: .argptr is pointer to data or pointer to function,
|
|
||||||
* conversion depends on .type
|
|
||||||
*
|
|
||||||
* ATTENTION: string `help` prints through macro PRNT(), bu default it is gettext,
|
|
||||||
* but you can redefine it before `#include "parseargs.h"`
|
|
||||||
*
|
|
||||||
* if arg is string, then value wil be strdup'ed like that:
|
|
||||||
* char *str;
|
|
||||||
* myoption opts[] = {{"string", 1, NULL, 's', arg_string, &str, "string val"}, ..., end_option};
|
|
||||||
* *(opts[1].str) = strdup(optarg);
|
|
||||||
* in other cases argptr should be address of some variable (or pointer to allocated memory)
|
|
||||||
*
|
|
||||||
* NON-NULL argptr should be written inside macro APTR(argptr) or directly: (void*)argptr
|
|
||||||
*
|
|
||||||
* !!!LAST VALUE OF ARRAY SHOULD BE `end_option` or ZEROS !!!
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
typedef enum{
|
|
||||||
NO_ARGS = 0, // first three are the same as in getopt_long
|
|
||||||
NEED_ARG = 1,
|
|
||||||
OPT_ARG = 2,
|
|
||||||
MULT_PAR
|
|
||||||
} hasarg;
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
// these are from struct option:
|
|
||||||
const char *name; // long option's name
|
|
||||||
hasarg has_arg; // 0 - no args, 1 - nesessary arg, 2 - optionally arg, 4 - need arg & key can repeat (args are stored in null-terminated array)
|
|
||||||
int *flag; // NULL to return val, pointer to int - to set its value of val (function returns 0)
|
|
||||||
int val; // short opt name (if flag == NULL) or flag's value
|
|
||||||
// and these are mine:
|
|
||||||
argtype type; // type of argument
|
|
||||||
void *argptr; // pointer to variable to assign optarg value or function `bool (*fn)(char *optarg, int N)`
|
|
||||||
const char *help; // help string which would be shown in function `showhelp` or NULL
|
|
||||||
} myoption;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Suboptions structure, almost the same like myoption
|
|
||||||
* used in parse_subopts()
|
|
||||||
*/
|
|
||||||
typedef struct{
|
|
||||||
const char *name;
|
|
||||||
hasarg has_arg;
|
|
||||||
argtype type;
|
|
||||||
void *argptr;
|
|
||||||
} mysuboption;
|
|
||||||
|
|
||||||
// last string of array (all zeros)
|
|
||||||
#define end_option {0,0,0,0,0,0,0}
|
|
||||||
#define end_suboption {0,0,0,0}
|
|
||||||
|
|
||||||
extern const char *__progname;
|
|
||||||
|
|
||||||
void showhelp(int oindex, myoption *options);
|
|
||||||
void parseargs(int *argc, char ***argv, myoption *options);
|
|
||||||
void change_helpstring(char *s);
|
|
||||||
bool get_suboption(char *str, mysuboption *opt);
|
|
||||||
|
|
||||||
#endif // __PARSEARGS_H__
|
|
||||||
0
src/netdaemon/plot
Normal file → Executable file
0
src/netdaemon/plot
Normal file → Executable file
15
src/netdaemon/scripts/getdata
Executable file
15
src/netdaemon/scripts/getdata
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# receive data from mirtemp & store it
|
||||||
|
|
||||||
|
export http_proxy=""
|
||||||
|
|
||||||
|
# don't call curl if there's no connection to server
|
||||||
|
curl --http0.9 http://mirtemp.sao.ru:4444/Tmean || exit 1
|
||||||
|
|
||||||
|
cd $1
|
||||||
|
DIR="$(date +%y.%m.%d)"
|
||||||
|
mkdir $DIR 2>/dev/null
|
||||||
|
FNAME="${DIR}/$(date +%H:%M)"
|
||||||
|
for Tdat in T0 T1 T2; do
|
||||||
|
curl --http0.9 http://mirtemp.sao.ru:4444/${Tdat} -o ${FNAME}_${Tdat}.dat > /dev/null 2>/dev/null
|
||||||
|
done
|
||||||
12
src/netdaemon/scripts/plot/Archive_one_month
Executable file
12
src/netdaemon/scripts/plot/Archive_one_month
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# ./Archive_one_month <prefix>, like:
|
||||||
|
#
|
||||||
|
# ./Archive_one_month 21.03
|
||||||
|
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo -e "Usage: $0 <prefix>, like\n\t$0 21.03"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for x in $(seq 1 31); do D=$(printf "$1.%02d" $x); echo "tar $D"; tar -zcf ${D}.tgz $D; done
|
||||||
9
src/netdaemon/scripts/plot/findallextr
Executable file
9
src/netdaemon/scripts/plot/findallextr
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
if [ $# != 1 ]; then
|
||||||
|
echo "USAGE: $0 # (# is 0 or 1)"
|
||||||
|
echo -e "\t to print all extrems for given sensors group"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
find . -name "*T${1}.dat" -exec ./findextrems {} \;
|
||||||
13
src/netdaemon/scripts/plot/findextrems
Executable file
13
src/netdaemon/scripts/plot/findextrems
Executable file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
if [ $# != 1 ]; then
|
||||||
|
echo "USAGE: $0 file.dat"
|
||||||
|
echo -e "\t to print extremal delta T"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
MIN=$(cat $1 | awk '{print $4}' |sort -n | head -1)
|
||||||
|
MAX=$(cat $1 | awk '{print $4}' |sort -n | tail -1)
|
||||||
|
|
||||||
|
echo "$1: $(echo $MAX - $MIN | bc -l)"
|
||||||
|
|
||||||
54
src/netdaemon/scripts/plot/plotALLjpg
Executable file
54
src/netdaemon/scripts/plot/plotALLjpg
Executable file
@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# run it like
|
||||||
|
# for f in *.dat; do ../plotALLjpg $f; done
|
||||||
|
#
|
||||||
|
OUT=tmpfile.txt
|
||||||
|
awk '{print $2 "\t" $3 "\t" $4}' $1 > $OUT
|
||||||
|
DATE=$(echo $1 | sed -e 's|/| |' -e 's|_.*||')
|
||||||
|
TX=$(echo $1 | sed 's|.*_\(.*\).dat|\1|') #'
|
||||||
|
TXO=$(echo $1 | sed 's|\.dat|.jpg|') #'
|
||||||
|
if [ $TX = "T0" ]; then Tname="TOP side"
|
||||||
|
else Tname="BOTTOM side"
|
||||||
|
fi
|
||||||
|
VAL=$(head -n1 $1 | awk '{print $4}')
|
||||||
|
echo -e "30\t30\t$VAL\n-30\t-30\t$VAL" >> $OUT
|
||||||
|
cat << EOF > gnutplt
|
||||||
|
#!/usr/bin/gnuplot
|
||||||
|
set contour
|
||||||
|
unset surface
|
||||||
|
set cntrparam order 4
|
||||||
|
set cntrparam bspline
|
||||||
|
#set cntrparam levels auto 6
|
||||||
|
#set cntrparam levels incremental -30,0.1,30
|
||||||
|
set view map
|
||||||
|
set size square
|
||||||
|
set xrange [-40:40]
|
||||||
|
set yrange [-40:40]
|
||||||
|
set dgrid3d 100,100,4
|
||||||
|
set table "contour.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
unset contour
|
||||||
|
set surface
|
||||||
|
set table "dgrid.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
reset
|
||||||
|
set terminal jpeg enhanced size 1024,768
|
||||||
|
set output "$TXO"
|
||||||
|
set size square
|
||||||
|
set xrange [-30:30]
|
||||||
|
set yrange [-30:30]
|
||||||
|
set xlabel "X, dm"
|
||||||
|
set ylabel "Y, dm"
|
||||||
|
set title "Mirror temperature $TX for $DATE ($Tname)"
|
||||||
|
set pm3d map
|
||||||
|
unset key
|
||||||
|
circle(x,y,z) = x**2+y**2 > 900 ? NaN : z
|
||||||
|
splot 'dgrid.txt' u 1:2:(circle(\$1,\$2,\$3)) w pm3d, 'contour.txt' u 1:2:(circle(\$1,\$2,\$3)) w l lc rgb "black", '$OUT' u 1:2:(circle(\$1,\$2,\$3)):3 with labels font ",8"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 gnutplt
|
||||||
|
./gnutplt
|
||||||
|
rm -f gnutplt $OUT contour.txt dgrid.txt
|
||||||
53
src/netdaemon/scripts/plot/plotjpg
Executable file
53
src/netdaemon/scripts/plot/plotjpg
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# run it like
|
||||||
|
# ./plot 19.12.25/11\:20_T0.dat
|
||||||
|
#
|
||||||
|
OUT=tmpfile.txt
|
||||||
|
awk '{print $2 "\t" $3 "\t" $4}' $1 > $OUT
|
||||||
|
DATE=$(echo $1 | sed -e 's|/| |' -e 's|_.*||')
|
||||||
|
TX=$(echo $1 | sed 's|.*_\(.*\).dat|\1|')
|
||||||
|
if [ $TX = "T0" ]; then Tname="TOP side"
|
||||||
|
else Tname="BOTTOM side"
|
||||||
|
fi
|
||||||
|
VAL=$(head -n1 $1 | awk '{print $4}')
|
||||||
|
echo -e "30\t30\t$VAL\n-30\t-30\t$VAL" >> $OUT
|
||||||
|
cat << EOF > gnutplt
|
||||||
|
#!/usr/bin/gnuplot
|
||||||
|
set contour
|
||||||
|
unset surface
|
||||||
|
set cntrparam order 4
|
||||||
|
set cntrparam bspline
|
||||||
|
#set cntrparam levels auto 6
|
||||||
|
#set cntrparam levels incremental -30,0.1,30
|
||||||
|
set view map
|
||||||
|
set size square
|
||||||
|
set xrange [-40:40]
|
||||||
|
set yrange [-40:40]
|
||||||
|
set dgrid3d 100,100,4
|
||||||
|
set table "contour.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
unset contour
|
||||||
|
set surface
|
||||||
|
set table "dgrid.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
reset
|
||||||
|
set terminal jpeg enhanced size 1024,768
|
||||||
|
set output "$TX.jpg"
|
||||||
|
set size square
|
||||||
|
set xrange [-30:30]
|
||||||
|
set yrange [-30:30]
|
||||||
|
set xlabel "X, dm"
|
||||||
|
set ylabel "Y, dm"
|
||||||
|
set title "Mirror temperature $TX for $DATE ($Tname)"
|
||||||
|
set pm3d map
|
||||||
|
unset key
|
||||||
|
circle(x,y,z) = x**2+y**2 > 900 ? NaN : z
|
||||||
|
splot 'dgrid.txt' u 1:2:(circle(\$1,\$2,\$3)) w pm3d, 'contour.txt' u 1:2:(circle(\$1,\$2,\$3)) w l lc rgb "black", '$OUT' u 1:2:(circle(\$1,\$2,\$3)):3 with labels font ",8"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 gnutplt
|
||||||
|
./gnutplt
|
||||||
|
rm -f gnutplt $OUT contour.txt dgrid.txt
|
||||||
@ -16,10 +16,13 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <math.h> // fabs
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
#include "sens_place.h"
|
#include "sens_place.h"
|
||||||
#include "stdbool.h"
|
|
||||||
#include "usefull_macros.h"
|
|
||||||
#include "math.h" // fabs
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Sensor place Dt X Y Z
|
Sensor place Dt X Y Z
|
||||||
@ -294,13 +297,13 @@ cont:
|
|||||||
if(fabs(Tadj[i]) > DBL_EPSILON){
|
if(fabs(Tadj[i]) > DBL_EPSILON){
|
||||||
printf("\tTadj[%02d] = %g\n", i, Tadj[i]);
|
printf("\tTadj[%02d] = %g\n", i, Tadj[i]);
|
||||||
}
|
}
|
||||||
if(fabs(sensors[i].Tadj - Tadj[i]) > 0.001) LOG("Tadj[%d] = %g", i, Tadj[i]);
|
if(fabs(sensors[i].Tadj - Tadj[i]) > 0.001) LOGMSG("Tadj[%d] = %g", i, Tadj[i]);
|
||||||
sensors[i].Tadj = Tadj[i];
|
sensors[i].Tadj = Tadj[i];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
reperr:
|
reperr:
|
||||||
red("Error in string %d:\n", strnum);
|
red("Error in string %d:\n", strnum);
|
||||||
printf("%s\n", adjf);
|
printf("%s\n", adjf);
|
||||||
LOG("Erroneous adjustment file %s in line %d", fname, strnum);
|
LOGWARN("Erroneous adjustment file %s in line %d", fname, strnum);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,20 +20,22 @@
|
|||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "usefull_macros.h"
|
#include <arpa/inet.h> // inet_ntop
|
||||||
|
#include <limits.h> // INT_xxx
|
||||||
|
#include <netdb.h> // addrinfo
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <signal.h> // pthread_kill
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/syscall.h> // syscall
|
||||||
|
#include <unistd.h> // daemon
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "cmdlnopts.h" // glob_pars
|
||||||
|
#include "gnuplot.h" // plot graphs
|
||||||
|
#include "sens_place.h" // sensors coordinates
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
#include <netdb.h> // addrinfo
|
|
||||||
#include <arpa/inet.h> // inet_ntop
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <limits.h> // INT_xxx
|
|
||||||
#include <signal.h> // pthread_kill
|
|
||||||
#include <unistd.h> // daemon
|
|
||||||
#include <sys/syscall.h> // syscall
|
|
||||||
|
|
||||||
#include "sens_place.h" // sensors coordinates
|
|
||||||
#include "gnuplot.h" // plot graphs
|
|
||||||
#include "cmdlnopts.h" // glob_pars
|
|
||||||
|
|
||||||
#define BUFLEN (10240)
|
#define BUFLEN (10240)
|
||||||
// Max amount of connections
|
// Max amount of connections
|
||||||
@ -191,14 +193,14 @@ static void *handle_socket(void *asock){
|
|||||||
}
|
}
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
if(!send_data(sock, webquery, Nsens)){
|
if(!send_data(sock, webquery, Nsens)){
|
||||||
LOG("can't send data, some error occured");
|
LOGWARN("can't send data, some error occured");
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
}else if(strncmp("Tmean", found, 5) == 0){ // send user meanT
|
}else if(strncmp("Tmean", found, 5) == 0){ // send user meanT
|
||||||
L = snprintf(tbuf, 128, "%.2f\n", meanT);
|
L = snprintf(tbuf, 128, "%.2f\n", meanT);
|
||||||
if(L != write(sock, tbuf, L)) WARN("write()");
|
if(L != write(sock, tbuf, L)) WARN("write()");
|
||||||
}else if(strncmp("ReBoOt", found, 6) == 0){
|
}else if(strncmp("ReBoOt", found, 6) == 0){
|
||||||
LOG("Reboot command from %s", C.host);
|
LOGWARN("Reboot command from %s", C.host);
|
||||||
L = write(sock, "Reboot system\n", 14);
|
L = write(sock, "Reboot system\n", 14);
|
||||||
if(0 != system("sudo reboot")) WARN("Can't reboot");
|
if(0 != system("sudo reboot")) WARN("Can't reboot");
|
||||||
// here can be more parsers
|
// here can be more parsers
|
||||||
@ -234,7 +236,7 @@ static void *server(void *asock){
|
|||||||
struct in_addr ipAddr = pV4Addr->sin_addr;
|
struct in_addr ipAddr = pV4Addr->sin_addr;
|
||||||
char str[INET_ADDRSTRLEN];
|
char str[INET_ADDRSTRLEN];
|
||||||
inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
|
inet_ntop(AF_INET, &ipAddr, str, INET_ADDRSTRLEN);
|
||||||
//LOG("get connection from %s", str);
|
LOGMSG("get connection from %s", str);
|
||||||
red("Got connection from %s\n", str);
|
red("Got connection from %s\n", str);
|
||||||
pthread_t handler_thread;
|
pthread_t handler_thread;
|
||||||
conn C = {.sockn = newsock};
|
conn C = {.sockn = newsock};
|
||||||
@ -246,7 +248,7 @@ static void *server(void *asock){
|
|||||||
pthread_detach(handler_thread); // don't care about thread state
|
pthread_detach(handler_thread); // don't care about thread state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG("server(): UNREACHABLE CODE REACHED!");
|
LOGERR("server(): UNREACHABLE CODE REACHED!");
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef double Item;
|
typedef double Item;
|
||||||
@ -368,7 +370,7 @@ static void daemon_(int sock){
|
|||||||
if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){
|
if(pthread_create(&sock_thread, NULL, server, (void*) &sock)){
|
||||||
ERR("pthread_create()");
|
ERR("pthread_create()");
|
||||||
}
|
}
|
||||||
double tgot = 0., tlastoff = dtime();
|
double tgot = 0.;//, tlastoff = dtime();
|
||||||
do{
|
do{
|
||||||
if(pthread_kill(sock_thread, 0) == ESRCH){ // died
|
if(pthread_kill(sock_thread, 0) == ESRCH){ // died
|
||||||
WARNX("Sockets thread died");
|
WARNX("Sockets thread died");
|
||||||
@ -381,12 +383,12 @@ static void daemon_(int sock){
|
|||||||
if(TurnOff){
|
if(TurnOff){
|
||||||
TurnOff = FALSE;
|
TurnOff = FALSE;
|
||||||
turn_all_off();
|
turn_all_off();
|
||||||
tlastoff = dtime();
|
//tlastoff = dtime();
|
||||||
}
|
}/*
|
||||||
if(dtime() - tlastoff > T_OFF_INTERVAL){
|
if(dtime() - tlastoff > T_OFF_INTERVAL){
|
||||||
turn_all_off();
|
turn_all_off();
|
||||||
tlastoff = dtime();
|
tlastoff = dtime();
|
||||||
}
|
}*/
|
||||||
if(dtime() - tgot < T_INTERVAL) continue;
|
if(dtime() - tgot < T_INTERVAL) continue;
|
||||||
// get data
|
// get data
|
||||||
int i;
|
int i;
|
||||||
@ -428,7 +430,7 @@ static void daemon_(int sock){
|
|||||||
memcpy(strT, bufs, sizeof(strT));
|
memcpy(strT, bufs, sizeof(strT));
|
||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
}while(1);
|
}while(1);
|
||||||
LOG("daemon_(): UNREACHABLE CODE REACHED!");
|
LOGERR("daemon_(): UNREACHABLE CODE REACHED!");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -474,7 +476,7 @@ void daemonize(char *port){
|
|||||||
freeaddrinfo(res);
|
freeaddrinfo(res);
|
||||||
daemon_(sock);
|
daemon_(sock);
|
||||||
close(sock);
|
close(sock);
|
||||||
LOG("daemonize(): UNREACHABLE CODE REACHED!");
|
LOGERR("daemonize(): UNREACHABLE CODE REACHED!");
|
||||||
signals(0);
|
signals(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1 +1,6 @@
|
|||||||
#No dT (Treal = T - dT)
|
#No dT (Treal = T - dT)
|
||||||
|
251 -0.7
|
||||||
|
320 0.12
|
||||||
|
330 0.15
|
||||||
|
360 0.15
|
||||||
|
520 0.05
|
||||||
|
|||||||
@ -18,11 +18,23 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||||
* MA 02110-1301, USA.
|
* MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
#include "usefull_macros.h"
|
#include <arpa/inet.h>
|
||||||
#include "term.h"
|
|
||||||
#include <strings.h> // strncasecmp
|
|
||||||
#include <time.h> // time(NULL)
|
|
||||||
#include <limits.h> // INT_MAX, INT_MIN
|
#include <limits.h> // INT_MAX, INT_MIN
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <strings.h> // strncasecmp
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/un.h> // unix socket
|
||||||
|
#include <time.h> // time(NULL)
|
||||||
|
#include <usefull_macros.h>
|
||||||
|
|
||||||
|
#include "term.h"
|
||||||
|
|
||||||
#define BUFLEN 1024
|
#define BUFLEN 1024
|
||||||
|
|
||||||
@ -30,76 +42,79 @@
|
|||||||
time_t tmeasured[2][NCHANNEL_MAX+1][NCTRLR_MAX+1];
|
time_t tmeasured[2][NCHANNEL_MAX+1][NCTRLR_MAX+1];
|
||||||
// last temperatures read: [Ngroup][Nsensor][Ncontroller]
|
// last temperatures read: [Ngroup][Nsensor][Ncontroller]
|
||||||
double t_last[2][NCHANNEL_MAX+1][NCTRLR_MAX+1];
|
double t_last[2][NCHANNEL_MAX+1][NCTRLR_MAX+1];
|
||||||
|
static int sock = -1; // server UNIX-socket fd
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* read strings from terminal (ending with '\n') with timeout
|
* wait for answer from socket
|
||||||
* @param L - its length
|
* @param sock - socket fd
|
||||||
|
* @return 0 in case of error or timeout, 1 in case of socket ready
|
||||||
|
*/
|
||||||
|
static int waittoread(int sock){
|
||||||
|
fd_set fds;
|
||||||
|
struct timeval timeout;
|
||||||
|
int rc;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 100;
|
||||||
|
FD_ZERO(&fds);
|
||||||
|
FD_SET(sock, &fds);
|
||||||
|
do{
|
||||||
|
rc = select(sock+1, &fds, NULL, NULL, &timeout);
|
||||||
|
if(rc < 0){
|
||||||
|
if(errno != EINTR){
|
||||||
|
WARN("select()");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}while(1);
|
||||||
|
if(FD_ISSET(sock, &fds)){
|
||||||
|
//DBG("FD_ISSET");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* read string from server, remove trailing '\n'
|
||||||
* @return NULL if nothing was read or pointer to static buffer
|
* @return NULL if nothing was read or pointer to static buffer
|
||||||
*/
|
*/
|
||||||
static char *read_string(){
|
static char *read_string(){
|
||||||
size_t r = 0, l;
|
|
||||||
static char buf[BUFLEN];
|
static char buf[BUFLEN];
|
||||||
int LL = BUFLEN - 1;
|
if(!waittoread(sock)) return NULL;
|
||||||
char *ptr = NULL;
|
int n = read(sock, buf, BUFLEN-1);
|
||||||
static char *optr = NULL;
|
if(n == 0){
|
||||||
if(optr && *optr){
|
LOGERR("UNIX-socket server disconnected");
|
||||||
ptr = optr;
|
ERRX("Server disconnected");
|
||||||
optr = strchr(optr, '\n');
|
|
||||||
if(optr) ++optr;
|
|
||||||
//DBG("got data, roll to next; ptr=%s\noptr=%s",ptr,optr);
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
ptr = buf;
|
buf[n] = 0;
|
||||||
double d0 = dtime();
|
if(buf[n-1] == '\n') buf[n-1] = 0;
|
||||||
do{
|
LOGDBG("SERIAL: %s", buf);
|
||||||
if((l = read_tty(ptr, LL))){
|
DBG("SERIAL: %s", buf);
|
||||||
r += l; LL -= l; ptr += l;
|
return buf;
|
||||||
if(ptr[-1] == '\n') break;
|
|
||||||
d0 = dtime();
|
|
||||||
}
|
|
||||||
}while(dtime() - d0 < WAIT_TMOUT && LL);
|
|
||||||
if(r){
|
|
||||||
buf[r] = 0;
|
|
||||||
//DBG("r=%zd, got string: %s", r, buf);
|
|
||||||
optr = strchr(buf, '\n');
|
|
||||||
if(optr) ++optr;
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to connect to `device` at BAUD_RATE speed
|
* Try to connect to UNIX socket `path`
|
||||||
* @return connection speed if success or 0
|
* @return FALSE if failed
|
||||||
*/
|
*/
|
||||||
void try_connect(char *device){
|
int try_connect(char *path){
|
||||||
if(!device) return;
|
if(!path) return FALSE;
|
||||||
char tmpbuf[4096];
|
struct sockaddr_un saddr = {0};
|
||||||
fflush(stdout);
|
saddr.sun_family = AF_UNIX;
|
||||||
tty_init(device);
|
strncpy(saddr.sun_path, path, 106); // if sun_path[0] == 0 we don't create a file
|
||||||
read_tty(tmpbuf, 4096); // clear rbuf
|
if((sock = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0){ // or SOCK_STREAM?
|
||||||
LOG("Connected to %s", device);
|
WARN("socket()");
|
||||||
}
|
LOGERR("socket()");
|
||||||
|
return FALSE;
|
||||||
/**
|
|
||||||
* run terminal emulation: send user's commands and show answers
|
|
||||||
*/
|
|
||||||
void run_terminal(){
|
|
||||||
green(_("Work in terminal mode without echo\n"));
|
|
||||||
int rb;
|
|
||||||
char buf[BUFLEN];
|
|
||||||
size_t l;
|
|
||||||
setup_con();
|
|
||||||
while(1){
|
|
||||||
if((l = read_tty(buf, BUFLEN - 1))){
|
|
||||||
buf[l] = 0;
|
|
||||||
printf("%s", buf);
|
|
||||||
}
|
|
||||||
if((rb = read_console())){
|
|
||||||
buf[0] = (char) rb;
|
|
||||||
write_tty(buf, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if(connect(sock, &saddr, sizeof(saddr)) == -1){
|
||||||
|
WARN("connect()");
|
||||||
|
LOGERR("connect()");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
LOGMSG("Connected to server");
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -172,18 +187,22 @@ static int send_cmd(int N, char cmd){
|
|||||||
// clear all incomint data
|
// clear all incomint data
|
||||||
while(read_string());
|
while(read_string());
|
||||||
DBG("send cmd %s", buf);
|
DBG("send cmd %s", buf);
|
||||||
if(write_tty(buf, n)) return 1;
|
if(n != send(sock, buf, n, 0)) return 1;
|
||||||
if(N == 0) return 0;
|
if(N == 0) return 0;
|
||||||
if((rtn = read_string())){
|
double t0 = dtime();
|
||||||
DBG("read_string: %s", rtn);
|
while(dtime() - t0 < T_POLLING_TMOUT){
|
||||||
if(*rtn == cmd) return 0;
|
if((rtn = read_string())){
|
||||||
|
DBG("read_string: %s", rtn);
|
||||||
|
if(*rtn == cmd) return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
DBG("No answer");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Poll sensor for new dataportion
|
* Poll sensor for new dataportion
|
||||||
* @param N - number of controller (1..7)
|
* @param N - number of controller (0..7)
|
||||||
* @return: 0 if no data received or controller is absent, number of data points if valid data received
|
* @return: 0 if no data received or controller is absent, number of data points if valid data received
|
||||||
*/
|
*/
|
||||||
int poll_sensors(int N){
|
int poll_sensors(int N){
|
||||||
@ -229,8 +248,12 @@ int check_sensors(){
|
|||||||
for(i = 1; i <= NCTRLR_MAX; ++i){
|
for(i = 1; i <= NCTRLR_MAX; ++i){
|
||||||
//red("i = %d\n", i);
|
//red("i = %d\n", i);
|
||||||
double t0 = dtime();
|
double t0 = dtime();
|
||||||
|
if(send_cmd(i, CMD_PING)){
|
||||||
|
usleep(100000);
|
||||||
|
--i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
while(dtime() - t0 < POLLING_TMOUT){
|
while(dtime() - t0 < POLLING_TMOUT){
|
||||||
if(send_cmd(i, CMD_PING)) continue;
|
|
||||||
if((ans = read_string())){
|
if((ans = read_string())){
|
||||||
//DBG("got: %s", ans);
|
//DBG("got: %s", ans);
|
||||||
if(0 == strncmp(ans, ANS_PONG, sizeof(ANS_PONG)-1)){
|
if(0 == strncmp(ans, ANS_PONG, sizeof(ANS_PONG)-1)){
|
||||||
@ -238,7 +261,7 @@ int check_sensors(){
|
|||||||
if(i == ans[sizeof(ANS_PONG)-1] - '0'){
|
if(i == ans[sizeof(ANS_PONG)-1] - '0'){
|
||||||
++found;
|
++found;
|
||||||
green(_("Found controller #%d\n"), i);
|
green(_("Found controller #%d\n"), i);
|
||||||
LOG("Found controller #%d", i);
|
LOGMSG("Found controller #%d", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,8 @@
|
|||||||
#ifndef __TERM_H__
|
#ifndef __TERM_H__
|
||||||
#define __TERM_H__
|
#define __TERM_H__
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "sens_place.h" // NCTRLR
|
#include "sens_place.h" // NCTRLR
|
||||||
|
|
||||||
// Terminal timeout (seconds)
|
// Terminal timeout (seconds)
|
||||||
@ -56,8 +58,7 @@ typedef enum{
|
|||||||
TRANS_TIMEOUT // no data in WAIT_TMOUT
|
TRANS_TIMEOUT // no data in WAIT_TMOUT
|
||||||
} trans_status;
|
} trans_status;
|
||||||
|
|
||||||
void run_terminal();
|
int try_connect(char *path);
|
||||||
void try_connect(char *device);
|
|
||||||
int poll_sensors(int N);
|
int poll_sensors(int N);
|
||||||
int check_sensors();
|
int check_sensors();
|
||||||
void turn_all_off();
|
void turn_all_off();
|
||||||
|
|||||||
@ -1,593 +0,0 @@
|
|||||||
/*
|
|
||||||
* usefull_macros.h - a set of usefull functions: memory, color etc
|
|
||||||
*
|
|
||||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
*
|
|
||||||
* This program 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 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "usefull_macros.h"
|
|
||||||
#include <time.h>
|
|
||||||
#include <linux/limits.h> // PATH_MAX
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* function for different purposes that need to know time intervals
|
|
||||||
* @return double value: time in seconds
|
|
||||||
*/
|
|
||||||
double dtime(){
|
|
||||||
double t;
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************\
|
|
||||||
* Coloured terminal
|
|
||||||
\******************************************************************************/
|
|
||||||
int globErr = 0; // errno for WARN/ERR
|
|
||||||
|
|
||||||
// pointers to coloured output printf
|
|
||||||
int (*red)(const char *fmt, ...);
|
|
||||||
int (*green)(const char *fmt, ...);
|
|
||||||
int (*_WARN)(const char *fmt, ...);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* format red / green messages
|
|
||||||
* name: r_pr_, g_pr_
|
|
||||||
* @param fmt ... - printf-like format
|
|
||||||
* @return number of printed symbols
|
|
||||||
*/
|
|
||||||
int r_pr_(const char *fmt, ...){
|
|
||||||
va_list ar; int i;
|
|
||||||
printf(RED);
|
|
||||||
va_start(ar, fmt);
|
|
||||||
i = vprintf(fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
printf(OLDCOLOR);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
int g_pr_(const char *fmt, ...){
|
|
||||||
va_list ar; int i;
|
|
||||||
printf(GREEN);
|
|
||||||
va_start(ar, fmt);
|
|
||||||
i = vprintf(fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
printf(OLDCOLOR);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* print red error/warning messages (if output is a tty)
|
|
||||||
* @param fmt ... - printf-like format
|
|
||||||
* @return number of printed symbols
|
|
||||||
*/
|
|
||||||
int r_WARN(const char *fmt, ...){
|
|
||||||
va_list ar; int i = 1;
|
|
||||||
fprintf(stderr, RED);
|
|
||||||
va_start(ar, fmt);
|
|
||||||
if(globErr){
|
|
||||||
errno = globErr;
|
|
||||||
vwarn(fmt, ar);
|
|
||||||
errno = 0;
|
|
||||||
}else
|
|
||||||
i = vfprintf(stderr, fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
i++;
|
|
||||||
fprintf(stderr, OLDCOLOR "\n");
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char stars[] = "****************************************";
|
|
||||||
/*
|
|
||||||
* notty variants of coloured printf
|
|
||||||
* name: s_WARN, r_pr_notty
|
|
||||||
* @param fmt ... - printf-like format
|
|
||||||
* @return number of printed symbols
|
|
||||||
*/
|
|
||||||
int s_WARN(const char *fmt, ...){
|
|
||||||
va_list ar; int i;
|
|
||||||
i = fprintf(stderr, "\n%s\n", stars);
|
|
||||||
va_start(ar, fmt);
|
|
||||||
if(globErr){
|
|
||||||
errno = globErr;
|
|
||||||
vwarn(fmt, ar);
|
|
||||||
errno = 0;
|
|
||||||
}else
|
|
||||||
i = +vfprintf(stderr, fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
i += fprintf(stderr, "\n%s\n", stars);
|
|
||||||
i += fprintf(stderr, "\n");
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
int r_pr_notty(const char *fmt, ...){
|
|
||||||
va_list ar; int i;
|
|
||||||
i = printf("\n%s\n", stars);
|
|
||||||
va_start(ar, fmt);
|
|
||||||
i += vprintf(fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
i += printf("\n%s\n", stars);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run this function in the beginning of main() to setup locale & coloured output
|
|
||||||
*/
|
|
||||||
void initial_setup(){
|
|
||||||
// setup coloured output
|
|
||||||
if(isatty(STDOUT_FILENO)){ // make color output in tty
|
|
||||||
red = r_pr_; green = g_pr_;
|
|
||||||
}else{ // no colors in case of pipe
|
|
||||||
red = r_pr_notty; green = printf;
|
|
||||||
}
|
|
||||||
if(isatty(STDERR_FILENO)) _WARN = r_WARN;
|
|
||||||
else _WARN = s_WARN;
|
|
||||||
// Setup locale
|
|
||||||
setlocale(LC_ALL, "");
|
|
||||||
setlocale(LC_NUMERIC, "C");
|
|
||||||
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
|
|
||||||
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
|
|
||||||
textdomain(GETTEXT_PACKAGE);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************\
|
|
||||||
* Memory
|
|
||||||
\******************************************************************************/
|
|
||||||
/*
|
|
||||||
* safe memory allocation for macro ALLOC
|
|
||||||
* @param N - number of elements to allocate
|
|
||||||
* @param S - size of single element (typically sizeof)
|
|
||||||
* @return pointer to allocated memory area
|
|
||||||
*/
|
|
||||||
void *my_alloc(size_t N, size_t S){
|
|
||||||
void *p = calloc(N, S);
|
|
||||||
if(!p) ERR("malloc");
|
|
||||||
//assert(p);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mmap file to a memory area
|
|
||||||
*
|
|
||||||
* @param filename (i) - name of file to mmap
|
|
||||||
* @return stuct with mmap'ed file or die
|
|
||||||
*/
|
|
||||||
mmapbuf *My_mmap(char *filename){
|
|
||||||
int fd;
|
|
||||||
char *ptr;
|
|
||||||
size_t Mlen;
|
|
||||||
struct stat statbuf;
|
|
||||||
/// "îÅ ÚÁÄÁÎÏ ÉÍÑ ÆÁÊÌÁ!"
|
|
||||||
if(!filename){
|
|
||||||
WARNX(_("No filename given!"));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if((fd = open(filename, O_RDONLY)) < 0){
|
|
||||||
/// "îÅ ÍÏÇÕ ÏÔËÒÙÔØ %s ÄÌÑ ÞÔÅÎÉÑ"
|
|
||||||
WARN(_("Can't open %s for reading"), filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if(fstat (fd, &statbuf) < 0){
|
|
||||||
/// "îÅ ÍÏÇÕ ×ÙÐÏÌÎÉÔØ stat %s"
|
|
||||||
WARN(_("Can't stat %s"), filename);
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
Mlen = statbuf.st_size;
|
|
||||||
if((ptr = mmap (0, Mlen, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED){
|
|
||||||
/// "ïÛÉÂËÁ mmap"
|
|
||||||
WARN(_("Mmap error for input"));
|
|
||||||
close(fd);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
/// "îÅ ÍÏÇÕ ÚÁËÒÙÔØ mmap'ÎÕÔÙÊ ÆÁÊÌ"
|
|
||||||
if(close(fd)) WARN(_("Can't close mmap'ed file"));
|
|
||||||
mmapbuf *ret = MALLOC(mmapbuf, 1);
|
|
||||||
ret->data = ptr;
|
|
||||||
ret->len = Mlen;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void My_munmap(mmapbuf *b){
|
|
||||||
if(munmap(b->data, b->len)){
|
|
||||||
/// "îÅ ÍÏÇÕ munmap"
|
|
||||||
WARN(_("Can't munmap"));
|
|
||||||
}
|
|
||||||
FREE(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************\
|
|
||||||
* Terminal in no-echo mode
|
|
||||||
\******************************************************************************/
|
|
||||||
static struct termios oldt, newt; // terminal flags
|
|
||||||
static int console_changed = 0;
|
|
||||||
// run on exit:
|
|
||||||
void restore_console(){
|
|
||||||
if(console_changed)
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
|
|
||||||
console_changed = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// initial setup:
|
|
||||||
void setup_con(){
|
|
||||||
if(console_changed) return;
|
|
||||||
tcgetattr(STDIN_FILENO, &oldt);
|
|
||||||
newt = oldt;
|
|
||||||
newt.c_lflag &= ~(ICANON | ECHO);
|
|
||||||
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
|
|
||||||
/// "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ"
|
|
||||||
WARN(_("Can't setup console"));
|
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
|
|
||||||
signals(0); //quit?
|
|
||||||
}
|
|
||||||
console_changed = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read character from console without echo
|
|
||||||
* @return char readed
|
|
||||||
*/
|
|
||||||
int read_console(){
|
|
||||||
int rb;
|
|
||||||
struct timeval tv;
|
|
||||||
int retval;
|
|
||||||
fd_set rfds;
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(STDIN_FILENO, &rfds);
|
|
||||||
tv.tv_sec = 0; tv.tv_usec = 10000;
|
|
||||||
retval = select(1, &rfds, NULL, NULL, &tv);
|
|
||||||
if(!retval) rb = 0;
|
|
||||||
else {
|
|
||||||
if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
|
|
||||||
else rb = 0;
|
|
||||||
}
|
|
||||||
return rb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* getchar() without echo
|
|
||||||
* wait until at least one character pressed
|
|
||||||
* @return character readed
|
|
||||||
*/
|
|
||||||
int mygetchar(){ // getchar() without need of pressing ENTER
|
|
||||||
int ret;
|
|
||||||
do ret = read_console();
|
|
||||||
while(ret == 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************\
|
|
||||||
* TTY with select()
|
|
||||||
\******************************************************************************/
|
|
||||||
static struct termio oldtty, tty; // TTY flags
|
|
||||||
static int comfd = -1; // TTY fd
|
|
||||||
|
|
||||||
// run on exit:
|
|
||||||
void restore_tty(){
|
|
||||||
if(comfd == -1) return;
|
|
||||||
ioctl(comfd, TCSANOW, &oldtty ); // return TTY to previous state
|
|
||||||
close(comfd);
|
|
||||||
comfd = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef BAUD_RATE
|
|
||||||
#define BAUD_RATE B9600
|
|
||||||
#endif
|
|
||||||
// init:
|
|
||||||
void tty_init(char *comdev){
|
|
||||||
DBG("\nOpen port %s ...", comdev);
|
|
||||||
do{
|
|
||||||
comfd = open(comdev,O_RDWR|O_NOCTTY|O_NONBLOCK);
|
|
||||||
}while (comfd == -1 && errno == EINTR);
|
|
||||||
if(comfd < 0){
|
|
||||||
WARN("Can't use port %s",comdev);
|
|
||||||
signals(-1); // quit?
|
|
||||||
}
|
|
||||||
// make exclusive open
|
|
||||||
if(ioctl(comfd, TIOCEXCL)){
|
|
||||||
WARN(_("Can't do exclusive open"));
|
|
||||||
close(comfd);
|
|
||||||
signals(2);
|
|
||||||
}
|
|
||||||
DBG(" OK\nGet current settings... ");
|
|
||||||
if(ioctl(comfd,TCGETA,&oldtty) < 0){ // Get settings
|
|
||||||
/// "îÅ ÍÏÇÕ ÐÏÌÕÞÉÔØ ÎÁÓÔÒÏÊËÉ"
|
|
||||||
WARN(_("Can't get settings"));
|
|
||||||
signals(-1);
|
|
||||||
}
|
|
||||||
tty = oldtty;
|
|
||||||
tty.c_lflag = 0; // ~(ICANON | ECHO | ECHOE | ISIG)
|
|
||||||
tty.c_oflag = 0;
|
|
||||||
tty.c_cflag = BAUD_RATE|CS8|CREAD|CLOCAL; // 9.6k, 8N1, RW, ignore line ctrl
|
|
||||||
tty.c_cc[VMIN] = 0; // non-canonical mode
|
|
||||||
tty.c_cc[VTIME] = 5;
|
|
||||||
if(ioctl(comfd,TCSETA,&tty) < 0){
|
|
||||||
/// "îÅ ÍÏÇÕ ÕÓÔÁÎÏ×ÉÔØ ÎÁÓÔÒÏÊËÉ"
|
|
||||||
WARN(_("Can't set settings"));
|
|
||||||
signals(-1);
|
|
||||||
}
|
|
||||||
DBG(" OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read data from TTY
|
|
||||||
* @param buff (o) - buffer for data read
|
|
||||||
* @param length - buffer len
|
|
||||||
* @return amount of bytes read
|
|
||||||
*/
|
|
||||||
size_t read_tty(char *buff, size_t length){
|
|
||||||
ssize_t L = 0, l;
|
|
||||||
char *ptr = buff;
|
|
||||||
fd_set rfds;
|
|
||||||
struct timeval tv;
|
|
||||||
int retval;
|
|
||||||
do{
|
|
||||||
l = 0;
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_SET(comfd, &rfds);
|
|
||||||
// wait for 100ms
|
|
||||||
tv.tv_sec = 0; tv.tv_usec = 100000;
|
|
||||||
retval = select(comfd + 1, &rfds, NULL, NULL, &tv);
|
|
||||||
if (retval < 1) break; // retval == 0 if there's no data, retval == 1 for EINTR
|
|
||||||
if(FD_ISSET(comfd, &rfds)){
|
|
||||||
if((l = read(comfd, ptr, length)) < 1){
|
|
||||||
//return 0;
|
|
||||||
ERR("USB disconnected!");
|
|
||||||
}
|
|
||||||
ptr += l; L += l;
|
|
||||||
length -= l;
|
|
||||||
}
|
|
||||||
}while(l);
|
|
||||||
return (size_t)L;
|
|
||||||
}
|
|
||||||
|
|
||||||
int write_tty(char *buff, size_t length){
|
|
||||||
ssize_t L = write(comfd, buff, length);
|
|
||||||
if((size_t)L != length){
|
|
||||||
/// "ïÛÉÂËÁ ÚÁÐÉÓÉ!"
|
|
||||||
ERR("Write error");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Safely convert data from string to double
|
|
||||||
*
|
|
||||||
* @param num (o) - double number read from string
|
|
||||||
* @param str (i) - input string
|
|
||||||
* @return 1 if success, 0 if fails
|
|
||||||
*/
|
|
||||||
int str2double(double *num, const char *str){
|
|
||||||
double res;
|
|
||||||
char *endptr;
|
|
||||||
if(!str) return 0;
|
|
||||||
res = strtod(str, &endptr);
|
|
||||||
if(endptr == str || *str == '\0' || *endptr != '\0'){
|
|
||||||
/// "îÅÐÒÁ×ÉÌØÎÙÊ ÆÏÒÍÁÔ ÞÉÓÌÁ double!"
|
|
||||||
WARNX("Wrong double number format!");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if(num) *num = res; // you may run it like myatod(NULL, str) to test wether str is double number
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////// logging
|
|
||||||
|
|
||||||
static Cl_log log = {0};
|
|
||||||
/**
|
|
||||||
* @brief Cl_createlog - create log file: init mutex, test file open ability
|
|
||||||
* @param log - log structure
|
|
||||||
* @return 0 if all OK
|
|
||||||
*/
|
|
||||||
int Cl_createlog(char *logname){
|
|
||||||
if(log.logpath){
|
|
||||||
FREE(log.logpath);
|
|
||||||
pthread_mutex_destroy(&log.mutex);
|
|
||||||
}
|
|
||||||
FILE *logfd = fopen(logname, "a");
|
|
||||||
if(!logfd){
|
|
||||||
WARN("Can't open log file");
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
log.logpath = strdup(logname);
|
|
||||||
fclose(logfd);
|
|
||||||
if(pthread_mutex_init(&log.mutex, NULL)){
|
|
||||||
WARN("Can't init log mutes");
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cl_putlog - put message to log file with/without timestamp
|
|
||||||
* @param timest - ==1 to put timestamp
|
|
||||||
* @param log - pointer to log structure
|
|
||||||
* @param lvl - message loglevel (if lvl > loglevel, message won't be printed)
|
|
||||||
* @param fmt - format and the rest part of message
|
|
||||||
* @return amount of symbols saved in file
|
|
||||||
*/
|
|
||||||
int Cl_putlogt(const char *fmt, ...){
|
|
||||||
if(pthread_mutex_lock(&log.mutex)){
|
|
||||||
WARN("Can't lock log mutex");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
int i = 0;
|
|
||||||
FILE *logfd = fopen(log.logpath, "a");
|
|
||||||
if(!logfd) goto rtn;
|
|
||||||
char strtm[128];
|
|
||||||
time_t t = time(NULL);
|
|
||||||
struct tm *curtm = localtime(&t);
|
|
||||||
strftime(strtm, 128, "%Y/%m/%d-%H:%M:%S", curtm);
|
|
||||||
i = fprintf(logfd, "%s\t", strtm);
|
|
||||||
va_list ar;
|
|
||||||
va_start(ar, fmt);
|
|
||||||
i += vfprintf(logfd, fmt, ar);
|
|
||||||
va_end(ar);
|
|
||||||
i += fprintf(logfd, "\n");
|
|
||||||
fclose(logfd);
|
|
||||||
rtn:
|
|
||||||
pthread_mutex_unlock(&log.mutex);
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 1988, 1993, 1994, 2017
|
|
||||||
* The Regents of the University of California. All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions
|
|
||||||
* are met:
|
|
||||||
* 1. Redistributions of source code must retain the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3. All advertising materials mentioning features or use of this software
|
|
||||||
* must display the following acknowledgement:
|
|
||||||
* This product includes software developed by the University of
|
|
||||||
* California, Berkeley and its contributors.
|
|
||||||
* 4. Neither the name of the University nor the names of its contributors
|
|
||||||
* may be used to endorse or promote products derived from this software
|
|
||||||
* without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
||||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
|
||||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
||||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
||||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
||||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
||||||
* SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* 2017-10-14 Niklas Hamb?chen <mail@nh2.me>
|
|
||||||
* - Extracted signal names mapping from kill.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Sami Kerola <kerolasa@iki.fi>
|
|
||||||
* Copyright (C) 2014 Karel Zak <kzak@redhat.com>
|
|
||||||
* Copyright (C) 2017 Niklas Hamb?chen <mail@nh2.me>
|
|
||||||
*/
|
|
||||||
|
|
||||||
// https://github.com/karelzak/util-linux/blob/master/lib/signames.c
|
|
||||||
static const struct ul_signal_name {
|
|
||||||
const char *name;
|
|
||||||
int val;
|
|
||||||
} ul_signames[] = {
|
|
||||||
/* POSIX signals */
|
|
||||||
{ "HUP", SIGHUP }, /* 1 */
|
|
||||||
{ "INT", SIGINT }, /* 2 */
|
|
||||||
{ "QUIT", SIGQUIT }, /* 3 */
|
|
||||||
{ "ILL", SIGILL }, /* 4 */
|
|
||||||
#ifdef SIGTRAP
|
|
||||||
{ "TRAP", SIGTRAP }, /* 5 */
|
|
||||||
#endif
|
|
||||||
{ "ABRT", SIGABRT }, /* 6 */
|
|
||||||
#ifdef SIGIOT
|
|
||||||
{ "IOT", SIGIOT }, /* 6, same as SIGABRT */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGEMT
|
|
||||||
{ "EMT", SIGEMT }, /* 7 (mips,alpha,sparc*) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGBUS
|
|
||||||
{ "BUS", SIGBUS }, /* 7 (arm,i386,m68k,ppc), 10 (mips,alpha,sparc*) */
|
|
||||||
#endif
|
|
||||||
{ "FPE", SIGFPE }, /* 8 */
|
|
||||||
{ "KILL", SIGKILL }, /* 9 */
|
|
||||||
{ "USR1", SIGUSR1 }, /* 10 (arm,i386,m68k,ppc), 30 (alpha,sparc*), 16 (mips) */
|
|
||||||
{ "SEGV", SIGSEGV }, /* 11 */
|
|
||||||
{ "USR2", SIGUSR2 }, /* 12 (arm,i386,m68k,ppc), 31 (alpha,sparc*), 17 (mips) */
|
|
||||||
{ "PIPE", SIGPIPE }, /* 13 */
|
|
||||||
{ "ALRM", SIGALRM }, /* 14 */
|
|
||||||
{ "TERM", SIGTERM }, /* 15 */
|
|
||||||
#ifdef SIGSTKFLT
|
|
||||||
{ "STKFLT", SIGSTKFLT }, /* 16 (arm,i386,m68k,ppc) */
|
|
||||||
#endif
|
|
||||||
{ "CHLD", SIGCHLD }, /* 17 (arm,i386,m68k,ppc), 20 (alpha,sparc*), 18 (mips) */
|
|
||||||
#ifdef SIGCLD
|
|
||||||
{ "CLD", SIGCLD }, /* same as SIGCHLD (mips) */
|
|
||||||
#endif
|
|
||||||
{ "CONT", SIGCONT }, /* 18 (arm,i386,m68k,ppc), 19 (alpha,sparc*), 25 (mips) */
|
|
||||||
{ "STOP", SIGSTOP }, /* 19 (arm,i386,m68k,ppc), 17 (alpha,sparc*), 23 (mips) */
|
|
||||||
{ "TSTP", SIGTSTP }, /* 20 (arm,i386,m68k,ppc), 18 (alpha,sparc*), 24 (mips) */
|
|
||||||
{ "TTIN", SIGTTIN }, /* 21 (arm,i386,m68k,ppc,alpha,sparc*), 26 (mips) */
|
|
||||||
{ "TTOU", SIGTTOU }, /* 22 (arm,i386,m68k,ppc,alpha,sparc*), 27 (mips) */
|
|
||||||
#ifdef SIGURG
|
|
||||||
{ "URG", SIGURG }, /* 23 (arm,i386,m68k,ppc), 16 (alpha,sparc*), 21 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGXCPU
|
|
||||||
{ "XCPU", SIGXCPU }, /* 24 (arm,i386,m68k,ppc,alpha,sparc*), 30 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGXFSZ
|
|
||||||
{ "XFSZ", SIGXFSZ }, /* 25 (arm,i386,m68k,ppc,alpha,sparc*), 31 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGVTALRM
|
|
||||||
{ "VTALRM", SIGVTALRM }, /* 26 (arm,i386,m68k,ppc,alpha,sparc*), 28 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGPROF
|
|
||||||
{ "PROF", SIGPROF }, /* 27 (arm,i386,m68k,ppc,alpha,sparc*), 29 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGWINCH
|
|
||||||
{ "WINCH", SIGWINCH }, /* 28 (arm,i386,m68k,ppc,alpha,sparc*), 20 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGIO
|
|
||||||
{ "IO", SIGIO }, /* 29 (arm,i386,m68k,ppc), 23 (alpha,sparc*), 22 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGPOLL
|
|
||||||
{ "POLL", SIGPOLL }, /* same as SIGIO */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGINFO
|
|
||||||
{ "INFO", SIGINFO }, /* 29 (alpha) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGLOST
|
|
||||||
{ "LOST", SIGLOST }, /* 29 (arm,i386,m68k,ppc,sparc*) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGPWR
|
|
||||||
{ "PWR", SIGPWR }, /* 30 (arm,i386,m68k,ppc), 29 (alpha,sparc*), 19 (mips) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGUNUSED
|
|
||||||
{ "UNUSED", SIGUNUSED }, /* 31 (arm,i386,m68k,ppc) */
|
|
||||||
#endif
|
|
||||||
#ifdef SIGSYS
|
|
||||||
{ "SYS", SIGSYS }, /* 31 (mips,alpha,sparc*) */
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
const char *signum_to_signame(int signum){
|
|
||||||
size_t n;
|
|
||||||
static char buf[32];
|
|
||||||
if(signum < 1) return NULL;
|
|
||||||
#if defined SIGRTMIN && defined SIGRTMAX
|
|
||||||
if(signum >= SIGRTMIN && signum <= SIGRTMAX){
|
|
||||||
snprintf(buf, 32, "SIGRT%d", signum - SIGRTMIN);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
for (n = 0; n < ARRAY_SIZE(ul_signames); n++) {
|
|
||||||
if(ul_signames[n].val == signum){
|
|
||||||
snprintf(buf, 32, "SIG%s", ul_signames[n].name);
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
/*
|
|
||||||
* usefull_macros.h - a set of usefull macros: memory, color etc
|
|
||||||
*
|
|
||||||
* Copyright 2013 Edward V. Emelianoff <eddy@sao.ru>
|
|
||||||
*
|
|
||||||
* This program 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 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#ifndef __USEFULL_MACROS_H__
|
|
||||||
#define __USEFULL_MACROS_H__
|
|
||||||
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/mman.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <err.h>
|
|
||||||
#include <locale.h>
|
|
||||||
#if defined GETTEXT_PACKAGE && defined LOCALEDIR
|
|
||||||
/*
|
|
||||||
* GETTEXT
|
|
||||||
*/
|
|
||||||
#include <libintl.h>
|
|
||||||
#define _(String) gettext(String)
|
|
||||||
#define gettext_noop(String) String
|
|
||||||
#define N_(String) gettext_noop(String)
|
|
||||||
#else
|
|
||||||
#define _(String) (String)
|
|
||||||
#define N_(String) (String)
|
|
||||||
#endif
|
|
||||||
#include <pthread.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <termio.h>
|
|
||||||
#include <termios.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
|
|
||||||
// unused arguments with -Wall -Werror
|
|
||||||
#define _U_ __attribute__((__unused__))
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Coloured messages output
|
|
||||||
*/
|
|
||||||
#define RED "\033[1;31;40m"
|
|
||||||
#define GREEN "\033[1;32;40m"
|
|
||||||
#define OLDCOLOR "\033[0;0;0m"
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE (0)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE (1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* ERROR/WARNING messages
|
|
||||||
*/
|
|
||||||
extern int globErr;
|
|
||||||
extern void signals(int sig);
|
|
||||||
#define ERR(...) do{globErr=errno; Cl_putlogt(__VA_ARGS__); _WARN(__VA_ARGS__); signals(9);}while(0)
|
|
||||||
#define ERRX(...) do{globErr=0; Cl_putlogt(__VA_ARGS__); _WARN(__VA_ARGS__); signals(9);}while(0)
|
|
||||||
#define WARN(...) do{globErr=errno; Cl_putlogt(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0)
|
|
||||||
#define WARNX(...) do{globErr=0; Cl_putlogt(__VA_ARGS__); _WARN(__VA_ARGS__);}while(0)
|
|
||||||
#define LOG(...) do{Cl_putlogt(__VA_ARGS__); }while(0)
|
|
||||||
/*
|
|
||||||
* print function name, debug messages
|
|
||||||
* debug mode, -DEBUG
|
|
||||||
*/
|
|
||||||
#ifdef EBUG
|
|
||||||
#define FNAME() printf("\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
|
|
||||||
#define DBG(...) do{printf("%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
|
|
||||||
printf(__VA_ARGS__); printf("\n");} while(0)
|
|
||||||
#else
|
|
||||||
#define FNAME() do{}while(0)
|
|
||||||
#define DBG(...) do{}while(0)
|
|
||||||
#endif //EBUG
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Memory allocation
|
|
||||||
*/
|
|
||||||
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
|
|
||||||
#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
|
|
||||||
#define FREE(ptr) do{if(ptr){free(ptr); ptr = NULL;}}while(0)
|
|
||||||
|
|
||||||
#ifndef DBL_EPSILON
|
|
||||||
#define DBL_EPSILON (2.2204460492503131e-16)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
double dtime();
|
|
||||||
|
|
||||||
// functions for color output in tty & no-color in pipes
|
|
||||||
extern int (*red)(const char *fmt, ...);
|
|
||||||
extern int (*_WARN)(const char *fmt, ...);
|
|
||||||
extern int (*green)(const char *fmt, ...);
|
|
||||||
void * my_alloc(size_t N, size_t S);
|
|
||||||
void initial_setup();
|
|
||||||
|
|
||||||
// mmap file
|
|
||||||
typedef struct{
|
|
||||||
char *data;
|
|
||||||
size_t len;
|
|
||||||
} mmapbuf;
|
|
||||||
mmapbuf *My_mmap(char *filename);
|
|
||||||
void My_munmap(mmapbuf *b);
|
|
||||||
|
|
||||||
void restore_console();
|
|
||||||
void setup_con();
|
|
||||||
int read_console();
|
|
||||||
int mygetchar();
|
|
||||||
|
|
||||||
void restore_tty();
|
|
||||||
void tty_init(char *comdev);
|
|
||||||
size_t read_tty(char *buff, size_t length);
|
|
||||||
int write_tty(char *buff, size_t length);
|
|
||||||
|
|
||||||
int str2double(double *num, const char *str);
|
|
||||||
|
|
||||||
typedef struct{
|
|
||||||
char *logpath; // full path to logfile
|
|
||||||
pthread_mutex_t mutex; // log mutex
|
|
||||||
} Cl_log;
|
|
||||||
|
|
||||||
int Cl_createlog(char *logname);
|
|
||||||
int Cl_putlogt(const char *fmt, ...);
|
|
||||||
|
|
||||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
||||||
const char *signum_to_signame(int signum);
|
|
||||||
#endif // __USEFULL_MACROS_H__
|
|
||||||
1021
src/netdaemon/www/T.html
Normal file
1021
src/netdaemon/www/T.html
Normal file
File diff suppressed because it is too large
Load Diff
45
src/netdaemon/www/T0
Normal file
45
src/netdaemon/www/T0
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
19 -7 -2.85
|
||||||
|
17 -22 -2.99
|
||||||
|
15 -13 -2.92
|
||||||
|
22 -17 -2.80
|
||||||
|
25 -10 -2.81
|
||||||
|
27 -4 -2.73
|
||||||
|
27 4 -2.66
|
||||||
|
25 10 -2.58
|
||||||
|
10 25 -2.66
|
||||||
|
17 22 -2.69
|
||||||
|
-10 -25 -3.02
|
||||||
|
-4 -27 -3.11
|
||||||
|
-3 -20 -3.09
|
||||||
|
-10 -17 -3.03
|
||||||
|
-15 -13 -2.94
|
||||||
|
-19 -7 -2.84
|
||||||
|
-20 0 -2.78
|
||||||
|
-19 7 -2.84
|
||||||
|
-15 13 -2.83
|
||||||
|
-10 17 -2.76
|
||||||
|
-3 20 -2.75
|
||||||
|
3 20 -2.79
|
||||||
|
10 17 -2.76
|
||||||
|
9 9 -2.74
|
||||||
|
3 13 -2.73
|
||||||
|
-9 9 -2.76
|
||||||
|
-3 13 -2.70
|
||||||
|
-13 3 -2.77
|
||||||
|
-13 -3 -2.82
|
||||||
|
-9 -9 -2.86
|
||||||
|
-3 -13 -2.94
|
||||||
|
3 -13 -2.90
|
||||||
|
3 -20 -3.03
|
||||||
|
4 -27 -3.08
|
||||||
|
10 -17 -3.02
|
||||||
|
10 -25 -2.97
|
||||||
|
9 -9 -2.85
|
||||||
|
3 -5 -2.80
|
||||||
|
-3 -5 -2.81
|
||||||
|
-6 0 -2.75
|
||||||
|
-3 5 -2.78
|
||||||
|
3 5 -2.66
|
||||||
|
6 0 -2.73
|
||||||
|
13 -3 -2.73
|
||||||
|
13 3 -2.67
|
||||||
55395
src/netdaemon/www/T0.html
Normal file
55395
src/netdaemon/www/T0.html
Normal file
File diff suppressed because it is too large
Load Diff
14
src/netdaemon/www/T1
Normal file
14
src/netdaemon/www/T1
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
17 -10 -2.46
|
||||||
|
24 -14 -2.01
|
||||||
|
-17 -10 -2.50
|
||||||
|
-17 10 -2.44
|
||||||
|
0 20 -2.38
|
||||||
|
11 7 -2.40
|
||||||
|
0 13 -2.36
|
||||||
|
-11 7 -2.41
|
||||||
|
-11 -7 -2.47
|
||||||
|
0 -13 -2.56
|
||||||
|
0 -20 -2.56
|
||||||
|
0 -27 -2.34
|
||||||
|
11 -7 -2.48
|
||||||
|
0 -6 -2.52
|
||||||
54820
src/netdaemon/www/T1.html
Normal file
54820
src/netdaemon/www/T1.html
Normal file
File diff suppressed because it is too large
Load Diff
20
src/netdaemon/www/index.html
Normal file
20
src/netdaemon/www/index.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=koi8-r">
|
||||||
|
<title>Mirror temperatures main controller</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>çÒÁÆÉËÉ ÔÅÍÐÅÒÁÔÕÒ:</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="T0.html">×ÅÒÈÎÉÊ ÓÌÏÊ ÚÅÒËÁÌÁ</a>;</li>
|
||||||
|
<li><a href="T1.html">ÎÉÖÎÑÑ ÐÏ×ÅÒÈÎÏÓÔØ</a>;</li>
|
||||||
|
<!--li><a href="Tgrad.html">ÇÒÁÄÉÅÎÔ</a> (×ÅÒÈ ÍÉÎÕÓ ÎÉÚ).</li-->
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="position: absolute; top: 1px; right: 1px;">
|
||||||
|
\copyright åÍÅÌØÑÎÏ× ü.÷., eddy@sao.ru
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
108
src/netdaemon/www/js/README
Normal file
108
src/netdaemon/www/js/README
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
Notes on using the gnuplot canvas terminal driver to create web pages
|
||||||
|
=====================================================================
|
||||||
|
|
||||||
|
|
||||||
|
1) Using UTF-8 characters in your plots
|
||||||
|
|
||||||
|
I expect that eventually web browsers will learn to draw text onto the HTML
|
||||||
|
canvas element using their native font-handling code. But until then we
|
||||||
|
have to refer to an external character drawing library.
|
||||||
|
|
||||||
|
The gnuplot package includes two versions of a script to draw characters on
|
||||||
|
the canvas. The first one, canvastext.js, was written by Jim Studt. It only
|
||||||
|
knows about the 7-bit ascii characters. The second one, canvasmath.js, is
|
||||||
|
an expanded version of Jim Studt's script that I wrote to handle UTF8.
|
||||||
|
It contains glyphs for the first two unicode code pages (latin-1), the greek
|
||||||
|
alphabet, and select math and physics symbols. You can use this to replace
|
||||||
|
canvastext.js if you like, or refer to it explicitly in plots that need
|
||||||
|
non-ascii characters.
|
||||||
|
|
||||||
|
|
||||||
|
2) Browser dependencies
|
||||||
|
|
||||||
|
As of this time (May 2009) the HTML canvas element is supported by the
|
||||||
|
latest versions of Opera, Safari, Firefox, and Konqueror. However, each
|
||||||
|
of these has quirks.
|
||||||
|
|
||||||
|
For instance, only Firefox makes it easy to click and drag with the middle
|
||||||
|
or right mouse buttons; the other browsers try to pop up various menus instead.
|
||||||
|
We try to override this, but it doesn't always work.
|
||||||
|
|
||||||
|
Conversely, Opera and Safari make it easy to use hot keys ('e' for refresh,
|
||||||
|
'r' to toggle the ruler, etc), but I have not managed to get this to work
|
||||||
|
in Firefox.
|
||||||
|
|
||||||
|
If you run into problems, please try several browsers before concluding that it
|
||||||
|
is a gnuplot problem. If you figure out a work-around for one of these browser
|
||||||
|
quirks, please tell me so that we can try to incorporate into gnuplot output.
|
||||||
|
|
||||||
|
|
||||||
|
3) Creating a basic web page with a single mouseable plot
|
||||||
|
|
||||||
|
The canvas terminal driver itself will create a basic html document containing
|
||||||
|
a mousable plot. The command options to do this are
|
||||||
|
set term canvas standalone mousing jsdir "http://myserver"
|
||||||
|
set output 'myplot.html'
|
||||||
|
This document contains
|
||||||
|
- a reference to style sheet gnuplot_mouse.css
|
||||||
|
- a reference to support script gnuplot_mouse.js
|
||||||
|
- a javascript function named 'gnuplot_canvas'
|
||||||
|
- a canvas element named 'gnuplot_canvas' that will be drawn in by the
|
||||||
|
javascript function of the same name
|
||||||
|
- an html table containing the readout for mouse coordinates, as well
|
||||||
|
as clickable icons for additional mousing operations
|
||||||
|
The *.css and *.js references point back to whatever source URL you specified
|
||||||
|
in the jsdir option to the 'set term' command. For example:
|
||||||
|
<link type="text/css" href="http://myserver/gnuplot_mouse.css" rel="stylesheet">
|
||||||
|
In order for viewers to use your plot document, they must be able to access the
|
||||||
|
*.css and *.js files via the URL embedded in the document.
|
||||||
|
|
||||||
|
|
||||||
|
4) Creating a web page with multiple mouseable plots
|
||||||
|
|
||||||
|
In order to embed multiple plots in a single document, you must
|
||||||
|
provide your own html framework. You can use the one created by the canvas
|
||||||
|
driver in standalone mode as a starting point, including the references to
|
||||||
|
gnuplot_mouse.css and gnuplot_mouse.js. However, instead of a single
|
||||||
|
javascript routine named gnuplot_canvas() that always draws the same plot,
|
||||||
|
you must provide a wrapper routine with the same name that connects the
|
||||||
|
mousing code to whichever plot is currently active. Here is an example:
|
||||||
|
- create the individual plots as separate javascript files
|
||||||
|
set term canvas name 'plot1'
|
||||||
|
set output 'plot1.js'
|
||||||
|
plot something
|
||||||
|
set term canvas name 'plot2'
|
||||||
|
set output 'plot2.js'
|
||||||
|
plot something_else
|
||||||
|
- create your html wrapper, including a script block such as the one below.
|
||||||
|
You must use these specific variable names, as they are referenced by the
|
||||||
|
javascript code produced by the canvas terminal.
|
||||||
|
<script type="text/javascript">
|
||||||
|
var canvas, ctx;
|
||||||
|
var grid_lines = true;
|
||||||
|
var zoomed = false;
|
||||||
|
var active_plot_name = "gnuplot_canvas";
|
||||||
|
var active_plot = dummyplot;
|
||||||
|
function dummyplot() {};
|
||||||
|
function gnuplot_canvas( plot ) { active_plot(); };
|
||||||
|
</script>
|
||||||
|
- add one or more mousing output tables. As a model, you can use either the one
|
||||||
|
in a standalone plot or the file .../demo/html/mousebox.template.
|
||||||
|
The table id and text span ids in the "mousebox" table must match the ones
|
||||||
|
by your individual plots in order for mousing readout to work.
|
||||||
|
- each of the individual plots in the document should be explicitly called when
|
||||||
|
the document is loaded. For example, for each plot there could be a block
|
||||||
|
of html similar to the following:
|
||||||
|
<canvas id="plot1" width="600" height="400" tabindex="0"></canvas>
|
||||||
|
<script src="plot1.js"></script>
|
||||||
|
<script>
|
||||||
|
if (window.attachEvent) {window.attachEvent('onload', plot1);}
|
||||||
|
else if (window.addEventListener) {window.addEventListener('load', plot1, false);}
|
||||||
|
</script>
|
||||||
|
Alternatively, the onload attributes could be set in the html <BODY> element
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
- Ethan A Merritt (sfeam@users.sourceforge.net)
|
||||||
|
May 2009
|
||||||
|
|
||||||
413
src/netdaemon/www/js/canvasmath.js
Normal file
413
src/netdaemon/www/js/canvasmath.js
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
* $Id: canvasmath.js,v 1.11 2016/08/07 00:06:31 sfeam Exp $
|
||||||
|
*/
|
||||||
|
// The canvastext.js code was released to the public domain by Jim Studt, 2007.
|
||||||
|
// He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/
|
||||||
|
// Mar 2009 Ethan A Merritt (EAM) Modify code to work in non-ascii environments.
|
||||||
|
// Add Latin-1, Hershey simplex Greek, and math symbols with unicode indexing.
|
||||||
|
// Apr 2012 Ethan A Merritt Composite widths, tab, newline
|
||||||
|
// Nov 2012 Ethan A Merritt Additional UTF8 mathematical operators
|
||||||
|
//
|
||||||
|
var CanvasTextFunctions = { };
|
||||||
|
|
||||||
|
CanvasTextFunctions.letters = {
|
||||||
|
' ': { width: 16, points: [] },
|
||||||
|
'!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
'"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] },
|
||||||
|
'#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] },
|
||||||
|
'$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },
|
||||||
|
'%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] },
|
||||||
|
'&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] },
|
||||||
|
'\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] },
|
||||||
|
'(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] },
|
||||||
|
')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] },
|
||||||
|
'*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] },
|
||||||
|
'+': { width: 20, points: [[10,15],[10,3],[-1,-1],[4,9],[16,9]] },
|
||||||
|
',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },
|
||||||
|
'-': { width: 20, points: [[4,9],[16,9]] },
|
||||||
|
'.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
'/': { width: 20, points: [[19,25],[1,-7]] },
|
||||||
|
'0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] },
|
||||||
|
'1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] },
|
||||||
|
'2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] },
|
||||||
|
'3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
|
||||||
|
'4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] },
|
||||||
|
'5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
|
||||||
|
'6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] },
|
||||||
|
'7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] },
|
||||||
|
'8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] },
|
||||||
|
'9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] },
|
||||||
|
':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },
|
||||||
|
'<': { width: 24, points: [[20,18],[4,9],[20,0]] },
|
||||||
|
'=': { width: 24, points: [[3,12],[20,12],[-1,-1],[3,6],[20,6]] },
|
||||||
|
'>': { width: 24, points: [[4,18],[20,9],[4,0]] },
|
||||||
|
'?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] },
|
||||||
|
'@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] },
|
||||||
|
'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] },
|
||||||
|
'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] },
|
||||||
|
'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] },
|
||||||
|
'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] },
|
||||||
|
'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] },
|
||||||
|
'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] },
|
||||||
|
'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] },
|
||||||
|
'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] },
|
||||||
|
'I': { width: 8, points: [[4,21],[4,0]] },
|
||||||
|
'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] },
|
||||||
|
'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] },
|
||||||
|
'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] },
|
||||||
|
'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] },
|
||||||
|
'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] },
|
||||||
|
'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] },
|
||||||
|
'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] },
|
||||||
|
'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] },
|
||||||
|
'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] },
|
||||||
|
'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },
|
||||||
|
'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] },
|
||||||
|
'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] },
|
||||||
|
'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] },
|
||||||
|
'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] },
|
||||||
|
'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] },
|
||||||
|
'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] },
|
||||||
|
'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] },
|
||||||
|
'[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] },
|
||||||
|
'\\': { width: 14, points: [[0,21],[14,-3]] },
|
||||||
|
']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] },
|
||||||
|
'^': { width: 16, points: [[5,15],[8,19],[11,15],[-1,-1],[2,12],[8,18],[14,12]] },
|
||||||
|
'_': { width: 16, points: [[0,-2],[16,-2]] },
|
||||||
|
'`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] },
|
||||||
|
'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },
|
||||||
|
'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] },
|
||||||
|
'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },
|
||||||
|
'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] },
|
||||||
|
'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] },
|
||||||
|
'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] },
|
||||||
|
'l': { width: 8, points: [[4,21],[4,0]] },
|
||||||
|
'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] },
|
||||||
|
'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },
|
||||||
|
'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] },
|
||||||
|
'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },
|
||||||
|
'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] },
|
||||||
|
's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] },
|
||||||
|
't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] },
|
||||||
|
'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] },
|
||||||
|
'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] },
|
||||||
|
'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] },
|
||||||
|
'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] },
|
||||||
|
'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] },
|
||||||
|
'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] },
|
||||||
|
'{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] },
|
||||||
|
'|': { width: 8, points: [[4,25],[4,-7]] },
|
||||||
|
'}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] },
|
||||||
|
'~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] },
|
||||||
|
|
||||||
|
// latin-1 as diacritical + base character
|
||||||
|
|
||||||
|
192: { width: 0, points: [[4,28],[10,24],[-99,'A']] },
|
||||||
|
193: { width: 0, points: [[8,24],[14,28],[-99,'A']] },
|
||||||
|
194: { width: 0, points: [[5,24],[9,27],[13,24],[-99,'A']] },
|
||||||
|
195: { width: 0, points: [[4,24],[5,26],[6,27],[8,27], [10,24],[12,24],[13,25],[14,27],[-99,'A']] },
|
||||||
|
196: { width: 0, points: [[6,25],[6,26],[7,26],[7,25],[-1,-1],[12,25],[12,26],[13,26],[13,25],[-99,'A']] },
|
||||||
|
197: { width: 0, points: [[8,27],[6,25],[6,23],[8,21],[10,21],[12,23],[12,25],[10,27],[8,27],[-99,'A']]},
|
||||||
|
198: { width: 11, points: [[3,0],[14,21],[-1,-1],[7,8],[14,8],[-99,'E']] },
|
||||||
|
199: { width: 0, points: [[10,0],[10,-3],[11,-3],[12,-4],[12,-6],[11,-7],[8,-7],[-99,'C']] },
|
||||||
|
200: { width: 0, points: [[8,28],[14,24],[-99,'E']] },
|
||||||
|
201: { width: 0, points: [[6,24],[12,28],[-99,'E']] },
|
||||||
|
202: { width: 0, points: [[5,24],[9,27],[13,24],[-99,'E']] },
|
||||||
|
203: { width: 0, points: [[6,25],[6,26],[7,26],[7,25],[-1,-1],[12,25],[12,26],[13,26],[13,25],[-99,'E']] },
|
||||||
|
204: { width: 0, points: [[-99,'I']] },
|
||||||
|
205: { width: 0, points: [[-99,'I']] },
|
||||||
|
206: { width: 0, points: [[-99,'I']] },
|
||||||
|
207: { width: 0, points: [[-99,'I']] },
|
||||||
|
209: { width: 0, points: [[6,24],[7,26],[8,27],[10,27], [12,24],[14,24],[15,25],[16,27],[-99,'N']] },
|
||||||
|
210: { width: 0, points: [[8,28],[14,24],[-99,'O']] },
|
||||||
|
211: { width: 0, points: [[6,24],[12,28],[-99,'O']] },
|
||||||
|
212: { width: 0, points: [[7,24],[11,27],[15,24],[-99,'O']] },
|
||||||
|
213: { width: 0, points: [[6,24],[7,26],[8,27],[10,27], [12,24],[14,24],[15,25],[16,27],[-99,'O']] },
|
||||||
|
214: { width: 0, points: [[8,25],[8,26],[9,26],[9,25],[-1,-1],[14,25],[14,26],[15,26],[15,25],[-99,'O']] },
|
||||||
|
216: { width: 0, points: [[3,0],[19,21],[-99,'O']] },
|
||||||
|
217: { width: 0, points: [[8,28],[14,24],[-99,'U']] },
|
||||||
|
218: { width: 0, points: [[6,24],[12,28],[-99,'U']] },
|
||||||
|
219: { width: 0, points: [[7,24],[11,27],[15,24],[-99,'U']] },
|
||||||
|
220: { width: 0, points: [[8,25],[8,26],[9,26],[9,25],[-1,-1],[14,25],[14,26],[15,26],[15,25],[-99,'U']] },
|
||||||
|
224: { width: 0, points: [[8,21],[14,17],[-99,'a']] },
|
||||||
|
225: { width: 0, points: [[6,17],[12,21],[-99,'a']] },
|
||||||
|
226: { width: 0, points: [[5,17],[9,20],[13,17],[-99,'a']] },
|
||||||
|
227: { width: 0, points: [[4,17],[5,19],[6,20],[8,20], [10,17],[12,17],[13,18],[14,20],[-99,'a']] },
|
||||||
|
228: { width: 0, points: [[6,18],[6,19],[7,19],[7,18],[-1,-1],[12,18],[12,19],[13,19],[13,18],[-99,'a']] },
|
||||||
|
229: { width: 0, points: [[9,21],[7,19],[7,18],[9,16],[10,16],[12,18],[12,19],[10,21],[8,21],[-99,'a']] },
|
||||||
|
231: { width: 0, points: [[10,0],[10,-3],[11,-3],[12,-4],[12,-6],[11,-7],[8,-7],[-99,'c']] },
|
||||||
|
232: { width: 0, points: [[8,21],[14,17],[-99,'e']] },
|
||||||
|
233: { width: 0, points: [[6,17],[12,21],[-99,'e']] },
|
||||||
|
234: { width: 0, points: [[5,17],[9,20],[13,17],[-99,'e']] },
|
||||||
|
235: { width: 0, points: [[6,18],[6,19],[7,19],[7,18],[-1,-1],[12,18],[12,19],[13,19],[13,18],[-99,'e']] },
|
||||||
|
236: { width: 8, points: [[4,14],[4,0],[-1,-1],[1,21],[4,18]] },
|
||||||
|
237: { width: 8, points: [[4,14],[4,0],[-1,-1],[7,21],[4,18]] },
|
||||||
|
238: { width: 8, points: [[4,14],[4,0],[-1,-1],[1,17],[4,20],[7,17]] },
|
||||||
|
239: { width: 10, points: [[5,14],[5,0],[-1,-1],[2,18],[2,19],[3,19],[3,18],[-1,-1],[7,18],[7,19],[8,19],[8,18]] },
|
||||||
|
241: { width: 0, points: [[5,17],[6,19],[7,20],[9,20], [11,17],[13,17],[14,18],[15,20],[-99,'n']] },
|
||||||
|
242: { width: 0, points: [[8,21],[14,17],[-99,'o']] },
|
||||||
|
243: { width: 0, points: [[6,17],[12,21],[-99,'o']] },
|
||||||
|
244: { width: 0, points: [[5,17],[9,20],[13,17],[-99,'o']] },
|
||||||
|
245: { width: 0, points: [[4,17],[5,19],[6,20],[8,20], [10,17],[12,17],[13,18],[14,20],[-99,'o']] },
|
||||||
|
246: { width: 0, points: [[6,18],[6,19],[7,19],[7,18],[-1,-1],[12,18],[12,19],[13,19],[13,18],[-99,'o']] },
|
||||||
|
247: { width: 20, points: [[4,9],[16,9],[-1,-1],[10,14],[10,13],[11,13],[11,14],[-1,-1],[10,4],[10,5],[11,5],[11,4]] },
|
||||||
|
248: { width: 0, points: [[3,0],[17,14],[-99,'o']] },
|
||||||
|
249: { width: 0, points: [[8,21],[14,17],[-99,'u']] },
|
||||||
|
250: { width: 0, points: [[6,17],[12,21],[-99,'u']] },
|
||||||
|
251: { width: 0, points: [[5,17],[9,20],[13,17],[-99,'u']] },
|
||||||
|
252: { width: 0, points: [[6,18],[6,19],[7,19],[7,18],[-1,-1],[12,18],[12,19],[13,19],[13,18],[-99,'u']] },
|
||||||
|
253: { width: 0, points: [[12,21],[6,17],[-99,'y']] },
|
||||||
|
255: { width: 0, points: [[6,18],[6,19],[7,19],[7,18],[-1,-1],[12,18],[12,19],[13,19],[13,18],[-99,'y']] },
|
||||||
|
|
||||||
|
// Hershey simplex greek font
|
||||||
|
|
||||||
|
913: { width: 18, points: [[9,22],[1,1],[-1,-1],[9,22],[17,1],[-1,-1],[4,8],[14,8]] },
|
||||||
|
914: { width: 21, points: [[4,22],[4,1],[-1,-1],[4,22],[13,22],[16,21],[17,20],[18,18],[18,16],[17,14],[16,13],[13,12],[-1,-1],[4,12],[13,12],[16,11],[17,10],[18,8],[18,5],[17,3],[16,2],[13,1],[4,1]] },
|
||||||
|
915: { width: 17, points: [[4,22],[4,1],[-1,-1],[4,22],[16,22]] },
|
||||||
|
916: { width: 18, points: [[9,22],[1,1],[-1,-1],[9,22],[17,1],[-1,-1],[1,1],[17,1]] },
|
||||||
|
917: { width: 19, points: [[4,22],[4,1],[-1,-1],[4,22],[17,22],[-1,-1],[4,12],[12,12],[-1,-1],[4,1],[17,1]] },
|
||||||
|
918: { width: 20, points: [[17,22],[3,1],[-1,-1],[3,22],[17,22],[-1,-1],[3,1],[17,1]] },
|
||||||
|
919: { width: 22, points: [[4,22],[4,1],[-1,-1],[18,22],[18,1],[-1,-1],[4,12],[18,12]] },
|
||||||
|
920: { width: 22, points: [[9,22],[7,21],[5,19],[4,17],[3,14],[3,9],[4,6],[5,4],[7,2],[9,1],[13,1],[15,2],[17,4],[18,6],[19,9],[19,14],[18,17],[17,19],[15,21],[13,22],[9,22],[-1,-1],[8,12],[14,12]] },
|
||||||
|
921: { width: 8, points: [[4,22],[4,1]] },
|
||||||
|
922: { width: 21, points: [[4,22],[4,1],[-1,-1],[18,22],[4,8],[-1,-1],[9,13],[18,1]] },
|
||||||
|
923: { width: 18, points: [[9,22],[1,1],[-1,-1],[9,22],[17,1]] },
|
||||||
|
924: { width: 24, points: [[4,22],[4,1],[-1,-1],[4,22],[12,1],[-1,-1],[20,22],[12,1],[-1,-1],[20,22],[20,1]] },
|
||||||
|
925: { width: 22, points: [[4,22],[4,1],[-1,-1],[4,22],[18,1],[-1,-1],[18,22],[18,1]] },
|
||||||
|
926: { width: 18, points: [[2,22],[16,22],[-1,-1],[6,12],[12,12],[-1,-1],[2,1],[16,1]] },
|
||||||
|
927: { width: 22, points: [[9,22],[7,21],[5,19],[4,17],[3,14],[3,9],[4,6],[5,4],[7,2],[9,1],[13,1],[15,2],[17,4],[18,6],[19,9],[19,14],[18,17],[17,19],[15,21],[13,22],[9,22]] },
|
||||||
|
928: { width: 22, points: [[4,22],[4,1],[-1,-1],[18,22],[18,1],[-1,-1],[4,22],[18,22]] },
|
||||||
|
929: { width: 21, points: [[4,22],[4,1],[-1,-1],[4,22],[13,22],[16,21],[17,20],[18,18],[18,15],[17,13],[16,12],[13,11],[4,11]] },
|
||||||
|
931: { width: 18, points: [[2,22],[9,12],[2,1],[-1,-1],[2,22],[16,22],[-1,-1],[2,1],[16,1]] },
|
||||||
|
932: { width: 16, points: [[8,22],[8,1],[-1,-1],[1,22],[15,22]] },
|
||||||
|
933: { width: 18, points: [[2,17],[2,19],[3,21],[4,22],[6,22],[7,21],[8,19],[9,15],[9,1],[-1,-1],[16,17],[16,19],[15,21],[14,22],[12,22],[11,21],[10,19],[9,15]] },
|
||||||
|
934: { width: 20, points: [[10,22],[10,1],[-1,-1],[8,17],[5,16],[4,15],[3,13],[3,10],[4,8],[5,7],[8,6],[12,6],[15,7],[16,8],[17,10],[17,13],[16,15],[15,16],[12,17],[8,17]] },
|
||||||
|
935: { width: 20, points: [[3,22],[17,1],[-1,-1],[3,1],[17,22]] },
|
||||||
|
936: { width: 22, points: [[11,22],[11,1],[-1,-1],[2,16],[3,16],[4,15],[5,11],[6,9],[7,8],[10,7],[12,7],[15,8],[16,9],[17,11],[18,15],[19,16],[20,16]] },
|
||||||
|
937: { width: 20, points: [[3,1],[7,1],[4,8],[3,12],[3,16],[4,19],[6,21],[9,22],[11,22],[14,21],[16,19],[17,16],[17,12],[16,8],[13,1],[17,1]] },
|
||||||
|
945: { width: 21, points: [[9,15],[7,14],[5,12],[4,10],[3,7],[3,4],[4,2],[6,1],[8,1],[10,2],[13,5],[15,8],[17,12],[18,15],[-1,-1],[9,15],[11,15],[12,14],[13,12],[15,4],[16,2],[17,1],[18,1]] },
|
||||||
|
946: { width: 19, points: [[12,22],[10,21],[8,19],[6,15],[5,12],[4,8],[3,2],[2,-6],[-1,-1],[12,22],[14,22],[16,20],[16,17],[15,15],[14,14],[12,13],[9,13],[-1,-1],[9,13],[11,12],[13,10],[14,8],[14,5],[13,3],[12,2],[10,1],[8,1],[6,2],[5,3],[4,6]] },
|
||||||
|
947: { width: 19, points: [[1,12],[3,14],[5,15],[6,15],[8,14],[9,13],[10,10],[10,6],[9,1],[-1,-1],[17,15],[16,12],[15,10],[9,1],[7,-3],[6,-6]] },
|
||||||
|
948: { width: 18, points: [[11,15],[8,15],[6,14],[4,12],[3,9],[3,6],[4,3],[5,2],[7,1],[9,1],[11,2],[13,4],[14,7],[14,10],[13,13],[11,15],[9,17],[8,19],[8,21],[9,22],[11,22],[13,21],[15,19]] },
|
||||||
|
949: { width: 16, points: [[13,13],[12,14],[10,15],[7,15],[5,14],[5,12],[6,10],[9,9],[-1,-1],[9,9],[5,8],[3,6],[3,4],[4,2],[6,1],[9,1],[11,2],[13,4]] },
|
||||||
|
950: { width: 15, points: [[10,22],[8,21],[7,20],[7,19],[8,18],[11,17],[14,17],[-1,-1],[14,17],[10,15],[7,13],[4,10],[3,7],[3,5],[4,3],[6,1],[9,-1],[10,-3],[10,-5],[9,-6],[7,-6],[6,-4]] },
|
||||||
|
951: { width: 20, points: [[1,11],[2,13],[4,15],[6,15],[7,14],[7,12],[6,8],[4,1],[-1,-1],[6,8],[8,12],[10,14],[12,15],[14,15],[16,13],[16,10],[15,5],[12,-6]] },
|
||||||
|
952: { width: 17, points: [[10,22],[8,21],[6,18],[5,16],[4,13],[3,8],[3,4],[4,2],[5,1],[7,1],[9,2],[11,5],[12,7],[13,10],[14,15],[14,19],[13,21],[12,22],[10,22],[-1,-1],[4,12],[13,12]] },
|
||||||
|
953: { width: 11, points: [[6,15],[4,8],[3,4],[3,2],[4,1],[6,1],[8,3],[9,5]] },
|
||||||
|
954: { width: 18, points: [[6,15],[2,1],[-1,-1],[16,14],[15,15],[14,15],[12,14],[8,10],[6,9],[5,9],[-1,-1],[5,9],[7,8],[8,7],[10,2],[11,1],[12,1],[13,2]] },
|
||||||
|
955: { width: 16, points: [[1,22],[3,22],[5,21],[6,20],[14,1],[-1,-1],[8,15],[2,1]] },
|
||||||
|
956: { width: 21, points: [[7,15],[1,-6],[-1,-1],[6,11],[5,6],[5,3],[7,1],[9,1],[11,2],[13,4],[15,8],[-1,-1],[17,15],[15,8],[14,4],[14,2],[15,1],[17,1],[19,3],[20,5]] },
|
||||||
|
957: { width: 18, points: [[3,15],[6,15],[5,9],[4,4],[3,1],[-1,-1],[16,15],[15,12],[14,10],[12,7],[9,4],[6,2],[3,1]] },
|
||||||
|
958: { width: 16, points: [[10,22],[8,21],[7,20],[7,19],[8,18],[11,17],[14,17],[-1,-1],[11,17],[8,16],[6,15],[5,13],[5,11],[7,9],[10,8],[12,8],[-1,-1],[10,8],[6,7],[4,6],[3,4],[3,2],[5,0],[9,-2],[10,-3],[10,-5],[8,-6],[6,-6]] },
|
||||||
|
959: { width: 17, points: [[8,15],[6,14],[4,12],[3,9],[3,6],[4,3],[5,2],[7,1],[9,1],[11,2],[13,4],[14,7],[14,10],[13,13],[12,14],[10,15],[8,15]] },
|
||||||
|
960: { width: 18, points: [[6,15],[2,1],[-1,-1],[16,14],[15,15],[14,15],[12,14],[8,10],[6,9],[5,9],[-1,-1],[5,9],[7,8],[8,7],[10,2],[11,1],[12,1],[13,2]] },
|
||||||
|
960: { width: 22, points: [[9,15],[5,1],[-1,-1],[14,15],[15,9],[16,4],[17,1],[-1,-1],[2,12],[4,14],[7,15],[20,15]] },
|
||||||
|
961: { width: 18, points: [[4,9],[4,6],[5,3],[6,2],[8,1],[10,1],[12,2],[14,4],[15,7],[15,10],[14,13],[13,14],[11,15],[9,15],[7,14],[5,12],[4,9],[0,-6]] },
|
||||||
|
962: { width: 18, points: [[15,13],[14,14],[11,15],[8,15],[5,14],[4,13],[3,11],[3,9],[4,7],[6,5],[10,2],[11,0],[11,-2],[10,-3],[8,-3]] },
|
||||||
|
963: { width: 18, points: [[3,15],[6,15],[5,9],[4,4],[3,1],[-1,-1],[16,15],[15,12],[14,10],[12,7],[9,4],[6,2],[3,1]] },
|
||||||
|
963: { width: 20, points: [[18,15],[8,15],[6,14],[4,12],[3,9],[3,6],[4,3],[5,2],[7,1],[9,1],[11,2],[13,4],[14,7],[14,10],[13,13],[12,14],[10,15]] },
|
||||||
|
964: { width: 20, points: [[11,15],[8,1],[-1,-1],[2,12],[4,14],[7,15],[18,15]] },
|
||||||
|
965: { width: 20, points: [[1,11],[2,13],[4,15],[6,15],[7,14],[7,12],[5,6],[5,3],[7,1],[9,1],[12,2],[14,4],[16,8],[17,12],[17,15]] },
|
||||||
|
966: { width: 22, points: [[8,14],[6,13],[4,11],[3,8],[3,5],[4,3],[5,2],[7,1],[10,1],[13,2],[16,4],[18,7],[19,10],[19,13],[17,15],[15,15],[13,13],[11,9],[9,4],[6,-6]] },
|
||||||
|
967: { width: 18, points: [[2,15],[4,15],[6,13],[12,-4],[14,-6],[16,-6],[-1,-1],[17,15],[16,13],[14,10],[4,-1],[2,-4],[1,-6]] },
|
||||||
|
968: { width: 23, points: [[16,22],[8,-6],[-1,-1],[1,11],[2,13],[4,15],[6,15],[7,14],[7,12],[6,7],[6,4],[7,2],[9,1],[11,1],[14,2],[16,4],[18,7],[20,12],[21,15]] },
|
||||||
|
969: { width: 23, points: [[8,15],[6,14],[4,11],[3,8],[3,5],[4,2],[5,1],[7,1],[9,2],[11,5],[-1,-1],[12,9],[11,5],[12,2],[13,1],[15,1],[17,2],[19,5],[20,8],[20,11],[19,14],[18,15]] },
|
||||||
|
977: { width: 21, points: [[1,11],[2,13],[4,15],[6,15],[7,14],[7,12],[6,7],[6,4],[7,2],[8,1],[10,1],[12,2],[14,5],[15,7],[16,10],[17,15],[17,18],[16,21],[14,22],[12,22],[11,20],[11,18],[12,15],[14,12],[16,10],[19,8]] },
|
||||||
|
981: { width: 20, points: [[14,22],[6,-6],[-1,-1],[9,15],[6,14],[4,12],[3,9],[3,6],[4,4],[6,2],[9,1],[11,1],[14,2],[16,4],[17,7],[17,10],[16,12],[14,14],[11,15],[9,15]] },
|
||||||
|
982: { width: 23, points: [[9,14],[6,13],[4,11],[3,8],[3,5],[4,2],[5,1],[7,1],[9,2],[11,5],[-1,-1],[12,9],[11,5],[12,2],[13,1],[15,1],[17,2],[19,5],[20,8],[20,11],[19,14],[18,15],[-1,-1],[2,14],[4,15],[20,15]] },
|
||||||
|
986: { width: 18, points: [[15,13],[14,14],[11,15],[8,15],[5,14],[4,13],[3,11],[3,9],[4,7],[6,5],[10,2],[11,0],[11,-2],[10,-3],[8,-3]] },
|
||||||
|
|
||||||
|
// Hershey math symbols
|
||||||
|
|
||||||
|
8501: { width: 20, points: [[3,19],[4,17],[16,5],[17,3],[17,1],[-1,-1],[4,16],[16,4],[-1,-1],[3,19],[3,17],[4,15],[16,3],[17,1],[-1,-1],[8,12],[4,8],[3,6],[3,4],[4,2],[3,1],[-1,-1],[3,6],[5,2],[-1,-1],[4,8],[4,6],[5,4],[5,2],[3,1],[-1,-1],[11,9],[16,14],[-1,-1],[14,19],[14,16],[15,14],[17,14],[17,16],[15,17],[14,19],[-1,-1],[14,19],[15,16],[17,14]] },
|
||||||
|
8592: { width: 26, points: [[7,12],[4,10],[7,8],[-1,-1],[10,15],[5,10],[10,5],[-1,-1],[5,10],[22,10]] },
|
||||||
|
8593: { width: 16, points: [[6,16],[8,19],[10,16],[-1,-1],[3,13],[8,18],[13,13],[-1,-1],[8,18],[8,1]] },
|
||||||
|
8594: { width: 26, points: [[19,12],[22,10],[19,8],[-1,-1],[16,15],[21,10],[16,5],[-1,-1],[4,10],[21,10]] },
|
||||||
|
8595: { width: 16, points: [[6,4],[8,1],[10,4],[-1,-1],[3,7],[8,2],[13,7],[-1,-1],[8,19],[8,2]] },
|
||||||
|
8706: { width: 19, points: [[15,10],[14,13],[13,14],[11,15],[9,15],[6,14],[4,11],[3,8],[3,5],[4,3],[5,2],[7,1],[9,1],[12,2],[14,4],[15,7],[16,12],[16,17],[15,20],[14,21],[12,22],[9,22],[7,21],[6,20],[6,19],[7,19],[7,20],[-1,-1],[9,15],[7,14],[5,11],[4,8],[4,4],[5,2],[-1,-1],[9,1],[11,2],[13,4],[14,7],[15,12],[15,17],[14,20],[12,22]] },
|
||||||
|
8710: { width: 20, points: [[2,1],[10,22],[-1,-1],[17,1],[10,20],[-1,-1],[18,1],[10,22],[-1,-1],[2,1],[18,1],[-1,-1],[3,2],[17,2]] },
|
||||||
|
8711: { width: 20, points: [[2,22],[10,1],[-1,-1],[3,22],[10,3],[-1,-1],[18,22],[10,1],[-1,-1],[2,22],[18,22],[-1,-1],[3,21],[17,21]] },
|
||||||
|
8712: { width: 24, points: [[20,18],[13,18],[9,17],[7,16],[5,14],[4,11],[4,9],[5,6],[7,4],[9,3],[13,2],[20,2],[-1,-1],[4,10],[16,10]] },
|
||||||
|
8713: { width: 24, points: [[20,18],[13,18],[9,17],[7,16],[5,14],[4,11],[4,9],[5,6],[7,4],[9,3],[13,2],[20,2],[-1,-1],[4,10],[16,10],[-1,-1],[18,19],[6,1]] },
|
||||||
|
8719: { width: 34, points: [[7,26],[7,-6],[-1,-1],[8,26],[8,-6],[-1,-1],[26,26],[26,-6],[-1,-1],[27,26],[27,-6],[-1,-1],[3,26],[31,26],[-1,-1],[3,-6],[12,-6],[-1,-1],[22,-6],[31,-6]] },
|
||||||
|
8721: { width: 31, points: [[5,26],[15,12],[4,-6],[-1,-1],[4,26],[14,12],[-1,-1],[3,26],[14,11],[-1,-1],[3,26],[26,26],[28,19],[25,26],[-1,-1],[5,-5],[26,-5],[-1,-1],[4,-6],[26,-6],[28,1],[25,-6]] },
|
||||||
|
8728: { width: 16, points: [[7,13],[5,11],[5,9],[7,7],[9,7],[11,9],[11,11],[9,13],[7,13]] },
|
||||||
|
8729: { width: 16, points: [[7,13],[5,11],[5,9],[7,7],[9,7],[11,9],[11,11],[9,13],[7,13],[-1,-1],[7,12],[6,11],[6,9],[7,8],[9,8],[10,9],[10,11],[9,12],[7,12],[-1,-1],[8,11],[7,10],[8,9],[9,10],[8,11]] },
|
||||||
|
8730: { width: 22, points: [[3,15],[7,15],[13,3],[-1,-1],[6,15],[13,1],[-1,-1],[22,26],[13,1]] },
|
||||||
|
8733: { width: 25, points: [[21,5],[19,5],[17,6],[15,8],[12,12],[11,13],[9,14],[7,14],[5,13],[4,11],[4,9],[5,7],[7,6],[9,6],[11,7],[12,8],[15,12],[17,14],[19,15],[21,15]] },
|
||||||
|
8734: { width: 25, points: [[22,9],[21,7],[19,6],[17,6],[15,7],[14,8],[11,12],[10,13],[8,14],[6,14],[4,13],[3,11],[3,9],[4,7],[6,6],[8,6],[10,7],[11,8],[14,12],[15,13],[17,14],[19,14],[21,13],[22,11],[22,9]] },
|
||||||
|
8745: { width: 24, points: [[4,2],[4,9],[5,13],[6,15],[8,17],[11,18],[13,18],[16,17],[18,15],[19,13],[20,9],[20,2]] },
|
||||||
|
8746: { width: 24, points: [[4,18],[4,11],[5,7],[6,5],[8,3],[11,2],[13,2],[16,3],[18,5],[19,7],[20,11],[20,18]] },
|
||||||
|
8747: { width: 24, points: [[21,25],[20,24],[21,23],[22,24],[22,25],[21,26],[19,26],[17,25],[15,23],[14,21],[13,18],[12,14],[10,2],[9,-2],[8,-4],[-1,-1],[16,24],[15,22],[14,18],[12,6],[11,2],[10,-1],[9,-3],[7,-5],[5,-6],[3,-6],[2,-5],[2,-4],[3,-3],[4,-4],[3,-5]] },
|
||||||
|
8771: { width: 24, points: [[3,10],[3,11],[4,13],[6,14],[8,14],[10,13],[14,11],[16,10],[18,10],[20,11],[22,13],[22,14],[-1,-1],[3,6],[22,6]] },
|
||||||
|
8776: { width: 24, points: [[3,10],[3,11],[4,13],[6,14],[8,14],[10,13],[14,11],[16,10],[18,10],[20,11],[22,13],[22,14],[-1,-1],[3,4],[3,5],[4,7],[6,8],[8,8],[10,7],[14,5],[16,4],[18,4],[20,5],[22,7],[22,8]] },
|
||||||
|
8800: { width: 24, points: [[18,19],[6,1],[-1,-1],[3,12],[20,12],[-1,-1],[3,6],[20,6]] },
|
||||||
|
8804: { width: 24, points: [[20,4],[4,11],[20,18],[-1,-1],[4,0],[20,0]] },
|
||||||
|
8805: { width: 24, points: [[4,4],[20,11],[4,18],[-1,-1],[4,0],[20,0]] },
|
||||||
|
8834: { width: 24, points: [[20,18],[13,18],[9,17],[7,16],[5,14],[4,11],[4,9],[5,6],[7,4],[9,3],[13,2],[20,2]] },
|
||||||
|
8835: { width: 24, points: [[4,18],[11,18],[15,17],[17,16],[19,14],[20,11],[20,9],[19,6],[17,4],[15,3],[11,2],[4,2]] },
|
||||||
|
8838: { width: 24, points: [[20,20],[13,20],[9,19],[7,18],[5,16],[4,13],[4,11],[5,8],[7,6],[9,5],[13,4],[20,4],[-1,-1],[4,0],[20,0]] },
|
||||||
|
8839: { width: 24, points: [[4,20],[11,20],[15,19],[17,18],[19,16],[20,13],[20,11],[19,8],[17,6],[15,5],[11,4],[4,4],[-1,-1],[4,0],[20,0]] },
|
||||||
|
8853: { width: 20, points: [[9,17],[6,16],[4,14],[3,11],[3,9],[4,6],[6,4],[9,3],[11,3],[14,4],[16,6],[17,9],[17,11],[16,14],[14,16],[11,17],[9,17],[-1,-1],[5,10],[15,10],[-1,-1],[10,5],[10,15]] },
|
||||||
|
8855: { width: 20, points: [[9,17],[6,16],[4,14],[3,11],[3,9],[4,6],[6,4],[9,3],[11,3],[14,4],[16,6],[17,9],[17,11],[16,14],[14,16],[11,17],[9,17],[-1,-1],[6,6],[14,14],[-1,-1],[14,6],[6,14]] },
|
||||||
|
8857: { width: 20, points: [[9,17],[6,16],[4,14],[3,11],[3,9],[4,6],[6,4],[9,3],[11,3],[14,4],[16,6],[17,9],[17,11],[16,14],[14,16],[11,17],[9,17],[-1,-1],[10,11],[9,10],[10,9],[11,10],[10,11]] },
|
||||||
|
9737: { width: 27, points: [[12,22],[9,21],[6,19],[4,16],[3,13],[3,10],[4,7],[6,4],[9,2],[12,1],[15,1],[18,2],[21,4],[23,7],[24,10],[24,13],[23,16],[21,19],[18,21],[15,22],[12,22],[-1,-1],[13,13],[12,12],[12,11],[13,10],[14,10],[15,11],[15,12],[14,13],[13,13],[-1,-1],[13,12],[13,11],[14,11],[14,12],[13,12]] },
|
||||||
|
|
||||||
|
// Miscellaneous glyphs (EAM)
|
||||||
|
|
||||||
|
176: { width: 14, points: [[6,22],[4,21],[3,19],[3,17],[4,15],[6,14],[8,14],[10,15],[11,17],[11,19],[10,21],[8,22],[6,22]] },
|
||||||
|
177: { width: 20, points: [[10,15],[10,5],[-1,-1],[4,10],[16,10],[-1,-1],[4,2],[16,2]] },
|
||||||
|
181: { width: 0, points: [[-99,956]] },
|
||||||
|
183: { width: 10, points: [[5,11],[4,10],[5,9],[6,10],[5,11]] },
|
||||||
|
188: { width: 23, points: [[4,0],[16,20],[-1,-1],[2,18],[4,20],[4,10],[-1,-1],[21,3],[12,3],[17,12],[18,12],[18,-1]] },
|
||||||
|
189: { width: 23, points: [[4,0],[16,20],[-1,-1],[2,18],[4,20],[4,10],[-1,-1],[14,8],[16,10],[18,10],[20,8],[20,6],[14,1],[14,0],[21,0]] },
|
||||||
|
215: { width: 20, points: [[4,16],[16,4],[-1,-1],[4,4],[16,16]] },
|
||||||
|
402: { width: 15, points: [[15,21],[14,20],[15,19],[16,20],[16,21],[15,22],[13,22],[11,21],[10,20],[9,18],[8,15],[5,1],[4,-3],[3,-5],[-1,-1],[13,22],[11,20],[10,18],[9,14],[7,5],[6,1],[5,-2],[4,-4],[3,-5],[1,-6],[-1,-6],[-2,-5],[-2,-4],[-1,-3],[0,-4],[-1,-5],[-1,-1],[4,15],[14,15]] },
|
||||||
|
8242: { width: 8, points: [[5,24],[3,16],[-1,-1],[3,16],[6,24]] },
|
||||||
|
8243: { width: 11, points: [[4,24],[2,16],[-1,-1],[2,16],[5,24],[-1,-1],[9,24],[7,16],[-1,-1],[7,16],[10,24]] },
|
||||||
|
8463: { width: 21, points: [[9,22],[3,1],[-1,-1],[5,7],[7,11],[9,13],[11,14],[13,14],[15,14],[16,12],[16,10],[14,5],[14,2],[15,1],[19,3],[-1,-1],[7,21],[9,22],[-1,-1],[4,15],[14,20]] },
|
||||||
|
8491: { width: 0, points: [[-99,197]] },
|
||||||
|
8495: { width: 18, points: [[4,6],[8,7],[11,8],[14,10],[15,12],[14,14],[12,15],[9,15],[6,14],[4,11],[3,8],[3,5],[4,3],[5,2],[7,1],[9,1],[12,2],[14,4],[-1,-1],[9,15],[7,14],[5,11],[4,8],[4,4],[5,2]] },
|
||||||
|
8722: { width: 20, points: [[2,9],[18,9]] },
|
||||||
|
|
||||||
|
// Used to indicate missing glyph
|
||||||
|
129: { width: 18, points: [[2,-2],[2,21],[16,21],[16,-2],[2,-2]] }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
CanvasTextFunctions.letter = function (ch)
|
||||||
|
{
|
||||||
|
glyph = CanvasTextFunctions.letters[ch];
|
||||||
|
|
||||||
|
// EAM - Draw an empty box for undefined glyphs
|
||||||
|
if (glyph == undefined)
|
||||||
|
glyph = CanvasTextFunctions.letters[129];
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.ascent = function( font, size)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.descent = function( font, size)
|
||||||
|
{
|
||||||
|
return 7.0*size/25.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.measure = function( font, size, str)
|
||||||
|
{
|
||||||
|
var total = 0;
|
||||||
|
var len = str.length;
|
||||||
|
|
||||||
|
for ( i = 0; i < len; i++) {
|
||||||
|
var index = str.charAt(i);
|
||||||
|
// EAM deal with non-ascii characaters
|
||||||
|
if (index > '~')
|
||||||
|
index = str.charCodeAt(i);
|
||||||
|
|
||||||
|
var c = CanvasTextFunctions.letter(index);
|
||||||
|
if (!c) break;
|
||||||
|
total += c.width * size / 25.0;
|
||||||
|
if (c.width == 0) {
|
||||||
|
for ( j = 0; j < c.points.length; j++) {
|
||||||
|
var a = c.points[j];
|
||||||
|
if (a[0] == -99)
|
||||||
|
total += CanvasTextFunctions.letter(a[1]).width * size / 25.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.draw = function(ctx,font,size,x,y,str)
|
||||||
|
{
|
||||||
|
var total = 0;
|
||||||
|
var len = str.length;
|
||||||
|
var mag = size / 25.0;
|
||||||
|
var composite = 0;
|
||||||
|
var xorig = x;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.lineCap = "round";
|
||||||
|
ctx.lineWidth = 2.0 * mag;
|
||||||
|
|
||||||
|
for (var i = 0; i < len; i++) {
|
||||||
|
var index = str.charAt(i);
|
||||||
|
|
||||||
|
// EAM tab and newline
|
||||||
|
if (index == ' ') {
|
||||||
|
var tabstop = 48 * mag;
|
||||||
|
x = tabstop * Math.ceil(x/tabstop);
|
||||||
|
continue;
|
||||||
|
} else if (index < ' ') {
|
||||||
|
x = xorig; y += size;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// EAM deal with non-ascii characaters
|
||||||
|
if (index > '~')
|
||||||
|
index = str.charCodeAt(i);
|
||||||
|
|
||||||
|
// EAM allow composing characters
|
||||||
|
if (composite != 0) {
|
||||||
|
index = composite;
|
||||||
|
composite = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var c = CanvasTextFunctions.letter(index);
|
||||||
|
if ( !c) continue;
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
|
||||||
|
var penUp = 1;
|
||||||
|
var needStroke = 0;
|
||||||
|
for (var j = 0; j < c.points.length; j++) {
|
||||||
|
var a = c.points[j];
|
||||||
|
if ( a[0] == -1 && a[1] == -1) {
|
||||||
|
penUp = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( a[0] == -99 ) {
|
||||||
|
composite = a[1];
|
||||||
|
i--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( penUp) {
|
||||||
|
ctx.moveTo( x + a[0]*mag, y - a[1]*mag);
|
||||||
|
penUp = false;
|
||||||
|
} else {
|
||||||
|
ctx.lineTo( x + a[0]*mag, y - a[1]*mag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
x += c.width*mag;
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.enable = function( ctx)
|
||||||
|
{
|
||||||
|
ctx.drawText = function(font,size,x,y,text) { return CanvasTextFunctions.draw( ctx, font,size,x,y,text); };
|
||||||
|
ctx.measureText = function(font,size,text) { return CanvasTextFunctions.measure( font,size,text); };
|
||||||
|
ctx.fontAscent = function(font,size) { return CanvasTextFunctions.ascent(font,size); }
|
||||||
|
ctx.fontDescent = function(font,size) { return CanvasTextFunctions.descent(font,size); }
|
||||||
|
|
||||||
|
ctx.drawTextRight = function(font,size,x,y,text) {
|
||||||
|
var w = CanvasTextFunctions.measure(font,size,text);
|
||||||
|
return CanvasTextFunctions.draw( ctx, font,size,x-w,y,text);
|
||||||
|
};
|
||||||
|
ctx.drawTextCenter = function(font,size,x,y,text) {
|
||||||
|
var w = CanvasTextFunctions.measure(font,size,text);
|
||||||
|
return CanvasTextFunctions.draw( ctx, font,size,x-w/2,y,text);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
211
src/netdaemon/www/js/canvastext.js
Normal file
211
src/netdaemon/www/js/canvastext.js
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/*
|
||||||
|
* $Id: canvastext.js,v 1.3 2009/02/22 19:14:05 sfeam Exp $
|
||||||
|
*/
|
||||||
|
// The canvastext.js code was released to the public domain by Jim Studt, 2007.
|
||||||
|
// He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/
|
||||||
|
// Feb 2009 Ethan A Merritt (EAM) Modify code to work in non-ascii environments.
|
||||||
|
//
|
||||||
|
var CanvasTextFunctions = { };
|
||||||
|
|
||||||
|
CanvasTextFunctions.letters = {
|
||||||
|
' ': { width: 16, points: [] },
|
||||||
|
'!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
'"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] },
|
||||||
|
'#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] },
|
||||||
|
'$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },
|
||||||
|
'%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] },
|
||||||
|
'&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] },
|
||||||
|
'\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] },
|
||||||
|
'(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] },
|
||||||
|
')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] },
|
||||||
|
'*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] },
|
||||||
|
'+': { width: 26, points: [[13,18],[13,0],[-1,-1],[4,9],[22,9]] },
|
||||||
|
',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },
|
||||||
|
'-': { width: 26, points: [[4,9],[22,9]] },
|
||||||
|
'.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
'/': { width: 22, points: [[20,25],[2,-7]] },
|
||||||
|
'0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] },
|
||||||
|
'1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] },
|
||||||
|
'2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] },
|
||||||
|
'3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
|
||||||
|
'4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] },
|
||||||
|
'5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] },
|
||||||
|
'6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] },
|
||||||
|
'7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] },
|
||||||
|
'8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] },
|
||||||
|
'9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] },
|
||||||
|
':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] },
|
||||||
|
';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] },
|
||||||
|
'<': { width: 24, points: [[20,18],[4,9],[20,0]] },
|
||||||
|
'=': { width: 26, points: [[4,12],[22,12],[-1,-1],[4,6],[22,6]] },
|
||||||
|
'>': { width: 24, points: [[4,18],[20,9],[4,0]] },
|
||||||
|
'?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] },
|
||||||
|
'@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] },
|
||||||
|
'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] },
|
||||||
|
'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] },
|
||||||
|
'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] },
|
||||||
|
'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] },
|
||||||
|
'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] },
|
||||||
|
'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] },
|
||||||
|
'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] },
|
||||||
|
'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] },
|
||||||
|
'I': { width: 8, points: [[4,21],[4,0]] },
|
||||||
|
'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] },
|
||||||
|
'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] },
|
||||||
|
'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] },
|
||||||
|
'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] },
|
||||||
|
'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] },
|
||||||
|
'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] },
|
||||||
|
'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] },
|
||||||
|
'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] },
|
||||||
|
'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] },
|
||||||
|
'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] },
|
||||||
|
'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] },
|
||||||
|
'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] },
|
||||||
|
'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] },
|
||||||
|
'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] },
|
||||||
|
'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] },
|
||||||
|
'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] },
|
||||||
|
'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] },
|
||||||
|
'[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] },
|
||||||
|
'\\': { width: 14, points: [[0,21],[14,-3]] },
|
||||||
|
']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] },
|
||||||
|
'^': { width: 16, points: [[5,15],[8,19],[11,15],[-1,-1],[2,12],[8,18],[14,12]] },
|
||||||
|
'_': { width: 16, points: [[0,-2],[16,-2]] },
|
||||||
|
'`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] },
|
||||||
|
'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },
|
||||||
|
'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] },
|
||||||
|
'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },
|
||||||
|
'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] },
|
||||||
|
'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] },
|
||||||
|
'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] },
|
||||||
|
'l': { width: 8, points: [[4,21],[4,0]] },
|
||||||
|
'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] },
|
||||||
|
'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] },
|
||||||
|
'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] },
|
||||||
|
'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] },
|
||||||
|
'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] },
|
||||||
|
'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] },
|
||||||
|
's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] },
|
||||||
|
't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] },
|
||||||
|
'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] },
|
||||||
|
'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] },
|
||||||
|
'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] },
|
||||||
|
'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] },
|
||||||
|
'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] },
|
||||||
|
'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] },
|
||||||
|
'{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] },
|
||||||
|
'|': { width: 8, points: [[4,25],[4,-7]] },
|
||||||
|
'}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] },
|
||||||
|
'~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] },
|
||||||
|
|
||||||
|
// Miscellaneous glyphs (EAM)
|
||||||
|
129: { width: 18, points: [[2,-2],[2,21],[16,21],[16,-2],[2,-2]] },
|
||||||
|
176: { width: 8, points: [[3,22],[1,20],[1,18],[3,16],[5,16],[7,18],[7,20],[5,22],[3,22]]},
|
||||||
|
197: { width: 18, points: [[9,18],[1,0],[-1,-1],[9,18],[17,0],[-1,-1],[4,7],[14,7],[-1,-1], [8,22],[6,20],[6,18],[8,16],[10,16],[12,18],[12,20],[10,22],[8,22]]},
|
||||||
|
215: { width: 26, points: [[6,17],[20,3],[-1,-1],[6,3],[20,17]] }
|
||||||
|
};
|
||||||
|
|
||||||
|
CanvasTextFunctions.letter = function (ch)
|
||||||
|
{
|
||||||
|
glyph = CanvasTextFunctions.letters[ch];
|
||||||
|
|
||||||
|
// EAM - Draw an empty box for undefined glyphs
|
||||||
|
if (glyph == undefined)
|
||||||
|
glyph = CanvasTextFunctions.letters[129];
|
||||||
|
|
||||||
|
return glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.ascent = function( font, size)
|
||||||
|
{
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.descent = function( font, size)
|
||||||
|
{
|
||||||
|
return 7.0*size/25.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.measure = function( font, size, str)
|
||||||
|
{
|
||||||
|
var total = 0;
|
||||||
|
var len = str.length;
|
||||||
|
|
||||||
|
for ( i = 0; i < len; i++) {
|
||||||
|
var index = str.charAt(i);
|
||||||
|
// EAM deal with non-ascii characaters
|
||||||
|
if (index > '~')
|
||||||
|
index = str.charCodeAt(i);
|
||||||
|
|
||||||
|
var c = CanvasTextFunctions.letter(index);
|
||||||
|
if (c) total += c.width * size / 25.0;
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.draw = function(ctx,font,size,x,y,str)
|
||||||
|
{
|
||||||
|
var total = 0;
|
||||||
|
var len = str.length;
|
||||||
|
var mag = size / 25.0;
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.lineCap = "round";
|
||||||
|
ctx.lineWidth = 2.0 * mag;
|
||||||
|
|
||||||
|
for ( i = 0; i < len; i++) {
|
||||||
|
var index = str.charAt(i);
|
||||||
|
// EAM deal with non-ascii characaters
|
||||||
|
if (index > '~')
|
||||||
|
index = str.charCodeAt(i);
|
||||||
|
|
||||||
|
var c = CanvasTextFunctions.letter(index);
|
||||||
|
if ( !c) continue;
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
|
||||||
|
var penUp = 1;
|
||||||
|
var needStroke = 0;
|
||||||
|
for ( j = 0; j < c.points.length; j++) {
|
||||||
|
var a = c.points[j];
|
||||||
|
if ( a[0] == -1 && a[1] == -1) {
|
||||||
|
penUp = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( penUp) {
|
||||||
|
ctx.moveTo( x + a[0]*mag, y - a[1]*mag);
|
||||||
|
penUp = false;
|
||||||
|
} else {
|
||||||
|
ctx.lineTo( x + a[0]*mag, y - a[1]*mag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx.stroke();
|
||||||
|
x += c.width*mag;
|
||||||
|
}
|
||||||
|
ctx.restore();
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasTextFunctions.enable = function( ctx)
|
||||||
|
{
|
||||||
|
ctx.drawText = function(font,size,x,y,text) { return CanvasTextFunctions.draw( ctx, font,size,x,y,text); };
|
||||||
|
ctx.measureText = function(font,size,text) { return CanvasTextFunctions.measure( font,size,text); };
|
||||||
|
ctx.fontAscent = function(font,size) { return CanvasTextFunctions.ascent(font,size); }
|
||||||
|
ctx.fontDescent = function(font,size) { return CanvasTextFunctions.descent(font,size); }
|
||||||
|
|
||||||
|
ctx.drawTextRight = function(font,size,x,y,text) {
|
||||||
|
var w = CanvasTextFunctions.measure(font,size,text);
|
||||||
|
return CanvasTextFunctions.draw( ctx, font,size,x-w,y,text);
|
||||||
|
};
|
||||||
|
ctx.drawTextCenter = function(font,size,x,y,text) {
|
||||||
|
var w = CanvasTextFunctions.measure(font,size,text);
|
||||||
|
return CanvasTextFunctions.draw( ctx, font,size,x-w/2,y,text);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
170
src/netdaemon/www/js/gnuplot_common.js
Normal file
170
src/netdaemon/www/js/gnuplot_common.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
/*
|
||||||
|
* $Id: gnuplot_common.js,v 1.10 2012/05/03 20:35:22 sfeam Exp $
|
||||||
|
*/
|
||||||
|
// Shared routines for gnuplot's HTML5 canvas terminal driver.
|
||||||
|
|
||||||
|
var gnuplot = { };
|
||||||
|
|
||||||
|
gnuplot.common_version = "3 May 2012";
|
||||||
|
|
||||||
|
gnuplot.L = function (x,y) {
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var zoom = gnuplot.zoomXY(x/10.0,y/10.0);
|
||||||
|
ctx.lineTo(zoom.x,zoom.y);
|
||||||
|
} else
|
||||||
|
ctx.lineTo(x/10.0,y/10.0);
|
||||||
|
}
|
||||||
|
gnuplot.M = function (x,y) {
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var zoom = gnuplot.zoomXY(x/10.0,y/10.0);
|
||||||
|
ctx.moveTo(zoom.x,zoom.y);
|
||||||
|
} else
|
||||||
|
ctx.moveTo(x/10.0,y/10.0);
|
||||||
|
}
|
||||||
|
gnuplot.R = function (x,y,w,h) {
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var dx, dy, dw, dh;
|
||||||
|
var zoom = gnuplot.zoomXY(x/10.0,y/10.0);
|
||||||
|
if (zoom.x >= gnuplot.plot_xmax) return;
|
||||||
|
if (zoom.y >= gnuplot.plot_ybot) return;
|
||||||
|
dx = zoom.x; dy = zoom.y;
|
||||||
|
zoom = gnuplot.zoomXY((x+w)/10.,(y+h)/10.);
|
||||||
|
if (zoom.xraw <= gnuplot.plot_xmin) return;
|
||||||
|
if (zoom.yraw <= gnuplot.plot_ytop) return;
|
||||||
|
dw = zoom.x - dx; dh = zoom.y -dy;
|
||||||
|
ctx.fillRect(dx, dy, dw, dh);
|
||||||
|
} else
|
||||||
|
ctx.fillRect(x/10.0, y/10.0, w/10.0, h/10.0);
|
||||||
|
}
|
||||||
|
gnuplot.T = function (x,y,fontsize,justify,string) {
|
||||||
|
var xx = x/10.0; var yy = y/10.0;
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var zoom = gnuplot.zoomXY(xx,yy);
|
||||||
|
if (zoom.clip) return;
|
||||||
|
xx = zoom.x; yy = zoom.y;
|
||||||
|
if (gnuplot.plot_xmin < xx && xx < gnuplot.plot_xmax && gnuplot.plot_ybot > yy && yy > gnuplot.plot_ytop)
|
||||||
|
if ((typeof(gnuplot.zoom_text) != "undefined") && (gnuplot.zoom_text == true))
|
||||||
|
fontsize = Math.sqrt(gnuplot.zoomW(fontsize)*gnuplot.zoomH(fontsize));
|
||||||
|
}
|
||||||
|
if (justify=="") ctx.drawText("sans", fontsize, xx, yy, string);
|
||||||
|
else if (justify=="Right") ctx.drawTextRight("sans", fontsize, xx, yy, string);
|
||||||
|
else if (justify=="Center") ctx.drawTextCenter("sans", fontsize, xx, yy, string);
|
||||||
|
}
|
||||||
|
gnuplot.TR = function (x,y,angle,fontsize,justify,string) {
|
||||||
|
var xx = x/10.0; var yy = y/10.0;
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var zoom = gnuplot.zoomXY(xx,yy);
|
||||||
|
if (zoom.clip) return;
|
||||||
|
xx = zoom.x; yy = zoom.y;
|
||||||
|
if (gnuplot.plot_xmin < xx && xx < gnuplot.plot_xmax && gnuplot.plot_ybot > yy && yy > gnuplot.plot_ytop)
|
||||||
|
if ((typeof(gnuplot.zoom_text) != "undefined") && (gnuplot.zoom_text == true))
|
||||||
|
fontsize = Math.sqrt(gnuplot.zoomW(fontsize)*gnuplot.zoomH(fontsize));
|
||||||
|
}
|
||||||
|
ctx.save();
|
||||||
|
ctx.translate(xx,yy);
|
||||||
|
ctx.rotate(angle * Math.PI / 180);
|
||||||
|
if (justify=="") ctx.drawText("sans", fontsize, 0, 0, string);
|
||||||
|
else if (justify=="Right") ctx.drawTextRight("sans", fontsize, 0, 0, string);
|
||||||
|
else if (justify=="Center") ctx.drawTextCenter("sans", fontsize, 0, 0, string);
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
gnuplot.bp = function (x,y) // begin polygon
|
||||||
|
{ ctx.beginPath(); gnuplot.M(x,y); }
|
||||||
|
gnuplot.cfp = function () // close and fill polygon
|
||||||
|
{ ctx.closePath(); ctx.fill(); }
|
||||||
|
gnuplot.cfsp = function () // close and fill polygon with stroke color
|
||||||
|
{ ctx.closePath(); ctx.fillStyle = ctx.strokeStyle; ctx.stroke(); ctx.fill(); }
|
||||||
|
gnuplot.Dot = function (x,y) {
|
||||||
|
var xx = x; var yy = y;
|
||||||
|
if (gnuplot.zoomed) {zoom = gnuplot.zoomXY(xx,yy); xx = zoom.x; yy = zoom.y; if (zoom.clip) return;}
|
||||||
|
ctx.strokeRect(xx,yy,0.5,0.5);
|
||||||
|
}
|
||||||
|
gnuplot.Pt = function (N,x,y,w) {
|
||||||
|
var xx = x; var yy = y;
|
||||||
|
if (gnuplot.zoomed) {var zoom = gnuplot.zoomXY(xx,yy); xx = zoom.x; yy = zoom.y; if (zoom.clip) return;}
|
||||||
|
if (w==0) return;
|
||||||
|
switch (N)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(xx-w,yy); ctx.lineTo(xx+w,yy);
|
||||||
|
ctx.moveTo(xx,yy-w); ctx.lineTo(xx,yy+w);
|
||||||
|
ctx.stroke();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
var ww = w * 3/4;
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(xx-ww,yy-ww); ctx.lineTo(xx+ww,yy+ww);
|
||||||
|
ctx.moveTo(xx+ww,yy-ww); ctx.lineTo(xx-ww,yy+ww);
|
||||||
|
ctx.stroke();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
gnuplot.Pt(0,x,y,w); gnuplot.Pt(1,x,y,w);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
ctx.strokeRect(xx-w/2,yy-w/2,w,w);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
ctx.save(); ctx.strokeRect(xx-w/2,yy-w/2,w,w); ctx.restore();
|
||||||
|
ctx.fillRect(xx-w/2,yy-w/2,w,w);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
ctx.beginPath(); ctx.arc(xx,yy,w/2,0,Math.PI*2,true); ctx.stroke();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 6:
|
||||||
|
ctx.beginPath(); ctx.arc(xx,yy,w/2,0,Math.PI*2,true); ctx.fill();
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(xx,yy-w); ctx.lineTo(xx-w,yy+w/2); ctx.lineTo(xx+w,yy+w/2);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.stroke();
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(xx,yy-w); ctx.lineTo(xx-w,yy+w/2); ctx.lineTo(xx+w,yy+w/2);
|
||||||
|
ctx.closePath();
|
||||||
|
ctx.fill();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Zoomable image
|
||||||
|
gnuplot.ZI = function (image, m, n, x1, y1, x2, y2) {
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var sx, sy, sw, sh, dx, dy, dw, dh;
|
||||||
|
|
||||||
|
var zoom = gnuplot.zoomXY(x1/10.0,y1/10.0);
|
||||||
|
if (zoom.x >= gnuplot.plot_xmax) return;
|
||||||
|
if (zoom.y >= gnuplot.plot_ybot) return;
|
||||||
|
x1raw = zoom.xraw; y1raw = zoom.yraw;
|
||||||
|
dx = zoom.x; dy = zoom.y;
|
||||||
|
|
||||||
|
zoom = gnuplot.zoomXY((x2)/10.,(y2)/10.);
|
||||||
|
if (zoom.xraw <= gnuplot.plot_xmin) return;
|
||||||
|
if (zoom.yraw <= gnuplot.plot_ytop) return;
|
||||||
|
var x2raw = zoom.xraw; var y2raw = zoom.yraw;
|
||||||
|
dw = zoom.x - dx; dh = zoom.y - dy;
|
||||||
|
|
||||||
|
// FIXME: This is sometimes flaky. Needs integer truncation?
|
||||||
|
sx = 0; sy = 0; sw = m; sh = n;
|
||||||
|
if (x1raw < dx) sx = m * (dx - x1raw) / (x2raw - x1raw);
|
||||||
|
if (y1raw < dy) sy = n * (dy - y1raw) / (y2raw - y1raw);
|
||||||
|
if (x2raw > zoom.x)
|
||||||
|
sw = m * (1. - ((x2raw - zoom.x) / (x2raw - x1raw)));
|
||||||
|
if (y2raw > zoom.y)
|
||||||
|
sh = n * (1. - ((y2raw - zoom.y) / (y2raw - y1raw)));
|
||||||
|
sw = sw - sx; sh = sh - sy;
|
||||||
|
|
||||||
|
ctx.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
|
||||||
|
} else
|
||||||
|
ctx.drawImage(image, x1/10.0, y1/10.0, (x2-x1)/10.0, (y2-y1)/10.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// These methods are place holders that are loaded by gnuplot_dashedlines.js
|
||||||
|
|
||||||
|
gnuplot.dashtype = function (dt) {} ;
|
||||||
|
gnuplot.dashstart = function (x,y) {gnuplot.M(x,y);} ;
|
||||||
|
gnuplot.dashstep = function (x,y) {gnuplot.L(x,y);} ;
|
||||||
|
gnuplot.pattern = [];
|
||||||
68
src/netdaemon/www/js/gnuplot_dashedlines.js
Normal file
68
src/netdaemon/www/js/gnuplot_dashedlines.js
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* $Id: gnuplot_dashedlines.js,v 1.3 2012/05/03 20:35:22 sfeam Exp $
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Ethan Merritt November 2010
|
||||||
|
* Add a dashed line method to gnuplot's HTML5 canvas toolset.
|
||||||
|
* To start a path use DS(x0,y0) instead of M(x0,y0)
|
||||||
|
* To draw line segments use DL(x,y) instead of L(x,y)
|
||||||
|
* Finish as usual with ctx.stroke(); ctx.closePath();
|
||||||
|
*/
|
||||||
|
|
||||||
|
gnuplot.solid = [];
|
||||||
|
gnuplot.dashpattern1 = gnuplot.solid;
|
||||||
|
gnuplot.dashpattern2 = [ 0.5, 1.0 ];
|
||||||
|
gnuplot.dashpattern3 = [ .12, .25, .37, .50, .62, .75, .87, 1.0 ];
|
||||||
|
gnuplot.dashpattern4 = [ 0.50, 0.70, 0.80, 1.0 ];
|
||||||
|
gnuplot.dashpattern5 = [ 0.30, 0.50, 0.60, 0.75, 0.85, 1.0 ];
|
||||||
|
|
||||||
|
gnuplot.dashlength = 200.; // length of one complete pattern
|
||||||
|
gnuplot.dashfraction = 0; // how far in the pattern we got last time
|
||||||
|
gnuplot.dash_x = 0;
|
||||||
|
gnuplot.dash_y = 0;
|
||||||
|
|
||||||
|
gnuplot.dashtype = function(dt) {
|
||||||
|
gnuplot.pattern = dt;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.dashstart = function(x,y) {
|
||||||
|
gnuplot.dash_x = x;
|
||||||
|
gnuplot.dash_y = y;
|
||||||
|
gnuplot.dashfraction = 0;
|
||||||
|
gnuplot.M(x,y);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.dashstep = function(x,y) {
|
||||||
|
var delx = x - gnuplot.dash_x;
|
||||||
|
var dely = y - gnuplot.dash_y;
|
||||||
|
var stride = Math.sqrt(delx*delx + dely*dely) / gnuplot.dashlength;
|
||||||
|
var this_step; var new_x, new_y;
|
||||||
|
|
||||||
|
if (gnuplot.pattern.length == 0) {gnuplot.L(x,y); return;}
|
||||||
|
|
||||||
|
while (stride > 0) {
|
||||||
|
// Find which piece of the pattern we are in
|
||||||
|
for (i=0; gnuplot.pattern[i] <= gnuplot.dashfraction; i++);
|
||||||
|
|
||||||
|
this_step = gnuplot.pattern[i] - gnuplot.dashfraction;
|
||||||
|
if (stride > this_step) {
|
||||||
|
new_x = gnuplot.dash_x + delx*this_step/stride;
|
||||||
|
new_y = gnuplot.dash_y + dely*this_step/stride;
|
||||||
|
stride = stride - this_step;
|
||||||
|
gnuplot.dashfraction = gnuplot.pattern[i];
|
||||||
|
delx = x - new_x;
|
||||||
|
dely = y - new_y;
|
||||||
|
} else {
|
||||||
|
new_x = x;
|
||||||
|
new_y = y;
|
||||||
|
gnuplot.dashfraction = gnuplot.dashfraction + stride;
|
||||||
|
stride = 0;
|
||||||
|
}
|
||||||
|
if (i%2==0) gnuplot.L(new_x,new_y);
|
||||||
|
else gnuplot.M(new_x,new_y);
|
||||||
|
|
||||||
|
gnuplot.dash_x = new_x;
|
||||||
|
gnuplot.dash_y = new_y;
|
||||||
|
if (gnuplot.dashfraction >= 1.0) gnuplot.dashfraction = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/netdaemon/www/js/gnuplot_mouse.css
Normal file
19
src/netdaemon/www/js/gnuplot_mouse.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
canvas { border:0; background-color: white; }
|
||||||
|
td.mousebox { vertical-align: top; }
|
||||||
|
td.mbh { height: 16pt; }
|
||||||
|
td.mb0 { text-align: left; font-size: smaller; width: 20px; padding-left: 15px;
|
||||||
|
color:#000; background-color: #EEE}
|
||||||
|
td.mb1 { text-align: left; font-size: smaller; width: 80px; padding-left: 15px;
|
||||||
|
color:#070; background-color: #EEE}
|
||||||
|
td.icon { width: 16px; height: 16px; font-size: 14px; text-align: right;
|
||||||
|
background-color: #EEE}
|
||||||
|
td.blank { height: 16px; font-size: 12pt; text-align: right;
|
||||||
|
background-color: #EEE}
|
||||||
|
.icon-image { float:right; margin: 0 0 0 0; }
|
||||||
|
.noborder { border: 0; vertical-align: text-top; }
|
||||||
|
table.mbleft { border-collapse: collapse; border: 0; margin-left: auto; margin-right: auto; }
|
||||||
|
table.mbright { border-collapse: collapse; border: 0; margin-left: 0; margin-right: auto; }
|
||||||
|
table.mbunder { border-collapse: collapse; border: 0; margin-left: auto; margin-right: auto; }
|
||||||
|
table.plot { border-collapse: collapse; border: 0; margin-left: auto; margin-right: auto; }
|
||||||
|
table.mousebox { border-collapse: collapse; margin-left: 0; margin-right: 10px; border: 0; }
|
||||||
|
div.gnuplot { background-color: white; }
|
||||||
619
src/netdaemon/www/js/gnuplot_mouse.js
Normal file
619
src/netdaemon/www/js/gnuplot_mouse.js
Normal file
@ -0,0 +1,619 @@
|
|||||||
|
/*
|
||||||
|
* $Id: gnuplot_mouse.js,v 1.28 2017/02/17 21:27:53 sfeam Exp $
|
||||||
|
*/
|
||||||
|
gnuplot.mouse_version = " 17 February 2017";
|
||||||
|
|
||||||
|
// Mousing code for use with gnuplot's 'canvas' terminal driver.
|
||||||
|
// The functions defined here assume that the javascript plot produced by
|
||||||
|
// gnuplot initializes the plot boundary and scaling parameters.
|
||||||
|
|
||||||
|
gnuplot.mousex = 0;
|
||||||
|
gnuplot.mousey = 0;
|
||||||
|
gnuplot.plotx = 0;
|
||||||
|
gnuplot.ploty = 0;
|
||||||
|
gnuplot.scaled_x = 0;
|
||||||
|
gnuplot.scaled_y = 0;
|
||||||
|
|
||||||
|
// These will be initialized by the gnuplot canvas-drawing function
|
||||||
|
gnuplot.plot_xmin = 0;
|
||||||
|
gnuplot.plot_xmax = 0;
|
||||||
|
gnuplot.plot_ybot = 0;
|
||||||
|
gnuplot.plot_ytop = 0;
|
||||||
|
gnuplot.plot_width = 0
|
||||||
|
gnuplot.plot_height = 0
|
||||||
|
gnuplot.plot_term_ymax = 0;
|
||||||
|
gnuplot.plot_axis_xmin = 0;
|
||||||
|
gnuplot.plot_axis_xmax = 0;
|
||||||
|
gnuplot.plot_axis_width = 0;
|
||||||
|
gnuplot.plot_axis_height = 0;
|
||||||
|
gnuplot.plot_axis_ymin = 0;
|
||||||
|
gnuplot.plot_axis_ymax = 0;
|
||||||
|
gnuplot.plot_axis_x2min = "none";
|
||||||
|
gnuplot.plot_axis_y2min = "none";
|
||||||
|
gnuplot.plot_logaxis_x = 0;
|
||||||
|
gnuplot.plot_logaxis_y = 0;
|
||||||
|
gnuplot.grid_lines = true;
|
||||||
|
gnuplot.zoom_text = false;
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
|
||||||
|
// These are the equivalent parameters while zooming
|
||||||
|
gnuplot.zoom_axis_xmin = 0;
|
||||||
|
gnuplot.zoom_axis_xmax = 0;
|
||||||
|
gnuplot.zoom_axis_ymin = 0;
|
||||||
|
gnuplot.zoom_axis_ymax = 0;
|
||||||
|
gnuplot.zoom_axis_x2min = 0;
|
||||||
|
gnuplot.zoom_axis_x2max = 0;
|
||||||
|
gnuplot.zoom_axis_y2min = 0;
|
||||||
|
gnuplot.zoom_axis_y2max = 0;
|
||||||
|
gnuplot.zoom_axis_width = 0;
|
||||||
|
gnuplot.zoom_axis_height = 0;
|
||||||
|
gnuplot.zoom_temp_xmin = 0;
|
||||||
|
gnuplot.zoom_temp_ymin = 0;
|
||||||
|
gnuplot.zoom_temp_x2min = 0;
|
||||||
|
gnuplot.zoom_temp_y2min = 0;
|
||||||
|
gnuplot.zoom_in_progress = false;
|
||||||
|
|
||||||
|
gnuplot.full_canvas_image = null;
|
||||||
|
gnuplot.axisdate = new Date();
|
||||||
|
|
||||||
|
gnuplot.init = function ()
|
||||||
|
{
|
||||||
|
if (document.getElementById("gnuplot_canvas"))
|
||||||
|
document.getElementById("gnuplot_canvas").onmousemove = gnuplot.mouse_update;
|
||||||
|
if (document.getElementById("gnuplot_canvas"))
|
||||||
|
document.getElementById("gnuplot_canvas").onmouseup = gnuplot.zoom_in;
|
||||||
|
if (document.getElementById("gnuplot_canvas"))
|
||||||
|
document.getElementById("gnuplot_canvas").onmousedown = gnuplot.saveclick;
|
||||||
|
if (document.getElementById("gnuplot_canvas"))
|
||||||
|
document.getElementById("gnuplot_canvas").onkeydown = gnuplot.do_hotkey;
|
||||||
|
if (document.getElementById("gnuplot_grid_icon"))
|
||||||
|
document.getElementById("gnuplot_grid_icon").onmouseup = gnuplot.toggle_grid;
|
||||||
|
if (document.getElementById("gnuplot_textzoom_icon"))
|
||||||
|
document.getElementById("gnuplot_textzoom_icon").onmouseup = gnuplot.toggle_zoom_text;
|
||||||
|
if (document.getElementById("gnuplot_rezoom_icon"))
|
||||||
|
document.getElementById("gnuplot_rezoom_icon").onmouseup = gnuplot.rezoom;
|
||||||
|
if (document.getElementById("gnuplot_unzoom_icon"))
|
||||||
|
document.getElementById("gnuplot_unzoom_icon").onmouseup = gnuplot.unzoom;
|
||||||
|
gnuplot.mouse_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.getMouseCoordsWithinTarget = function(event)
|
||||||
|
{
|
||||||
|
var coords = { x: 0, y: 0};
|
||||||
|
|
||||||
|
if(!event) // then we're in a non-DOM (probably IE) browser
|
||||||
|
{
|
||||||
|
event = window.event;
|
||||||
|
if (event) {
|
||||||
|
coords.x = event.offsetX;
|
||||||
|
coords.y = event.offsetY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // we assume DOM modeled javascript
|
||||||
|
{
|
||||||
|
var Element = event.target ;
|
||||||
|
var CalculatedTotalOffsetLeft = 0;
|
||||||
|
var CalculatedTotalOffsetTop = 0 ;
|
||||||
|
|
||||||
|
while (Element.offsetParent)
|
||||||
|
{
|
||||||
|
CalculatedTotalOffsetLeft += Element.offsetLeft ;
|
||||||
|
CalculatedTotalOffsetTop += Element.offsetTop ;
|
||||||
|
Element = Element.offsetParent ;
|
||||||
|
}
|
||||||
|
|
||||||
|
coords.x = event.pageX - CalculatedTotalOffsetLeft ;
|
||||||
|
coords.y = event.pageY - CalculatedTotalOffsetTop ;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.mousex = coords.x;
|
||||||
|
gnuplot.mousey = coords.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gnuplot.mouse_update = function(e)
|
||||||
|
{
|
||||||
|
gnuplot.getMouseCoordsWithinTarget(e);
|
||||||
|
|
||||||
|
gnuplot.plotx = gnuplot.mousex - gnuplot.plot_xmin;
|
||||||
|
gnuplot.ploty = -(gnuplot.mousey - gnuplot.plot_ybot);
|
||||||
|
|
||||||
|
// Limit tracking to the interior of the plot
|
||||||
|
if (gnuplot.plotx < 0 || gnuplot.ploty < 0){
|
||||||
|
if (gnuplot.hypertext_list != "undefined" && gnuplot.hypertext_list.length > 0) {
|
||||||
|
gnuplot.check_hypertext();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (gnuplot.mousex > gnuplot.plot_xmax || gnuplot.mousey < gnuplot.plot_ytop){
|
||||||
|
if (gnuplot.hypertext_list != "undefined" && gnuplot.hypertext_list.length > 0) {
|
||||||
|
gnuplot.check_hypertext();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var axis_xmin = (gnuplot.zoomed) ? gnuplot.zoom_axis_xmin : gnuplot.plot_axis_xmin;
|
||||||
|
var axis_xmax = (gnuplot.zoomed) ? gnuplot.zoom_axis_xmax : gnuplot.plot_axis_xmax;
|
||||||
|
var axis_ymin = (gnuplot.zoomed) ? gnuplot.zoom_axis_ymin : gnuplot.plot_axis_ymin;
|
||||||
|
var axis_ymax = (gnuplot.zoomed) ? gnuplot.zoom_axis_ymax : gnuplot.plot_axis_ymax;
|
||||||
|
|
||||||
|
if (gnuplot.plot_logaxis_x != 0) {
|
||||||
|
x = Math.log(axis_xmax) - Math.log(axis_xmin);
|
||||||
|
x = x * (gnuplot.plotx / (gnuplot.plot_xmax-gnuplot.plot_xmin)) + Math.log(axis_xmin);
|
||||||
|
x = Math.exp(x);
|
||||||
|
} else {
|
||||||
|
x = axis_xmin + (gnuplot.plotx / (gnuplot.plot_xmax-gnuplot.plot_xmin)) * (axis_xmax - axis_xmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnuplot.plot_logaxis_y != 0) {
|
||||||
|
y = Math.log(axis_ymax) - Math.log(axis_ymin);
|
||||||
|
y = y * (-gnuplot.ploty / (gnuplot.plot_ytop-gnuplot.plot_ybot)) + Math.log(axis_ymin);
|
||||||
|
y = Math.exp(y);
|
||||||
|
} else {
|
||||||
|
y = axis_ymin - (gnuplot.ploty / (gnuplot.plot_ytop-gnuplot.plot_ybot)) * (axis_ymax - axis_ymin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnuplot.plot_axis_x2min != "none") {
|
||||||
|
gnuplot.axis_x2min = (gnuplot.zoomed) ? gnuplot.zoom_axis_x2min : gnuplot.plot_axis_x2min;
|
||||||
|
gnuplot.axis_x2max = (gnuplot.zoomed) ? gnuplot.zoom_axis_x2max : gnuplot.plot_axis_x2max;
|
||||||
|
if (gnuplot.x2_mapping != undefined)
|
||||||
|
x2 = gnuplot.x2_mapping(x);
|
||||||
|
else
|
||||||
|
x2 = gnuplot.axis_x2min + (gnuplot.plotx / (gnuplot.plot_xmax-gnuplot.plot_xmin)) * (gnuplot.axis_x2max - gnuplot.axis_x2min);
|
||||||
|
if (document.getElementById(gnuplot.active_plot_name + "_x2"))
|
||||||
|
document.getElementById(gnuplot.active_plot_name + "_x2").innerHTML = x2.toPrecision(4);
|
||||||
|
}
|
||||||
|
if (gnuplot.plot_axis_y2min != "none") {
|
||||||
|
gnuplot.axis_y2min = (gnuplot.zoomed) ? gnuplot.zoom_axis_y2min : gnuplot.plot_axis_y2min;
|
||||||
|
gnuplot.axis_y2max = (gnuplot.zoomed) ? gnuplot.zoom_axis_y2max : gnuplot.plot_axis_y2max;
|
||||||
|
if (gnuplot.y2_mapping != undefined)
|
||||||
|
y2 = gnuplot.y2_mapping(y);
|
||||||
|
else
|
||||||
|
y2 = gnuplot.axis_y2min - (gnuplot.ploty / (gnuplot.plot_ytop-gnuplot.plot_ybot)) * (gnuplot.axis_y2max - gnuplot.axis_y2min);
|
||||||
|
if (document.getElementById(gnuplot.active_plot_name + "_y2"))
|
||||||
|
document.getElementById(gnuplot.active_plot_name + "_y2").innerHTML = y2.toPrecision(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
var label_x, label_y;
|
||||||
|
if (gnuplot.polar_mode) {
|
||||||
|
var polar = gnuplot.convert_to_polar(x,y);
|
||||||
|
label_x = "ang= " + polar.ang.toPrecision(4);
|
||||||
|
label_y = "R= " + polar.r.toPrecision(4);
|
||||||
|
} else {
|
||||||
|
if (typeof(gnuplot.plot_timeaxis_x) == "string" && gnuplot.plot_timeaxis_x != "")
|
||||||
|
label_x = gnuplot.datafmt(x);
|
||||||
|
else
|
||||||
|
label_x = x.toPrecision(4);
|
||||||
|
if (typeof(gnuplot.plot_timeaxis_y) == "string" && gnuplot.plot_timeaxis_y != "")
|
||||||
|
label_y = gnuplot.datafmt(y);
|
||||||
|
else
|
||||||
|
label_y = y.toPrecision(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.getElementById(gnuplot.active_plot_name + "_x"))
|
||||||
|
document.getElementById(gnuplot.active_plot_name + "_x").innerHTML = label_x;
|
||||||
|
if (document.getElementById(gnuplot.active_plot_name + "_y"))
|
||||||
|
document.getElementById(gnuplot.active_plot_name + "_y").innerHTML = label_y;
|
||||||
|
|
||||||
|
// Echo the zoom box interactively
|
||||||
|
if (gnuplot.zoom_in_progress) {
|
||||||
|
// Clear previous box before drawing a new one
|
||||||
|
if (gnuplot.full_canvas_image == null) {
|
||||||
|
gnuplot.full_canvas_image = ctx.getImageData(0,0,canvas.width,canvas.height);
|
||||||
|
} else {
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
ctx.putImageData(gnuplot.full_canvas_image,0,0);
|
||||||
|
}
|
||||||
|
ctx.strokeStyle="rgba(128,128,128,0.60)";
|
||||||
|
var x0 = gnuplot.plot_xmin + gnuplot.zoom_temp_plotx;
|
||||||
|
var y0 = gnuplot.plot_ybot - gnuplot.zoom_temp_ploty;
|
||||||
|
var w = gnuplot.plotx - gnuplot.zoom_temp_plotx;
|
||||||
|
var h = -(gnuplot.ploty - gnuplot.zoom_temp_ploty);
|
||||||
|
if (w<0) {x0 = x0 + w; w = -w;}
|
||||||
|
if (h<0) {y0 = y0 + h; h = -h;}
|
||||||
|
ctx.strokeRect(x0,y0,w,h);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if we are over a hypertext anchor point
|
||||||
|
if (gnuplot.hypertext_list != "undefined" && gnuplot.hypertext_list.length > 0) {
|
||||||
|
gnuplot.check_hypertext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.check_hypertext = function()
|
||||||
|
{
|
||||||
|
var nitems = gnuplot.hypertext_list.length;
|
||||||
|
for (var i=0; i<nitems; i++) {
|
||||||
|
var linkx = gnuplot.hypertext_list[i].x / 10.;
|
||||||
|
var linky = gnuplot.hypertext_list[i].y / 10.;
|
||||||
|
if (gnuplot.zoomed) {
|
||||||
|
var zoom = gnuplot.zoomXY(linkx,linky);
|
||||||
|
linkx = zoom.x; linky = zoom.y;
|
||||||
|
}
|
||||||
|
var delx = Math.abs(gnuplot.mousex - linkx);
|
||||||
|
var dely = Math.abs(gnuplot.mousey - linky);
|
||||||
|
var w = gnuplot.hypertext_list[i].w / 20.;
|
||||||
|
if (delx < w && dely < w) {
|
||||||
|
if (i == gnuplot.on_hypertext)
|
||||||
|
break;
|
||||||
|
gnuplot.on_hypertext = i;
|
||||||
|
var text = gnuplot.hypertext_list[i].text;
|
||||||
|
var lines = text.split('\v');
|
||||||
|
var len = 0;
|
||||||
|
if (lines.length <= 1) {
|
||||||
|
len = ctx.measureText("sans", 10, text);
|
||||||
|
} else {
|
||||||
|
for (var l=0; l<lines.length; l++) {
|
||||||
|
var ll = ctx.measureText("sans", 10, lines[l]);
|
||||||
|
if (len < ll) len = ll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// text shift (so it is not covered by cursor)
|
||||||
|
var shiftx = 14;
|
||||||
|
|
||||||
|
if (linkx > gnuplot.plot_term_xmax-(len+8) ){
|
||||||
|
// position text left of cursor if we are to far in the right hemisphere
|
||||||
|
// else we might print over the border
|
||||||
|
linkx = linkx - len;
|
||||||
|
shiftx = -shiftx;
|
||||||
|
}
|
||||||
|
if (linky > 14*lines.length ){
|
||||||
|
// position text top of cursor if we are low enough in the plot
|
||||||
|
// else we might print over the border
|
||||||
|
linky = linky - 14*lines.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.fillStyle = "rgba(238,238,238,0.8)"
|
||||||
|
ctx.fillRect(linkx+shiftx, linky+4, len+8, 14*lines.length);
|
||||||
|
for (var l=0; l<lines.length; l++) {
|
||||||
|
ctx.drawText("sans", 10, linkx+shiftx+4, linky+14+l*14, lines[l]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i == nitems && gnuplot.on_hypertext >= 0) {
|
||||||
|
gnuplot.on_hypertext = -1;
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.datafmt = function (x)
|
||||||
|
{
|
||||||
|
if (gnuplot.plot_timeaxis_x == "DMS") {
|
||||||
|
return gnuplot.convert_to_DMS(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gnuplot 4.6 used (x + 946684800)
|
||||||
|
gnuplot.axisdate.setTime(1000. * x);
|
||||||
|
|
||||||
|
if (gnuplot.plot_timeaxis_x == "DateTime") {
|
||||||
|
return gnuplot.axisdate.toUTCString();
|
||||||
|
}
|
||||||
|
if (gnuplot.plot_timeaxis_x == "Date") {
|
||||||
|
var year = gnuplot.axisdate.getUTCFullYear();
|
||||||
|
var month = gnuplot.axisdate.getUTCMonth();
|
||||||
|
var date = gnuplot.axisdate.getUTCDate();
|
||||||
|
return (" " + date).slice (-2) + "/"
|
||||||
|
+ ("0" + (month+1)).slice (-2) + "/"
|
||||||
|
+ year;
|
||||||
|
}
|
||||||
|
if (gnuplot.plot_timeaxis_x == "Time") {
|
||||||
|
var hour = gnuplot.axisdate.getUTCHours();
|
||||||
|
var minute = gnuplot.axisdate.getUTCMinutes();
|
||||||
|
var second = gnuplot.axisdate.getUTCSeconds();
|
||||||
|
return ("0" + hour).slice (-2) + ":"
|
||||||
|
+ ("0" + minute).slice (-2) + ":"
|
||||||
|
+ ("0" + second).slice (-2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.convert_to_DMS = function (x)
|
||||||
|
{
|
||||||
|
var dms = {d:0, m:0, s:0};
|
||||||
|
var deg = Math.abs(x);
|
||||||
|
dms.d = Math.floor(deg);
|
||||||
|
dms.m = Math.floor((deg - dms.d) * 60.);
|
||||||
|
dms.s = Math.floor((deg - dms.d) * 3600. - dms.m * 60.);
|
||||||
|
fmt = ((x<0)?"-":" ")
|
||||||
|
+ dms.d.toFixed(0) + "°"
|
||||||
|
+ dms.m.toFixed(0) + "\""
|
||||||
|
+ dms.s.toFixed(0) + "'";
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.convert_to_polar = function (x,y)
|
||||||
|
{
|
||||||
|
var polar = new Object;
|
||||||
|
var phi, r;
|
||||||
|
phi = Math.atan2(y,x);
|
||||||
|
if (gnuplot.plot_logaxis_r)
|
||||||
|
r = Math.exp( (x/Math.cos(phi) + Math.log(gnuplot.plot_axis_rmin)/Math.LN10) * Math.LN10);
|
||||||
|
else if (gnuplot.plot_axis_rmin > gnuplot.plot_axis_rmax)
|
||||||
|
r = gnuplot.plot_axis_rmin - x/Math.cos(phi);
|
||||||
|
else
|
||||||
|
r = gnuplot.plot_axis_rmin + x/Math.cos(phi);
|
||||||
|
phi = phi * (180./Math.PI);
|
||||||
|
if (gnuplot.polar_sense < 0)
|
||||||
|
phi = -phi;
|
||||||
|
if (gnuplot.polar_theta0 != undefined)
|
||||||
|
phi = phi + gnuplot.polar_theta0;
|
||||||
|
if (phi > 180.)
|
||||||
|
phi = phi - 360.;
|
||||||
|
polar.r = r;
|
||||||
|
polar.ang = phi;
|
||||||
|
return polar;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.saveclick = function (event)
|
||||||
|
{
|
||||||
|
gnuplot.mouse_update(event);
|
||||||
|
var button, label_x, label_y;
|
||||||
|
|
||||||
|
// Limit tracking to the interior of the plot
|
||||||
|
if (gnuplot.plotx < 0 || gnuplot.ploty < 0) return;
|
||||||
|
if (gnuplot.mousex > gnuplot.plot_xmax || gnuplot.mousey < gnuplot.plot_ytop) return;
|
||||||
|
|
||||||
|
if (event.which == null) /* IE case */
|
||||||
|
button= (event.button < 2) ? "LEFT" : ((event.button == 4) ? "MIDDLE" : "RIGHT");
|
||||||
|
else /* All others */
|
||||||
|
button= (event.which < 2) ? "LEFT" : ((event.which == 2) ? "MIDDLE" : "RIGHT");
|
||||||
|
|
||||||
|
if (button == "LEFT") {
|
||||||
|
ctx.strokeStyle="black";
|
||||||
|
ctx.strokeRect(gnuplot.mousex, gnuplot.mousey, 1, 1);
|
||||||
|
if (typeof(gnuplot.plot_timeaxis_x) == "string" && gnuplot.plot_timeaxis_x != "")
|
||||||
|
label_x = gnuplot.datafmt(x);
|
||||||
|
else
|
||||||
|
label_x = x.toPrecision(4);
|
||||||
|
if (typeof(gnuplot.plot_timeaxis_y) == "string" && gnuplot.plot_timeaxis_y != "")
|
||||||
|
label_y = gnuplot.datafmt(y);
|
||||||
|
else
|
||||||
|
label_y = y.toPrecision(4);
|
||||||
|
click = " " + label_x + ", " + label_y;
|
||||||
|
|
||||||
|
var len = ctx.measureText("sans", 9, click);
|
||||||
|
if (gnuplot.mousex > gnuplot.plot_term_xmax-(len) ){
|
||||||
|
// draw left of cursor when we are near the right side of the plot
|
||||||
|
len += ctx.measureText("sans", 9, " ");
|
||||||
|
ctx.drawText("sans", 9, gnuplot.mousex-len, gnuplot.mousey, click);
|
||||||
|
} else {
|
||||||
|
ctx.drawText("sans", 9, gnuplot.mousex, gnuplot.mousey, click);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save starting corner of zoom box
|
||||||
|
else {
|
||||||
|
gnuplot.zoom_temp_xmin = x;
|
||||||
|
gnuplot.zoom_temp_ymin = y;
|
||||||
|
if (gnuplot.plot_axis_x2min != "none") gnuplot.zoom_temp_x2min = x2;
|
||||||
|
if (gnuplot.plot_axis_y2min != "none") gnuplot.zoom_temp_y2min = y2;
|
||||||
|
// Only used to echo the zoom box interactively
|
||||||
|
gnuplot.zoom_temp_plotx = gnuplot.plotx;
|
||||||
|
gnuplot.zoom_temp_ploty = gnuplot.ploty;
|
||||||
|
gnuplot.zoom_in_progress = true;
|
||||||
|
gnuplot.full_canvas_image = null;
|
||||||
|
}
|
||||||
|
return false; // Nobody else should respond to this event
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.zoom_in = function (event)
|
||||||
|
{
|
||||||
|
if (!gnuplot.zoom_in_progress)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
gnuplot.mouse_update(event);
|
||||||
|
|
||||||
|
var button;
|
||||||
|
|
||||||
|
if (event.which == null) /* IE case */
|
||||||
|
button= (event.button < 2) ? "LEFT" : ((event.button == 4) ? "MIDDLE" : "RIGHT");
|
||||||
|
else /* All others */
|
||||||
|
button= (event.which < 2) ? "LEFT" : ((event.which == 2) ? "MIDDLE" : "RIGHT");
|
||||||
|
|
||||||
|
// Save ending corner of zoom box
|
||||||
|
if (button != "LEFT") {
|
||||||
|
if (x > gnuplot.zoom_temp_xmin) {
|
||||||
|
gnuplot.zoom_axis_xmin = gnuplot.zoom_temp_xmin;
|
||||||
|
gnuplot.zoom_axis_xmax = x;
|
||||||
|
if (gnuplot.plot_axis_x2min != "none") {
|
||||||
|
gnuplot.zoom_axis_x2min = gnuplot.zoom_temp_x2min;
|
||||||
|
gnuplot.zoom_axis_x2max = x2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gnuplot.zoom_axis_xmin = x;
|
||||||
|
gnuplot.zoom_axis_xmax = gnuplot.zoom_temp_xmin;
|
||||||
|
if (gnuplot.plot_axis_x2min != "none") {
|
||||||
|
gnuplot.zoom_axis_x2min = x2;
|
||||||
|
gnuplot.zoom_axis_x2max = gnuplot.zoom_temp_x2min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (y > gnuplot.zoom_temp_ymin) {
|
||||||
|
gnuplot.zoom_axis_ymin = gnuplot.zoom_temp_ymin;
|
||||||
|
gnuplot.zoom_axis_ymax = y;
|
||||||
|
if (gnuplot.plot_axis_y2min != "none") {
|
||||||
|
gnuplot.zoom_axis_y2min = gnuplot.zoom_temp_y2min;
|
||||||
|
gnuplot.zoom_axis_y2max = y2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
gnuplot.zoom_axis_ymin = y;
|
||||||
|
gnuplot.zoom_axis_ymax = gnuplot.zoom_temp_ymin;
|
||||||
|
if (gnuplot.plot_axis_y2min != "none") {
|
||||||
|
gnuplot.zoom_axis_y2min = y2;
|
||||||
|
gnuplot.zoom_axis_y2max = gnuplot.zoom_temp_y2min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gnuplot.zoom_axis_width = gnuplot.zoom_axis_xmax - gnuplot.zoom_axis_xmin;
|
||||||
|
gnuplot.zoom_axis_height = gnuplot.zoom_axis_ymax - gnuplot.zoom_axis_ymin;
|
||||||
|
gnuplot.zoom_in_progress = false;
|
||||||
|
gnuplot.rezoom(event);
|
||||||
|
}
|
||||||
|
return false; // Nobody else should respond to this event
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.toggle_grid = function (e)
|
||||||
|
{
|
||||||
|
if (!gnuplot.grid_lines) gnuplot.grid_lines = true;
|
||||||
|
else gnuplot.grid_lines = false;
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.toggle_zoom_text = function (e)
|
||||||
|
{
|
||||||
|
if (!gnuplot.zoom_text) gnuplot.zoom_text = true;
|
||||||
|
else gnuplot.zoom_text = false;
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.rezoom = function (e)
|
||||||
|
{
|
||||||
|
if (gnuplot.zoom_axis_width > 0)
|
||||||
|
gnuplot.zoomed = true;
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.unzoom = function (e)
|
||||||
|
{
|
||||||
|
gnuplot.zoomed = false;
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.zoomXY = function(x,y)
|
||||||
|
{
|
||||||
|
var zoom = new Object;
|
||||||
|
var xreal, yreal;
|
||||||
|
|
||||||
|
zoom.x = x; zoom.y = y; zoom.clip = false;
|
||||||
|
|
||||||
|
if (gnuplot.plot_logaxis_x != 0) {
|
||||||
|
xreal = Math.log(gnuplot.plot_axis_xmax) - Math.log(gnuplot.plot_axis_xmin);
|
||||||
|
xreal = Math.log(gnuplot.plot_axis_xmin) + (x - gnuplot.plot_xmin) * xreal/gnuplot.plot_width;
|
||||||
|
zoom.x = Math.log(gnuplot.zoom_axis_xmax) - Math.log(gnuplot.zoom_axis_xmin);
|
||||||
|
zoom.x = gnuplot.plot_xmin + (xreal - Math.log(gnuplot.zoom_axis_xmin)) * gnuplot.plot_width/zoom.x;
|
||||||
|
} else {
|
||||||
|
xreal = gnuplot.plot_axis_xmin + (x - gnuplot.plot_xmin) * (gnuplot.plot_axis_width/gnuplot.plot_width);
|
||||||
|
zoom.x = gnuplot.plot_xmin + (xreal - gnuplot.zoom_axis_xmin) * (gnuplot.plot_width/gnuplot.zoom_axis_width);
|
||||||
|
}
|
||||||
|
if (gnuplot.plot_logaxis_y != 0) {
|
||||||
|
yreal = Math.log(gnuplot.plot_axis_ymax) - Math.log(gnuplot.plot_axis_ymin);
|
||||||
|
yreal = Math.log(gnuplot.plot_axis_ymin) + (gnuplot.plot_ybot - y) * yreal/gnuplot.plot_height;
|
||||||
|
zoom.y = Math.log(gnuplot.zoom_axis_ymax) - Math.log(gnuplot.zoom_axis_ymin);
|
||||||
|
zoom.y = gnuplot.plot_ybot - (yreal - Math.log(gnuplot.zoom_axis_ymin)) * gnuplot.plot_height/zoom.y;
|
||||||
|
} else {
|
||||||
|
yreal = gnuplot.plot_axis_ymin + (gnuplot.plot_ybot - y) * (gnuplot.plot_axis_height/gnuplot.plot_height);
|
||||||
|
zoom.y = gnuplot.plot_ybot - (yreal - gnuplot.zoom_axis_ymin) * (gnuplot.plot_height/gnuplot.zoom_axis_height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Report unclipped coords also
|
||||||
|
zoom.xraw = zoom.x; zoom.yraw = zoom.y;
|
||||||
|
|
||||||
|
// Limit the zoomed plot to the original plot area
|
||||||
|
if (x > gnuplot.plot_xmax) {
|
||||||
|
zoom.x = x;
|
||||||
|
if (gnuplot.plot_axis_y2min == "none") {
|
||||||
|
zoom.y = y;
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
if (gnuplot.plot_ybot <= y && y <= gnuplot.plot_ybot + 15)
|
||||||
|
zoom.clip = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (x < gnuplot.plot_xmin)
|
||||||
|
zoom.x = x;
|
||||||
|
else if (zoom.x < gnuplot.plot_xmin)
|
||||||
|
{ zoom.x = gnuplot.plot_xmin; zoom.clip = true; }
|
||||||
|
else if (zoom.x > gnuplot.plot_xmax)
|
||||||
|
{ zoom.x = gnuplot.plot_xmax; zoom.clip = true; }
|
||||||
|
|
||||||
|
if (y < gnuplot.plot_ytop) {
|
||||||
|
zoom.y = y;
|
||||||
|
if (gnuplot.plot_axis_x2min == "none") {
|
||||||
|
zoom.x = x; zoom.clip = false;
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (y > gnuplot.plot_ybot)
|
||||||
|
zoom.y = y;
|
||||||
|
else if (zoom.y > gnuplot.plot_ybot)
|
||||||
|
{ zoom.y = gnuplot.plot_ybot; zoom.clip = true; }
|
||||||
|
else if (zoom.y < gnuplot.plot_ytop)
|
||||||
|
{ zoom.y = gnuplot.plot_ytop; zoom.clip = true; }
|
||||||
|
|
||||||
|
return zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.zoomW = function (w) { return (w*gnuplot.plot_axis_width/gnuplot.zoom_axis_width); }
|
||||||
|
gnuplot.zoomH = function (h) { return (h*gnuplot.plot_axis_height/gnuplot.zoom_axis_height); }
|
||||||
|
|
||||||
|
gnuplot.popup_help = function(URL) {
|
||||||
|
if (typeof(URL) != "string") {
|
||||||
|
if (typeof(gnuplot.help_URL) == "string")
|
||||||
|
URL = gnuplot.help_URL;
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// FIXME: Placeholder for useful action
|
||||||
|
if (URL != "")
|
||||||
|
window.open (URL,"gnuplot help");
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.toggle_plot = function(plotid) {
|
||||||
|
if (typeof(gnuplot["hide_"+plotid]) == "unknown")
|
||||||
|
gnuplot["hide_"+plotid] = false;
|
||||||
|
gnuplot["hide_"+plotid] = !gnuplot["hide_"+plotid];
|
||||||
|
ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot.do_hotkey = function(event) {
|
||||||
|
keychar = String.fromCharCode(event.charCode ? event.charCode : event.keyCode);
|
||||||
|
switch (keychar) {
|
||||||
|
case 'e': ctx.clearRect(0,0,gnuplot.plot_term_xmax,gnuplot.plot_term_ymax);
|
||||||
|
gnuplot.display_is_uptodate = false;
|
||||||
|
gnuplot_canvas();
|
||||||
|
break;
|
||||||
|
case 'g': gnuplot.toggle_grid();
|
||||||
|
break;
|
||||||
|
case 'n': gnuplot.rezoom();
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
ctx.lineWidth = 0.5;
|
||||||
|
ctx.strokeStyle="rgba(128,128,128,0.50)";
|
||||||
|
ctx.moveTo(gnuplot.plot_xmin, gnuplot.mousey); ctx.lineTo(gnuplot.plot_xmax, gnuplot.mousey);
|
||||||
|
ctx.moveTo(gnuplot.mousex, gnuplot.plot_ybot); ctx.lineTo(gnuplot.mousex, gnuplot.plot_ytop);
|
||||||
|
ctx.stroke();
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
case 'u': gnuplot.unzoom();
|
||||||
|
break;
|
||||||
|
case '': zoom_in_progress = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Arrow keys
|
||||||
|
case '%': // ctx.drawText("sans", 10, gnuplot.mousex, gnuplot.mousey, "<");
|
||||||
|
break;
|
||||||
|
case '\'': // ctx.drawText("sans", 10, gnuplot.mousex, gnuplot.mousey, ">");
|
||||||
|
break;
|
||||||
|
case '&': // ctx.drawText("sans", 10, gnuplot.mousex, gnuplot.mousey, "^");
|
||||||
|
break;
|
||||||
|
case '(': // ctx.drawText("sans", 10, gnuplot.mousex, gnuplot.mousey, "v");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: ctx.drawText("sans", 10, gnuplot.mousex, gnuplot.mousey, keychar);
|
||||||
|
return true; // Let someone else handle it
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false; // Nobody else should respond to this keypress
|
||||||
|
}
|
||||||
376
src/netdaemon/www/js/gnuplot_svg.js
Normal file
376
src/netdaemon/www/js/gnuplot_svg.js
Normal file
@ -0,0 +1,376 @@
|
|||||||
|
// Javascript routines for interaction with SVG documents produced by
|
||||||
|
// gnuplot's SVG terminal driver.
|
||||||
|
|
||||||
|
// Find your root SVG element
|
||||||
|
var svg = document.querySelector('svg');
|
||||||
|
|
||||||
|
// Create an SVGPoint for future math
|
||||||
|
var pt = svg.createSVGPoint();
|
||||||
|
|
||||||
|
// Get point in global SVG space
|
||||||
|
function cursorPoint(evt){
|
||||||
|
pt.x = evt.clientX; pt.y = evt.clientY;
|
||||||
|
return pt.matrixTransform(svg.getScreenCTM().inverse());
|
||||||
|
}
|
||||||
|
|
||||||
|
var gnuplot_svg = { };
|
||||||
|
|
||||||
|
gnuplot_svg.version = "17 February 2017";
|
||||||
|
|
||||||
|
gnuplot_svg.SVGDoc = null;
|
||||||
|
gnuplot_svg.SVGRoot = null;
|
||||||
|
|
||||||
|
gnuplot_svg.Init = function(e)
|
||||||
|
{
|
||||||
|
gnuplot_svg.SVGDoc = e.target.ownerDocument;
|
||||||
|
gnuplot_svg.SVGRoot = gnuplot_svg.SVGDoc.documentElement;
|
||||||
|
gnuplot_svg.axisdate = new Date();
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.toggleVisibility = function(evt, targetId)
|
||||||
|
{
|
||||||
|
var newTarget = evt.target;
|
||||||
|
if (targetId)
|
||||||
|
newTarget = gnuplot_svg.SVGDoc.getElementById(targetId);
|
||||||
|
|
||||||
|
var newValue = newTarget.getAttributeNS(null, 'visibility')
|
||||||
|
|
||||||
|
if ('hidden' != newValue)
|
||||||
|
newValue = 'hidden';
|
||||||
|
else
|
||||||
|
newValue = 'visible';
|
||||||
|
|
||||||
|
newTarget.setAttributeNS(null, 'visibility', newValue);
|
||||||
|
|
||||||
|
if (targetId) {
|
||||||
|
newTarget = gnuplot_svg.SVGDoc.getElementById(targetId.concat("_keyentry"));
|
||||||
|
if (newTarget)
|
||||||
|
newTarget.setAttributeNS(null, 'style',
|
||||||
|
newValue == 'hidden' ? 'filter:url(#greybox)' : 'none');
|
||||||
|
}
|
||||||
|
|
||||||
|
evt.preventDefault();
|
||||||
|
evt.stopPropagation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse tracking echos coordinates to a floating text box
|
||||||
|
|
||||||
|
gnuplot_svg.getText = function() {
|
||||||
|
return(document.getElementById("coord_text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.updateCoordBox = function(t, evt) {
|
||||||
|
/*
|
||||||
|
* Apply screen CTM transformation to the evt screenX and screenY to get
|
||||||
|
* coordinates in SVG coordinate space. Use scaling parameters stored in
|
||||||
|
* the plot document by gnuplot to convert further into plot coordinates.
|
||||||
|
* Then position the floating text box using the SVG coordinates.
|
||||||
|
*/
|
||||||
|
var m = document.documentElement.getScreenCTM();
|
||||||
|
var p = document.documentElement.createSVGPoint();
|
||||||
|
var loc = cursorPoint(evt);
|
||||||
|
p.x = loc.x;
|
||||||
|
p.y = loc.y;
|
||||||
|
var label_x, label_y;
|
||||||
|
|
||||||
|
// Allow for scrollbar position (Firefox, others?)
|
||||||
|
if (typeof evt.pageX != 'undefined') {
|
||||||
|
p.x = evt.pageX; p.y = evt.pageY;
|
||||||
|
}
|
||||||
|
t.setAttribute("x", p.x);
|
||||||
|
t.setAttribute("y", p.y);
|
||||||
|
|
||||||
|
var plotcoord = gnuplot_svg.mouse2plot(p.x,p.y);
|
||||||
|
|
||||||
|
if (gnuplot_svg.plot_timeaxis_x == "DMS" || gnuplot_svg.plot_timeaxis_y == "DMS") {
|
||||||
|
if (gnuplot_svg.plot_timeaxis_x == "DMS")
|
||||||
|
label_x = gnuplot_svg.convert_to_DMS(x);
|
||||||
|
else
|
||||||
|
label_x = plotcoord.x.toFixed(2);
|
||||||
|
if (gnuplot_svg.plot_timeaxis_y == "DMS")
|
||||||
|
label_y = gnuplot_svg.convert_to_DMS(y);
|
||||||
|
else
|
||||||
|
label_y = plotcoord.y.toFixed(2);
|
||||||
|
|
||||||
|
} else if (gnuplot_svg.polar_mode) {
|
||||||
|
polar = gnuplot_svg.convert_to_polar(plotcoord.x,plotcoord.y);
|
||||||
|
label_x = "ang= " + polar.ang.toPrecision(4);
|
||||||
|
label_y = "R= " + polar.r.toPrecision(4);
|
||||||
|
|
||||||
|
} else if (gnuplot_svg.plot_timeaxis_x == "Date") {
|
||||||
|
gnuplot_svg.axisdate.setTime(1000. * plotcoord.x);
|
||||||
|
var year = gnuplot_svg.axisdate.getUTCFullYear();
|
||||||
|
var month = gnuplot_svg.axisdate.getUTCMonth();
|
||||||
|
var date = gnuplot_svg.axisdate.getUTCDate();
|
||||||
|
label_x = (" " + date).slice (-2) + "/"
|
||||||
|
+ ("0" + (month+1)).slice (-2) + "/"
|
||||||
|
+ year;
|
||||||
|
label_y = plotcoord.y.toFixed(2);
|
||||||
|
} else if (gnuplot_svg.plot_timeaxis_x == "Time") {
|
||||||
|
gnuplot_svg.axisdate.setTime(1000. * plotcoord.x);
|
||||||
|
var hour = gnuplot_svg.axisdate.getUTCHours();
|
||||||
|
var minute = gnuplot_svg.axisdate.getUTCMinutes();
|
||||||
|
var second = gnuplot_svg.axisdate.getUTCSeconds();
|
||||||
|
label_x = ("0" + hour).slice (-2) + ":"
|
||||||
|
+ ("0" + minute).slice (-2) + ":"
|
||||||
|
+ ("0" + second).slice (-2);
|
||||||
|
label_y = plotcoord.y.toFixed(2);
|
||||||
|
} else if (gnuplot_svg.plot_timeaxis_x == "DateTime") {
|
||||||
|
gnuplot_svg.axisdate.setTime(1000. * plotcoord.x);
|
||||||
|
label_x = gnuplot_svg.axisdate.toUTCString();
|
||||||
|
label_y = plotcoord.y.toFixed(2);
|
||||||
|
} else {
|
||||||
|
label_x = plotcoord.x.toFixed(2);
|
||||||
|
label_y = plotcoord.y.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (null != t.firstChild) {
|
||||||
|
t.removeChild(t.firstChild);
|
||||||
|
}
|
||||||
|
var textNode = document.createTextNode(". "+label_x+" "+label_y);
|
||||||
|
t.appendChild(textNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.showCoordBox = function(evt) {
|
||||||
|
var t = gnuplot_svg.getText();
|
||||||
|
if (null != t) {
|
||||||
|
t.setAttribute("visibility", "visible");
|
||||||
|
gnuplot_svg.updateCoordBox(t, evt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.moveCoordBox = function(evt) {
|
||||||
|
var t = gnuplot_svg.getText();
|
||||||
|
if (null != t)
|
||||||
|
gnuplot_svg.updateCoordBox(t, evt);
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.hideCoordBox = function(evt) {
|
||||||
|
var t = gnuplot_svg.getText();
|
||||||
|
if (null != t)
|
||||||
|
t.setAttribute("visibility", "hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.toggleCoordBox = function(evt) {
|
||||||
|
var t = gnuplot_svg.getText();
|
||||||
|
if (null != t) {
|
||||||
|
var state = t.getAttribute('visibility');
|
||||||
|
if ('hidden' != state)
|
||||||
|
state = 'hidden';
|
||||||
|
else
|
||||||
|
state = 'visible';
|
||||||
|
t.setAttribute('visibility', state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.toggleGrid = function() {
|
||||||
|
if (!gnuplot_svg.SVGDoc.getElementsByClassName) // Old browsers
|
||||||
|
return;
|
||||||
|
var grid = gnuplot_svg.SVGDoc.getElementsByClassName('gridline');
|
||||||
|
for (var i=0; i<grid.length; i++) {
|
||||||
|
var state = grid[i].getAttribute('visibility');
|
||||||
|
grid[i].setAttribute('visibility', (state == 'hidden') ? 'visible' : 'hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.showHypertext = function(evt, mouseovertext)
|
||||||
|
{
|
||||||
|
var lines = mouseovertext.split('\n');
|
||||||
|
|
||||||
|
// If text starts with "image:" process it as an xlinked bitmap
|
||||||
|
if (lines[0].substring(0,5) == "image") {
|
||||||
|
var nameindex = lines[0].indexOf(":");
|
||||||
|
if (nameindex > 0) {
|
||||||
|
gnuplot_svg.showHyperimage(evt, lines[0]);
|
||||||
|
lines[0] = lines[0].slice(nameindex+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var loc = cursorPoint(evt);
|
||||||
|
var anchor_x = loc.x;
|
||||||
|
var anchor_y = loc.y;
|
||||||
|
|
||||||
|
var hypertextbox = document.getElementById("hypertextbox")
|
||||||
|
hypertextbox.setAttributeNS(null,"x",anchor_x+10);
|
||||||
|
hypertextbox.setAttributeNS(null,"y",anchor_y+4);
|
||||||
|
hypertextbox.setAttributeNS(null,"visibility","visible");
|
||||||
|
|
||||||
|
var hypertext = document.getElementById("hypertext")
|
||||||
|
hypertext.setAttributeNS(null,"x",anchor_x+14);
|
||||||
|
hypertext.setAttributeNS(null,"y",anchor_y+18);
|
||||||
|
hypertext.setAttributeNS(null,"visibility","visible");
|
||||||
|
|
||||||
|
var height = 2+16*lines.length;
|
||||||
|
hypertextbox.setAttributeNS(null,"height",height);
|
||||||
|
var length = hypertext.getComputedTextLength();
|
||||||
|
hypertextbox.setAttributeNS(null,"width",length+8);
|
||||||
|
|
||||||
|
// bounce off frame bottom
|
||||||
|
if (anchor_y > gnuplot_svg.plot_ybot + 16 - height) {
|
||||||
|
anchor_y -= height;
|
||||||
|
hypertextbox.setAttributeNS(null,"y",anchor_y+4);
|
||||||
|
hypertext.setAttributeNS(null,"y",anchor_y+18);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (null != hypertext.firstChild) {
|
||||||
|
hypertext.removeChild(hypertext.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
var textNode = document.createTextNode(lines[0]);
|
||||||
|
|
||||||
|
if (lines.length <= 1) {
|
||||||
|
hypertext.appendChild(textNode);
|
||||||
|
} else {
|
||||||
|
xmlns="http://www.w3.org/2000/svg";
|
||||||
|
var tspan_element = document.createElementNS(xmlns, "tspan");
|
||||||
|
tspan_element.appendChild(textNode);
|
||||||
|
hypertext.appendChild(tspan_element);
|
||||||
|
length = tspan_element.getComputedTextLength();
|
||||||
|
var ll = length;
|
||||||
|
|
||||||
|
for (var l=1; l<lines.length; l++) {
|
||||||
|
var tspan_element = document.createElementNS(xmlns, "tspan");
|
||||||
|
tspan_element.setAttributeNS(null,"dy", 16);
|
||||||
|
textNode = document.createTextNode(lines[l]);
|
||||||
|
tspan_element.appendChild(textNode);
|
||||||
|
hypertext.appendChild(tspan_element);
|
||||||
|
|
||||||
|
ll = tspan_element.getComputedTextLength();
|
||||||
|
if (length < ll) length = ll;
|
||||||
|
}
|
||||||
|
hypertextbox.setAttributeNS(null,"width",length+8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bounce off right edge
|
||||||
|
if (anchor_x > gnuplot_svg.plot_xmax + 14 - length) {
|
||||||
|
anchor_x -= length;
|
||||||
|
hypertextbox.setAttributeNS(null,"x",anchor_x+10);
|
||||||
|
hypertext.setAttributeNS(null,"x",anchor_x+14);
|
||||||
|
}
|
||||||
|
|
||||||
|
// left-justify multiline text
|
||||||
|
var tspan_element = hypertext.firstChild;
|
||||||
|
while (tspan_element) {
|
||||||
|
tspan_element.setAttributeNS(null,"x",anchor_x+14);
|
||||||
|
tspan_element = tspan_element.nextElementSibling;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.hideHypertext = function ()
|
||||||
|
{
|
||||||
|
var hypertextbox = document.getElementById("hypertextbox")
|
||||||
|
var hypertext = document.getElementById("hypertext")
|
||||||
|
var hyperimage = document.getElementById("hyperimage")
|
||||||
|
hypertextbox.setAttributeNS(null,"visibility","hidden");
|
||||||
|
hypertext.setAttributeNS(null,"visibility","hidden");
|
||||||
|
hyperimage.setAttributeNS(null,"visibility","hidden");
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.showHyperimage = function(evt, linktext)
|
||||||
|
{
|
||||||
|
var loc = cursorPoint(evt);
|
||||||
|
var anchor_x = loc.x;
|
||||||
|
var anchor_y = loc.y;
|
||||||
|
// Allow for scrollbar position (Firefox, others?)
|
||||||
|
if (typeof evt.pageX != 'undefined') {
|
||||||
|
anchor_x = evt.pageX; anchor_y = evt.pageY;
|
||||||
|
}
|
||||||
|
|
||||||
|
var hyperimage = document.getElementById("hyperimage")
|
||||||
|
hyperimage.setAttributeNS(null,"x",anchor_x);
|
||||||
|
hyperimage.setAttributeNS(null,"y",anchor_y);
|
||||||
|
hyperimage.setAttributeNS(null,"visibility","visible");
|
||||||
|
|
||||||
|
// Pick up height and width from "image(width,height):name"
|
||||||
|
var width = hyperimage.getAttributeNS(null,"width");
|
||||||
|
var height = hyperimage.getAttributeNS(null,"height");
|
||||||
|
if (linktext.charAt(5) == "(") {
|
||||||
|
width = parseInt(linktext.slice(6));
|
||||||
|
height = parseInt(linktext.slice(linktext.indexOf(",") + 1));
|
||||||
|
hyperimage.setAttributeNS(null,"width",width);
|
||||||
|
hyperimage.setAttributeNS(null,"height",height);
|
||||||
|
hyperimage.setAttributeNS(null,"preserveAspectRatio","none");
|
||||||
|
}
|
||||||
|
|
||||||
|
// bounce off frame bottom and right
|
||||||
|
if (anchor_y > gnuplot_svg.plot_ybot + 50 - height)
|
||||||
|
hyperimage.setAttributeNS(null,"y",20 + anchor_y-height);
|
||||||
|
if (anchor_x > gnuplot_svg.plot_xmax + 150 - width)
|
||||||
|
hyperimage.setAttributeNS(null,"x",10 + anchor_x-width);
|
||||||
|
|
||||||
|
// attach image URL as a link
|
||||||
|
linktext = linktext.slice(linktext.indexOf(":") + 1);
|
||||||
|
var xlinkns = "http://www.w3.org/1999/xlink";
|
||||||
|
hyperimage.setAttributeNS(xlinkns,"xlink:href",linktext);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert from svg panel mouse coordinates to the coordinate
|
||||||
|
// system of the gnuplot figure
|
||||||
|
gnuplot_svg.mouse2plot = function(mousex,mousey) {
|
||||||
|
var plotcoord = new Object;
|
||||||
|
var plotx = mousex - gnuplot_svg.plot_xmin;
|
||||||
|
var ploty = mousey - gnuplot_svg.plot_ybot;
|
||||||
|
var x,y;
|
||||||
|
|
||||||
|
if (gnuplot_svg.plot_logaxis_x != 0) {
|
||||||
|
x = Math.log(gnuplot_svg.plot_axis_xmax)
|
||||||
|
- Math.log(gnuplot_svg.plot_axis_xmin);
|
||||||
|
x = x * (plotx / (gnuplot_svg.plot_xmax - gnuplot_svg.plot_xmin))
|
||||||
|
+ Math.log(gnuplot_svg.plot_axis_xmin);
|
||||||
|
x = Math.exp(x);
|
||||||
|
} else {
|
||||||
|
x = gnuplot_svg.plot_axis_xmin + (plotx / (gnuplot_svg.plot_xmax-gnuplot_svg.plot_xmin)) * (gnuplot_svg.plot_axis_xmax - gnuplot_svg.plot_axis_xmin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gnuplot_svg.plot_logaxis_y != 0) {
|
||||||
|
y = Math.log(gnuplot_svg.plot_axis_ymax)
|
||||||
|
- Math.log(gnuplot_svg.plot_axis_ymin);
|
||||||
|
y = y * (ploty / (gnuplot_svg.plot_ytop - gnuplot_svg.plot_ybot))
|
||||||
|
+ Math.log(gnuplot_svg.plot_axis_ymin);
|
||||||
|
y = Math.exp(y);
|
||||||
|
} else {
|
||||||
|
y = gnuplot_svg.plot_axis_ymin + (ploty / (gnuplot_svg.plot_ytop-gnuplot_svg.plot_ybot)) * (gnuplot_svg.plot_axis_ymax - gnuplot_svg.plot_axis_ymin);
|
||||||
|
}
|
||||||
|
|
||||||
|
plotcoord.x = x;
|
||||||
|
plotcoord.y = y;
|
||||||
|
return plotcoord;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.convert_to_polar = function (x,y)
|
||||||
|
{
|
||||||
|
polar = new Object;
|
||||||
|
var phi, r;
|
||||||
|
phi = Math.atan2(y,x);
|
||||||
|
if (gnuplot_svg.plot_logaxis_r)
|
||||||
|
r = Math.exp( (x/Math.cos(phi) + Math.log(gnuplot_svg.plot_axis_rmin)/Math.LN10) * Math.LN10);
|
||||||
|
else if (gnuplot_svg.plot_axis_rmin > gnuplot_svg.plot_axis_rmax)
|
||||||
|
r = gnuplot_svg.plot_axis_rmin - x/Math.cos(phi);
|
||||||
|
else
|
||||||
|
r = gnuplot_svg.plot_axis_rmin + x/Math.cos(phi);
|
||||||
|
phi = phi * (180./Math.PI);
|
||||||
|
if (gnuplot_svg.polar_sense < 0)
|
||||||
|
phi = -phi;
|
||||||
|
if (gnuplot_svg.polar_theta0 != undefined)
|
||||||
|
phi = phi + gnuplot_svg.polar_theta0;
|
||||||
|
if (phi > 180.)
|
||||||
|
phi = phi - 360.;
|
||||||
|
polar.r = r;
|
||||||
|
polar.ang = phi;
|
||||||
|
return polar;
|
||||||
|
}
|
||||||
|
|
||||||
|
gnuplot_svg.convert_to_DMS = function (x)
|
||||||
|
{
|
||||||
|
var dms = {d:0, m:0, s:0};
|
||||||
|
var deg = Math.abs(x);
|
||||||
|
dms.d = Math.floor(deg);
|
||||||
|
dms.m = Math.floor((deg - dms.d) * 60.);
|
||||||
|
dms.s = Math.floor((deg - dms.d) * 3600. - dms.m * 60.);
|
||||||
|
fmt = ((x<0)?"-":" ")
|
||||||
|
+ dms.d.toFixed(0) + "°"
|
||||||
|
+ dms.m.toFixed(0) + "\""
|
||||||
|
+ dms.s.toFixed(0) + "'";
|
||||||
|
return fmt;
|
||||||
|
}
|
||||||
BIN
src/netdaemon/www/js/grid.png
Normal file
BIN
src/netdaemon/www/js/grid.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 124 B |
BIN
src/netdaemon/www/js/help.png
Normal file
BIN
src/netdaemon/www/js/help.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 481 B |
BIN
src/netdaemon/www/js/nextzoom.png
Normal file
BIN
src/netdaemon/www/js/nextzoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 609 B |
BIN
src/netdaemon/www/js/previouszoom.png
Normal file
BIN
src/netdaemon/www/js/previouszoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 734 B |
BIN
src/netdaemon/www/js/return.png
Normal file
BIN
src/netdaemon/www/js/return.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
BIN
src/netdaemon/www/js/textzoom.png
Normal file
BIN
src/netdaemon/www/js/textzoom.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 391 B |
48
src/netdaemon/www/plot
Executable file
48
src/netdaemon/www/plot
Executable file
@ -0,0 +1,48 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
OUT=tmpfile.txt
|
||||||
|
cat $1 > $OUT
|
||||||
|
VAL=$(head -n1 $1 | awk '{print $3}')
|
||||||
|
NM=$(basename $1)
|
||||||
|
if [ $NM = "T0" ]; then Tname="TOP side"
|
||||||
|
else Tname="BOTTOM side"
|
||||||
|
fi
|
||||||
|
echo -e "30\t30\t$VAL\n-30\t-30\t$VAL" >> $OUT
|
||||||
|
cat << EOF > gnutplt
|
||||||
|
#!/usr/bin/gnuplot
|
||||||
|
set contour
|
||||||
|
unset surface
|
||||||
|
set cntrparam order 4
|
||||||
|
set cntrparam bspline
|
||||||
|
#set cntrparam levels auto 6
|
||||||
|
#set cntrparam levels incremental -30,0.1,30
|
||||||
|
set view map
|
||||||
|
set size square
|
||||||
|
set xrange [-40:40]
|
||||||
|
set yrange [-40:40]
|
||||||
|
set dgrid3d 100,100,4
|
||||||
|
set table "contour.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
unset contour
|
||||||
|
set surface
|
||||||
|
set table "dgrid.txt"
|
||||||
|
splot '$OUT' u 1:2:3
|
||||||
|
unset table
|
||||||
|
reset
|
||||||
|
set terminal canvas enhanced mousing size 1024,768 jsdir 'js'
|
||||||
|
set output "$1.html"
|
||||||
|
set size square
|
||||||
|
set xrange [-30:30]
|
||||||
|
set yrange [-30:30]
|
||||||
|
set xlabel "X, dm"
|
||||||
|
set ylabel "Y, dm"
|
||||||
|
set title "Mirror temperature $NM for $2 ($Tname)"
|
||||||
|
set pm3d map
|
||||||
|
unset key
|
||||||
|
circle(x,y,z) = x**2+y**2 > 900 ? NaN : z
|
||||||
|
splot 'dgrid.txt' u 1:2:(circle(\$1,\$2,\$3)) w pm3d, 'contour.txt' u 1:2:(circle(\$1,\$2,\$3)) w l lc rgb "black", '$OUT' u 1:2:(circle(\$1,\$2,\$3)):3 with labels font ",8"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 755 gnutplt
|
||||||
|
./gnutplt
|
||||||
|
rm gnutplt dgrid.txt contour.txt tmpfile.txt 2>&1 > /dev/null
|
||||||
Loading…
x
Reference in New Issue
Block a user