Compare commits
No commits in common. "0.2-rc1" and "master" have entirely different histories.
41
.gitignore
vendored
|
@ -1,6 +1,35 @@
|
|||
etc/volkszaehler.conf.php
|
||||
misc/sql/demo/pulses.dummy.copy
|
||||
.project
|
||||
.buildpath
|
||||
.settings/
|
||||
lib/vendor/*
|
||||
*~
|
||||
|
||||
# Binaries
|
||||
/src/vzlogger
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.so.*
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
|
||||
# automake
|
||||
Makefile
|
||||
.deps
|
||||
|
||||
# autoconf
|
||||
/autom4te.cache
|
||||
|
||||
/config.status
|
||||
/config.log
|
||||
/config.h
|
||||
stamp-h1
|
||||
|
||||
/libtool
|
||||
|
||||
# Debian packaging
|
||||
/debian/config.log
|
||||
|
|
3
.gitmodules
vendored
|
@ -1,3 +0,0 @@
|
|||
[submodule "misc/frontend/fnordlicht"]
|
||||
path = misc/frontend/fnordlicht
|
||||
url = git://github.com/stv0g/libfn.git
|
|
@ -1,2 +0,0 @@
|
|||
Deny from all
|
||||
Allow from localhost
|
1
AUTHORS
Normal file
|
@ -0,0 +1 @@
|
|||
Written by Steffen Vogel <info@steffenvogel.de>
|
|
@ -1 +0,0 @@
|
|||
There is no stable release yet. Have some patience please or contribute.
|
53
COPYING
|
@ -619,56 +619,3 @@ Program, unless a warranty or assumption of liability accompanies a
|
|||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
|
0
ChangeLog
Normal file
5
INSTALL
|
@ -1 +1,4 @@
|
|||
Refer to the wiki: http://wiki.volkszaehler.org/howto/getstarted
|
||||
vzlogger is build with the GNU Autotools buildsystem. All required files
|
||||
are included in this repository. There is no dependecy on autotools!
|
||||
|
||||
Just use the standard './configure && make && make install' triplet
|
||||
|
|
3
Makefile.am
Normal file
|
@ -0,0 +1,3 @@
|
|||
sysconf_DATA = etc/vzlogger.conf
|
||||
|
||||
SUBDIRS = src docs
|
|
@ -36,7 +36,7 @@ subdir = .
|
|||
DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
|
||||
$(srcdir)/Makefile.in $(srcdir)/config.h.in \
|
||||
$(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
|
||||
depcomp install-sh missing
|
||||
compile depcomp install-sh missing
|
||||
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
|
||||
am__aclocal_m4_deps = $(top_srcdir)/configure.ac
|
||||
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
|
||||
|
@ -137,8 +137,12 @@ CPPFLAGS = @CPPFLAGS@
|
|||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DEPS_CFLAGS = @DEPS_CFLAGS@
|
||||
DEPS_LIBS = @DEPS_LIBS@
|
||||
DEPS_LOCAL_CFLAGS = @DEPS_LOCAL_CFLAGS@
|
||||
DEPS_LOCAL_LIBS = @DEPS_LOCAL_LIBS@
|
||||
DEPS_SML_CFLAGS = @DEPS_SML_CFLAGS@
|
||||
DEPS_SML_LIBS = @DEPS_SML_LIBS@
|
||||
DEPS_VZ_CFLAGS = @DEPS_VZ_CFLAGS@
|
||||
DEPS_VZ_LIBS = @DEPS_VZ_LIBS@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
|
@ -168,6 +172,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
|
|||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
||||
|
@ -214,7 +219,7 @@ target_alias = @target_alias@
|
|||
top_build_prefix = @top_build_prefix@
|
||||
top_builddir = @top_builddir@
|
||||
top_srcdir = @top_srcdir@
|
||||
sysconf_DATA = vzlogger.conf
|
||||
sysconf_DATA = etc/vzlogger.conf
|
||||
SUBDIRS = src docs
|
||||
all: config.h
|
||||
$(MAKE) $(AM_MAKEFLAGS) all-recursive
|
0
NEWS
Normal file
35
README
|
@ -1,28 +1,11 @@
|
|||
This are the scripts running on volkszaehler.org
|
||||
Feel free to setup your own installation and protect your privacy!
|
||||
vzlogger...
|
||||
* is a tool to read and log measurements of a wide variety of smartmeters, sensors to the volkszaehler.org middleware.
|
||||
* can run as a daemon or via Cron.
|
||||
* includes a tiny onboard httpd to serve realtime readings to the AJAX web frontend.
|
||||
* is written in ANSI C and should run on most embedded devices which conform to the POSIX standard.
|
||||
|
||||
volkszaehler.org/
|
||||
|_ htdocs/ static files accessible through the web
|
||||
| |_ middleware.php middleware bootstrapping
|
||||
| \_ frontend web frontend
|
||||
|
|
||||
|_ etc/ configuration files
|
||||
|_ var/ SQLite database (optional)
|
||||
|_ lib/ middleware libraries
|
||||
|_ misc/
|
||||
|_ controller/
|
||||
| |_ vzlogger/ command line tool to log meters/sensors
|
||||
| \_ batch/ batch scripts for logging (prototypes)
|
||||
|
|
||||
|_ docs/ documentation
|
||||
|_ frontend/
|
||||
|_ graphics/ several graphics for docs, etc..
|
||||
|_ sql/ database schema dumps
|
||||
| \_ demo/ demo data
|
||||
|
|
||||
|_ tools/ scripts for imports, installation etc.
|
||||
\_ tests/ simple tests for middleware classes
|
||||
Feel free to implement support your own hardware ;)
|
||||
If you have questions, contact Steffen Vogel <info@steffenvogel.de>
|
||||
|
||||
Wiki: http://wiki.volkszaehler.org
|
||||
Other: http://volkszaehler.org
|
||||
Or contact our mailing list: volkszaehler-dev@lists.volkszaehler.org
|
||||
More information is available in our wiki:
|
||||
http://wiki.volkszaehler.org/software/controller/vzlogger
|
||||
|
|
35
misc/controller/vzlogger/aclocal.m4 → aclocal.m4
vendored
|
@ -797,6 +797,41 @@ AC_MSG_RESULT([$_am_result])
|
|||
rm -f confinc confmf
|
||||
])
|
||||
|
||||
# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
|
||||
# Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; the Free Software Foundation
|
||||
# gives unlimited permission to copy and/or distribute it,
|
||||
# with or without modifications, as long as this notice is preserved.
|
||||
|
||||
# serial 6
|
||||
|
||||
# AM_PROG_CC_C_O
|
||||
# --------------
|
||||
# Like AC_PROG_CC_C_O, but changed for automake.
|
||||
AC_DEFUN([AM_PROG_CC_C_O],
|
||||
[AC_REQUIRE([AC_PROG_CC_C_O])dnl
|
||||
AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
|
||||
AC_REQUIRE_AUX_FILE([compile])dnl
|
||||
# FIXME: we rely on the cache variable name because
|
||||
# there is no other way.
|
||||
set dummy $CC
|
||||
am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
|
||||
eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
|
||||
if test "$am_t" != yes; then
|
||||
# Losing compiler, so override with the script.
|
||||
# FIXME: It is wrong to rewrite CC.
|
||||
# But if we don't then we get into trouble of one sort or another.
|
||||
# A longer-term fix would be to have automake use am__CC in this case,
|
||||
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
|
||||
CC="$am_aux_dir/compile $CC"
|
||||
fi
|
||||
dnl Make sure AC_PROG_CC is never called again, or it will override our
|
||||
dnl setting of CC.
|
||||
m4_define([AC_PROG_CC],
|
||||
[m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
|
||||
])
|
||||
|
||||
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
|
||||
|
||||
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
|
143
compile
Executable file
|
@ -0,0 +1,143 @@
|
|||
#! /bin/sh
|
||||
# Wrapper for compilers which do not understand `-c -o'.
|
||||
|
||||
scriptversion=2009-10-06.20; # UTC
|
||||
|
||||
# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software
|
||||
# Foundation, Inc.
|
||||
# Written by Tom Tromey <tromey@cygnus.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 2, 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/>.
|
||||
|
||||
# As a special exception to the GNU General Public License, if you
|
||||
# distribute this file as part of a program that contains a
|
||||
# configuration script generated by Autoconf, you may include it under
|
||||
# the same distribution terms that you use for the rest of that program.
|
||||
|
||||
# This file is maintained in Automake, please report
|
||||
# bugs to <bug-automake@gnu.org> or send patches to
|
||||
# <automake-patches@gnu.org>.
|
||||
|
||||
case $1 in
|
||||
'')
|
||||
echo "$0: No command. Try \`$0 --help' for more information." 1>&2
|
||||
exit 1;
|
||||
;;
|
||||
-h | --h*)
|
||||
cat <<\EOF
|
||||
Usage: compile [--help] [--version] PROGRAM [ARGS]
|
||||
|
||||
Wrapper for compilers which do not understand `-c -o'.
|
||||
Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
|
||||
arguments, and rename the output as expected.
|
||||
|
||||
If you are trying to build a whole package this is not the
|
||||
right script to run: please start by reading the file `INSTALL'.
|
||||
|
||||
Report bugs to <bug-automake@gnu.org>.
|
||||
EOF
|
||||
exit $?
|
||||
;;
|
||||
-v | --v*)
|
||||
echo "compile $scriptversion"
|
||||
exit $?
|
||||
;;
|
||||
esac
|
||||
|
||||
ofile=
|
||||
cfile=
|
||||
eat=
|
||||
|
||||
for arg
|
||||
do
|
||||
if test -n "$eat"; then
|
||||
eat=
|
||||
else
|
||||
case $1 in
|
||||
-o)
|
||||
# configure might choose to run compile as `compile cc -o foo foo.c'.
|
||||
# So we strip `-o arg' only if arg is an object.
|
||||
eat=1
|
||||
case $2 in
|
||||
*.o | *.obj)
|
||||
ofile=$2
|
||||
;;
|
||||
*)
|
||||
set x "$@" -o "$2"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
*.c)
|
||||
cfile=$1
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
set x "$@" "$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
shift
|
||||
done
|
||||
|
||||
if test -z "$ofile" || test -z "$cfile"; then
|
||||
# If no `-o' option was seen then we might have been invoked from a
|
||||
# pattern rule where we don't need one. That is ok -- this is a
|
||||
# normal compilation that the losing compiler can handle. If no
|
||||
# `.c' file was seen then we are probably linking. That is also
|
||||
# ok.
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
# Name of file we expect compiler to create.
|
||||
cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
|
||||
|
||||
# Create the lock directory.
|
||||
# Note: use `[/\\:.-]' here to ensure that we don't use the same name
|
||||
# that we are using for the .o file. Also, base the name on the expected
|
||||
# object file name, since that is what matters with a parallel build.
|
||||
lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
|
||||
while true; do
|
||||
if mkdir "$lockdir" >/dev/null 2>&1; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
# FIXME: race condition here if user kills between mkdir and trap.
|
||||
trap "rmdir '$lockdir'; exit 1" 1 2 15
|
||||
|
||||
# Run the compile.
|
||||
"$@"
|
||||
ret=$?
|
||||
|
||||
if test -f "$cofile"; then
|
||||
test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
|
||||
elif test -f "${cofile}bj"; then
|
||||
test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
|
||||
fi
|
||||
|
||||
rmdir "$lockdir"
|
||||
exit $ret
|
||||
|
||||
# Local Variables:
|
||||
# mode: shell-script
|
||||
# sh-indentation: 2
|
||||
# eval: (add-hook 'write-file-hooks 'time-stamp)
|
||||
# time-stamp-start: "scriptversion="
|
||||
# time-stamp-format: "%:y-%02m-%02d.%02H"
|
||||
# time-stamp-time-zone: "UTC"
|
||||
# time-stamp-end: "; # UTC"
|
||||
# End:
|
|
@ -10,6 +10,9 @@
|
|||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#undef HAVE_FCNTL_H
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
#undef HAVE_GETOPT_H
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
|
||||
|
@ -26,10 +29,16 @@
|
|||
/* Define to 1 if you have the `memset' function. */
|
||||
#undef HAVE_MEMSET
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
#undef HAVE_PTHREAD_H
|
||||
|
||||
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
|
||||
and to 0 otherwise. */
|
||||
#undef HAVE_REALLOC
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#undef HAVE_SIGNAL_H
|
||||
|
||||
/* Define to 1 if you have the `sqrt' function. */
|
||||
#undef HAVE_SQRT
|
||||
|
||||
|
@ -72,8 +81,11 @@
|
|||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* No-debug Mode */
|
||||
#undef NDEBUG
|
||||
/* Local interface */
|
||||
#undef LOCAL_SUPPORT
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
@ -96,6 +108,9 @@
|
|||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Smart Messaging Language */
|
||||
#undef SML_SUPPORT
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
646
misc/controller/vzlogger/configure → configure
vendored
|
@ -1,8 +1,8 @@
|
|||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.67 for vzlogger 0.2.
|
||||
# Generated by GNU Autoconf 2.67 for vzlogger 0.3.3.
|
||||
#
|
||||
# Report bugs to <info@steffenvogel.de>.
|
||||
# Report bugs to <http://bugs.volkszaehler.org>.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
|
||||
|
@ -231,10 +231,10 @@ fi
|
|||
$as_echo "$0: be upgraded to zsh 4.3.4 or later."
|
||||
else
|
||||
$as_echo "$0: Please tell bug-autoconf@gnu.org and
|
||||
$0: info@steffenvogel.de about your system, including any
|
||||
$0: error possibly output before this message. Then install
|
||||
$0: a modern shell, or manually run the script under such a
|
||||
$0: shell if you do have one."
|
||||
$0: http://bugs.volkszaehler.org about your system,
|
||||
$0: including any error possibly output before this
|
||||
$0: message. Then install a modern shell, or manually run
|
||||
$0: the script under such a shell if you do have one."
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
@ -552,12 +552,12 @@ MAKEFLAGS=
|
|||
# Identity of this package.
|
||||
PACKAGE_NAME='vzlogger'
|
||||
PACKAGE_TARNAME='vzlogger'
|
||||
PACKAGE_VERSION='0.2'
|
||||
PACKAGE_STRING='vzlogger 0.2'
|
||||
PACKAGE_BUGREPORT='info@steffenvogel.de'
|
||||
PACKAGE_VERSION='0.3.3'
|
||||
PACKAGE_STRING='vzlogger 0.3.3'
|
||||
PACKAGE_BUGREPORT='http://bugs.volkszaehler.org'
|
||||
PACKAGE_URL=''
|
||||
|
||||
ac_unique_file="src/main.c"
|
||||
ac_unique_file="src/meter.c"
|
||||
# Factoring default headers for most tests.
|
||||
ac_includes_default="\
|
||||
#include <stdio.h>
|
||||
|
@ -597,15 +597,26 @@ ac_includes_default="\
|
|||
ac_subst_vars='am__EXEEXT_FALSE
|
||||
am__EXEEXT_TRUE
|
||||
LTLIBOBJS
|
||||
READER_BUILD_FALSE
|
||||
READER_BUILD_TRUE
|
||||
DEPS_LOCAL_LIBS
|
||||
DEPS_LOCAL_CFLAGS
|
||||
LOCAL_SUPPORT_FALSE
|
||||
LOCAL_SUPPORT_TRUE
|
||||
DEPS_SML_LIBS
|
||||
DEPS_SML_CFLAGS
|
||||
SML_SUPPORT_FALSE
|
||||
SML_SUPPORT_TRUE
|
||||
LIBOBJS
|
||||
EGREP
|
||||
GREP
|
||||
CPP
|
||||
DEPS_LIBS
|
||||
DEPS_CFLAGS
|
||||
DEPS_VZ_LIBS
|
||||
DEPS_VZ_CFLAGS
|
||||
PKG_CONFIG_LIBDIR
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG
|
||||
RANLIB
|
||||
am__fastdepCC_FALSE
|
||||
am__fastdepCC_TRUE
|
||||
CCDEPMODE
|
||||
|
@ -687,6 +698,9 @@ ac_subst_files=''
|
|||
ac_user_opts='
|
||||
enable_option_checking
|
||||
enable_dependency_tracking
|
||||
enable_sml
|
||||
enable_local
|
||||
with_reader
|
||||
enable_debug
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
|
@ -700,9 +714,13 @@ CPPFLAGS
|
|||
PKG_CONFIG
|
||||
PKG_CONFIG_PATH
|
||||
PKG_CONFIG_LIBDIR
|
||||
DEPS_CFLAGS
|
||||
DEPS_LIBS
|
||||
CPP'
|
||||
DEPS_VZ_CFLAGS
|
||||
DEPS_VZ_LIBS
|
||||
CPP
|
||||
DEPS_SML_CFLAGS
|
||||
DEPS_SML_LIBS
|
||||
DEPS_LOCAL_CFLAGS
|
||||
DEPS_LOCAL_LIBS'
|
||||
|
||||
|
||||
# Initialize some variables set by options.
|
||||
|
@ -1245,7 +1263,7 @@ if test "$ac_init_help" = "long"; then
|
|||
# Omit some internal or obsolete options to make the list less imposing.
|
||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||
cat <<_ACEOF
|
||||
\`configure' configures vzlogger 0.2 to adapt to many kinds of systems.
|
||||
\`configure' configures vzlogger 0.3.3 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
|
@ -1311,7 +1329,7 @@ fi
|
|||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of vzlogger 0.2:";;
|
||||
short | recursive ) echo "Configuration of vzlogger 0.3.3:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
|
@ -1321,8 +1339,16 @@ Optional Features:
|
|||
--enable-FEATURE[=ARG] include FEATURE [ARG=yes]
|
||||
--disable-dependency-tracking speeds up one-time build
|
||||
--enable-dependency-tracking do not reject slow dependency extractors
|
||||
--enable-sml enable support for smart messaging language
|
||||
(def=yes)
|
||||
--enable-local enable support for local HTTPd (def=yes)
|
||||
--enable-debug enable debug data generation (def=no)
|
||||
|
||||
Optional Packages:
|
||||
--with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
|
||||
--without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
|
||||
--with-reader compile reader to for testing your meters (def=yes)
|
||||
|
||||
Some influential environment variables:
|
||||
CC C compiler command
|
||||
CFLAGS C compiler flags
|
||||
|
@ -1336,14 +1362,24 @@ Some influential environment variables:
|
|||
directories to add to pkg-config's search path
|
||||
PKG_CONFIG_LIBDIR
|
||||
path overriding pkg-config's built-in search path
|
||||
DEPS_CFLAGS C compiler flags for DEPS, overriding pkg-config
|
||||
DEPS_LIBS linker flags for DEPS, overriding pkg-config
|
||||
DEPS_VZ_CFLAGS
|
||||
C compiler flags for DEPS_VZ, overriding pkg-config
|
||||
DEPS_VZ_LIBS
|
||||
linker flags for DEPS_VZ, overriding pkg-config
|
||||
CPP C preprocessor
|
||||
DEPS_SML_CFLAGS
|
||||
C compiler flags for DEPS_SML, overriding pkg-config
|
||||
DEPS_SML_LIBS
|
||||
linker flags for DEPS_SML, overriding pkg-config
|
||||
DEPS_LOCAL_CFLAGS
|
||||
C compiler flags for DEPS_LOCAL, overriding pkg-config
|
||||
DEPS_LOCAL_LIBS
|
||||
linker flags for DEPS_LOCAL, overriding pkg-config
|
||||
|
||||
Use these variables to override the choices made by `configure' or to help
|
||||
it to find libraries and programs with nonstandard names/locations.
|
||||
|
||||
Report bugs to <info@steffenvogel.de>.
|
||||
Report bugs to <http://bugs.volkszaehler.org>.
|
||||
_ACEOF
|
||||
ac_status=$?
|
||||
fi
|
||||
|
@ -1406,7 +1442,7 @@ fi
|
|||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
vzlogger configure 0.2
|
||||
vzlogger configure 0.3.3
|
||||
generated by GNU Autoconf 2.67
|
||||
|
||||
Copyright (C) 2010 Free Software Foundation, Inc.
|
||||
|
@ -1565,9 +1601,9 @@ $as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
|
|||
$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
|
||||
$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
|
||||
( $as_echo "## ----------------------------------- ##
|
||||
## Report this to info@steffenvogel.de ##
|
||||
## ----------------------------------- ##"
|
||||
( $as_echo "## ------------------------------------------- ##
|
||||
## Report this to http://bugs.volkszaehler.org ##
|
||||
## ------------------------------------------- ##"
|
||||
) | sed "s/^/$as_me: WARNING: /" >&2
|
||||
;;
|
||||
esac
|
||||
|
@ -1875,7 +1911,7 @@ cat >config.log <<_ACEOF
|
|||
This file contains any messages produced by compilers while
|
||||
running configure, to aid debugging if configure makes a mistake.
|
||||
|
||||
It was created by vzlogger $as_me 0.2, which was
|
||||
It was created by vzlogger $as_me 0.3.3, which was
|
||||
generated by GNU Autoconf 2.67. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
|
@ -2690,7 +2726,7 @@ fi
|
|||
|
||||
# Define the identity of the package.
|
||||
PACKAGE=vzlogger
|
||||
VERSION=0.2
|
||||
VERSION=0.3.3
|
||||
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
|
@ -2731,9 +2767,10 @@ am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'
|
|||
|
||||
|
||||
|
||||
|
||||
ac_config_headers="$ac_config_headers config.h"
|
||||
|
||||
ac_config_files="$ac_config_files Makefile src/Makefile docs/Makefile"
|
||||
ac_config_files="$ac_config_files Makefile docs/Makefile src/Makefile"
|
||||
|
||||
|
||||
# Checks for programs.
|
||||
|
@ -3717,6 +3754,228 @@ fi
|
|||
|
||||
|
||||
|
||||
# We use per target compiler flags
|
||||
if test "x$CC" != xcc; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC and cc understand -c and -o together" >&5
|
||||
$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether cc understands -c and -o together" >&5
|
||||
$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
|
||||
fi
|
||||
set dummy $CC; ac_cc=`$as_echo "$2" |
|
||||
sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
|
||||
if eval "test \"\${ac_cv_prog_cc_${ac_cc}_c_o+set}\"" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
# Make sure it works both with $CC and with simple cc.
|
||||
# We do the test twice because some compilers refuse to overwrite an
|
||||
# existing .o file with -o, though they will create one.
|
||||
ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
|
||||
rm -f conftest2.*
|
||||
if { { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; } &&
|
||||
test -f conftest2.$ac_objext && { { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; };
|
||||
then
|
||||
eval ac_cv_prog_cc_${ac_cc}_c_o=yes
|
||||
if test "x$CC" != xcc; then
|
||||
# Test first that cc exists at all.
|
||||
if { ac_try='cc -c conftest.$ac_ext >&5'
|
||||
{ { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }; then
|
||||
ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
|
||||
rm -f conftest2.*
|
||||
if { { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; } &&
|
||||
test -f conftest2.$ac_objext && { { case "(($ac_try" in
|
||||
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||
*) ac_try_echo=$ac_try;;
|
||||
esac
|
||||
eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
|
||||
$as_echo "$ac_try_echo"; } >&5
|
||||
(eval "$ac_try") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; };
|
||||
then
|
||||
# cc works too.
|
||||
:
|
||||
else
|
||||
# cc exists but doesn't like -o.
|
||||
eval ac_cv_prog_cc_${ac_cc}_c_o=no
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
else
|
||||
eval ac_cv_prog_cc_${ac_cc}_c_o=no
|
||||
fi
|
||||
rm -f core conftest*
|
||||
|
||||
fi
|
||||
if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
$as_echo "#define NO_MINUS_C_MINUS_O 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
|
||||
# FIXME: we rely on the cache variable name because
|
||||
# there is no other way.
|
||||
set dummy $CC
|
||||
am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
|
||||
eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
|
||||
if test "$am_t" != yes; then
|
||||
# Losing compiler, so override with the script.
|
||||
# FIXME: It is wrong to rewrite CC.
|
||||
# But if we don't then we get into trouble of one sort or another.
|
||||
# A longer-term fix would be to have automake use am__CC in this case,
|
||||
# and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
|
||||
CC="$am_aux_dir/compile $CC"
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Link libraries
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
# Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
|
||||
set dummy ${ac_tool_prefix}ranlib; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if test "${ac_cv_prog_RANLIB+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$RANLIB"; then
|
||||
ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
RANLIB=$ac_cv_prog_RANLIB
|
||||
if test -n "$RANLIB"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
|
||||
$as_echo "$RANLIB" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
|
||||
fi
|
||||
if test -z "$ac_cv_prog_RANLIB"; then
|
||||
ac_ct_RANLIB=$RANLIB
|
||||
# Extract the first word of "ranlib", so it can be a program name with args.
|
||||
set dummy ranlib; ac_word=$2
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
|
||||
$as_echo_n "checking for $ac_word... " >&6; }
|
||||
if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
if test -n "$ac_ct_RANLIB"; then
|
||||
ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
|
||||
else
|
||||
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
|
||||
for as_dir in $PATH
|
||||
do
|
||||
IFS=$as_save_IFS
|
||||
test -z "$as_dir" && as_dir=.
|
||||
for ac_exec_ext in '' $ac_executable_extensions; do
|
||||
if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then
|
||||
ac_cv_prog_ac_ct_RANLIB="ranlib"
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
|
||||
break 2
|
||||
fi
|
||||
done
|
||||
done
|
||||
IFS=$as_save_IFS
|
||||
|
||||
fi
|
||||
fi
|
||||
ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
|
||||
if test -n "$ac_ct_RANLIB"; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
|
||||
$as_echo "$ac_ct_RANLIB" >&6; }
|
||||
else
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
fi
|
||||
|
||||
if test "x$ac_ct_RANLIB" = x; then
|
||||
RANLIB=":"
|
||||
else
|
||||
case $cross_compiling:$ac_tool_warned in
|
||||
yes:)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
|
||||
$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
|
||||
ac_tool_warned=yes ;;
|
||||
esac
|
||||
RANLIB=$ac_ct_RANLIB
|
||||
fi
|
||||
else
|
||||
RANLIB="$ac_cv_prog_RANLIB"
|
||||
fi
|
||||
|
||||
|
||||
# Checks for libraries.
|
||||
|
||||
|
||||
|
@ -3839,35 +4098,35 @@ $as_echo "no" >&6; }
|
|||
fi
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEPS" >&5
|
||||
$as_echo_n "checking for DEPS... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEPS_VZ" >&5
|
||||
$as_echo_n "checking for DEPS_VZ... " >&6; }
|
||||
|
||||
if test -n "$DEPS_CFLAGS"; then
|
||||
pkg_cv_DEPS_CFLAGS="$DEPS_CFLAGS"
|
||||
if test -n "$DEPS_VZ_CFLAGS"; then
|
||||
pkg_cv_DEPS_VZ_CFLAGS="$DEPS_VZ_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3") 2>&5
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.19\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.19") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_CFLAGS=`$PKG_CONFIG --cflags "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>/dev/null`
|
||||
pkg_cv_DEPS_VZ_CFLAGS=`$PKG_CONFIG --cflags "json >= 0.9 libcurl >= 7.19" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$DEPS_LIBS"; then
|
||||
pkg_cv_DEPS_LIBS="$DEPS_LIBS"
|
||||
if test -n "$DEPS_VZ_LIBS"; then
|
||||
pkg_cv_DEPS_VZ_LIBS="$DEPS_VZ_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3") 2>&5
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"json >= 0.9 libcurl >= 7.19\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "json >= 0.9 libcurl >= 7.19") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_LIBS=`$PKG_CONFIG --libs "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>/dev/null`
|
||||
pkg_cv_DEPS_VZ_LIBS=`$PKG_CONFIG --libs "json >= 0.9 libcurl >= 7.19" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
|
@ -3887,22 +4146,22 @@ else
|
|||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
DEPS_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>&1`
|
||||
DEPS_VZ_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "json >= 0.9 libcurl >= 7.19" 2>&1`
|
||||
else
|
||||
DEPS_PKG_ERRORS=`$PKG_CONFIG --print-errors "json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3" 2>&1`
|
||||
DEPS_VZ_PKG_ERRORS=`$PKG_CONFIG --print-errors "json >= 0.9 libcurl >= 7.19" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$DEPS_PKG_ERRORS" >&5
|
||||
echo "$DEPS_VZ_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "Package requirements (json >= 0.9 libcurl >= 7.21.0 libmicrohttpd >= 0.9.3) were not met:
|
||||
as_fn_error $? "Package requirements (json >= 0.9 libcurl >= 7.19) were not met:
|
||||
|
||||
$DEPS_PKG_ERRORS
|
||||
$DEPS_VZ_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_CFLAGS
|
||||
and DEPS_LIBS to avoid the need to call pkg-config.
|
||||
Alternatively, you may set the environment variables DEPS_VZ_CFLAGS
|
||||
and DEPS_VZ_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details." "$LINENO" 5
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
|
@ -3913,15 +4172,15 @@ as_fn_error $? "The pkg-config script could not be found or is too old. Make su
|
|||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_CFLAGS
|
||||
and DEPS_LIBS to avoid the need to call pkg-config.
|
||||
Alternatively, you may set the environment variables DEPS_VZ_CFLAGS
|
||||
and DEPS_VZ_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||
See \`config.log' for more details" "$LINENO" 5 ; }
|
||||
else
|
||||
DEPS_CFLAGS=$pkg_cv_DEPS_CFLAGS
|
||||
DEPS_LIBS=$pkg_cv_DEPS_LIBS
|
||||
DEPS_VZ_CFLAGS=$pkg_cv_DEPS_VZ_CFLAGS
|
||||
DEPS_VZ_LIBS=$pkg_cv_DEPS_VZ_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
|
@ -4326,7 +4585,7 @@ fi
|
|||
done
|
||||
|
||||
|
||||
for ac_header in fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h termios.h unistd.h
|
||||
for ac_header in fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h termios.h unistd.h getopt.h signal.h pthread.h
|
||||
do :
|
||||
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||
ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
|
||||
|
@ -4604,28 +4863,267 @@ fi
|
|||
done
|
||||
|
||||
|
||||
# debug compilation support
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build with debug information" >&5
|
||||
$as_echo_n "checking whether to build with debug information... " >&6; }
|
||||
# Check whether --enable-debug was given.
|
||||
if test "${enable_debug+set}" = set; then :
|
||||
enableval=$enable_debug; debugit="$enableval"
|
||||
# SML support
|
||||
# Check whether --enable-sml was given.
|
||||
if test "${enable_sml+set}" = set; then :
|
||||
enableval=$enable_sml; sml=$enableval
|
||||
else
|
||||
debugit=no
|
||||
sml=yes
|
||||
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $debugit" >&5
|
||||
$as_echo "$debugit" >&6; }
|
||||
|
||||
if test x"$debugit" = x"yes"; then
|
||||
if test x"$sml" = x"yes"; then
|
||||
SML_SUPPORT_TRUE=
|
||||
SML_SUPPORT_FALSE='#'
|
||||
else
|
||||
SML_SUPPORT_TRUE='#'
|
||||
SML_SUPPORT_FALSE=
|
||||
fi
|
||||
|
||||
if test x"$sml" = x"yes"; then
|
||||
|
||||
$as_echo "#define SML_SUPPORT /**/" >>confdefs.h
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEPS_SML" >&5
|
||||
$as_echo_n "checking for DEPS_SML... " >&6; }
|
||||
|
||||
if test -n "$DEPS_SML_CFLAGS"; then
|
||||
pkg_cv_DEPS_SML_CFLAGS="$DEPS_SML_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sml >= 0.1\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "sml >= 0.1") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_SML_CFLAGS=`$PKG_CONFIG --cflags "sml >= 0.1" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$DEPS_SML_LIBS"; then
|
||||
pkg_cv_DEPS_SML_LIBS="$DEPS_SML_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"sml >= 0.1\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "sml >= 0.1") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_SML_LIBS=`$PKG_CONFIG --libs "sml >= 0.1" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
DEPS_SML_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "sml >= 0.1" 2>&1`
|
||||
else
|
||||
DEPS_SML_PKG_ERRORS=`$PKG_CONFIG --print-errors "sml >= 0.1" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$DEPS_SML_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "Package requirements (sml >= 0.1) were not met:
|
||||
|
||||
$DEPS_SML_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_SML_CFLAGS
|
||||
and DEPS_SML_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details." "$LINENO" 5
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_SML_CFLAGS
|
||||
and DEPS_SML_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||
See \`config.log' for more details" "$LINENO" 5 ; }
|
||||
else
|
||||
DEPS_SML_CFLAGS=$pkg_cv_DEPS_SML_CFLAGS
|
||||
DEPS_SML_LIBS=$pkg_cv_DEPS_SML_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# local interface support
|
||||
# Check whether --enable-local was given.
|
||||
if test "${enable_local+set}" = set; then :
|
||||
enableval=$enable_local; local=$enableval
|
||||
else
|
||||
local=yes
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test x"$local" = x"yes"; then
|
||||
LOCAL_SUPPORT_TRUE=
|
||||
LOCAL_SUPPORT_FALSE='#'
|
||||
else
|
||||
LOCAL_SUPPORT_TRUE='#'
|
||||
LOCAL_SUPPORT_FALSE=
|
||||
fi
|
||||
|
||||
if test x"$local" = x"yes"; then
|
||||
|
||||
$as_echo "#define LOCAL_SUPPORT /**/" >>confdefs.h
|
||||
|
||||
|
||||
pkg_failed=no
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for DEPS_LOCAL" >&5
|
||||
$as_echo_n "checking for DEPS_LOCAL... " >&6; }
|
||||
|
||||
if test -n "$DEPS_LOCAL_CFLAGS"; then
|
||||
pkg_cv_DEPS_LOCAL_CFLAGS="$DEPS_LOCAL_CFLAGS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmicrohttpd >= 0.4.6\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libmicrohttpd >= 0.4.6") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_LOCAL_CFLAGS=`$PKG_CONFIG --cflags "libmicrohttpd >= 0.4.6" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
if test -n "$DEPS_LOCAL_LIBS"; then
|
||||
pkg_cv_DEPS_LOCAL_LIBS="$DEPS_LOCAL_LIBS"
|
||||
elif test -n "$PKG_CONFIG"; then
|
||||
if test -n "$PKG_CONFIG" && \
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libmicrohttpd >= 0.4.6\""; } >&5
|
||||
($PKG_CONFIG --exists --print-errors "libmicrohttpd >= 0.4.6") 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; then
|
||||
pkg_cv_DEPS_LOCAL_LIBS=`$PKG_CONFIG --libs "libmicrohttpd >= 0.4.6" 2>/dev/null`
|
||||
else
|
||||
pkg_failed=yes
|
||||
fi
|
||||
else
|
||||
pkg_failed=untried
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if test $pkg_failed = yes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
|
||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||
_pkg_short_errors_supported=yes
|
||||
else
|
||||
_pkg_short_errors_supported=no
|
||||
fi
|
||||
if test $_pkg_short_errors_supported = yes; then
|
||||
DEPS_LOCAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libmicrohttpd >= 0.4.6" 2>&1`
|
||||
else
|
||||
DEPS_LOCAL_PKG_ERRORS=`$PKG_CONFIG --print-errors "libmicrohttpd >= 0.4.6" 2>&1`
|
||||
fi
|
||||
# Put the nasty error message in config.log where it belongs
|
||||
echo "$DEPS_LOCAL_PKG_ERRORS" >&5
|
||||
|
||||
as_fn_error $? "Package requirements (libmicrohttpd >= 0.4.6) were not met:
|
||||
|
||||
$DEPS_LOCAL_PKG_ERRORS
|
||||
|
||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
||||
installed software in a non-standard prefix.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_LOCAL_CFLAGS
|
||||
and DEPS_LOCAL_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details." "$LINENO" 5
|
||||
elif test $pkg_failed = untried; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
|
||||
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
|
||||
as_fn_error $? "The pkg-config script could not be found or is too old. Make sure it
|
||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
||||
path to pkg-config.
|
||||
|
||||
Alternatively, you may set the environment variables DEPS_LOCAL_CFLAGS
|
||||
and DEPS_LOCAL_LIBS to avoid the need to call pkg-config.
|
||||
See the pkg-config man page for more details.
|
||||
|
||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.
|
||||
See \`config.log' for more details" "$LINENO" 5 ; }
|
||||
else
|
||||
DEPS_LOCAL_CFLAGS=$pkg_cv_DEPS_LOCAL_CFLAGS
|
||||
DEPS_LOCAL_LIBS=$pkg_cv_DEPS_LOCAL_LIBS
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# build reader binary
|
||||
|
||||
# Check whether --with-reader was given.
|
||||
if test "${with_reader+set}" = set; then :
|
||||
withval=$with_reader; reader=$withval
|
||||
reader=yes
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test x"$reader" = x"yes"; then
|
||||
READER_BUILD_TRUE=
|
||||
READER_BUILD_FALSE='#'
|
||||
else
|
||||
READER_BUILD_TRUE='#'
|
||||
READER_BUILD_FALSE=
|
||||
fi
|
||||
|
||||
|
||||
# debug compilation support
|
||||
# Check whether --enable-debug was given.
|
||||
if test "${enable_debug+set}" = set; then :
|
||||
enableval=$enable_debug; debug=$enableval
|
||||
else
|
||||
debug=no
|
||||
|
||||
fi
|
||||
|
||||
|
||||
if test x"$debug" = x"yes"; then
|
||||
|
||||
$as_echo "#define DEBUG /**/" >>confdefs.h
|
||||
|
||||
AM_CXXFLAGS="$AM_CXXFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
|
||||
else
|
||||
|
||||
$as_echo "#define NDEBUG /**/" >>confdefs.h
|
||||
|
||||
AM_CXXFLAGS="$AM_CXXFLAGS -O3"
|
||||
fi
|
||||
|
||||
|
@ -4743,6 +5241,18 @@ if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then
|
|||
as_fn_error $? "conditional \"am__fastdepCC\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
if test -z "${SML_SUPPORT_TRUE}" && test -z "${SML_SUPPORT_FALSE}"; then
|
||||
as_fn_error $? "conditional \"SML_SUPPORT\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
if test -z "${LOCAL_SUPPORT_TRUE}" && test -z "${LOCAL_SUPPORT_FALSE}"; then
|
||||
as_fn_error $? "conditional \"LOCAL_SUPPORT\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
if test -z "${READER_BUILD_TRUE}" && test -z "${READER_BUILD_FALSE}"; then
|
||||
as_fn_error $? "conditional \"READER_BUILD\" was never defined.
|
||||
Usually this means the macro was only invoked conditionally." "$LINENO" 5
|
||||
fi
|
||||
|
||||
: ${CONFIG_STATUS=./config.status}
|
||||
ac_write_fail=0
|
||||
|
@ -5151,7 +5661,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||
# report actual input values of CONFIG_FILES etc. instead of their
|
||||
# values after options handling.
|
||||
ac_log="
|
||||
This file was extended by vzlogger $as_me 0.2, which was
|
||||
This file was extended by vzlogger $as_me 0.3.3, which was
|
||||
generated by GNU Autoconf 2.67. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
|
@ -5211,13 +5721,13 @@ $config_headers
|
|||
Configuration commands:
|
||||
$config_commands
|
||||
|
||||
Report bugs to <info@steffenvogel.de>."
|
||||
Report bugs to <http://bugs.volkszaehler.org>."
|
||||
|
||||
_ACEOF
|
||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||
ac_cs_version="\\
|
||||
vzlogger config.status 0.2
|
||||
vzlogger config.status 0.3.3
|
||||
configured by $0, generated by GNU Autoconf 2.67,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
@ -5348,8 +5858,8 @@ do
|
|||
case $ac_config_target in
|
||||
"config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
|
||||
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
"docs/Makefile") CONFIG_FILES="$CONFIG_FILES docs/Makefile" ;;
|
||||
"src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;;
|
||||
"depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;;
|
||||
|
||||
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5 ;;
|
96
configure.ac
Normal file
|
@ -0,0 +1,96 @@
|
|||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.67])
|
||||
|
||||
# update version here!
|
||||
AC_INIT([vzlogger], [0.3.3], [http://bugs.volkszaehler.org])
|
||||
AM_INIT_AUTOMAKE([vzlogger], [0.3.3])
|
||||
|
||||
AC_CONFIG_SRCDIR([src/meter.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
docs/Makefile
|
||||
src/Makefile
|
||||
])
|
||||
|
||||
# Checks for programs.
|
||||
AC_PROG_CC
|
||||
|
||||
# We use per target compiler flags
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
# Link libraries
|
||||
AC_PROG_RANLIB
|
||||
|
||||
# Checks for libraries.
|
||||
PKG_CHECK_MODULES([DEPS_VZ], [json >= 0.9 libcurl >= 7.19])
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h sys/time.h termios.h unistd.h getopt.h signal.h pthread.h])
|
||||
|
||||
# Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_TYPE_MODE_T
|
||||
AC_TYPE_SIZE_T
|
||||
|
||||
# Checks for library functions.
|
||||
AC_FUNC_MALLOC
|
||||
AC_FUNC_REALLOC
|
||||
AC_FUNC_STRERROR_R
|
||||
AC_CHECK_FUNCS([gettimeofday memset sqrt strchr strtol])
|
||||
|
||||
# SML support
|
||||
AC_ARG_ENABLE(
|
||||
[sml],
|
||||
[AS_HELP_STRING([--enable-sml], [enable support for smart messaging language (def=yes)])],
|
||||
[sml=$enableval],
|
||||
[sml=yes]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([SML_SUPPORT], [test x"$sml" = x"yes"])
|
||||
if test x"$sml" = x"yes"; then
|
||||
AC_DEFINE([SML_SUPPORT], [], [Smart Messaging Language])
|
||||
PKG_CHECK_MODULES([DEPS_SML], [sml >= 0.1])
|
||||
fi
|
||||
|
||||
# local interface support
|
||||
AC_ARG_ENABLE(
|
||||
[local],
|
||||
[AS_HELP_STRING([--enable-local], [enable support for local HTTPd (def=yes)])],
|
||||
[local=$enableval],
|
||||
[local=yes]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([LOCAL_SUPPORT], [test x"$local" = x"yes"])
|
||||
if test x"$local" = x"yes"; then
|
||||
AC_DEFINE([LOCAL_SUPPORT], [], [Local interface])
|
||||
PKG_CHECK_MODULES([DEPS_LOCAL], [libmicrohttpd >= 0.4.6])
|
||||
fi
|
||||
|
||||
# build reader binary
|
||||
AC_ARG_WITH(
|
||||
[reader],
|
||||
[AS_HELP_STRING([--with-reader], [compile reader to for testing your meters (def=yes)])],
|
||||
[reader=$withval]
|
||||
[reader=yes]
|
||||
)
|
||||
|
||||
AM_CONDITIONAL([READER_BUILD], [test x"$reader" = x"yes"])
|
||||
|
||||
# debug compilation support
|
||||
AC_ARG_ENABLE(
|
||||
[debug],
|
||||
[AS_HELP_STRING([--enable-debug], [enable debug data generation (def=no)])],
|
||||
[debug=$enableval],
|
||||
[debug=no]
|
||||
)
|
||||
|
||||
if test x"$debug" = x"yes"; then
|
||||
AC_DEFINE([DEBUG], [], [Debug Mode])
|
||||
AM_CXXFLAGS="$AM_CXXFLAGS -g -Wall -Werror -Wno-uninitialized -O0"
|
||||
else
|
||||
AM_CXXFLAGS="$AM_CXXFLAGS -O3"
|
||||
fi
|
||||
|
||||
AC_OUTPUT
|
54
debian/changelog
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
vzlogger (0.3.3-1) stable; urgency=low
|
||||
|
||||
* added support for new fluksometer
|
||||
* some code refactoring & cleanup
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Thu, 19 Jan 2012 18:52:32 +0100
|
||||
|
||||
vzlogger (0.3.2-1) stable; urgency=low
|
||||
|
||||
* new release with improvments to various protocols and configuration parsing
|
||||
* do not run with root privileges anymore
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Tue, 06 Dec 2011 02:37:26 +0100
|
||||
|
||||
vzlogger (0.3.1-2) stable; urgency=low
|
||||
|
||||
* updated version number
|
||||
* fixed forking behavior of init script
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Sun, 16 Oct 2011 14:45:32 +0200
|
||||
|
||||
vzlogger (0.3.1-1) stable; urgency=low
|
||||
|
||||
* fixed bug in parsing configuration for sml meters
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Sun, 16 Oct 2011 14:31:26 +0200
|
||||
|
||||
vzlogger (0.3-2) stable; urgency=low
|
||||
|
||||
* fixed typo in description
|
||||
* fixed static linking of libsml
|
||||
* added dependency for libsml
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Sun, 16 Oct 2011 00:25:27 +0200
|
||||
|
||||
vzlogger (0.3-1) stable; urgency=high
|
||||
|
||||
* Rewrite of meter & channel mapping
|
||||
* Added SML support
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Thu, 15 Sep 2011 23:26:31 +0200
|
||||
|
||||
vzlogger (0.2-1) stable; urgency=low
|
||||
|
||||
* Fixed some bugs after porting to armel architecture
|
||||
* Improved init script
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Thu, 04 Aug 2011 20:00:25 +0200
|
||||
|
||||
vzlogger (0.2) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Steffen Vogel <info@steffenvogel.de> Thu, 09 Jun 2011 16:04:25 +0200
|
23
debian/control
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Source: vzlogger
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Steffen Vogel <info@steffenvogel.de>
|
||||
Build-Depends: debhelper (>= 7.0.50~), pkg-config (>= 0.25), libjson0-dev (>= 0.9), libcurl4-openssl-dev (>= 7.19), libmicrohttpd-dev (>= 0.4.6)
|
||||
Standards-Version: 3.9.1
|
||||
Homepage: http://wiki.volkszaehler.org/software/controller/vzlogger
|
||||
Vcs-Git: git://github.com/volkszaehler/volkszaehler.org.git
|
||||
Vcs-Browser: http://github.com/volkszaehler/volkszaehler.org/tree/master/misc/controller/vzlogger/
|
||||
|
||||
Package: vzlogger
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, adduser
|
||||
Description: program for logging measurements to an volkszaehler.org middleware
|
||||
vzlogger...
|
||||
* is a tool to read and log measurements of a wide variety of smartmeters and
|
||||
sensors to the volkszaehler.org middleware.
|
||||
* can run as a daemon or via Cron.
|
||||
* includes a tiny onboard httpd to serve
|
||||
realtime readings to the AJAX web frontend.
|
||||
* is written in ANSI C and should run on most embedded devices
|
||||
which conform to the POSIX standard.
|
||||
|
|
@ -12,12 +12,14 @@
|
|||
|
||||
# PATH should only include /usr/* if it runs after the mountnfs.sh script
|
||||
PATH=/sbin:/usr/sbin:/bin:/usr/bin
|
||||
DESC=vzlogger # Introduce a short description here
|
||||
NAME=vzlogger # Introduce the short server's name here
|
||||
DAEMON=/usr/sbin/vzlogger # Introduce the server's location here
|
||||
DAEMON_ARGS="" # Arguments to run the daemon with
|
||||
DESC="smartmetering server"
|
||||
NAME=vzlogger
|
||||
DAEMON=/usr/bin/vzlogger
|
||||
DAEMON_ARGS="-d" # Arguments to run the daemon with
|
||||
PIDFILE=/var/run/$NAME.pid
|
||||
SCRIPTNAME=/etc/init.d/$NAME
|
||||
USER=vzlogger
|
||||
GROUP=vzlogger
|
||||
|
||||
# Exit if the package is not installed
|
||||
[ -x $DAEMON ] || exit 0
|
||||
|
@ -41,9 +43,9 @@ do_start()
|
|||
# 0 if daemon has been started
|
||||
# 1 if daemon was already running
|
||||
# 2 if daemon could not be started
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
start-stop-daemon --start --chuid $USER --group $GROUP --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
|
||||
|| return 1
|
||||
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||
start-stop-daemon --start --chuid $USER --group $GROUP --quiet --pidfile $PIDFILE --exec $DAEMON -- \
|
||||
$DAEMON_ARGS \
|
||||
|| return 2
|
||||
# Add code here, if necessary, that waits for the process to be ready
|
26
debian/vzlogger.postinst
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
#!/bin/sh -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
if ! id vzlogger > /dev/null 2>&1 ; then
|
||||
adduser --system --home /usr/share/vzlogger --no-create-home \
|
||||
--group --disabled-password --shell /bin/false \
|
||||
vzlogger
|
||||
usermod -a -G dialout vzlogger
|
||||
fi
|
||||
|
||||
touch /var/log/vzlogger.log
|
||||
chown vzlogger:adm /var/log/vzlogger.log
|
||||
chown vzlogger:adm /etc/vzlogger.conf
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "$0 called with unknown argument \`$1'" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
#DEBHELPER#
|
|
@ -83,8 +83,12 @@ CPPFLAGS = @CPPFLAGS@
|
|||
CYGPATH_W = @CYGPATH_W@
|
||||
DEFS = @DEFS@
|
||||
DEPDIR = @DEPDIR@
|
||||
DEPS_CFLAGS = @DEPS_CFLAGS@
|
||||
DEPS_LIBS = @DEPS_LIBS@
|
||||
DEPS_LOCAL_CFLAGS = @DEPS_LOCAL_CFLAGS@
|
||||
DEPS_LOCAL_LIBS = @DEPS_LOCAL_LIBS@
|
||||
DEPS_SML_CFLAGS = @DEPS_SML_CFLAGS@
|
||||
DEPS_SML_LIBS = @DEPS_SML_LIBS@
|
||||
DEPS_VZ_CFLAGS = @DEPS_VZ_CFLAGS@
|
||||
DEPS_VZ_LIBS = @DEPS_VZ_LIBS@
|
||||
ECHO_C = @ECHO_C@
|
||||
ECHO_N = @ECHO_N@
|
||||
ECHO_T = @ECHO_T@
|
||||
|
@ -114,6 +118,7 @@ PATH_SEPARATOR = @PATH_SEPARATOR@
|
|||
PKG_CONFIG = @PKG_CONFIG@
|
||||
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
|
||||
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
|
||||
RANLIB = @RANLIB@
|
||||
SET_MAKE = @SET_MAKE@
|
||||
SHELL = @SHELL@
|
||||
STRIP = @STRIP@
|
|
@ -1,110 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Configuration template
|
||||
*
|
||||
* You should use this file to obtain your custom configuration
|
||||
* new parameters should be documented
|
||||
*
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @package default
|
||||
* @license http://www.opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* any later version.
|
||||
*
|
||||
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @var string PDO driver for Doctrine DBAL
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en#getting-a-connection:driver
|
||||
*/
|
||||
$config['db']['driver'] = 'pdo_mysql';
|
||||
|
||||
/**
|
||||
* @var string hostname of database server. Use 'localhost' for the machine your webserver is running on.
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en
|
||||
*/
|
||||
$config['db']['host'] = 'localhost';
|
||||
|
||||
/**
|
||||
* @var string username for the database server
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en
|
||||
*/
|
||||
$config['db']['user'] = 'vz';
|
||||
|
||||
/**
|
||||
* @var string password for the database server
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en
|
||||
*/
|
||||
$config['db']['password'] = 'demo';
|
||||
|
||||
/**
|
||||
* @var string database name
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en
|
||||
*/
|
||||
$config['db']['dbname'] = 'volkszaehler';
|
||||
|
||||
/**
|
||||
* For administration tasks (used by doctrine cli and the setup script)
|
||||
* the following $['db']['admin'] settings will be merged with $config['db']
|
||||
*/
|
||||
//$config['db']['admin']['user'] = 'vz_admin';
|
||||
//$config['db']['admin']['password'] = 'admin_demo';
|
||||
|
||||
/**
|
||||
* @var string path of the sqlite database
|
||||
* @link http://www.doctrine-project.org/projects/dbal/2.0/docs/reference/configuration/en
|
||||
*/
|
||||
//$config['db']['path'] = 'volkszaehler';
|
||||
|
||||
/**
|
||||
* Vendor libs
|
||||
* Set to NULL to use PHP's include path
|
||||
* @var string path to vendor libs
|
||||
* @link http://www.php.net/manual/en/ini.core.php#ini.include-path
|
||||
*/
|
||||
$config['lib']['doctrine'] = VZ_DIR . '/lib/vendor/Doctrine';
|
||||
//$config['lib']['jpgraph'] = VZ_DIR . '/lib/vendor/JpGraph';
|
||||
|
||||
/**
|
||||
* @var string timezone for the middleware
|
||||
* @link http://www.php.net/manual/de/timezones.php
|
||||
* @link http://www.php.net/manual/de/datetime.configuration.php#ini.date.timezone
|
||||
*/
|
||||
//$config['timezone'] = 'Europe/Berlin';
|
||||
|
||||
/**
|
||||
* @var string Locale used for regular expressions
|
||||
* @link http://php.net/manual/de/function.setlocale.php
|
||||
*/
|
||||
$config['locale'] = array('de_DE', 'en_US', 'C');
|
||||
|
||||
/**
|
||||
* @var array of colors for plot series
|
||||
*/
|
||||
$config['colors'] = array('#83CAFF', '#7E0021', '#579D1C', '#FFD320', '#FF420E', '#004586', '#0084D1', '#C5000B', '#FF950E', '#4B1F6F', '#AECF00', '#314004');
|
||||
|
||||
/**
|
||||
* @var boolean disables some optimizations. Only use it when you exactly know what you are doing.
|
||||
*/
|
||||
$config['devmode'] = FALSE;
|
||||
|
||||
/**
|
||||
* @var integer set to > 0 to show debugging messages
|
||||
*/
|
||||
$config['debug'] = 0;
|
||||
|
||||
?>
|
78
etc/vzlogger.conf
Normal file
|
@ -0,0 +1,78 @@
|
|||
/**
|
||||
* vzlogger configuration
|
||||
*
|
||||
* use proper encoded JSON with javascript comments
|
||||
*
|
||||
* take a look at the wiki for detailed information:
|
||||
* http://wiki.volkszaehler.org/software/controller/vzlogger#configuration
|
||||
*/
|
||||
|
||||
{
|
||||
"retry" : 30, /* how long to sleep between failed requests, in seconds */
|
||||
//"daemon": false, /* run periodically */
|
||||
//"foreground" : true, /* dont run in background (prevents forking) */
|
||||
//"verbosity" : 5, /* between 0 and 15 */
|
||||
//"log" : "/var/log/vzlogger.log",/* path to logfile, optional */
|
||||
|
||||
"local" : {
|
||||
// "enabled" : false, /* should we start the local HTTPd for serving live readings? */
|
||||
"port" : 8080, /* the TCP port for the local HTTPd */
|
||||
"index" : true, /* should we provide a index listing of available channels if no UUID was requested? */
|
||||
"timeout" : 30, /* timeout for long polling comet requests, 0 disables comet, in seconds */
|
||||
"buffer" : 600 /* how long to buffer readings for the local interface, in seconds */
|
||||
},
|
||||
|
||||
"meters" : [{
|
||||
"enabled" : false, /* disabled meters will be ignored */
|
||||
"protocol" : "sml", /* see 'vzlogger -h' for list of available protocols */
|
||||
"host" : "meinzaehler.dyndns.info:7331",
|
||||
"channels": [{
|
||||
"uuid" : "fde8f1d0-c5d0-11e0-856e-f9e4360ced10",
|
||||
"middleware" : "http://localhost/volkszaehler/middleware.php",
|
||||
"identifier" : "power" /* alias for '1-0:1.7.ff', see 'vzlogger -h' for list of available aliases */
|
||||
}, {
|
||||
"uuid" : "a8da012a-9eb4-49ed-b7f3-38c95142a90c",
|
||||
"middleware" : "http://localhost/volkszaehler/middleware.php",
|
||||
"identifier" : "counter",
|
||||
}, {
|
||||
"uuid" : "d5c6db0f-533e-498d-a85a-be972c104b48",
|
||||
"middleware" : "http://localhost/volkszaehler/middleware.php",
|
||||
"identifier" : "1-0:1.8.0" /* see 'vzlogger -v20' for an output with all available identifiers/OBIS ids */
|
||||
}]
|
||||
}, {
|
||||
"protocol" : "random",
|
||||
"interval" : 2,
|
||||
"max" : 40.0, /* has to be double! */
|
||||
"min" : -5.0, /* has to be double! */
|
||||
"channel" : {
|
||||
"uuid" : "bac2e840-f72c-11e0-bedf-3f850c1e5a66",
|
||||
"middleware" : "http://demo.volkszaehler.org/middleware.php"
|
||||
}
|
||||
}, {
|
||||
"protocol" : "s0",
|
||||
"device" : "/dev/ttyUSB0",
|
||||
"channel" : {
|
||||
"uuid" : "d495a390-f747-11e0-b3ca-f7890e45c7b2",
|
||||
"middleware" : "http://demo.volkszaehler.org/middleware.php"
|
||||
}
|
||||
},
|
||||
{
|
||||
"protocol" : "file",
|
||||
"path" : "/proc/loadavg",
|
||||
// "format" : "$i $v $t", /* a format string for parsing complex logfiles */
|
||||
/* arbitrary text and whitespaces are allowed, see 'scanf()' */
|
||||
/* at least $v has to be used */
|
||||
/* $i => identifier, $v => value, $t => timestamp */
|
||||
"rewind" : true, /* reset file pointer each interval to the beginning of the file */
|
||||
"interval" : 2 /* of ommitted, we will try to listen on changes with inotify */
|
||||
},
|
||||
{
|
||||
"protocol" : "fluksov2",
|
||||
"fifo" : "/var/spid/delta/out",
|
||||
"channel" : {
|
||||
"uuid" : "3b4da450-42a8-11e1-8b8d-c526d853edec",
|
||||
"middleware" : "http://demo.volkszaehler.org/middleware.php",
|
||||
"identifier" : "sensor0/power" /* or "sensor2/consumption" e.g. */
|
||||
}
|
||||
}
|
||||
]}
|
|
@ -1,6 +0,0 @@
|
|||
Allow from all
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^middleware/(.*) middleware.php/$1 [L]
|
||||
</IfModule>
|
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 733 B |
Before Width: | Height: | Size: 685 B |
Before Width: | Height: | Size: 349 B |
Before Width: | Height: | Size: 526 B |
Before Width: | Height: | Size: 737 B |
Before Width: | Height: | Size: 736 B |
Before Width: | Height: | Size: 745 B |
Before Width: | Height: | Size: 720 B |
Before Width: | Height: | Size: 655 B |
Before Width: | Height: | Size: 715 B |
Before Width: | Height: | Size: 894 B |
Before Width: | Height: | Size: 915 B |
Before Width: | Height: | Size: 750 B |
Before Width: | Height: | Size: 516 B |
Before Width: | Height: | Size: 778 B |
Before Width: | Height: | Size: 343 B |
Before Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 620 B |
Before Width: | Height: | Size: 530 B |
Before Width: | Height: | Size: 225 B |
Before Width: | Height: | Size: 670 B |
Before Width: | Height: | Size: 566 B |
Before Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 2.8 KiB |
Before Width: | Height: | Size: 634 B |
Before Width: | Height: | Size: 882 B |
Before Width: | Height: | Size: 581 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 537 B |
Before Width: | Height: | Size: 806 B |
Before Width: | Height: | Size: 579 B |
Before Width: | Height: | Size: 242 B |
Before Width: | Height: | Size: 626 B |
Before Width: | Height: | Size: 623 B |
Before Width: | Height: | Size: 262 B |
Before Width: | Height: | Size: 741 B |
Before Width: | Height: | Size: 555 B |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 610 B |
Before Width: | Height: | Size: 488 B |
Before Width: | Height: | Size: 692 B |
Before Width: | Height: | Size: 729 B |
Before Width: | Height: | Size: 742 B |
|
@ -1,168 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>volkszaehler.org - web frontend</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
|
||||
<link rel="shortcut icon" type="image/x-icon" href="../favicon.ico">
|
||||
<link rel="apple-touch-icon" href="../favicon.ico">
|
||||
|
||||
<!-- jQuery -->
|
||||
<script type="text/javascript" src="javascripts/jquery/jquery-1.5.1.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery/jquery-ui-1.8.10.min.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery/jquery-treeTable.js"></script>
|
||||
<script type="text/javascript" src="javascripts/jquery/jquery-extensions.js"></script>
|
||||
|
||||
<!--[if IE]><script language="javascript" type="text/javascript" src="javascripts/flot/excanvas.min.js"></script><![endif]-->
|
||||
<script type="text/javascript" src="javascripts/flot/jquery.flot.js"></script>
|
||||
<script type="text/javascript" src="javascripts/flot/jquery.flot.crosshair.js"></script>
|
||||
<script type="text/javascript" src="javascripts/flot/jquery.flot.selection.js"></script>
|
||||
|
||||
<script type="text/javascript" src="javascripts/helper.js"></script>
|
||||
<script type="text/javascript" src="javascripts/init.js"></script>
|
||||
<script type="text/javascript" src="javascripts/options.js"></script>
|
||||
<script type="text/javascript" src="javascripts/functions.js"></script>
|
||||
<script type="text/javascript" src="javascripts/entities.js"></script>
|
||||
<script type="text/javascript" src="javascripts/wui.js"></script>
|
||||
<script type="text/javascript" src="javascripts/entity.js"></script>
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/ui-lightness/jquery-ui-1.8.10.css" />
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/jquery.treeTable.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/jquery.ui.custom.css">
|
||||
<link rel="stylesheet" type="text/css" href="stylesheets/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="header"></div>
|
||||
<div id="content">
|
||||
<div id="headline">
|
||||
<h2 id="title"></h2>
|
||||
|
||||
<div id="export">
|
||||
<img alt="export" src="images/export.png" />
|
||||
<select class="icons">
|
||||
<option value="default" style="background-image: url(images/export.png)" selected="selected">Export...</option>
|
||||
<option value="permalink" style="background-image: url(images/link.png)" >Permalink</option>
|
||||
<option value="png" style="background-image: url(images/image.png)" disabled="disabled" >Snapshot</option>
|
||||
<option value="csv" style="background-image: url(images/table.png)" >CSV</option>
|
||||
<option value="xml" style="background-image: url(images/xml.png)" >XML</option>
|
||||
</select>
|
||||
</div>
|
||||
<br style="clear: both" />
|
||||
</div>
|
||||
<div id="plot">
|
||||
<div id="flot"></div>
|
||||
<div id="overlay"></div>
|
||||
</div>
|
||||
|
||||
<div id="accordion">
|
||||
<div id="controls">
|
||||
<button value="move-back" title="scroll backward"><img src="images/control_rewind_blue.png"/></button>
|
||||
<button value="move-forward" title="scroll forward"><img src="images/control_fastforward_blue.png"/></button>
|
||||
<button value="move-last" title="scroll to presence">Jetzt <img src="images/control_end_blue.png"/></button>
|
||||
<button value="zoom-in" title="zoom in"><img src="images/zoom_in.png"/></button>
|
||||
<button value="zoom-out" title="zoom out"><img src="images/zoom_out.png"/></button>
|
||||
<button value="zoom-hour">Stunde</button>
|
||||
<button value="zoom-day">Tag</button>
|
||||
<button value="zoom-week">Woche</button>
|
||||
<button value="zoom-month">Monat</button>
|
||||
<button value="zoom-year">Jahr</button>
|
||||
</div>
|
||||
|
||||
<h3><img src="images/table.png" alt="" /> Kanäle</h3>
|
||||
<div id="entity-list">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><img src="images/eye.png" alt="Anzeige" title="Anzeige" /></th>
|
||||
<th></th>
|
||||
<th>Titel</th>
|
||||
<th>Typ</th>
|
||||
<th>Min.</th>
|
||||
<th>Max.</th>
|
||||
<th>∅</th>
|
||||
<th>aktuell</th>
|
||||
<th>Verbrauch</th>
|
||||
<th>Kosten</th>
|
||||
<th>Aktion</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
<div><button name="entity-add"><img src="images/add.png" alt="add" /> Kanal hinzufügen</button></div>
|
||||
</div>
|
||||
<h3><img src="images/wrench.png" alt="" /> Optionen</h3>
|
||||
<div id="options">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Option</th>
|
||||
<th>Wert</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><label for="refresh"><img src="images/arrow_refresh.png" alt="" /> Automatisch aktualisieren</label></td>
|
||||
<td><input type="checkbox" id="refresh" /> <span id="refresh-time"><span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div><button name="options-save"><img src="images/save.png" alt="save" /> Einstellungen speichern</button></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="footer">
|
||||
© 2011 - <a href="http://volkszaehler.org/">volkszaehler.org</a> - the open smartmeter platform
|
||||
</div>
|
||||
|
||||
<!-- dialogs -->
|
||||
<div id="entity-move" class="dialog">
|
||||
<p>
|
||||
<span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;"></span>
|
||||
Sie sind im Begriff einen Kanal oder eine Gruppe zu Verschieben!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="entity-add" class="dialog">
|
||||
<div class="tabs">
|
||||
<ul>
|
||||
<li><a href="#entity-subscribe">Kanal abonnieren</a></li>
|
||||
<li><a href="#entity-public">öffentliche Kanäle</a></li>
|
||||
<li><a href="#entity-create">Kanal erstellen</a></li>
|
||||
</ul>
|
||||
<div id="entity-subscribe">
|
||||
<p>Hier können Sie einen existierenden Kanal über seine UUID hinzufügen</p>
|
||||
<table>
|
||||
<tr><td><label for="entity-subscribe-middleware">Middleware:</label></td><td><input id="entity-subscribe-middleware" type="text" size="36" /></td></tr>
|
||||
<tr><td><label for="entity-subscribe-uuid">UUID:</label></td><td><input id="entity-subscribe-uuid" type="text" size="36" maxlength="36" /></td></tr>
|
||||
</table>
|
||||
<p><input type="button" value="Abonnieren" /> <label for="entity-subscribe-cookie">Cookie:</label> <input id="entity-subscribe-cookie" type="checkbox" /></p>
|
||||
</div>
|
||||
<div id="entity-public">
|
||||
<p>Hier können Sie öffentliche Kanäle abonnieren.</p>
|
||||
<table>
|
||||
<tr><td><label for="entity-public-middleware">Middleware:</label></td><td><select id="entity-public-middleware"></select></td></tr>
|
||||
<tr><td><label for="entity-public-entity">Kanal:</label></td><td><select id="entity-public-entity" size="1"></select></td></tr>
|
||||
</table>
|
||||
<p><input type="button" value="Abonnieren" /> <label for="entity-public-cookie">Cookie:</label> <input id="entity-public-cookie" type="checkbox" /></p>
|
||||
</div>
|
||||
<div id="entity-create">
|
||||
<form method="get" target="_blank">
|
||||
<table>
|
||||
<tr class="property"><th>Eigenschaft</th><th>Wert</th></tr>
|
||||
<tr class="property"><td>Middleware:</td><td><input type="text" id="entity-create-middleware" /></td></tr>
|
||||
<tr class="property"><td>Typ:</td><td><select class="icons" name="type" size="1"></select></td></tr>
|
||||
<tr class="property"><td>Öffentlich:</td><td><input type="radio" name="public" value="1"> ja <input type="radio" name="public" value="0"> nein</td></tr>
|
||||
<tr class="property"><td>Titel:</td><td><input type="text" name="title" value="Kühlschrank" /></td></tr>
|
||||
<tr class="property"><td>Auflösung:</td><td><input type="text" name="resolution" value="1000" /></td></tr>
|
||||
<tr class="property"><td>Kosten:<br /><p style="font-size: small">pro Wh</p></td><td><input type="text" name="cost" value="0.00025" /> €</td></tr>
|
||||
<tr class="property"><td>Beschreibung:</td><td><input type="text" name="description" value="Swissnox 1-phasig" /></td></tr>
|
||||
</table>
|
||||
<p><input type="submit" value="Erstellen" /> <label for="entity-create-cookie">Cookie:</label> <input id="entity-create-cookie" type="checkbox" /></p>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -1,189 +0,0 @@
|
|||
/**
|
||||
*
|
||||
*
|
||||
* @author Florian Ziegler <fz@f10-home.de>
|
||||
* @author Justin Otherguy <justin@justinotherguy.org>
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @package default
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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 any later version.
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Save minimal Entity in JSON cookie
|
||||
*/
|
||||
vz.entities.saveCookie = function() {
|
||||
var expires = new Date(new Date().getTime() + 3e10); // in about a year
|
||||
var arr = new Array;
|
||||
|
||||
this.each(function(entity) {
|
||||
if (entity.cookie === true) {
|
||||
arr.push(entity.uuid + '@' + entity.middleware);
|
||||
}
|
||||
}, true); // recursive!
|
||||
|
||||
$.setCookie('vz_entities', arr.join('|'), {expires: expires});
|
||||
};
|
||||
|
||||
/**
|
||||
* Load entities from JSON cookie
|
||||
*/
|
||||
vz.entities.loadCookie = function() {
|
||||
var cookie = $.getCookie('vz_entities');
|
||||
if (cookie) {
|
||||
var arr = cookie.split('|');
|
||||
arr.each(function(index, entry) {
|
||||
var entity = entry.split('@');
|
||||
vz.entities.push(new Entity({
|
||||
middleware: entity[1],
|
||||
uuid: entity[0],
|
||||
cookie: true
|
||||
}));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load JSON data from the middleware
|
||||
*/
|
||||
vz.entities.loadData = function() {
|
||||
$('#overlay').html('<img src="images/loading.gif" alt="loading..." /><p>loading...</p>');
|
||||
|
||||
var queue = new Array;
|
||||
this.each(function(entity) {
|
||||
if (entity.active && entity.definition.model == 'Volkszaehler\\Model\\Channel') {
|
||||
queue.push(entity.loadData());
|
||||
}
|
||||
}, true); // recursive!
|
||||
|
||||
return $.when.apply($, queue);
|
||||
};
|
||||
|
||||
/**
|
||||
* Overwritten each iterator to iterate recursively throug all entities
|
||||
*/
|
||||
vz.entities.each = function(cb, recursive) {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
cb(this[i]);
|
||||
|
||||
if (recursive && this[i] !== undefined) {
|
||||
this[i].each(cb, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create nested entity list
|
||||
*
|
||||
* @todo move to Entity class
|
||||
*/
|
||||
vz.entities.showTable = function() {
|
||||
$('#entity-list tbody').empty();
|
||||
|
||||
vz.entities.sort(Entity.compare);
|
||||
|
||||
this.each(function(entity, parent) {
|
||||
$('#entity-list tbody').append(entity.getDOMRow(parent));
|
||||
}, true); // recursive!
|
||||
|
||||
/*
|
||||
* Initialize treeTable
|
||||
*
|
||||
* http://ludo.cubicphuse.nl/jquery-plugins/treeTable/doc/index.html
|
||||
* https://github.com/ludo/jquery-plugins/tree/master/treeTable
|
||||
*/
|
||||
// configure entities as draggable
|
||||
$('#entity-list tr.channel span.indicator, #entity-list tr.aggregator span.indicator').draggable({
|
||||
helper: 'clone',
|
||||
opacity: 0.75,
|
||||
refreshPositions: true, // Performance?
|
||||
revert: 'invalid',
|
||||
revertDuration: 300,
|
||||
scroll: true
|
||||
});
|
||||
|
||||
// configure aggregators as droppable
|
||||
$('#entity-list tr.aggregator span.indicator').each(function() {
|
||||
$(this).parents('tr').droppable({
|
||||
//accept: 'tr.channel span.indicator, tr.aggregator span.indicator', // TODO
|
||||
drop: function(event, ui) {
|
||||
var child = $(ui.draggable.parents('tr')[0]).data('entity');
|
||||
var from = child.parent;
|
||||
var to = $(this).data('entity');
|
||||
|
||||
$('#entity-move').dialog({ // confirm prompt
|
||||
resizable: false,
|
||||
modal: true,
|
||||
title: 'Verschieben',
|
||||
width: 400,
|
||||
buttons: {
|
||||
'Verschieben': function() {
|
||||
try {
|
||||
var queue = new Array;
|
||||
queue.push(to.addChild(child)); // add to new aggregator
|
||||
|
||||
if (from !== undefined) {
|
||||
queue.push(from.removeChild(child)); // remove from aggregator
|
||||
}
|
||||
else {
|
||||
child.cookie = false; // remove from cookies
|
||||
vz.entities.saveCookie();
|
||||
}
|
||||
} catch (e) {
|
||||
vz.wui.dialogs.exception(e);
|
||||
} finally {
|
||||
$.when(queue).done(function() {
|
||||
// wait for middleware
|
||||
$.when(from.loadDetails(), to.loadDetails).done(vz.entities.showTable);
|
||||
});
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
'Abbrechen': function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
hoverClass: 'accept',
|
||||
over: function(event, ui) {
|
||||
// make the droppable branch expand when a draggable node is moved over it
|
||||
if (this.id != $(ui.draggable.parents('tr')[0]).id && !$(this).hasClass('expanded')) {
|
||||
$(this).expand();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// make visible that a row is clicked
|
||||
$('#entity-list table tbody tr').mousedown(function() {
|
||||
$('tr.selected').removeClass('selected'); // deselect currently selected rows
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
|
||||
// make sure row is selected when span is clicked
|
||||
$('#entity-list table tbody tr span').mousedown(function() {
|
||||
$($(this).parents('tr')[0]).trigger('mousedown');
|
||||
});
|
||||
|
||||
$('#entity-list table').treeTable({
|
||||
treeColumn: 2,
|
||||
clickableNodeNames: true,
|
||||
initialState: 'expanded'
|
||||
});
|
||||
};
|
|
@ -1,455 +0,0 @@
|
|||
/**
|
||||
* Entity handling, parsing & validation
|
||||
*
|
||||
* @author Justin Otherguy <justin@justinotherguy.org>
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @package default
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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 any later version.
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Entity constructor
|
||||
* @todo add validation
|
||||
*/
|
||||
var Entity = function(json) {
|
||||
this.parseJSON(json);
|
||||
};
|
||||
|
||||
Entity.colors = 0;
|
||||
|
||||
Entity.prototype.parseJSON = function(json) {
|
||||
$.extend(true, this, json);
|
||||
|
||||
// parse children
|
||||
if (this.children) {
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
this.children[i].middleware = this.middleware; // children inherit parent middleware
|
||||
this.children[i] = new Entity(this.children[i]);
|
||||
}
|
||||
|
||||
this.children.sort(Entity.compare);
|
||||
}
|
||||
|
||||
// setting defaults
|
||||
if (this.type !== undefined) {
|
||||
this.definition = vz.capabilities.definitions.get('entities', this.type);
|
||||
|
||||
if (this.style === undefined) {
|
||||
if (this.definition.style) {
|
||||
this.style = this.definition.style;
|
||||
}
|
||||
else {
|
||||
this.style = (this.definition.interpreter == 'Volkszaehler\\Interpreter\\SensorInterpreter') ? 'lines' : 'steps';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.active === undefined) {
|
||||
this.active = true; // activate by default
|
||||
}
|
||||
|
||||
if (this.color === undefined) {
|
||||
this.color = vz.options.plot.colors[Entity.colors++ % vz.options.plot.colors.length];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Query middleware for details
|
||||
*/
|
||||
Entity.prototype.loadDetails = function() {
|
||||
return vz.load({
|
||||
url: this.middleware,
|
||||
controller: 'entity',
|
||||
identifier: this.uuid,
|
||||
context: this,
|
||||
success: function(json) {
|
||||
this.parseJSON(json.entity);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Entity.prototype.loadData = function() {
|
||||
return vz.load({
|
||||
controller: 'data',
|
||||
url: this.middleware,
|
||||
identifier: this.uuid,
|
||||
context: this,
|
||||
data: {
|
||||
from: Math.floor(vz.options.plot.xaxis.min),
|
||||
to: Math.ceil(vz.options.plot.xaxis.max),
|
||||
tuples: vz.options.tuples
|
||||
},
|
||||
success: function(json) {
|
||||
this.data = json.data;
|
||||
|
||||
if (this.data.tuples && this.data.tuples.length > 0) {
|
||||
if (this.data.min[1] < vz.options.plot.yaxis.min) { // allow negative values for temperature sensors
|
||||
vz.options.plot.yaxis.min = null;
|
||||
}
|
||||
}
|
||||
|
||||
this.updateDOMRow();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show and edit entity details
|
||||
*/
|
||||
Entity.prototype.showDetails = function() {
|
||||
var entity = this;
|
||||
|
||||
$('<div>')
|
||||
.addClass('details')
|
||||
.append(this.getDOMDetails())
|
||||
.dialog({
|
||||
title: 'Details für ' + this.title,
|
||||
width: 480,
|
||||
resizable: false,
|
||||
buttons : {
|
||||
'Schließen': function() {
|
||||
$(this).dialog('close');
|
||||
},
|
||||
'Löschen' : function() {
|
||||
entity.cookie = false;
|
||||
vz.entities.saveCookie();
|
||||
|
||||
entity.delete().done(function() {
|
||||
vz.entities.each(function(it, parent) {
|
||||
if (entity == it) {
|
||||
var array = (parent) ? parent.children : vz.entities;
|
||||
array.remove(it);
|
||||
}
|
||||
}, true);
|
||||
|
||||
vz.entities.showTable();
|
||||
vz.wui.drawPlot();
|
||||
});
|
||||
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show from for new Channel
|
||||
*
|
||||
* @todo implement/test
|
||||
*/
|
||||
Entity.prototype.getDOMDetails = function(edit) {
|
||||
var table = $('<table><thead><tr><th>Eigenschaft</th><th>Wert</th></tr></thead></table>');
|
||||
var data = $('<tbody>');
|
||||
|
||||
// general properties
|
||||
var general = ['title', 'type', 'uuid', 'middleware', 'color', 'style', 'active', 'cookie'];
|
||||
var sections = ['required', 'optional'];
|
||||
|
||||
general.each(function(index, property) {
|
||||
var definition = vz.capabilities.definitions.get('properties', property);
|
||||
var title = (definition) ? definition.translation[vz.options.language] : property;
|
||||
var value = this[property];
|
||||
|
||||
switch(property) {
|
||||
case 'type':
|
||||
var title = 'Typ';
|
||||
var icon = $('<img>').
|
||||
attr('src', 'images/types/' + this.definition.icon)
|
||||
.css('margin-right', 4);
|
||||
var value = $('<span>')
|
||||
.text(this.definition.translation[vz.options.language])
|
||||
.prepend(icon);
|
||||
break;
|
||||
|
||||
case 'middleware':
|
||||
var title = 'Middleware';
|
||||
var value = '<a href="' + this.middleware + '/capabilities.json">' + this.middleware + '</a>';
|
||||
break;
|
||||
|
||||
case 'uuid':
|
||||
var title = 'UUID';
|
||||
var value = '<a href="' + this.middleware + '/entity/' + this.uuid + '.json">' + this.uuid + '</a>';
|
||||
break;
|
||||
|
||||
case 'color':
|
||||
var value = $('<span>')
|
||||
.text(this.color)
|
||||
.css('background-color', this.color)
|
||||
.css('padding-left', 5)
|
||||
.css('padding-right', 5);
|
||||
break;
|
||||
|
||||
case 'cookie':
|
||||
var title = 'Cookie';
|
||||
value = '<img src="images/' + ((this.cookie) ? 'tick' : 'cross') + '.png" alt="' + ((value) ? 'ja' : 'nein') + '" />';
|
||||
break;
|
||||
case 'active':
|
||||
var value = '<img src="images/' + ((this.active) ? 'tick' : 'cross') + '.png" alt="' + ((this.active) ? 'ja' : 'nein') + '" />';
|
||||
break;
|
||||
case 'style':
|
||||
switch (this.style) {
|
||||
case 'lines': var value = 'Linien'; break;
|
||||
case 'steps': var value = 'Stufen'; break;
|
||||
case 'points': var value = 'Punkte'; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
data.append($('<tr>')
|
||||
.addClass('property')
|
||||
.addClass('general')
|
||||
.append($('<td>')
|
||||
.addClass('key')
|
||||
.text(title)
|
||||
)
|
||||
.append($('<td>')
|
||||
.addClass('value')
|
||||
.append(value)
|
||||
)
|
||||
);
|
||||
}, this);
|
||||
|
||||
sections.each(function(index, section) {
|
||||
this.definition[section].each(function(index, property) {
|
||||
if (this.hasOwnProperty(property) && !general.contains(property)) {
|
||||
var definition = vz.capabilities.definitions.get('properties', property);
|
||||
var title = definition.translation[vz.options.language];
|
||||
var value = this[property];
|
||||
|
||||
if (definition.type == 'boolean') {
|
||||
value = '<img src="images/' + ((value) ? 'tick' : 'cross') + '.png" alt="' + ((value) ? 'ja' : 'nein') + '" />';
|
||||
}
|
||||
|
||||
if (property == 'cost') {
|
||||
value = (value * 1000 * 100) + ' ct/k' + this.definition.unit + 'h'; // ct per kWh
|
||||
}
|
||||
|
||||
data.append($('<tr>')
|
||||
.addClass('property')
|
||||
.addClass(section)
|
||||
.append($('<td>')
|
||||
.addClass('key')
|
||||
.text(title)
|
||||
)
|
||||
.append($('<td>')
|
||||
.addClass('value')
|
||||
.append(value)
|
||||
)
|
||||
);
|
||||
}
|
||||
}, this);
|
||||
}, this);
|
||||
return table.append(data);
|
||||
};
|
||||
|
||||
Entity.prototype.getDOMRow = function(parent) {
|
||||
var row = $('<tr>')
|
||||
.addClass((parent) ? 'child-of-entity-' + parent.uuid : '')
|
||||
.addClass((this.definition.model == 'Volkszaehler\\Model\\Aggregator') ? 'aggregator' : 'channel')
|
||||
.addClass('entity')
|
||||
.attr('id', 'entity-' + this.uuid)
|
||||
.append($('<td>')
|
||||
.addClass('visibility')
|
||||
.css('background-color', this.color)
|
||||
.append($('<input>')
|
||||
.attr('type', 'checkbox')
|
||||
.attr('checked', this.active)
|
||||
.bind('change', this, function(event) {
|
||||
var state = $(this).attr('checked');
|
||||
|
||||
event.data.active = state;
|
||||
$('#entity-' + event.data.uuid + ((parent) ? '.child-of-entity-' + parent.uuid : '') + ' input[type=checkbox]');
|
||||
|
||||
event.data.each(function(entity, parent) {
|
||||
$('#entity-' + entity.uuid + ((parent) ? '.child-of-entity-' + parent.uuid : '') + ' input[type=checkbox]')
|
||||
.attr('checked', state);
|
||||
entity.active = state;
|
||||
}, true); // recursive!
|
||||
|
||||
vz.wui.drawPlot();
|
||||
})
|
||||
)
|
||||
)
|
||||
.append($('<td>').addClass('expander'))
|
||||
.append($('<td>')
|
||||
.append($('<span>')
|
||||
.text(this.title)
|
||||
.addClass('indicator')
|
||||
.css('background-image', 'url(images/types/' + this.definition.icon + ')')
|
||||
)
|
||||
)
|
||||
.append($('<td>').text(this.definition.translation[vz.options.language])) // channel type
|
||||
.append($('<td>').addClass('min')) // min
|
||||
.append($('<td>').addClass('max')) // max
|
||||
.append($('<td>').addClass('average')) // avg
|
||||
.append($('<td>').addClass('last')) // last value
|
||||
.append($('<td>').addClass('consumption')) // consumption
|
||||
.append($('<td>').addClass('cost')) // costs
|
||||
.append($('<td>') // operations
|
||||
.addClass('ops')
|
||||
.append($('<input>')
|
||||
.attr('type', 'image')
|
||||
.attr('src', 'images/information.png')
|
||||
.attr('alt', 'details')
|
||||
.bind('click', this, function(event) {
|
||||
event.data.showDetails();
|
||||
})
|
||||
)
|
||||
)
|
||||
.data('entity', this);
|
||||
|
||||
if (this.cookie) {
|
||||
$('td.ops', row).prepend($('<input>')
|
||||
.attr('type', 'image')
|
||||
.attr('src', 'images/delete.png')
|
||||
.attr('alt', 'delete')
|
||||
.bind('click', this, function(event) {
|
||||
vz.entities.remove(event.data);
|
||||
vz.entities.saveCookie();
|
||||
vz.entities.showTable();
|
||||
vz.wui.drawPlot();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
return row;
|
||||
};
|
||||
|
||||
Entity.prototype.updateDOMRow = function() {
|
||||
var row = $('#entity-' + this.uuid);
|
||||
|
||||
var delta = this.data.to - this.data.from;
|
||||
var year = 365*24*60*60*1000;
|
||||
|
||||
if (this.data.rows > 0) { // update statistics if data available
|
||||
$('.min', row)
|
||||
.text(vz.wui.formatNumber(this.data.min[1], true) + this.definition.unit)
|
||||
.attr('title', $.plot.formatDate(new Date(this.data.min[0]), '%d. %b %y %h:%M:%S', vz.options.plot.xaxis.monthNames, true));
|
||||
$('.max', row)
|
||||
.text(vz.wui.formatNumber(this.data.max[1], true) + this.definition.unit)
|
||||
.attr('title', $.plot.formatDate(new Date(this.data.max[0]), '%d. %b %y %h:%M:%S', vz.options.plot.xaxis.monthNames, true));
|
||||
$('.average', row)
|
||||
.text(vz.wui.formatNumber(this.data.average, true) + this.definition.unit);
|
||||
$('.last', row)
|
||||
.text(vz.wui.formatNumber(this.data.tuples.last()[1], true) + this.definition.unit);
|
||||
|
||||
$('.consumption', row)
|
||||
.text(vz.wui.formatNumber(this.data.consumption, true) + this.definition.unit + 'h')
|
||||
.attr('title', vz.wui.formatNumber(this.data.consumption * (year/delta), true) + this.definition.unit + 'h' + '/Jahr');
|
||||
|
||||
if (this.cost) {
|
||||
$('.cost', row)
|
||||
.text(vz.wui.formatNumber(this.cost * this.data.consumption) + ' €')
|
||||
.attr('title', vz.wui.formatNumber(this.cost * this.data.consumption * (year/delta)) + ' €/Jahr');
|
||||
}
|
||||
}
|
||||
else { // no data available, clear table
|
||||
$('.min', row).text('').attr('title', '');
|
||||
$('.max', row).text('').attr('title', '');
|
||||
$('.average', row).text('');
|
||||
$('.last', row).text('');
|
||||
$('.consumption', row).text('');
|
||||
$('.cost', row).text('');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Permanently deletes this entity and its data from the middleware
|
||||
*/
|
||||
Entity.prototype.delete = function() {
|
||||
return vz.load({
|
||||
controller: 'entity',
|
||||
context: this,
|
||||
identifier: this.uuid,
|
||||
url: this.middleware,
|
||||
type: 'DELETE'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Add entity as child
|
||||
*/
|
||||
Entity.prototype.addChild = function(child) {
|
||||
if (this.definition.model != 'Volkszaehler\\Model\\Aggregator') {
|
||||
throw new Exception('EntityException', 'Entity is not an Aggregator');
|
||||
}
|
||||
|
||||
return vz.load({
|
||||
controller: 'group',
|
||||
identifier: this.uuid,
|
||||
url: this.middleware,
|
||||
data: {
|
||||
uuid: child.uuid
|
||||
},
|
||||
type: 'POST'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove entity from children
|
||||
*/
|
||||
Entity.prototype.removeChild = function(child) {
|
||||
if (this.definition.model != 'Volkszaehler\\Model\\Aggregator') {
|
||||
throw new Exception('EntityException', 'Entity is not an Aggregator');
|
||||
}
|
||||
|
||||
return vz.load({
|
||||
controller: 'group',
|
||||
identifier: this.uuid,
|
||||
url: this.middleware,
|
||||
data: {
|
||||
uuid: child.uuid,
|
||||
type: 'DELETE'
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Calls the callback function for the entity and all nested children
|
||||
*
|
||||
* @param cb callback function
|
||||
*/
|
||||
Entity.prototype.each = function(cb, recursive) {
|
||||
if (this.children) {
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
cb(this.children[i], this);
|
||||
|
||||
if (recursive && this.children[i] !== undefined) {
|
||||
this.children[i].each(cb, true); // call recursive
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Compares two entities for sorting
|
||||
*
|
||||
* @static
|
||||
* @todo Channels before Aggregators
|
||||
*/
|
||||
Entity.compare = function(a, b) {
|
||||
if (a.definition.model == 'Volkszaehler\\Model\\Channel' && // Channels before Aggregators
|
||||
b.definition.model == 'Volkszaehler\\Model\\Aggregator')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return ((a.title < b.title) ? -1 : ((a.title > b.title) ? 1 : 0));
|
||||
}
|
||||
}
|
|
@ -1,179 +0,0 @@
|
|||
/* Plugin for jQuery for working with colors.
|
||||
*
|
||||
* Version 1.1.
|
||||
*
|
||||
* Inspiration from jQuery color animation plugin by John Resig.
|
||||
*
|
||||
* Released under the MIT license by Ole Laursen, October 2009.
|
||||
*
|
||||
* Examples:
|
||||
*
|
||||
* $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString()
|
||||
* var c = $.color.extract($("#mydiv"), 'background-color');
|
||||
* console.log(c.r, c.g, c.b, c.a);
|
||||
* $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"
|
||||
*
|
||||
* Note that .scale() and .add() return the same modified object
|
||||
* instead of making a new one.
|
||||
*
|
||||
* V. 1.1: Fix error handling so e.g. parsing an empty string does
|
||||
* produce a color rather than just crashing.
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
$.color = {};
|
||||
|
||||
// construct color object with some convenient chainable helpers
|
||||
$.color.make = function (r, g, b, a) {
|
||||
var o = {};
|
||||
o.r = r || 0;
|
||||
o.g = g || 0;
|
||||
o.b = b || 0;
|
||||
o.a = a != null ? a : 1;
|
||||
|
||||
o.add = function (c, d) {
|
||||
for (var i = 0; i < c.length; ++i)
|
||||
o[c.charAt(i)] += d;
|
||||
return o.normalize();
|
||||
};
|
||||
|
||||
o.scale = function (c, f) {
|
||||
for (var i = 0; i < c.length; ++i)
|
||||
o[c.charAt(i)] *= f;
|
||||
return o.normalize();
|
||||
};
|
||||
|
||||
o.toString = function () {
|
||||
if (o.a >= 1.0) {
|
||||
return "rgb("+[o.r, o.g, o.b].join(",")+")";
|
||||
} else {
|
||||
return "rgba("+[o.r, o.g, o.b, o.a].join(",")+")";
|
||||
}
|
||||
};
|
||||
|
||||
o.normalize = function () {
|
||||
function clamp(min, value, max) {
|
||||
return value < min ? min: (value > max ? max: value);
|
||||
}
|
||||
|
||||
o.r = clamp(0, parseInt(o.r), 255);
|
||||
o.g = clamp(0, parseInt(o.g), 255);
|
||||
o.b = clamp(0, parseInt(o.b), 255);
|
||||
o.a = clamp(0, o.a, 1);
|
||||
return o;
|
||||
};
|
||||
|
||||
o.clone = function () {
|
||||
return $.color.make(o.r, o.b, o.g, o.a);
|
||||
};
|
||||
|
||||
return o.normalize();
|
||||
}
|
||||
|
||||
// extract CSS color property from element, going up in the DOM
|
||||
// if it's "transparent"
|
||||
$.color.extract = function (elem, css) {
|
||||
var c;
|
||||
do {
|
||||
c = elem.css(css).toLowerCase();
|
||||
// keep going until we find an element that has color, or
|
||||
// we hit the body
|
||||
if (c != '' && c != 'transparent')
|
||||
break;
|
||||
elem = elem.parent();
|
||||
} while (!$.nodeName(elem.get(0), "body"));
|
||||
|
||||
// catch Safari's way of signalling transparent
|
||||
if (c == "rgba(0, 0, 0, 0)")
|
||||
c = "transparent";
|
||||
|
||||
return $.color.parse(c);
|
||||
}
|
||||
|
||||
// parse CSS color string (like "rgb(10, 32, 43)" or "#fff"),
|
||||
// returns color object, if parsing failed, you get black (0, 0,
|
||||
// 0) out
|
||||
$.color.parse = function (str) {
|
||||
var res, m = $.color.make;
|
||||
|
||||
// Look for rgb(num,num,num)
|
||||
if (res = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(str))
|
||||
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10));
|
||||
|
||||
// Look for rgba(num,num,num,num)
|
||||
if (res = /rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
|
||||
return m(parseInt(res[1], 10), parseInt(res[2], 10), parseInt(res[3], 10), parseFloat(res[4]));
|
||||
|
||||
// Look for rgb(num%,num%,num%)
|
||||
if (res = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(str))
|
||||
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55);
|
||||
|
||||
// Look for rgba(num%,num%,num%,num)
|
||||
if (res = /rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(str))
|
||||
return m(parseFloat(res[1])*2.55, parseFloat(res[2])*2.55, parseFloat(res[3])*2.55, parseFloat(res[4]));
|
||||
|
||||
// Look for #a0b1c2
|
||||
if (res = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))
|
||||
return m(parseInt(res[1], 16), parseInt(res[2], 16), parseInt(res[3], 16));
|
||||
|
||||
// Look for #fff
|
||||
if (res = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))
|
||||
return m(parseInt(res[1]+res[1], 16), parseInt(res[2]+res[2], 16), parseInt(res[3]+res[3], 16));
|
||||
|
||||
// Otherwise, we're most likely dealing with a named color
|
||||
var name = $.trim(str).toLowerCase();
|
||||
if (name == "transparent")
|
||||
return m(255, 255, 255, 0);
|
||||
else {
|
||||
// default to black
|
||||
res = lookupColors[name] || [0, 0, 0];
|
||||
return m(res[0], res[1], res[2]);
|
||||
}
|
||||
}
|
||||
|
||||
var lookupColors = {
|
||||
aqua:[0,255,255],
|
||||
azure:[240,255,255],
|
||||
beige:[245,245,220],
|
||||
black:[0,0,0],
|
||||
blue:[0,0,255],
|
||||
brown:[165,42,42],
|
||||
cyan:[0,255,255],
|
||||
darkblue:[0,0,139],
|
||||
darkcyan:[0,139,139],
|
||||
darkgrey:[169,169,169],
|
||||
darkgreen:[0,100,0],
|
||||
darkkhaki:[189,183,107],
|
||||
darkmagenta:[139,0,139],
|
||||
darkolivegreen:[85,107,47],
|
||||
darkorange:[255,140,0],
|
||||
darkorchid:[153,50,204],
|
||||
darkred:[139,0,0],
|
||||
darksalmon:[233,150,122],
|
||||
darkviolet:[148,0,211],
|
||||
fuchsia:[255,0,255],
|
||||
gold:[255,215,0],
|
||||
green:[0,128,0],
|
||||
indigo:[75,0,130],
|
||||
khaki:[240,230,140],
|
||||
lightblue:[173,216,230],
|
||||
lightcyan:[224,255,255],
|
||||
lightgreen:[144,238,144],
|
||||
lightgrey:[211,211,211],
|
||||
lightpink:[255,182,193],
|
||||
lightyellow:[255,255,224],
|
||||
lime:[0,255,0],
|
||||
magenta:[255,0,255],
|
||||
maroon:[128,0,0],
|
||||
navy:[0,0,128],
|
||||
olive:[128,128,0],
|
||||
orange:[255,165,0],
|
||||
pink:[255,192,203],
|
||||
purple:[128,0,128],
|
||||
violet:[128,0,128],
|
||||
red:[255,0,0],
|
||||
silver:[192,192,192],
|
||||
white:[255,255,255],
|
||||
yellow:[255,255,0]
|
||||
};
|
||||
})(jQuery);
|
|
@ -1,167 +0,0 @@
|
|||
/*
|
||||
Flot plugin for showing crosshairs, thin lines, when the mouse hovers
|
||||
over the plot.
|
||||
|
||||
crosshair: {
|
||||
mode: null or "x" or "y" or "xy"
|
||||
color: color
|
||||
lineWidth: number
|
||||
}
|
||||
|
||||
Set the mode to one of "x", "y" or "xy". The "x" mode enables a
|
||||
vertical crosshair that lets you trace the values on the x axis, "y"
|
||||
enables a horizontal crosshair and "xy" enables them both. "color" is
|
||||
the color of the crosshair (default is "rgba(170, 0, 0, 0.80)"),
|
||||
"lineWidth" is the width of the drawn lines (default is 1).
|
||||
|
||||
The plugin also adds four public methods:
|
||||
|
||||
- setCrosshair(pos)
|
||||
|
||||
Set the position of the crosshair. Note that this is cleared if
|
||||
the user moves the mouse. "pos" is in coordinates of the plot and
|
||||
should be on the form { x: xpos, y: ypos } (you can use x2/x3/...
|
||||
if you're using multiple axes), which is coincidentally the same
|
||||
format as what you get from a "plothover" event. If "pos" is null,
|
||||
the crosshair is cleared.
|
||||
|
||||
- clearCrosshair()
|
||||
|
||||
Clear the crosshair.
|
||||
|
||||
- lockCrosshair(pos)
|
||||
|
||||
Cause the crosshair to lock to the current location, no longer
|
||||
updating if the user moves the mouse. Optionally supply a position
|
||||
(passed on to setCrosshair()) to move it to.
|
||||
|
||||
Example usage:
|
||||
var myFlot = $.plot( $("#graph"), ..., { crosshair: { mode: "x" } } };
|
||||
$("#graph").bind("plothover", function (evt, position, item) {
|
||||
if (item) {
|
||||
// Lock the crosshair to the data point being hovered
|
||||
myFlot.lockCrosshair({ x: item.datapoint[0], y: item.datapoint[1] });
|
||||
}
|
||||
else {
|
||||
// Return normal crosshair operation
|
||||
myFlot.unlockCrosshair();
|
||||
}
|
||||
});
|
||||
|
||||
- unlockCrosshair()
|
||||
|
||||
Free the crosshair to move again after locking it.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
crosshair: {
|
||||
mode: null, // one of null, "x", "y" or "xy",
|
||||
color: "rgba(170, 0, 0, 0.80)",
|
||||
lineWidth: 1
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
// position of crosshair in pixels
|
||||
var crosshair = { x: -1, y: -1, locked: false };
|
||||
|
||||
plot.setCrosshair = function setCrosshair(pos) {
|
||||
if (!pos)
|
||||
crosshair.x = -1;
|
||||
else {
|
||||
var o = plot.p2c(pos);
|
||||
crosshair.x = Math.max(0, Math.min(o.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(o.top, plot.height()));
|
||||
}
|
||||
|
||||
plot.triggerRedrawOverlay();
|
||||
};
|
||||
|
||||
plot.clearCrosshair = plot.setCrosshair; // passes null for pos
|
||||
|
||||
plot.lockCrosshair = function lockCrosshair(pos) {
|
||||
if (pos)
|
||||
plot.setCrosshair(pos);
|
||||
crosshair.locked = true;
|
||||
}
|
||||
|
||||
plot.unlockCrosshair = function unlockCrosshair() {
|
||||
crosshair.locked = false;
|
||||
}
|
||||
|
||||
function onMouseOut(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
crosshair.x = -1;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (crosshair.locked)
|
||||
return;
|
||||
|
||||
if (plot.getSelection && plot.getSelection()) {
|
||||
crosshair.x = -1; // hide the crosshair while selecting
|
||||
return;
|
||||
}
|
||||
|
||||
var offset = plot.offset();
|
||||
crosshair.x = Math.max(0, Math.min(e.pageX - offset.left, plot.width()));
|
||||
crosshair.y = Math.max(0, Math.min(e.pageY - offset.top, plot.height()));
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(function (plot, eventHolder) {
|
||||
if (!plot.getOptions().crosshair.mode)
|
||||
return;
|
||||
|
||||
eventHolder.mouseout(onMouseOut);
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
});
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
var c = plot.getOptions().crosshair;
|
||||
if (!c.mode)
|
||||
return;
|
||||
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
if (crosshair.x != -1) {
|
||||
ctx.strokeStyle = c.color;
|
||||
ctx.lineWidth = c.lineWidth;
|
||||
ctx.lineJoin = "round";
|
||||
|
||||
ctx.beginPath();
|
||||
if (c.mode.indexOf("x") != -1) {
|
||||
ctx.moveTo(crosshair.x, 0);
|
||||
ctx.lineTo(crosshair.x, plot.height());
|
||||
}
|
||||
if (c.mode.indexOf("y") != -1) {
|
||||
ctx.moveTo(0, crosshair.y);
|
||||
ctx.lineTo(plot.width(), crosshair.y);
|
||||
}
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.restore();
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mouseout", onMouseOut);
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'crosshair',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
Flot plugin for computing bottoms for filled line and bar charts.
|
||||
|
||||
The case: you've got two series that you want to fill the area
|
||||
between. In Flot terms, you need to use one as the fill bottom of the
|
||||
other. You can specify the bottom of each data point as the third
|
||||
coordinate manually, or you can use this plugin to compute it for you.
|
||||
|
||||
In order to name the other series, you need to give it an id, like this
|
||||
|
||||
var dataset = [
|
||||
{ data: [ ... ], id: "foo" } , // use default bottom
|
||||
{ data: [ ... ], fillBetween: "foo" }, // use first dataset as bottom
|
||||
];
|
||||
|
||||
$.plot($("#placeholder"), dataset, { line: { show: true, fill: true }});
|
||||
|
||||
As a convenience, if the id given is a number that doesn't appear as
|
||||
an id in the series, it is interpreted as the index in the array
|
||||
instead (so fillBetween: 0 can also mean the first series).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series. For
|
||||
line series, extra data points might be inserted through
|
||||
interpolation. Note that at points where the bottom line is not
|
||||
defined (due to a null point or start/end of line), the current line
|
||||
will show a gap too. The algorithm comes from the jquery.flot.stack.js
|
||||
plugin, possibly some code could be shared.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { fillBetween: null } // or number
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function findBottomSeries(s, allseries) {
|
||||
var i;
|
||||
for (i = 0; i < allseries.length; ++i) {
|
||||
if (allseries[i].id == s.fillBetween)
|
||||
return allseries[i];
|
||||
}
|
||||
|
||||
if (typeof s.fillBetween == "number") {
|
||||
i = s.fillBetween;
|
||||
|
||||
if (i < 0 || i >= allseries.length)
|
||||
return null;
|
||||
|
||||
return allseries[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function computeFillBottoms(plot, s, datapoints) {
|
||||
if (s.fillBetween == null)
|
||||
return;
|
||||
|
||||
var other = findBottomSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
withbottom = ps > 2 && datapoints.format[2].y,
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
i = 0, j = 0, l;
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// for lines, we can't use the rest of the points
|
||||
if (!withlines) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
}
|
||||
i += ps;
|
||||
}
|
||||
else if (otherpoints[j] == null) {
|
||||
// oops, got a gap
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(null);
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i];
|
||||
py = points[i + 1];
|
||||
qx = otherpoints[j];
|
||||
qy = otherpoints[j + 1];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
//newpoints[l + 1] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + 1] - py) * (qx - px) / (points[i - ps] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery)
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else { // px < qx
|
||||
if (fromgap && withlines) {
|
||||
// if we come from a gap, we just skip this point
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - otherps] != null)
|
||||
bottom = qy + (otherpoints[j - otherps + 1] - qy) * (px - qx) / (otherpoints[j - otherps] - qx);
|
||||
|
||||
//newpoints[l + 1] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] = bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(computeFillBottoms);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'fillbetween',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
Flot plugin for plotting images, e.g. useful for putting ticks on a
|
||||
prerendered complex visualization.
|
||||
|
||||
The data syntax is [[image, x1, y1, x2, y2], ...] where (x1, y1) and
|
||||
(x2, y2) are where you intend the two opposite corners of the image to
|
||||
end up in the plot. Image must be a fully loaded Javascript image (you
|
||||
can make one with new Image()). If the image is not complete, it's
|
||||
skipped when plotting.
|
||||
|
||||
There are two helpers included for retrieving images. The easiest work
|
||||
the way that you put in URLs instead of images in the data (like
|
||||
["myimage.png", 0, 0, 10, 10]), then call $.plot.image.loadData(data,
|
||||
options, callback) where data and options are the same as you pass in
|
||||
to $.plot. This loads the images, replaces the URLs in the data with
|
||||
the corresponding images and calls "callback" when all images are
|
||||
loaded (or failed loading). In the callback, you can then call $.plot
|
||||
with the data set. See the included example.
|
||||
|
||||
A more low-level helper, $.plot.image.load(urls, callback) is also
|
||||
included. Given a list of URLs, it calls callback with an object
|
||||
mapping from URL to Image object when all images are loaded or have
|
||||
failed loading.
|
||||
|
||||
Options for the plugin are
|
||||
|
||||
series: {
|
||||
images: {
|
||||
show: boolean
|
||||
anchor: "corner" or "center"
|
||||
alpha: [0,1]
|
||||
}
|
||||
}
|
||||
|
||||
which can be specified for a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], images: { ... } ])
|
||||
|
||||
Note that because the data format is different from usual data points,
|
||||
you can't use images with anything else in a specific data series.
|
||||
|
||||
Setting "anchor" to "center" causes the pixels in the image to be
|
||||
anchored at the corner pixel centers inside of at the pixel corners,
|
||||
effectively letting half a pixel stick out to each side in the plot.
|
||||
|
||||
|
||||
A possible future direction could be support for tiling for large
|
||||
images (like Google Maps).
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: {
|
||||
images: {
|
||||
show: false,
|
||||
alpha: 1,
|
||||
anchor: "corner" // or "center"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.image = {};
|
||||
|
||||
$.plot.image.loadDataImages = function (series, options, callback) {
|
||||
var urls = [], points = [];
|
||||
|
||||
var defaultShow = options.series.images.show;
|
||||
|
||||
$.each(series, function (i, s) {
|
||||
if (!(defaultShow || s.images.show))
|
||||
return;
|
||||
|
||||
if (s.data)
|
||||
s = s.data;
|
||||
|
||||
$.each(s, function (i, p) {
|
||||
if (typeof p[0] == "string") {
|
||||
urls.push(p[0]);
|
||||
points.push(p);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$.plot.image.load(urls, function (loadedImages) {
|
||||
$.each(points, function (i, p) {
|
||||
var url = p[0];
|
||||
if (loadedImages[url])
|
||||
p[0] = loadedImages[url];
|
||||
});
|
||||
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
||||
$.plot.image.load = function (urls, callback) {
|
||||
var missing = urls.length, loaded = {};
|
||||
if (missing == 0)
|
||||
callback({});
|
||||
|
||||
$.each(urls, function (i, url) {
|
||||
var handler = function () {
|
||||
--missing;
|
||||
|
||||
loaded[url] = this;
|
||||
|
||||
if (missing == 0)
|
||||
callback(loaded);
|
||||
};
|
||||
|
||||
$('<img />').load(handler).error(handler).attr('src', url);
|
||||
});
|
||||
}
|
||||
|
||||
function drawSeries(plot, ctx, series) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
|
||||
if (!series.images || !series.images.show)
|
||||
return;
|
||||
|
||||
var points = series.datapoints.points,
|
||||
ps = series.datapoints.pointsize;
|
||||
|
||||
for (var i = 0; i < points.length; i += ps) {
|
||||
var img = points[i],
|
||||
x1 = points[i + 1], y1 = points[i + 2],
|
||||
x2 = points[i + 3], y2 = points[i + 4],
|
||||
xaxis = series.xaxis, yaxis = series.yaxis,
|
||||
tmp;
|
||||
|
||||
// actually we should check img.complete, but it
|
||||
// appears to be a somewhat unreliable indicator in
|
||||
// IE6 (false even after load event)
|
||||
if (!img || img.width <= 0 || img.height <= 0)
|
||||
continue;
|
||||
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
// if the anchor is at the center of the pixel, expand the
|
||||
// image by 1/2 pixel in each direction
|
||||
if (series.images.anchor == "center") {
|
||||
tmp = 0.5 * (x2-x1) / (img.width - 1);
|
||||
x1 -= tmp;
|
||||
x2 += tmp;
|
||||
tmp = 0.5 * (y2-y1) / (img.height - 1);
|
||||
y1 -= tmp;
|
||||
y2 += tmp;
|
||||
}
|
||||
|
||||
// clip
|
||||
if (x1 == x2 || y1 == y2 ||
|
||||
x1 >= xaxis.max || x2 <= xaxis.min ||
|
||||
y1 >= yaxis.max || y2 <= yaxis.min)
|
||||
continue;
|
||||
|
||||
var sx1 = 0, sy1 = 0, sx2 = img.width, sy2 = img.height;
|
||||
if (x1 < xaxis.min) {
|
||||
sx1 += (sx2 - sx1) * (xaxis.min - x1) / (x2 - x1);
|
||||
x1 = xaxis.min;
|
||||
}
|
||||
|
||||
if (x2 > xaxis.max) {
|
||||
sx2 += (sx2 - sx1) * (xaxis.max - x2) / (x2 - x1);
|
||||
x2 = xaxis.max;
|
||||
}
|
||||
|
||||
if (y1 < yaxis.min) {
|
||||
sy2 += (sy1 - sy2) * (yaxis.min - y1) / (y2 - y1);
|
||||
y1 = yaxis.min;
|
||||
}
|
||||
|
||||
if (y2 > yaxis.max) {
|
||||
sy1 += (sy1 - sy2) * (yaxis.max - y2) / (y2 - y1);
|
||||
y2 = yaxis.max;
|
||||
}
|
||||
|
||||
x1 = xaxis.p2c(x1);
|
||||
x2 = xaxis.p2c(x2);
|
||||
y1 = yaxis.p2c(y1);
|
||||
y2 = yaxis.p2c(y2);
|
||||
|
||||
// the transformation may have swapped us
|
||||
if (x1 > x2) {
|
||||
tmp = x2;
|
||||
x2 = x1;
|
||||
x1 = tmp;
|
||||
}
|
||||
if (y1 > y2) {
|
||||
tmp = y2;
|
||||
y2 = y1;
|
||||
y1 = tmp;
|
||||
}
|
||||
|
||||
tmp = ctx.globalAlpha;
|
||||
ctx.globalAlpha *= series.images.alpha;
|
||||
ctx.drawImage(img,
|
||||
sx1, sy1, sx2 - sx1, sy2 - sy1,
|
||||
x1 + plotOffset.left, y1 + plotOffset.top,
|
||||
x2 - x1, y2 - y1);
|
||||
ctx.globalAlpha = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
function processRawData(plot, series, data, datapoints) {
|
||||
if (!series.images.show)
|
||||
return;
|
||||
|
||||
// format is Image, x1, y1, x2, y2 (opposite corners)
|
||||
datapoints.format = [
|
||||
{ required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true },
|
||||
{ x: true, number: true, required: true },
|
||||
{ y: true, number: true, required: true }
|
||||
];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processRawData.push(processRawData);
|
||||
plot.hooks.drawSeries.push(drawSeries);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'image',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,336 +0,0 @@
|
|||
/*
|
||||
Flot plugin for adding panning and zooming capabilities to a plot.
|
||||
|
||||
The default behaviour is double click and scrollwheel up/down to zoom
|
||||
in, drag to pan. The plugin defines plot.zoom({ center }),
|
||||
plot.zoomOut() and plot.pan(offset) so you easily can add custom
|
||||
controls. It also fires a "plotpan" and "plotzoom" event when
|
||||
something happens, useful for synchronizing plots.
|
||||
|
||||
Options:
|
||||
|
||||
zoom: {
|
||||
interactive: false
|
||||
trigger: "dblclick" // or "click" for single click
|
||||
amount: 1.5 // 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
}
|
||||
|
||||
pan: {
|
||||
interactive: false
|
||||
cursor: "move" // CSS mouse cursor value used when dragging, e.g. "pointer"
|
||||
frameRate: 20
|
||||
}
|
||||
|
||||
xaxis, yaxis, x2axis, y2axis: {
|
||||
zoomRange: null // or [number, number] (min range, max range) or false
|
||||
panRange: null // or [number, number] (min, max) or false
|
||||
}
|
||||
|
||||
"interactive" enables the built-in drag/click behaviour. If you enable
|
||||
interactive for pan, then you'll have a basic plot that supports
|
||||
moving around; the same for zoom.
|
||||
|
||||
"amount" specifies the default amount to zoom in (so 1.5 = 150%)
|
||||
relative to the current viewport.
|
||||
|
||||
"cursor" is a standard CSS mouse cursor string used for visual
|
||||
feedback to the user when dragging.
|
||||
|
||||
"frameRate" specifies the maximum number of times per second the plot
|
||||
will update itself while the user is panning around on it (set to null
|
||||
to disable intermediate pans, the plot will then not update until the
|
||||
mouse button is released).
|
||||
|
||||
"zoomRange" is the interval in which zooming can happen, e.g. with
|
||||
zoomRange: [1, 100] the zoom will never scale the axis so that the
|
||||
difference between min and max is smaller than 1 or larger than 100.
|
||||
You can set either end to null to ignore, e.g. [1, null]. If you set
|
||||
zoomRange to false, zooming on that axis will be disabled.
|
||||
|
||||
"panRange" confines the panning to stay within a range, e.g. with
|
||||
panRange: [-10, 20] panning stops at -10 in one end and at 20 in the
|
||||
other. Either can be null, e.g. [-10, null]. If you set
|
||||
panRange to false, panning on that axis will be disabled.
|
||||
|
||||
Example API usage:
|
||||
|
||||
plot = $.plot(...);
|
||||
|
||||
// zoom default amount in on the pixel (10, 20)
|
||||
plot.zoom({ center: { left: 10, top: 20 } });
|
||||
|
||||
// zoom out again
|
||||
plot.zoomOut({ center: { left: 10, top: 20 } });
|
||||
|
||||
// zoom 200% in on the pixel (10, 20)
|
||||
plot.zoom({ amount: 2, center: { left: 10, top: 20 } });
|
||||
|
||||
// pan 100 pixels to the left and 20 down
|
||||
plot.pan({ left: -100, top: 20 })
|
||||
|
||||
Here, "center" specifies where the center of the zooming should
|
||||
happen. Note that this is defined in pixel space, not the space of the
|
||||
data points (you can use the p2c helpers on the axes in Flot to help
|
||||
you convert between these).
|
||||
|
||||
"amount" is the amount to zoom the viewport relative to the current
|
||||
range, so 1 is 100% (i.e. no change), 1.5 is 150% (zoom in), 0.7 is
|
||||
70% (zoom out). You can set the default in the options.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// First two dependencies, jquery.event.drag.js and
|
||||
// jquery.mousewheel.js, we put them inline here to save people the
|
||||
// effort of downloading them.
|
||||
|
||||
/*
|
||||
jquery.event.drag.js ~ v1.5 ~ Copyright (c) 2008, Three Dub Media (http://threedubmedia.com)
|
||||
Licensed under the MIT License ~ http://threedubmedia.googlecode.com/files/MIT-LICENSE.txt
|
||||
*/
|
||||
(function(E){E.fn.drag=function(L,K,J){if(K){this.bind("dragstart",L)}if(J){this.bind("dragend",J)}return !L?this.trigger("drag"):this.bind("drag",K?K:L)};var A=E.event,B=A.special,F=B.drag={not:":input",distance:0,which:1,dragging:false,setup:function(J){J=E.extend({distance:F.distance,which:F.which,not:F.not},J||{});J.distance=I(J.distance);A.add(this,"mousedown",H,J);if(this.attachEvent){this.attachEvent("ondragstart",D)}},teardown:function(){A.remove(this,"mousedown",H);if(this===F.dragging){F.dragging=F.proxy=false}G(this,true);if(this.detachEvent){this.detachEvent("ondragstart",D)}}};B.dragstart=B.dragend={setup:function(){},teardown:function(){}};function H(L){var K=this,J,M=L.data||{};if(M.elem){K=L.dragTarget=M.elem;L.dragProxy=F.proxy||K;L.cursorOffsetX=M.pageX-M.left;L.cursorOffsetY=M.pageY-M.top;L.offsetX=L.pageX-L.cursorOffsetX;L.offsetY=L.pageY-L.cursorOffsetY}else{if(F.dragging||(M.which>0&&L.which!=M.which)||E(L.target).is(M.not)){return }}switch(L.type){case"mousedown":E.extend(M,E(K).offset(),{elem:K,target:L.target,pageX:L.pageX,pageY:L.pageY});A.add(document,"mousemove mouseup",H,M);G(K,false);F.dragging=null;return false;case !F.dragging&&"mousemove":if(I(L.pageX-M.pageX)+I(L.pageY-M.pageY)<M.distance){break}L.target=M.target;J=C(L,"dragstart",K);if(J!==false){F.dragging=K;F.proxy=L.dragProxy=E(J||K)[0]}case"mousemove":if(F.dragging){J=C(L,"drag",K);if(B.drop){B.drop.allowed=(J!==false);B.drop.handler(L)}if(J!==false){break}L.type="mouseup"}case"mouseup":A.remove(document,"mousemove mouseup",H);if(F.dragging){if(B.drop){B.drop.handler(L)}C(L,"dragend",K)}G(K,true);F.dragging=F.proxy=M.elem=false;break}return true}function C(M,K,L){M.type=K;var J=E.event.handle.call(L,M);return J===false?false:J||M.result}function I(J){return Math.pow(J,2)}function D(){return(F.dragging===false)}function G(K,J){if(!K){return }K.unselectable=J?"off":"on";K.onselectstart=function(){return J};if(K.style){K.style.MozUserSelect=J?"":"none"}}})(jQuery);
|
||||
|
||||
|
||||
/* jquery.mousewheel.min.js
|
||||
* Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net)
|
||||
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
||||
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
||||
* Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
|
||||
* Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
|
||||
*
|
||||
* Version: 3.0.2
|
||||
*
|
||||
* Requires: 1.2.2+
|
||||
*/
|
||||
(function(c){var a=["DOMMouseScroll","mousewheel"];c.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var d=a.length;d;){this.addEventListener(a[--d],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var d=a.length;d;){this.removeEventListener(a[--d],b,false)}}else{this.onmousewheel=null}}};c.fn.extend({mousewheel:function(d){return d?this.bind("mousewheel",d):this.trigger("mousewheel")},unmousewheel:function(d){return this.unbind("mousewheel",d)}});function b(f){var d=[].slice.call(arguments,1),g=0,e=true;f=c.event.fix(f||window.event);f.type="mousewheel";if(f.wheelDelta){g=f.wheelDelta/120}if(f.detail){g=-f.detail/3}d.unshift(f,g);return c.event.handle.apply(this,d)}})(jQuery);
|
||||
|
||||
|
||||
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
xaxis: {
|
||||
zoomRange: null, // or [number, number] (min range, max range)
|
||||
panRange: null // or [number, number] (min, max)
|
||||
},
|
||||
zoom: {
|
||||
interactive: false,
|
||||
trigger: "dblclick", // or "click" for single click
|
||||
amount: 1.5 // how much to zoom relative to current position, 2 = 200% (zoom in), 0.5 = 50% (zoom out)
|
||||
},
|
||||
pan: {
|
||||
interactive: false,
|
||||
cursor: "move",
|
||||
frameRate: 20
|
||||
}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function onZoomClick(e, zoomOut) {
|
||||
var c = plot.offset();
|
||||
c.left = e.pageX - c.left;
|
||||
c.top = e.pageY - c.top;
|
||||
if (zoomOut)
|
||||
plot.zoomOut({ center: c });
|
||||
else
|
||||
plot.zoom({ center: c });
|
||||
}
|
||||
|
||||
function onMouseWheel(e, delta) {
|
||||
onZoomClick(e, delta < 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
var prevCursor = 'default', prevPageX = 0, prevPageY = 0,
|
||||
panTimeout = null;
|
||||
|
||||
function onDragStart(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return false;
|
||||
var c = plot.getPlaceholder().css('cursor');
|
||||
if (c)
|
||||
prevCursor = c;
|
||||
plot.getPlaceholder().css('cursor', plot.getOptions().pan.cursor);
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
}
|
||||
|
||||
function onDrag(e) {
|
||||
var frameRate = plot.getOptions().pan.frameRate;
|
||||
if (panTimeout || !frameRate)
|
||||
return;
|
||||
|
||||
panTimeout = setTimeout(function () {
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
prevPageX = e.pageX;
|
||||
prevPageY = e.pageY;
|
||||
|
||||
panTimeout = null;
|
||||
}, 1 / frameRate * 1000);
|
||||
}
|
||||
|
||||
function onDragEnd(e) {
|
||||
if (panTimeout) {
|
||||
clearTimeout(panTimeout);
|
||||
panTimeout = null;
|
||||
}
|
||||
|
||||
plot.getPlaceholder().css('cursor', prevCursor);
|
||||
plot.pan({ left: prevPageX - e.pageX,
|
||||
top: prevPageY - e.pageY });
|
||||
}
|
||||
|
||||
function bindEvents(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.zoom.interactive) {
|
||||
eventHolder[o.zoom.trigger](onZoomClick);
|
||||
eventHolder.mousewheel(onMouseWheel);
|
||||
}
|
||||
|
||||
if (o.pan.interactive) {
|
||||
eventHolder.bind("dragstart", { distance: 10 }, onDragStart);
|
||||
eventHolder.bind("drag", onDrag);
|
||||
eventHolder.bind("dragend", onDragEnd);
|
||||
}
|
||||
}
|
||||
|
||||
plot.zoomOut = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
if (!args.amount)
|
||||
args.amount = plot.getOptions().zoom.amount
|
||||
|
||||
args.amount = 1 / args.amount;
|
||||
plot.zoom(args);
|
||||
}
|
||||
|
||||
plot.zoom = function (args) {
|
||||
if (!args)
|
||||
args = {};
|
||||
|
||||
var c = args.center,
|
||||
amount = args.amount || plot.getOptions().zoom.amount,
|
||||
w = plot.width(), h = plot.height();
|
||||
|
||||
if (!c)
|
||||
c = { left: w / 2, top: h / 2 };
|
||||
|
||||
var xf = c.left / w,
|
||||
yf = c.top / h,
|
||||
minmax = {
|
||||
x: {
|
||||
min: c.left - xf * w / amount,
|
||||
max: c.left + (1 - xf) * w / amount
|
||||
},
|
||||
y: {
|
||||
min: c.top - yf * h / amount,
|
||||
max: c.top + (1 - yf) * h / amount
|
||||
}
|
||||
};
|
||||
|
||||
$.each(plot.getAxes(), function(_, axis) {
|
||||
var opts = axis.options,
|
||||
min = minmax[axis.direction].min,
|
||||
max = minmax[axis.direction].max,
|
||||
zr = opts.zoomRange;
|
||||
|
||||
if (zr === false) // no zooming on this axis
|
||||
return;
|
||||
|
||||
min = axis.c2p(min);
|
||||
max = axis.c2p(max);
|
||||
if (min > max) {
|
||||
// make sure min < max
|
||||
var tmp = min;
|
||||
min = max;
|
||||
max = tmp;
|
||||
}
|
||||
|
||||
var range = max - min;
|
||||
if (zr &&
|
||||
((zr[0] != null && range < zr[0]) ||
|
||||
(zr[1] != null && range > zr[1])))
|
||||
return;
|
||||
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotzoom", [ plot ]);
|
||||
}
|
||||
|
||||
plot.pan = function (args) {
|
||||
var delta = {
|
||||
x: +args.left,
|
||||
y: +args.top
|
||||
};
|
||||
|
||||
if (isNaN(delta.x))
|
||||
delta.x = 0;
|
||||
if (isNaN(delta.y))
|
||||
delta.y = 0;
|
||||
|
||||
$.each(plot.getAxes(), function (_, axis) {
|
||||
var opts = axis.options,
|
||||
min, max, d = delta[axis.direction];
|
||||
|
||||
min = axis.c2p(axis.p2c(axis.min) + d),
|
||||
max = axis.c2p(axis.p2c(axis.max) + d);
|
||||
|
||||
var pr = opts.panRange;
|
||||
if (pr === false) // no panning on this axis
|
||||
return;
|
||||
|
||||
if (pr) {
|
||||
// check whether we hit the wall
|
||||
if (pr[0] != null && pr[0] > min) {
|
||||
d = pr[0] - min;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
|
||||
if (pr[1] != null && pr[1] < max) {
|
||||
d = pr[1] - max;
|
||||
min += d;
|
||||
max += d;
|
||||
}
|
||||
}
|
||||
|
||||
opts.min = min;
|
||||
opts.max = max;
|
||||
});
|
||||
|
||||
plot.setupGrid();
|
||||
plot.draw();
|
||||
|
||||
if (!args.preventEvent)
|
||||
plot.getPlaceholder().trigger("plotpan", [ plot ]);
|
||||
}
|
||||
|
||||
function shutdown(plot, eventHolder) {
|
||||
eventHolder.unbind(plot.getOptions().zoom.trigger, onZoomClick);
|
||||
eventHolder.unbind("mousewheel", onMouseWheel);
|
||||
eventHolder.unbind("dragstart", onDragStart);
|
||||
eventHolder.unbind("drag", onDrag);
|
||||
eventHolder.unbind("dragend", onDragEnd);
|
||||
if (panTimeout)
|
||||
clearTimeout(panTimeout);
|
||||
}
|
||||
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
plot.hooks.shutdown.push(shutdown);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'navigate',
|
||||
version: '1.3'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,750 +0,0 @@
|
|||
/*
|
||||
Flot plugin for rendering pie charts. The plugin assumes the data is
|
||||
coming is as a single data value for each series, and each of those
|
||||
values is a positive value or zero (negative numbers don't make
|
||||
any sense and will cause strange effects). The data values do
|
||||
NOT need to be passed in as percentage values because it
|
||||
internally calculates the total and percentages.
|
||||
|
||||
* Created by Brian Medendorp, June 2009
|
||||
* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars
|
||||
|
||||
* Changes:
|
||||
2009-10-22: lineJoin set to round
|
||||
2009-10-23: IE full circle fix, donut
|
||||
2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera
|
||||
2009-11-17: Added IE hover capability submitted by Anthony Aragues
|
||||
2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well)
|
||||
|
||||
|
||||
Available options are:
|
||||
series: {
|
||||
pie: {
|
||||
show: true/false
|
||||
radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto'
|
||||
innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect
|
||||
startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result
|
||||
tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show)
|
||||
offset: {
|
||||
top: integer value to move the pie up or down
|
||||
left: integer value to move the pie left or right, or 'auto'
|
||||
},
|
||||
stroke: {
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF')
|
||||
width: integer pixel width of the stroke
|
||||
},
|
||||
label: {
|
||||
show: true/false, or 'auto'
|
||||
formatter: a user-defined function that modifies the text/style of the label text
|
||||
radius: 0-1 for percentage of fullsize, or a specified pixel length
|
||||
background: {
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000')
|
||||
opacity: 0-1
|
||||
},
|
||||
threshold: 0-1 for the percentage value at which to hide labels (if they're too small)
|
||||
},
|
||||
combine: {
|
||||
threshold: 0-1 for the percentage value at which to combine slices (if they're too small)
|
||||
color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined
|
||||
label: any text value of what the combined slice should be labeled
|
||||
}
|
||||
highlight: {
|
||||
opacity: 0-1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
More detail and specific examples can be found in the included HTML file.
|
||||
|
||||
*/
|
||||
|
||||
(function ($)
|
||||
{
|
||||
function init(plot) // this is the "body" of the plugin
|
||||
{
|
||||
var canvas = null;
|
||||
var target = null;
|
||||
var maxRadius = null;
|
||||
var centerLeft = null;
|
||||
var centerTop = null;
|
||||
var total = 0;
|
||||
var redraw = true;
|
||||
var redrawAttempts = 10;
|
||||
var shrink = 0.95;
|
||||
var legendWidth = 0;
|
||||
var processed = false;
|
||||
var raw = false;
|
||||
|
||||
// interactive variables
|
||||
var highlights = [];
|
||||
|
||||
// add hook to determine if pie plugin in enabled, and then perform necessary operations
|
||||
plot.hooks.processOptions.push(checkPieEnabled);
|
||||
plot.hooks.bindEvents.push(bindEvents);
|
||||
|
||||
// check to see if the pie plugin is enabled
|
||||
function checkPieEnabled(plot, options)
|
||||
{
|
||||
if (options.series.pie.show)
|
||||
{
|
||||
//disable grid
|
||||
options.grid.show = false;
|
||||
|
||||
// set labels.show
|
||||
if (options.series.pie.label.show=='auto')
|
||||
if (options.legend.show)
|
||||
options.series.pie.label.show = false;
|
||||
else
|
||||
options.series.pie.label.show = true;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius=='auto')
|
||||
if (options.series.pie.label.show)
|
||||
options.series.pie.radius = 3/4;
|
||||
else
|
||||
options.series.pie.radius = 1;
|
||||
|
||||
// ensure sane tilt
|
||||
if (options.series.pie.tilt>1)
|
||||
options.series.pie.tilt=1;
|
||||
if (options.series.pie.tilt<0)
|
||||
options.series.pie.tilt=0;
|
||||
|
||||
// add processData hook to do transformations on the data
|
||||
plot.hooks.processDatapoints.push(processDatapoints);
|
||||
plot.hooks.drawOverlay.push(drawOverlay);
|
||||
|
||||
// add draw hook
|
||||
plot.hooks.draw.push(draw);
|
||||
}
|
||||
}
|
||||
|
||||
// bind hoverable events
|
||||
function bindEvents(plot, eventHolder)
|
||||
{
|
||||
var options = plot.getOptions();
|
||||
|
||||
if (options.series.pie.show && options.grid.hoverable)
|
||||
eventHolder.unbind('mousemove').mousemove(onMouseMove);
|
||||
|
||||
if (options.series.pie.show && options.grid.clickable)
|
||||
eventHolder.unbind('click').click(onClick);
|
||||
}
|
||||
|
||||
|
||||
// debugging function that prints out an object
|
||||
function alertObject(obj)
|
||||
{
|
||||
var msg = '';
|
||||
function traverse(obj, depth)
|
||||
{
|
||||
if (!depth)
|
||||
depth = 0;
|
||||
for (var i = 0; i < obj.length; ++i)
|
||||
{
|
||||
for (var j=0; j<depth; j++)
|
||||
msg += '\t';
|
||||
|
||||
if( typeof obj[i] == "object")
|
||||
{ // its an object
|
||||
msg += ''+i+':\n';
|
||||
traverse(obj[i], depth+1);
|
||||
}
|
||||
else
|
||||
{ // its a value
|
||||
msg += ''+i+': '+obj[i]+'\n';
|
||||
}
|
||||
}
|
||||
}
|
||||
traverse(obj);
|
||||
alert(msg);
|
||||
}
|
||||
|
||||
function calcTotal(data)
|
||||
{
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
var item = parseFloat(data[i].data[0][1]);
|
||||
if (item)
|
||||
total += item;
|
||||
}
|
||||
}
|
||||
|
||||
function processDatapoints(plot, series, data, datapoints)
|
||||
{
|
||||
if (!processed)
|
||||
{
|
||||
processed = true;
|
||||
|
||||
canvas = plot.getCanvas();
|
||||
target = $(canvas).parent();
|
||||
options = plot.getOptions();
|
||||
|
||||
plot.setData(combine(plot.getData()));
|
||||
}
|
||||
}
|
||||
|
||||
function setupPie()
|
||||
{
|
||||
legendWidth = target.children().filter('.legend').children().width();
|
||||
|
||||
// calculate maximum radius and center point
|
||||
maxRadius = Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2;
|
||||
centerTop = (canvas.height/2)+options.series.pie.offset.top;
|
||||
centerLeft = (canvas.width/2);
|
||||
|
||||
if (options.series.pie.offset.left=='auto')
|
||||
if (options.legend.position.match('w'))
|
||||
centerLeft += legendWidth/2;
|
||||
else
|
||||
centerLeft -= legendWidth/2;
|
||||
else
|
||||
centerLeft += options.series.pie.offset.left;
|
||||
|
||||
if (centerLeft<maxRadius)
|
||||
centerLeft = maxRadius;
|
||||
else if (centerLeft>canvas.width-maxRadius)
|
||||
centerLeft = canvas.width-maxRadius;
|
||||
}
|
||||
|
||||
function fixData(data)
|
||||
{
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
if (typeof(data[i].data)=='number')
|
||||
data[i].data = [[1,data[i].data]];
|
||||
else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined')
|
||||
{
|
||||
if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined')
|
||||
data[i].label = data[i].data.label; // fix weirdness coming from flot
|
||||
data[i].data = [[1,0]];
|
||||
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function combine(data)
|
||||
{
|
||||
data = fixData(data);
|
||||
calcTotal(data);
|
||||
var combined = 0;
|
||||
var numCombined = 0;
|
||||
var color = options.series.pie.combine.color;
|
||||
|
||||
var newdata = [];
|
||||
for (var i = 0; i < data.length; ++i)
|
||||
{
|
||||
// make sure its a number
|
||||
data[i].data[0][1] = parseFloat(data[i].data[0][1]);
|
||||
if (!data[i].data[0][1])
|
||||
data[i].data[0][1] = 0;
|
||||
|
||||
if (data[i].data[0][1]/total<=options.series.pie.combine.threshold)
|
||||
{
|
||||
combined += data[i].data[0][1];
|
||||
numCombined++;
|
||||
if (!color)
|
||||
color = data[i].color;
|
||||
}
|
||||
else
|
||||
{
|
||||
newdata.push({
|
||||
data: [[1,data[i].data[0][1]]],
|
||||
color: data[i].color,
|
||||
label: data[i].label,
|
||||
angle: (data[i].data[0][1]*(Math.PI*2))/total,
|
||||
percent: (data[i].data[0][1]/total*100)
|
||||
});
|
||||
}
|
||||
}
|
||||
if (numCombined>0)
|
||||
newdata.push({
|
||||
data: [[1,combined]],
|
||||
color: color,
|
||||
label: options.series.pie.combine.label,
|
||||
angle: (combined*(Math.PI*2))/total,
|
||||
percent: (combined/total*100)
|
||||
});
|
||||
return newdata;
|
||||
}
|
||||
|
||||
function draw(plot, newCtx)
|
||||
{
|
||||
if (!target) return; // if no series were passed
|
||||
ctx = newCtx;
|
||||
|
||||
setupPie();
|
||||
var slices = plot.getData();
|
||||
|
||||
var attempts = 0;
|
||||
while (redraw && attempts<redrawAttempts)
|
||||
{
|
||||
redraw = false;
|
||||
if (attempts>0)
|
||||
maxRadius *= shrink;
|
||||
attempts += 1;
|
||||
clear();
|
||||
if (options.series.pie.tilt<=0.8)
|
||||
drawShadow();
|
||||
drawPie();
|
||||
}
|
||||
if (attempts >= redrawAttempts) {
|
||||
clear();
|
||||
target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>');
|
||||
}
|
||||
|
||||
if ( plot.setSeries && plot.insertLegend )
|
||||
{
|
||||
plot.setSeries(slices);
|
||||
plot.insertLegend();
|
||||
}
|
||||
|
||||
// we're actually done at this point, just defining internal functions at this point
|
||||
|
||||
function clear()
|
||||
{
|
||||
ctx.clearRect(0,0,canvas.width,canvas.height);
|
||||
target.children().filter('.pieLabel, .pieLabelBackground').remove();
|
||||
}
|
||||
|
||||
function drawShadow()
|
||||
{
|
||||
var shadowLeft = 5;
|
||||
var shadowTop = 15;
|
||||
var edge = 10;
|
||||
var alpha = 0.02;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius>1)
|
||||
var radius = options.series.pie.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.radius;
|
||||
|
||||
if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge)
|
||||
return; // shadow would be outside canvas, so don't draw it
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(shadowLeft,shadowTop);
|
||||
ctx.globalAlpha = alpha;
|
||||
ctx.fillStyle = '#000';
|
||||
|
||||
// center and rotate to starting position
|
||||
ctx.translate(centerLeft,centerTop);
|
||||
ctx.scale(1, options.series.pie.tilt);
|
||||
|
||||
//radius -= edge;
|
||||
for (var i=1; i<=edge; i++)
|
||||
{
|
||||
ctx.beginPath();
|
||||
ctx.arc(0,0,radius,0,Math.PI*2,false);
|
||||
ctx.fill();
|
||||
radius -= i;
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
function drawPie()
|
||||
{
|
||||
startAngle = Math.PI*options.series.pie.startAngle;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.radius>1)
|
||||
var radius = options.series.pie.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.radius;
|
||||
|
||||
// center and rotate to starting position
|
||||
ctx.save();
|
||||
ctx.translate(centerLeft,centerTop);
|
||||
ctx.scale(1, options.series.pie.tilt);
|
||||
//ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera
|
||||
|
||||
// draw slices
|
||||
ctx.save();
|
||||
var currentAngle = startAngle;
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
slices[i].startAngle = currentAngle;
|
||||
drawSlice(slices[i].angle, slices[i].color, true);
|
||||
}
|
||||
ctx.restore();
|
||||
|
||||
// draw slice outlines
|
||||
ctx.save();
|
||||
ctx.lineWidth = options.series.pie.stroke.width;
|
||||
currentAngle = startAngle;
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
drawSlice(slices[i].angle, options.series.pie.stroke.color, false);
|
||||
ctx.restore();
|
||||
|
||||
// draw donut hole
|
||||
drawDonutHole(ctx);
|
||||
|
||||
// draw labels
|
||||
if (options.series.pie.label.show)
|
||||
drawLabels();
|
||||
|
||||
// restore to original state
|
||||
ctx.restore();
|
||||
|
||||
function drawSlice(angle, color, fill)
|
||||
{
|
||||
if (angle<=0)
|
||||
return;
|
||||
|
||||
if (fill)
|
||||
ctx.fillStyle = color;
|
||||
else
|
||||
{
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineJoin = 'round';
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
if (Math.abs(angle - Math.PI*2) > 0.000000001)
|
||||
ctx.moveTo(0,0); // Center of the pie
|
||||
else if ($.browser.msie)
|
||||
angle -= 0.0001;
|
||||
//ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera
|
||||
ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false);
|
||||
ctx.closePath();
|
||||
//ctx.rotate(angle); // This doesn't work properly in Opera
|
||||
currentAngle += angle;
|
||||
|
||||
if (fill)
|
||||
ctx.fill();
|
||||
else
|
||||
ctx.stroke();
|
||||
}
|
||||
|
||||
function drawLabels()
|
||||
{
|
||||
var currentAngle = startAngle;
|
||||
|
||||
// set radius
|
||||
if (options.series.pie.label.radius>1)
|
||||
var radius = options.series.pie.label.radius;
|
||||
else
|
||||
var radius = maxRadius * options.series.pie.label.radius;
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
if (slices[i].percent >= options.series.pie.label.threshold*100)
|
||||
drawLabel(slices[i], currentAngle, i);
|
||||
currentAngle += slices[i].angle;
|
||||
}
|
||||
|
||||
function drawLabel(slice, startAngle, index)
|
||||
{
|
||||
if (slice.data[0][1]==0)
|
||||
return;
|
||||
|
||||
// format label text
|
||||
var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter;
|
||||
if (lf)
|
||||
text = lf(slice.label, slice);
|
||||
else
|
||||
text = slice.label;
|
||||
if (plf)
|
||||
text = plf(text, slice);
|
||||
|
||||
var halfAngle = ((startAngle+slice.angle) + startAngle)/2;
|
||||
var x = centerLeft + Math.round(Math.cos(halfAngle) * radius);
|
||||
var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt;
|
||||
|
||||
var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>";
|
||||
target.append(html);
|
||||
var label = target.children('#pieLabel'+index);
|
||||
var labelTop = (y - label.height()/2);
|
||||
var labelLeft = (x - label.width()/2);
|
||||
label.css('top', labelTop);
|
||||
label.css('left', labelLeft);
|
||||
|
||||
// check to make sure that the label is not outside the canvas
|
||||
if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0)
|
||||
redraw = true;
|
||||
|
||||
if (options.series.pie.label.background.opacity != 0) {
|
||||
// put in the transparent background separately to avoid blended labels and label boxes
|
||||
var c = options.series.pie.label.background.color;
|
||||
if (c == null) {
|
||||
c = slice.color;
|
||||
}
|
||||
var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;';
|
||||
$('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity);
|
||||
}
|
||||
} // end individual label function
|
||||
} // end drawLabels function
|
||||
} // end drawPie function
|
||||
} // end draw function
|
||||
|
||||
// Placed here because it needs to be accessed from multiple locations
|
||||
function drawDonutHole(layer)
|
||||
{
|
||||
// draw donut hole
|
||||
if(options.series.pie.innerRadius > 0)
|
||||
{
|
||||
// subtract the center
|
||||
layer.save();
|
||||
innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius;
|
||||
layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color
|
||||
layer.beginPath();
|
||||
layer.fillStyle = options.series.pie.stroke.color;
|
||||
layer.arc(0,0,innerRadius,0,Math.PI*2,false);
|
||||
layer.fill();
|
||||
layer.closePath();
|
||||
layer.restore();
|
||||
|
||||
// add inner stroke
|
||||
layer.save();
|
||||
layer.beginPath();
|
||||
layer.strokeStyle = options.series.pie.stroke.color;
|
||||
layer.arc(0,0,innerRadius,0,Math.PI*2,false);
|
||||
layer.stroke();
|
||||
layer.closePath();
|
||||
layer.restore();
|
||||
// TODO: add extra shadow inside hole (with a mask) if the pie is tilted.
|
||||
}
|
||||
}
|
||||
|
||||
//-- Additional Interactive related functions --
|
||||
|
||||
function isPointInPoly(poly, pt)
|
||||
{
|
||||
for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
|
||||
((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1]))
|
||||
&& (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0])
|
||||
&& (c = !c);
|
||||
return c;
|
||||
}
|
||||
|
||||
function findNearbySlice(mouseX, mouseY)
|
||||
{
|
||||
var slices = plot.getData(),
|
||||
options = plot.getOptions(),
|
||||
radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
|
||||
|
||||
for (var i = 0; i < slices.length; ++i)
|
||||
{
|
||||
var s = slices[i];
|
||||
|
||||
if(s.pie.show)
|
||||
{
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0,0); // Center of the pie
|
||||
//ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here.
|
||||
ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false);
|
||||
ctx.closePath();
|
||||
x = mouseX-centerLeft;
|
||||
y = mouseY-centerTop;
|
||||
if(ctx.isPointInPath)
|
||||
{
|
||||
if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop))
|
||||
{
|
||||
//alert('found slice!');
|
||||
ctx.restore();
|
||||
return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// excanvas for IE doesn;t support isPointInPath, this is a workaround.
|
||||
p1X = (radius * Math.cos(s.startAngle));
|
||||
p1Y = (radius * Math.sin(s.startAngle));
|
||||
p2X = (radius * Math.cos(s.startAngle+(s.angle/4)));
|
||||
p2Y = (radius * Math.sin(s.startAngle+(s.angle/4)));
|
||||
p3X = (radius * Math.cos(s.startAngle+(s.angle/2)));
|
||||
p3Y = (radius * Math.sin(s.startAngle+(s.angle/2)));
|
||||
p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5)));
|
||||
p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5)));
|
||||
p5X = (radius * Math.cos(s.startAngle+s.angle));
|
||||
p5Y = (radius * Math.sin(s.startAngle+s.angle));
|
||||
arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]];
|
||||
arrPoint = [x,y];
|
||||
// TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt?
|
||||
if(isPointInPoly(arrPoly, arrPoint))
|
||||
{
|
||||
ctx.restore();
|
||||
return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i};
|
||||
}
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function onMouseMove(e)
|
||||
{
|
||||
triggerClickHoverEvent('plothover', e);
|
||||
}
|
||||
|
||||
function onClick(e)
|
||||
{
|
||||
triggerClickHoverEvent('plotclick', e);
|
||||
}
|
||||
|
||||
// trigger click or hover event (they send the same parameters so we share their code)
|
||||
function triggerClickHoverEvent(eventname, e)
|
||||
{
|
||||
var offset = plot.offset(),
|
||||
canvasX = parseInt(e.pageX - offset.left),
|
||||
canvasY = parseInt(e.pageY - offset.top),
|
||||
item = findNearbySlice(canvasX, canvasY);
|
||||
|
||||
if (options.grid.autoHighlight)
|
||||
{
|
||||
// clear auto-highlights
|
||||
for (var i = 0; i < highlights.length; ++i)
|
||||
{
|
||||
var h = highlights[i];
|
||||
if (h.auto == eventname && !(item && h.series == item.series))
|
||||
unhighlight(h.series);
|
||||
}
|
||||
}
|
||||
|
||||
// highlight the slice
|
||||
if (item)
|
||||
highlight(item.series, eventname);
|
||||
|
||||
// trigger any hover bind events
|
||||
var pos = { pageX: e.pageX, pageY: e.pageY };
|
||||
target.trigger(eventname, [ pos, item ]);
|
||||
}
|
||||
|
||||
function highlight(s, auto)
|
||||
{
|
||||
if (typeof s == "number")
|
||||
s = series[s];
|
||||
|
||||
var i = indexOfHighlight(s);
|
||||
if (i == -1)
|
||||
{
|
||||
highlights.push({ series: s, auto: auto });
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else if (!auto)
|
||||
highlights[i].auto = false;
|
||||
}
|
||||
|
||||
function unhighlight(s)
|
||||
{
|
||||
if (s == null)
|
||||
{
|
||||
highlights = [];
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
|
||||
if (typeof s == "number")
|
||||
s = series[s];
|
||||
|
||||
var i = indexOfHighlight(s);
|
||||
if (i != -1)
|
||||
{
|
||||
highlights.splice(i, 1);
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
function indexOfHighlight(s)
|
||||
{
|
||||
for (var i = 0; i < highlights.length; ++i)
|
||||
{
|
||||
var h = highlights[i];
|
||||
if (h.series == s)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function drawOverlay(plot, octx)
|
||||
{
|
||||
//alert(options.series.pie.radius);
|
||||
var options = plot.getOptions();
|
||||
//alert(options.series.pie.radius);
|
||||
|
||||
var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius;
|
||||
|
||||
octx.save();
|
||||
octx.translate(centerLeft, centerTop);
|
||||
octx.scale(1, options.series.pie.tilt);
|
||||
|
||||
for (i = 0; i < highlights.length; ++i)
|
||||
drawHighlight(highlights[i].series);
|
||||
|
||||
drawDonutHole(octx);
|
||||
|
||||
octx.restore();
|
||||
|
||||
function drawHighlight(series)
|
||||
{
|
||||
if (series.angle < 0) return;
|
||||
|
||||
//octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString();
|
||||
octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor
|
||||
|
||||
octx.beginPath();
|
||||
if (Math.abs(series.angle - Math.PI*2) > 0.000000001)
|
||||
octx.moveTo(0,0); // Center of the pie
|
||||
octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false);
|
||||
octx.closePath();
|
||||
octx.fill();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // end init (plugin body)
|
||||
|
||||
// define pie specific options and their default values
|
||||
var options = {
|
||||
series: {
|
||||
pie: {
|
||||
show: false,
|
||||
radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value)
|
||||
innerRadius:0, /* for donut */
|
||||
startAngle: 3/2,
|
||||
tilt: 1,
|
||||
offset: {
|
||||
top: 0,
|
||||
left: 'auto'
|
||||
},
|
||||
stroke: {
|
||||
color: '#FFF',
|
||||
width: 1
|
||||
},
|
||||
label: {
|
||||
show: 'auto',
|
||||
formatter: function(label, slice){
|
||||
return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>';
|
||||
}, // formatter function
|
||||
radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value)
|
||||
background: {
|
||||
color: null,
|
||||
opacity: 0
|
||||
},
|
||||
threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow)
|
||||
},
|
||||
combine: {
|
||||
threshold: -1, // percentage at which to combine little slices into one larger slice
|
||||
color: null, // color to give the new slice (auto-generated if null)
|
||||
label: 'Other' // label to give the new slice
|
||||
},
|
||||
highlight: {
|
||||
//color: '#FFF', // will add this functionality once parseColor is available
|
||||
opacity: 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: "pie",
|
||||
version: "1.0"
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,344 +0,0 @@
|
|||
/*
|
||||
Flot plugin for selecting regions.
|
||||
|
||||
The plugin defines the following options:
|
||||
|
||||
selection: {
|
||||
mode: null or "x" or "y" or "xy",
|
||||
color: color
|
||||
}
|
||||
|
||||
Selection support is enabled by setting the mode to one of "x", "y" or
|
||||
"xy". In "x" mode, the user will only be able to specify the x range,
|
||||
similarly for "y" mode. For "xy", the selection becomes a rectangle
|
||||
where both ranges can be specified. "color" is color of the selection
|
||||
(if you need to change the color later on, you can get to it with
|
||||
plot.getOptions().selection.color).
|
||||
|
||||
When selection support is enabled, a "plotselected" event will be
|
||||
emitted on the DOM element you passed into the plot function. The
|
||||
event handler gets a parameter with the ranges selected on the axes,
|
||||
like this:
|
||||
|
||||
placeholder.bind("plotselected", function(event, ranges) {
|
||||
alert("You selected " + ranges.xaxis.from + " to " + ranges.xaxis.to)
|
||||
// similar for yaxis - with multiple axes, the extra ones are in
|
||||
// x2axis, x3axis, ...
|
||||
});
|
||||
|
||||
The "plotselected" event is only fired when the user has finished
|
||||
making the selection. A "plotselecting" event is fired during the
|
||||
process with the same parameters as the "plotselected" event, in case
|
||||
you want to know what's happening while it's happening,
|
||||
|
||||
A "plotunselected" event with no arguments is emitted when the user
|
||||
clicks the mouse to remove the selection.
|
||||
|
||||
The plugin allso adds the following methods to the plot object:
|
||||
|
||||
- setSelection(ranges, preventEvent)
|
||||
|
||||
Set the selection rectangle. The passed in ranges is on the same
|
||||
form as returned in the "plotselected" event. If the selection mode
|
||||
is "x", you should put in either an xaxis range, if the mode is "y"
|
||||
you need to put in an yaxis range and both xaxis and yaxis if the
|
||||
selection mode is "xy", like this:
|
||||
|
||||
setSelection({ xaxis: { from: 0, to: 10 }, yaxis: { from: 40, to: 60 } });
|
||||
|
||||
setSelection will trigger the "plotselected" event when called. If
|
||||
you don't want that to happen, e.g. if you're inside a
|
||||
"plotselected" handler, pass true as the second parameter. If you
|
||||
are using multiple axes, you can specify the ranges on any of those,
|
||||
e.g. as x2axis/x3axis/... instead of xaxis, the plugin picks the
|
||||
first one it sees.
|
||||
|
||||
- clearSelection(preventEvent)
|
||||
|
||||
Clear the selection rectangle. Pass in true to avoid getting a
|
||||
"plotunselected" event.
|
||||
|
||||
- getSelection()
|
||||
|
||||
Returns the current selection in the same format as the
|
||||
"plotselected" event. If there's currently no selection, the
|
||||
function returns null.
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function init(plot) {
|
||||
var selection = {
|
||||
first: { x: -1, y: -1}, second: { x: -1, y: -1},
|
||||
show: false,
|
||||
active: false
|
||||
};
|
||||
|
||||
// FIXME: The drag handling implemented here should be
|
||||
// abstracted out, there's some similar code from a library in
|
||||
// the navigation plugin, this should be massaged a bit to fit
|
||||
// the Flot cases here better and reused. Doing this would
|
||||
// make this plugin much slimmer.
|
||||
var savedhandlers = {};
|
||||
|
||||
var mouseUpHandler = null;
|
||||
|
||||
function onMouseMove(e) {
|
||||
if (selection.active) {
|
||||
updateSelection(e);
|
||||
|
||||
plot.getPlaceholder().trigger("plotselecting", [ getSelection() ]);
|
||||
}
|
||||
}
|
||||
|
||||
function onMouseDown(e) {
|
||||
if (e.which != 1) // only accept left-click
|
||||
return;
|
||||
|
||||
// cancel out any text selections
|
||||
document.body.focus();
|
||||
|
||||
// prevent text selection and drag in old-school browsers
|
||||
if (document.onselectstart !== undefined && savedhandlers.onselectstart == null) {
|
||||
savedhandlers.onselectstart = document.onselectstart;
|
||||
document.onselectstart = function () { return false; };
|
||||
}
|
||||
if (document.ondrag !== undefined && savedhandlers.ondrag == null) {
|
||||
savedhandlers.ondrag = document.ondrag;
|
||||
document.ondrag = function () { return false; };
|
||||
}
|
||||
|
||||
setSelectionPos(selection.first, e);
|
||||
|
||||
selection.active = true;
|
||||
|
||||
// this is a bit silly, but we have to use a closure to be
|
||||
// able to whack the same handler again
|
||||
mouseUpHandler = function (e) { onMouseUp(e); };
|
||||
|
||||
$(document).one("mouseup", mouseUpHandler);
|
||||
}
|
||||
|
||||
function onMouseUp(e) {
|
||||
mouseUpHandler = null;
|
||||
|
||||
// revert drag stuff for old-school browsers
|
||||
if (document.onselectstart !== undefined)
|
||||
document.onselectstart = savedhandlers.onselectstart;
|
||||
if (document.ondrag !== undefined)
|
||||
document.ondrag = savedhandlers.ondrag;
|
||||
|
||||
// no more dragging
|
||||
selection.active = false;
|
||||
updateSelection(e);
|
||||
|
||||
if (selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
else {
|
||||
// this counts as a clear
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
plot.getPlaceholder().trigger("plotselecting", [ null ]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSelection() {
|
||||
if (!selectionIsSane())
|
||||
return null;
|
||||
|
||||
var r = {}, c1 = selection.first, c2 = selection.second;
|
||||
$.each(plot.getAxes(), function (name, axis) {
|
||||
if (axis.used) {
|
||||
var p1 = axis.c2p(c1[axis.direction]), p2 = axis.c2p(c2[axis.direction]);
|
||||
r[name] = { from: Math.min(p1, p2), to: Math.max(p1, p2) };
|
||||
}
|
||||
});
|
||||
return r;
|
||||
}
|
||||
|
||||
function triggerSelectedEvent() {
|
||||
var r = getSelection();
|
||||
|
||||
plot.getPlaceholder().trigger("plotselected", [ r ]);
|
||||
|
||||
// backwards-compat stuff, to be removed in future
|
||||
if (r.xaxis && r.yaxis)
|
||||
plot.getPlaceholder().trigger("selected", [ { x1: r.xaxis.from, y1: r.yaxis.from, x2: r.xaxis.to, y2: r.yaxis.to } ]);
|
||||
}
|
||||
|
||||
function clamp(min, value, max) {
|
||||
return value < min ? min: (value > max ? max: value);
|
||||
}
|
||||
|
||||
function setSelectionPos(pos, e) {
|
||||
var o = plot.getOptions();
|
||||
var offset = plot.getPlaceholder().offset();
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
pos.x = clamp(0, e.pageX - offset.left - plotOffset.left, plot.width());
|
||||
pos.y = clamp(0, e.pageY - offset.top - plotOffset.top, plot.height());
|
||||
|
||||
if (o.selection.mode == "y")
|
||||
pos.x = pos == selection.first ? 0 : plot.width();
|
||||
|
||||
if (o.selection.mode == "x")
|
||||
pos.y = pos == selection.first ? 0 : plot.height();
|
||||
}
|
||||
|
||||
function updateSelection(pos) {
|
||||
if (pos.pageX == null)
|
||||
return;
|
||||
|
||||
setSelectionPos(selection.second, pos);
|
||||
if (selectionIsSane()) {
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
}
|
||||
else
|
||||
clearSelection(true);
|
||||
}
|
||||
|
||||
function clearSelection(preventEvent) {
|
||||
if (selection.show) {
|
||||
selection.show = false;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent)
|
||||
plot.getPlaceholder().trigger("plotunselected", [ ]);
|
||||
}
|
||||
}
|
||||
|
||||
// function taken from markings support in Flot
|
||||
function extractRange(ranges, coord) {
|
||||
var axis, from, to, key, axes = plot.getAxes();
|
||||
|
||||
for (var k in axes) {
|
||||
axis = axes[k];
|
||||
if (axis.direction == coord) {
|
||||
key = coord + axis.n + "axis";
|
||||
if (!ranges[key] && axis.n == 1)
|
||||
key = coord + "axis"; // support x1axis as xaxis
|
||||
if (ranges[key]) {
|
||||
from = ranges[key].from;
|
||||
to = ranges[key].to;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// backwards-compat stuff - to be removed in future
|
||||
if (!ranges[key]) {
|
||||
axis = coord == "x" ? plot.getXAxes()[0] : plot.getYAxes()[0];
|
||||
from = ranges[coord + "1"];
|
||||
to = ranges[coord + "2"];
|
||||
}
|
||||
|
||||
// auto-reverse as an added bonus
|
||||
if (from != null && to != null && from > to) {
|
||||
var tmp = from;
|
||||
from = to;
|
||||
to = tmp;
|
||||
}
|
||||
|
||||
return { from: from, to: to, axis: axis };
|
||||
}
|
||||
|
||||
function setSelection(ranges, preventEvent) {
|
||||
var axis, range, o = plot.getOptions();
|
||||
|
||||
if (o.selection.mode == "y") {
|
||||
selection.first.x = 0;
|
||||
selection.second.x = plot.width();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "x");
|
||||
|
||||
selection.first.x = range.axis.p2c(range.from);
|
||||
selection.second.x = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
if (o.selection.mode == "x") {
|
||||
selection.first.y = 0;
|
||||
selection.second.y = plot.height();
|
||||
}
|
||||
else {
|
||||
range = extractRange(ranges, "y");
|
||||
|
||||
selection.first.y = range.axis.p2c(range.from);
|
||||
selection.second.y = range.axis.p2c(range.to);
|
||||
}
|
||||
|
||||
selection.show = true;
|
||||
plot.triggerRedrawOverlay();
|
||||
if (!preventEvent && selectionIsSane())
|
||||
triggerSelectedEvent();
|
||||
}
|
||||
|
||||
function selectionIsSane() {
|
||||
var minSize = 5;
|
||||
return Math.abs(selection.second.x - selection.first.x) >= minSize &&
|
||||
Math.abs(selection.second.y - selection.first.y) >= minSize;
|
||||
}
|
||||
|
||||
plot.clearSelection = clearSelection;
|
||||
plot.setSelection = setSelection;
|
||||
plot.getSelection = getSelection;
|
||||
|
||||
plot.hooks.bindEvents.push(function(plot, eventHolder) {
|
||||
var o = plot.getOptions();
|
||||
if (o.selection.mode != null) {
|
||||
eventHolder.mousemove(onMouseMove);
|
||||
eventHolder.mousedown(onMouseDown);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
plot.hooks.drawOverlay.push(function (plot, ctx) {
|
||||
// draw selection
|
||||
if (selection.show && selectionIsSane()) {
|
||||
var plotOffset = plot.getPlotOffset();
|
||||
var o = plot.getOptions();
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(plotOffset.left, plotOffset.top);
|
||||
|
||||
var c = $.color.parse(o.selection.color);
|
||||
|
||||
ctx.strokeStyle = c.scale('a', 0.8).toString();
|
||||
ctx.lineWidth = 1;
|
||||
ctx.lineJoin = "round";
|
||||
ctx.fillStyle = c.scale('a', 0.4).toString();
|
||||
|
||||
var x = Math.min(selection.first.x, selection.second.x),
|
||||
y = Math.min(selection.first.y, selection.second.y),
|
||||
w = Math.abs(selection.second.x - selection.first.x),
|
||||
h = Math.abs(selection.second.y - selection.first.y);
|
||||
|
||||
ctx.fillRect(x, y, w, h);
|
||||
ctx.strokeRect(x, y, w, h);
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
});
|
||||
|
||||
plot.hooks.shutdown.push(function (plot, eventHolder) {
|
||||
eventHolder.unbind("mousemove", onMouseMove);
|
||||
eventHolder.unbind("mousedown", onMouseDown);
|
||||
|
||||
if (mouseUpHandler)
|
||||
$(document).unbind("mouseup", mouseUpHandler);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: {
|
||||
selection: {
|
||||
mode: null, // one of null, "x", "y" or "xy"
|
||||
color: "#e8cfac"
|
||||
}
|
||||
},
|
||||
name: 'selection',
|
||||
version: '1.1'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,184 +0,0 @@
|
|||
/*
|
||||
Flot plugin for stacking data sets, i.e. putting them on top of each
|
||||
other, for accumulative graphs.
|
||||
|
||||
The plugin assumes the data is sorted on x (or y if stacking
|
||||
horizontally). For line charts, it is assumed that if a line has an
|
||||
undefined gap (from a null point), then the line above it should have
|
||||
the same gap - insert zeros instead of "null" if you want another
|
||||
behaviour. This also holds for the start and end of the chart. Note
|
||||
that stacking a mix of positive and negative values in most instances
|
||||
doesn't make sense (so it looks weird).
|
||||
|
||||
Two or more series are stacked when their "stack" attribute is set to
|
||||
the same key (which can be any number or string or just "true"). To
|
||||
specify the default stack, you can set
|
||||
|
||||
series: {
|
||||
stack: null or true or key (number/string)
|
||||
}
|
||||
|
||||
or specify it for a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], stack: true }])
|
||||
|
||||
The stacking order is determined by the order of the data series in
|
||||
the array (later series end up on top of the previous).
|
||||
|
||||
Internally, the plugin modifies the datapoints in each series, adding
|
||||
an offset to the y value. For line series, extra data points are
|
||||
inserted through interpolation. If there's a second y value, it's also
|
||||
adjusted (e.g for bar charts or filled areas).
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { stack: null } // or number/string
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function findMatchingSeries(s, allseries) {
|
||||
var res = null
|
||||
for (var i = 0; i < allseries.length; ++i) {
|
||||
if (s == allseries[i])
|
||||
break;
|
||||
|
||||
if (allseries[i].stack == s.stack)
|
||||
res = allseries[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
function stackData(plot, s, datapoints) {
|
||||
if (s.stack == null)
|
||||
return;
|
||||
|
||||
var other = findMatchingSeries(s, plot.getData());
|
||||
if (!other)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize,
|
||||
points = datapoints.points,
|
||||
otherps = other.datapoints.pointsize,
|
||||
otherpoints = other.datapoints.points,
|
||||
newpoints = [],
|
||||
px, py, intery, qx, qy, bottom,
|
||||
withlines = s.lines.show,
|
||||
horizontal = s.bars.horizontal,
|
||||
withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
|
||||
withsteps = withlines && s.lines.steps,
|
||||
fromgap = true,
|
||||
keyOffset = horizontal ? 1 : 0,
|
||||
accumulateOffset = horizontal ? 0 : 1,
|
||||
i = 0, j = 0, l;
|
||||
|
||||
while (true) {
|
||||
if (i >= points.length)
|
||||
break;
|
||||
|
||||
l = newpoints.length;
|
||||
|
||||
if (points[i] == null) {
|
||||
// copy gaps
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
i += ps;
|
||||
}
|
||||
else if (j >= otherpoints.length) {
|
||||
// for lines, we can't use the rest of the points
|
||||
if (!withlines) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
}
|
||||
i += ps;
|
||||
}
|
||||
else if (otherpoints[j] == null) {
|
||||
// oops, got a gap
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(null);
|
||||
fromgap = true;
|
||||
j += otherps;
|
||||
}
|
||||
else {
|
||||
// cases where we actually got two points
|
||||
px = points[i + keyOffset];
|
||||
py = points[i + accumulateOffset];
|
||||
qx = otherpoints[j + keyOffset];
|
||||
qy = otherpoints[j + accumulateOffset];
|
||||
bottom = 0;
|
||||
|
||||
if (px == qx) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
newpoints[l + accumulateOffset] += qy;
|
||||
bottom = qy;
|
||||
|
||||
i += ps;
|
||||
j += otherps;
|
||||
}
|
||||
else if (px > qx) {
|
||||
// we got past point below, might need to
|
||||
// insert interpolated extra point
|
||||
if (withlines && i > 0 && points[i - ps] != null) {
|
||||
intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
|
||||
newpoints.push(qx);
|
||||
newpoints.push(intery + qy);
|
||||
for (m = 2; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
bottom = qy;
|
||||
}
|
||||
|
||||
j += otherps;
|
||||
}
|
||||
else { // px < qx
|
||||
if (fromgap && withlines) {
|
||||
// if we come from a gap, we just skip this point
|
||||
i += ps;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints.push(points[i + m]);
|
||||
|
||||
// we might be able to interpolate a point below,
|
||||
// this can give us a better y
|
||||
if (withlines && j > 0 && otherpoints[j - otherps] != null)
|
||||
bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);
|
||||
|
||||
newpoints[l + accumulateOffset] += bottom;
|
||||
|
||||
i += ps;
|
||||
}
|
||||
|
||||
fromgap = false;
|
||||
|
||||
if (l != newpoints.length && withbottom)
|
||||
newpoints[l + 2] += bottom;
|
||||
}
|
||||
|
||||
// maintain the line steps invariant
|
||||
if (withsteps && l != newpoints.length && l > 0
|
||||
&& newpoints[l] != null
|
||||
&& newpoints[l] != newpoints[l - ps]
|
||||
&& newpoints[l + 1] != newpoints[l - ps + 1]) {
|
||||
for (m = 0; m < ps; ++m)
|
||||
newpoints[l + ps + m] = newpoints[l + m];
|
||||
newpoints[l + 1] = newpoints[l - ps + 1];
|
||||
}
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(stackData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'stack',
|
||||
version: '1.2'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
Flot plugin that adds some extra symbols for plotting points.
|
||||
|
||||
The symbols are accessed as strings through the standard symbol
|
||||
choice:
|
||||
|
||||
series: {
|
||||
points: {
|
||||
symbol: "square" // or "diamond", "triangle", "cross"
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
function processRawData(plot, series, datapoints) {
|
||||
// we normalize the area of each symbol so it is approximately the
|
||||
// same as a circle of the given radius
|
||||
|
||||
var handlers = {
|
||||
square: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.rect(x - size, y - size, size + size, size + size);
|
||||
},
|
||||
diamond: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 2s^2 => s = r * sqrt(pi/2)
|
||||
var size = radius * Math.sqrt(Math.PI / 2);
|
||||
ctx.moveTo(x - size, y);
|
||||
ctx.lineTo(x, y - size);
|
||||
ctx.lineTo(x + size, y);
|
||||
ctx.lineTo(x, y + size);
|
||||
ctx.lineTo(x - size, y);
|
||||
},
|
||||
triangle: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3))
|
||||
var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3));
|
||||
var height = size * Math.sin(Math.PI / 3);
|
||||
ctx.moveTo(x - size/2, y + height/2);
|
||||
ctx.lineTo(x + size/2, y + height/2);
|
||||
if (!shadow) {
|
||||
ctx.lineTo(x, y - height/2);
|
||||
ctx.lineTo(x - size/2, y + height/2);
|
||||
}
|
||||
},
|
||||
cross: function (ctx, x, y, radius, shadow) {
|
||||
// pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2
|
||||
var size = radius * Math.sqrt(Math.PI) / 2;
|
||||
ctx.moveTo(x - size, y - size);
|
||||
ctx.lineTo(x + size, y + size);
|
||||
ctx.moveTo(x - size, y + size);
|
||||
ctx.lineTo(x + size, y - size);
|
||||
}
|
||||
}
|
||||
|
||||
var s = series.points.symbol;
|
||||
if (handlers[s])
|
||||
series.points.symbol = handlers[s];
|
||||
}
|
||||
|
||||
function init(plot) {
|
||||
plot.hooks.processDatapoints.push(processRawData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
name: 'symbols',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
Flot plugin for thresholding data. Controlled through the option
|
||||
"threshold" in either the global series options
|
||||
|
||||
series: {
|
||||
threshold: {
|
||||
below: number
|
||||
color: colorspec
|
||||
}
|
||||
}
|
||||
|
||||
or in a specific series
|
||||
|
||||
$.plot($("#placeholder"), [{ data: [ ... ], threshold: { ... }}])
|
||||
|
||||
The data points below "below" are drawn with the specified color. This
|
||||
makes it easy to mark points below 0, e.g. for budget data.
|
||||
|
||||
Internally, the plugin works by splitting the data into two series,
|
||||
above and below the threshold. The extra series below the threshold
|
||||
will have its label cleared and the special "originSeries" attribute
|
||||
set to the original series. You may need to check for this in hover
|
||||
events.
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
var options = {
|
||||
series: { threshold: null } // or { below: number, color: color spec}
|
||||
};
|
||||
|
||||
function init(plot) {
|
||||
function thresholdData(plot, s, datapoints) {
|
||||
if (!s.threshold)
|
||||
return;
|
||||
|
||||
var ps = datapoints.pointsize, i, x, y, p, prevp,
|
||||
thresholded = $.extend({}, s); // note: shallow copy
|
||||
|
||||
thresholded.datapoints = { points: [], pointsize: ps };
|
||||
thresholded.label = null;
|
||||
thresholded.color = s.threshold.color;
|
||||
thresholded.threshold = null;
|
||||
thresholded.originSeries = s;
|
||||
thresholded.data = [];
|
||||
|
||||
var below = s.threshold.below,
|
||||
origpoints = datapoints.points,
|
||||
addCrossingPoints = s.lines.show;
|
||||
|
||||
threspoints = [];
|
||||
newpoints = [];
|
||||
|
||||
for (i = 0; i < origpoints.length; i += ps) {
|
||||
x = origpoints[i]
|
||||
y = origpoints[i + 1];
|
||||
|
||||
prevp = p;
|
||||
if (y < below)
|
||||
p = threspoints;
|
||||
else
|
||||
p = newpoints;
|
||||
|
||||
if (addCrossingPoints && prevp != p && x != null
|
||||
&& i > 0 && origpoints[i - ps] != null) {
|
||||
var interx = (x - origpoints[i - ps]) / (y - origpoints[i - ps + 1]) * (below - y) + x;
|
||||
prevp.push(interx);
|
||||
prevp.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
prevp.push(origpoints[i + m]);
|
||||
|
||||
p.push(null); // start new segment
|
||||
p.push(null);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
p.push(interx);
|
||||
p.push(below);
|
||||
for (m = 2; m < ps; ++m)
|
||||
p.push(origpoints[i + m]);
|
||||
}
|
||||
|
||||
p.push(x);
|
||||
p.push(y);
|
||||
}
|
||||
|
||||
datapoints.points = newpoints;
|
||||
thresholded.datapoints.points = threspoints;
|
||||
|
||||
if (thresholded.datapoints.points.length > 0)
|
||||
plot.getData().push(thresholded);
|
||||
|
||||
// FIXME: there are probably some edge cases left in bars
|
||||
}
|
||||
|
||||
plot.hooks.processDatapoints.push(thresholdData);
|
||||
}
|
||||
|
||||
$.plot.plugins.push({
|
||||
init: init,
|
||||
options: options,
|
||||
name: 'threshold',
|
||||
version: '1.0'
|
||||
});
|
||||
})(jQuery);
|
|
@ -1,161 +0,0 @@
|
|||
/**
|
||||
* Some general functions we need for the frontend
|
||||
*
|
||||
* @author Florian Ziegler <fz@f10-home.de>
|
||||
* @author Justin Otherguy <justin@justinotherguy.org>
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @package default
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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 any later version.
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
var Exception = function(type, message, code) {
|
||||
return {
|
||||
type: type,
|
||||
message: message,
|
||||
code: code
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Universal helper for middleware ajax requests with error handling
|
||||
*/
|
||||
vz.load = function(args) {
|
||||
$.extend(args, {
|
||||
accepts: 'application/json',
|
||||
error: function(xhr) {
|
||||
try {
|
||||
if (xhr.getResponseHeader('Content-type') == 'application/json') {
|
||||
var json = $.parseJSON(xhr.responseText);
|
||||
|
||||
if (json.exception) {
|
||||
throw new Exception(json.exception.type, json.exception.message, (json.exception.code) ? json.exception.code : xhr.status);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Exception(xhr.statusText, 'Unknown middleware response', xhr.status)
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
vz.wui.dialogs.exception(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (args.url === undefined) { // local middleware by default
|
||||
args.url = vz.middleware[0].url;
|
||||
}
|
||||
|
||||
if (args.url == vz.middleware[0].url) { // local request
|
||||
args.dataType = 'json';
|
||||
}
|
||||
else { // remote request
|
||||
args.dataType = 'jsonp';
|
||||
args.jsonp = 'padding';
|
||||
}
|
||||
|
||||
if (args.controller !== undefined) {
|
||||
args.url += '/' + args.controller;
|
||||
}
|
||||
|
||||
if (args.identifier !== undefined) {
|
||||
args.url += '/' + args.identifier;
|
||||
}
|
||||
|
||||
args.url += '.json';
|
||||
|
||||
if (args.data === undefined) {
|
||||
args.data = { };
|
||||
}
|
||||
|
||||
if (args.type) {
|
||||
args.data.operation = args.type.toLowerCase();
|
||||
}
|
||||
|
||||
return $.ajax(args);
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse URL GET parameters
|
||||
*/
|
||||
vz.parseUrlParams = function() {
|
||||
var vars = $.getUrlParams();
|
||||
var uuids = new Array;
|
||||
var save = false;
|
||||
|
||||
for (var key in vars) {
|
||||
if (vars.hasOwnProperty(key)) {
|
||||
switch (key) {
|
||||
case 'uuid': // add optional uuid from url
|
||||
uuids = (typeof vars[key] == 'string') ? [vars[key]] : vars[key]; // handle multiple uuids
|
||||
break;
|
||||
|
||||
case 'save': // save new uuids in cookie
|
||||
save = true;
|
||||
break;
|
||||
|
||||
case 'from':
|
||||
vz.options.plot.xaxis.min = parseInt(vars[key]);
|
||||
break;
|
||||
|
||||
case 'to':
|
||||
vz.options.plot.xaxis.max = parseInt(vars[key]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uuids.each(function(index, uuid) {
|
||||
try {
|
||||
vz.entities.push(new Entity({
|
||||
middleware: vz.middleware[0].url,
|
||||
uuid: uuid,
|
||||
cookie: save
|
||||
}));
|
||||
} catch (exception) {
|
||||
/* ignore exception */
|
||||
}
|
||||
});
|
||||
|
||||
if (save) {
|
||||
vz.entities.saveCookie();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load capabilities from middleware
|
||||
*/
|
||||
vz.capabilities.load = function() {
|
||||
return vz.load({
|
||||
controller: 'capabilities',
|
||||
success: function(json) {
|
||||
$.extend(true, vz.capabilities, json.capabilities);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Lookup definition
|
||||
*/
|
||||
vz.capabilities.definitions.get = function(section, name) {
|
||||
for (var i in this[section]) {
|
||||
if (this[section][i].name == name) {
|
||||
return this[section][i];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/**
|
||||
* Some functions and prototypes which make our life easier
|
||||
*
|
||||
* not volkszaehler.org related
|
||||
*
|
||||
* @author Florian Ziegler <fz@f10-home.de>
|
||||
* @author Justin Otherguy <justin@justinotherguy.org>
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @package default
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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 any later version.
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Array extensions
|
||||
* according to js language specification ECMA 1.6
|
||||
*/
|
||||
Array.prototype.indexOf = function(n) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (n == this[i]) return i;
|
||||
}
|
||||
};
|
||||
|
||||
Array.prototype.remove = function(n) {
|
||||
this.splice(this.indexOf(n), 1);
|
||||
};
|
||||
|
||||
Array.prototype.each = function(cb, ctx) {
|
||||
for (var i = 0, l = this.length; i < l; i++) {
|
||||
if (cb.call((ctx === undefined) ? this[i] : ctx, i, this[i]) === false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Array.prototype.contains = function(n) {
|
||||
return this.indexOf(n) !== undefined;
|
||||
};
|
||||
|
||||
Array.prototype.clear = function() {
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
Array.prototype.unique = function() {
|
||||
var r = new Array;
|
||||
this.each(function(key, value) {
|
||||
if (!r.contains(value)) {
|
||||
r.push(value);
|
||||
}
|
||||
});
|
||||
return r;
|
||||
}
|
||||
|
||||
Array.prototype.last = function() {
|
||||
if (this.length > 0) {
|
||||
return this[this.length-1];
|
||||
}
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
/**
|
||||
* Initialization and configuration of frontend
|
||||
*
|
||||
* @author Florian Ziegler <fz@f10-home.de>
|
||||
* @author Justin Otherguy <justin@justinotherguy.org>
|
||||
* @author Steffen Vogel <info@steffenvogel.de>
|
||||
* @copyright Copyright (c) 2011, The volkszaehler.org project
|
||||
* @package default
|
||||
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
|
||||
*/
|
||||
/*
|
||||
* This file is part of volkzaehler.org
|
||||
*
|
||||
* volkzaehler.org 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
|
||||
* any later version.
|
||||
*
|
||||
* volkzaehler.org 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 volkszaehler.org. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* volkszaehler.org namespace
|
||||
*
|
||||
* holds all data, options and functions for the frontend
|
||||
* we dont want to pollute the global namespace
|
||||
*/
|
||||
var vz = {
|
||||
entities: new Array, // entity properties + data
|
||||
middleware: [{ // default middleware
|
||||
url: '../middleware.php',
|
||||
public: [ ] // public entities
|
||||
/* capabilities: { } */
|
||||
}],
|
||||
|
||||
// web user interface
|
||||
wui: {
|
||||
dialogs: { },
|
||||
timeout: null
|
||||
},
|
||||
|
||||
// debugging and runtime information from middleware
|
||||
capabilities: {
|
||||
definitions: { } // definitions of entities & properties
|
||||
},
|
||||
|
||||
// flot instance
|
||||
plot: { },
|
||||
|
||||
// options loaded from cookies in options.js
|
||||
options: { }
|
||||
};
|
||||
|
||||
/**
|
||||
* Executed on document loaded complete
|
||||
* this is where it all starts...
|
||||
*/
|
||||
$(document).ready(function() {
|
||||
// late binding
|
||||
$(window).resize(function() {
|
||||
vz.options.tuples = Math.round($('#flot').width() / 3);
|
||||
$('#tuples').val(vz.options.tuples);
|
||||
vz.wui.drawPlot();
|
||||
});
|
||||
|
||||
window.onerror = function(errorMsg, url, lineNumber) {
|
||||
vz.wui.dialogs.error('Javascript Runtime Error', errorMsg);
|
||||
};
|
||||
|
||||
vz.entities.loadCookie(); // load uuids from cookie
|
||||
vz.options.loadCookies(); // load options from cookie
|
||||
vz.parseUrlParams(); // parse additional url params (new uuid etc..)
|
||||
|
||||
// initialize user interface
|
||||
vz.wui.init();
|
||||
vz.wui.initEvents();
|
||||
|
||||
// chaining ajax request with jquery deferred object
|
||||
vz.capabilities.load().done(function() {
|
||||
if (vz.capabilities.formats.contains('png')) {
|
||||
$('#export option[value=png]').removeAttr('disabled');
|
||||
}
|
||||
|
||||
var queue = new Array;
|
||||
vz.entities.each(function(entity) {
|
||||
queue.push(entity.loadDetails());
|
||||
}, true);
|
||||
|
||||
$.when.apply($, queue).done(function() {
|
||||
if (vz.entities.length == 0) {
|
||||
vz.wui.dialogs.init();
|
||||
}
|
||||
|
||||
vz.entities.showTable();
|
||||
vz.entities.loadData().done(vz.wui.drawPlot);
|
||||
});
|
||||
});
|
||||
});
|
||||
|