mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 12:49:34 +00:00
d5b289bd96
git-svn-id: https://svn.fhem.de/fhem/trunk@1180 2b470e98-0d58-463d-a4d8-8e2adae1ed80
634 lines
17 KiB
Perl
634 lines
17 KiB
Perl
#################################################################################
|
|
# Copyright notice
|
|
#
|
|
# (c) 2008-2012
|
|
# Copyright: Dr. Olaf Droegehorn
|
|
# o.droegehorn@dhs-computertechnik.de
|
|
# www.dhs-computertechnik.de
|
|
# All rights reserved
|
|
#
|
|
# This script free software; you can redistribute it and/or modify
|
|
# it under the terms of the GNU General Public License as published by
|
|
# the Free Software Foundation; either version 2 of the License, or
|
|
# (at your option) any later version.
|
|
#
|
|
# The GNU General Public License can be found at
|
|
# http://www.gnu.org/copyleft/gpl.html.
|
|
# A copy is found in the textfile GPL.txt and important notices to the license
|
|
# from the author is found in LICENSE.txt distributed with these scripts.
|
|
#
|
|
# This script 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.
|
|
#
|
|
# This copyright notice MUST APPEAR in all copies of the script!
|
|
#################################################################################
|
|
|
|
package main;
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use IO::Socket;
|
|
|
|
|
|
###################
|
|
# Config
|
|
use vars qw($__ME);
|
|
my $FHEMRENDERERdir = "$attr{global}{modpath}/FHEM"; #
|
|
|
|
use vars qw(%defs);
|
|
use vars qw(%attr);
|
|
|
|
# Nothing to config below
|
|
#########################
|
|
|
|
#########################
|
|
# Forward declaration
|
|
|
|
sub FHEMRENDERER_getAttr($$);
|
|
sub FHEMRENDERER_setAttr($$);
|
|
sub FHEMRENDERER_parseXmlList($);
|
|
sub FHEMRENDERER_render($);
|
|
sub FHEMRENDERER_fatal($);
|
|
sub FHEMRENDERER_pF($@);
|
|
sub FHEMRENDERER_pO(@);
|
|
#sub FHEMRENDERER_zoomLink($$$$);
|
|
sub FHEMRENDERER_calcWeblink($$);
|
|
|
|
#########################
|
|
# As we are _not_ multithreaded, it is safe to use global variables.
|
|
my %__icons; # List of icons
|
|
my $__iconsread; # Timestamp of last icondir check
|
|
my %__rooms; # hash of all rooms
|
|
my %__devs; # hash of all devices ant their attributes
|
|
my %__types; # device types, for sorting
|
|
my $__room; # currently selected room
|
|
my $__detail; # durrently selected device for detail view
|
|
my $__title; # Page title
|
|
my $__cmdret; # Returned data by the fhem call
|
|
my $__scrolledweblinkcount; # Number of scrolled weblinks
|
|
my %__pos; # scroll position
|
|
my $__RET; # Returned data (html)
|
|
my $__RETTYPE; # image/png or the like
|
|
my $__SF; # Short for submit form
|
|
my $__ti; # Tabindex for all input fields
|
|
my @__zoom; # "qday", "day","week","month","year"
|
|
my %__zoom; # the same as @__zoom
|
|
my $__wname; # instance name
|
|
my $__plotmode; # Current plotmode
|
|
my $__plotsize; # Size for a plot
|
|
my $__timeinterval; # Time-Intervall for Renderer
|
|
my $__data; # Filecontent from browser when editing a file
|
|
my $__svgloaded; # Do not load the SVG twice
|
|
my $__lastxmllist; # last time xmllist was parsed
|
|
my $FHEMRENDERER_tmpfile; # TempDir & File for the rendered graphics
|
|
my $__mp;
|
|
|
|
#####################################
|
|
sub
|
|
FHEMRENDERER_Initialize($)
|
|
{
|
|
my ($hash) = @_;
|
|
|
|
# $hash->{ReadFn} = "FHEMRENDERER_Read";
|
|
$hash->{DefFn} = "FHEMRENDERER_Define";
|
|
$hash->{UndefFn} = "FHEMRENDERER_Undef";
|
|
$hash->{AttrList}= "loglevel:0,1,2,3,4,5,6 plotmode:gnuplot,gnuplot-scroll plotsize refresh tmpfile status multiprocess";
|
|
$hash->{SetFn} = "FHEMRENDERER_Set";
|
|
$hash->{GetFn} = "FHEMRENDERER_Get";
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
FHEMRENDERER_Define($$)
|
|
{
|
|
my ($hash, $def) = @_;
|
|
my ($name, $type, $global) = split("[ \t]+", $def);
|
|
return "Usage: define <name> FHEMRENDERER [global]"
|
|
if($global && $global ne "global");
|
|
|
|
$hash->{STATE} = "Initialized";
|
|
Log(2, "FHEMRENDERER defined");
|
|
|
|
###############
|
|
# Initialize internal structures
|
|
my $n = 0;
|
|
@__zoom = ("qday", "day","week","month","year");
|
|
%__zoom = map { $_, $n++ } @__zoom;
|
|
$__wname = $hash->{NAME};
|
|
|
|
$__timeinterval = FHEMRENDERER_getAttr("refresh", "00:10:00");
|
|
$__plotmode = FHEMRENDERER_getAttr("plotmode", "gnuplot");
|
|
$__plotsize = FHEMRENDERER_getAttr("plotsize", "800,200");
|
|
$__mp = FHEMRENDERER_getAttr("multiprocess", "off");
|
|
$FHEMRENDERER_tmpfile = FHEMRENDERER_getAttr("tmpfile", "/tmp/");
|
|
FHEMRENDERER_setAttr("status", "off");
|
|
|
|
return undef;
|
|
}
|
|
|
|
#####################################
|
|
sub
|
|
FHEMRENDERER_Undef($$)
|
|
{
|
|
my ($hash, $arg) = @_;
|
|
return undef;
|
|
}
|
|
|
|
|
|
###################################
|
|
sub
|
|
FHEMRENDERER_Set($@)
|
|
{
|
|
my ($hash, @a) = @_;
|
|
my $ret = undef;
|
|
my $na = int(@a);
|
|
$__wname = $hash->{NAME};
|
|
|
|
return "no set value specified" if($na < 2 || $na > 3);
|
|
|
|
# if($__plotmode eq "SVG" && !$modules{SVG}{LOADED}) {
|
|
# my $ret = CommandReload(undef, "98_SVG");
|
|
# Log 0, $ret if($ret);
|
|
# }
|
|
|
|
if($a[1] eq "on") {
|
|
$__timeinterval = FHEMRENDERER_getAttr("refresh", "00:10:00");
|
|
CommandDefine(undef, $hash->{NAME} . "_trigger at +*$__timeinterval get $a[0]");
|
|
FHEMRENDERER_setAttr("status", "on");
|
|
} elsif($a[1] eq "off") {
|
|
CommandDelete(undef, $__wname . "_trigger");
|
|
FHEMRENDERER_setAttr("status", "off");
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
|
|
#####################################
|
|
sub
|
|
FHEMRENDERER_Get($@)
|
|
{
|
|
my ($hash, @a) = @_;
|
|
|
|
my $ret = undef;
|
|
my $v;
|
|
my $t;
|
|
my $pid;
|
|
|
|
FHEMRENDERER_parseXmlList(0);
|
|
|
|
$__wname = "";
|
|
$__wname = $hash->{NAME};
|
|
|
|
$__plotmode = FHEMRENDERER_getAttr("plotmode", "gnuplot");
|
|
$__plotsize = FHEMRENDERER_getAttr("plotsize", "800,200");
|
|
$FHEMRENDERER_tmpfile = FHEMRENDERER_getAttr("tmpfile", "/tmp/");
|
|
$__mp = FHEMRENDERER_getAttr("multiprocess", "off");
|
|
|
|
if (@a <= 2) {
|
|
if (@a == 2) {
|
|
my ($p,$v) = split("=",$a[1], 2);
|
|
|
|
# Multiline: escape the NL for fhem
|
|
$v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data");
|
|
Log(2, "P: $p, V: $v");
|
|
|
|
if($p eq "pos") {
|
|
%__pos = split(/[=&]/, $v);
|
|
}
|
|
}
|
|
|
|
if ($__mp ne "off") {
|
|
$pid = fork();
|
|
if (not defined $pid) {
|
|
return ("ERROR: No MultiProcessing possible");
|
|
}
|
|
if ($pid > 0) {
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
foreach my $type (sort keys %__types) {
|
|
if($type eq "weblink") {
|
|
foreach my $d (sort keys %__devs ) {
|
|
next if($__devs{$d}{type} ne $type);
|
|
|
|
$v = $__devs{$d}{INT}{LINK}{VAL};
|
|
$t = $__devs{$d}{INT}{WLTYPE}{VAL};
|
|
if($t eq "fileplot") {
|
|
my @va = split(":", $v, 3);
|
|
if(@va != 3 || !$__devs{$va[0]}{INT}{currentlogfile}) {
|
|
FHEMRENDERER_pO "<td>Broken definition: $v</a></td>";
|
|
} else {
|
|
if($va[2] eq "CURRENT") {
|
|
$__devs{$va[0]}{INT}{currentlogfile}{VAL} =~ m,([^/]*)$,;
|
|
$va[2] = $1;
|
|
}
|
|
FHEMRENDERER_render ("undef $d $va[0] $va[1] $va[2]");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} elsif (@a == 4 ) {
|
|
FHEMRENDERER_render ("undef $a[3] $a[1] $a[2] $a[3]");
|
|
|
|
} elsif (@a == 5 ) {
|
|
my ($p,$v) = split("=",$a[4], 2);
|
|
|
|
# Multiline: escape the NL for fhem
|
|
$v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data");
|
|
Log(2, "P: $p, V: $v");
|
|
|
|
if($p eq "pos") {
|
|
%__pos = split(/[=&]/, $v);
|
|
FHEMRENDERER_render ("undef $a[3] $a[1] $a[2] $a[3]");
|
|
|
|
} else {
|
|
FHEMRENDERER_render ("undef $a[1] $a[2] $a[3] $a[4]");
|
|
}
|
|
|
|
} elsif (@a == 6 ) {
|
|
my ($p,$v) = split("=",$a[5], 2);
|
|
|
|
# Multiline: escape the NL for fhem
|
|
$v =~ s/[\r]\n/\\\n/g if($v && $p && $p ne "data");
|
|
Log(2, "P: $p, V: $v");
|
|
|
|
if($p eq "pos") {
|
|
%__pos = split(/[=&]/, $v);
|
|
FHEMRENDERER_render ("undef $a[1] $a[2] $a[3] $a[4]");
|
|
|
|
} else {
|
|
return "\"get FHEMRENDERER\" needs either none, 1(pos) or 3-5 arguments ([file-name] device type logfile [pos=zoom=XX&off=YYY])";
|
|
}
|
|
} else {
|
|
return "\"get FHEMRENDERER\" needs either none, 1(pos) or 3-5 arguments ([file-name] device type logfile [pos=zoom=XX&off=YYY])";
|
|
}
|
|
if (not defined $pid) {
|
|
return $ret;
|
|
} else {
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
#####################
|
|
# Get the data and parse it. We are parsing XML in a non-scientific way :-)
|
|
sub
|
|
FHEMRENDERER_parseXmlList($)
|
|
{
|
|
my $docmd = shift;
|
|
my $name;
|
|
|
|
if(!$docmd && $__lastxmllist && (time() - $__lastxmllist) < 2) {
|
|
$__room = $__devs{$__detail}{ATTR}{room}{VAL} if($__detail);
|
|
return;
|
|
}
|
|
|
|
$__lastxmllist = time();
|
|
%__rooms = ();
|
|
%__devs = ();
|
|
%__types = ();
|
|
$__title = "";
|
|
|
|
foreach my $l (split("\n", FHEMRENDERER_fC("xmllist"))) {
|
|
|
|
####### Device
|
|
if($l =~ m/^\t\t<(.*) name="(.*)" state="(.*)" sets="(.*)" attrs="(.*)">/){
|
|
$name = $2;
|
|
$__devs{$name}{type} = ($1 eq "HMS" ? "KS300" : $1);
|
|
$__devs{$name}{state} = $3;
|
|
$__devs{$name}{sets} = $4;
|
|
$__devs{$name}{attrs} = $5;
|
|
next;
|
|
}
|
|
####### INT, ATTR & STATE
|
|
if($l =~ m,^\t\t\t<(.*) key="(.*)" value="([^"]*)"(.*)/>,) {
|
|
my ($t, $n, $v, $m) = ($1, $2, $3, $4);
|
|
$v =~ s,<br>,<br/>,g;
|
|
$__devs{$name}{$t}{$n}{VAL} = $v;
|
|
if($m) {
|
|
$m =~ m/measured="(.*)"/;
|
|
$__devs{$name}{$t}{$n}{TIM} = $1;
|
|
}
|
|
|
|
if($t eq "ATTR" && $n eq "room") {
|
|
$__rooms{$v}{$name} = 1;
|
|
if($name eq "global") {
|
|
$__rooms{$v}{LogFile} = 1;
|
|
$__devs{LogFile}{ATTR}{room}{VAL} = $v;
|
|
}
|
|
}
|
|
|
|
if($name eq "global" && $n eq "logfile") {
|
|
my $ln = "LogFile";
|
|
$__devs{$ln}{type} = "FileLog";
|
|
$__devs{$ln}{INT}{logfile}{VAL} = $v;
|
|
$__devs{$ln}{state} = "active";
|
|
}
|
|
}
|
|
|
|
}
|
|
if(defined($__devs{global}{ATTR}{archivedir})) {
|
|
$__devs{LogFile}{ATTR}{archivedir}{VAL} =
|
|
$__devs{global}{ATTR}{archivedir}{VAL};
|
|
}
|
|
|
|
#################
|
|
#Tag the gadgets without room with "Unsorted"
|
|
if(%__rooms) {
|
|
foreach my $name (keys %__devs ) {
|
|
if(!$__devs{$name}{ATTR}{room}) {
|
|
$__devs{$name}{ATTR}{room}{VAL} = "Unsorted";
|
|
$__rooms{Unsorted}{$name} = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
###############
|
|
# Needed for type sorting
|
|
foreach my $d (sort keys %__devs ) {
|
|
$__types{$__devs{$d}{type}} = 1;
|
|
}
|
|
$__title = $__devs{global}{ATTR}{title}{VAL} ?
|
|
$__devs{global}{ATTR}{title}{VAL} : "First page";
|
|
$__room = $__devs{$__detail}{ATTR}{room}{VAL} if($__detail);
|
|
}
|
|
|
|
|
|
######################
|
|
# Generate an image from the log via gnuplot
|
|
sub
|
|
FHEMRENDERER_render($)
|
|
{
|
|
my ($cmd) = @_;
|
|
my (undef, $wl, $d, $type, $file) = split(" ", $cmd, 5);
|
|
|
|
my $gplot_pgm = "$FHEMRENDERERdir/$type.gplot";
|
|
return FHEMRENDERER_fatal("Cannot read $gplot_pgm") if(!-r $gplot_pgm);
|
|
FHEMRENDERER_calcWeblink($d,$wl);
|
|
|
|
if($__plotmode =~ m/gnuplot/) {
|
|
if($__plotmode eq "gnuplot" || !$__devs{$d}{from}) {
|
|
|
|
# Looking for the logfile....
|
|
|
|
$__devs{$d}{INT}{logfile}{VAL} =~ m,^(.*)/([^/]*)$,; # Dir and File
|
|
my $path = "$1/$file";
|
|
$path = $__devs{$d}{ATTR}{archivedir}{VAL} . "/$file" if(!-f $path);
|
|
return FHEMRENDERER_fatal("Cannot read $path") if(!-r $path);
|
|
|
|
open(FH, $gplot_pgm) || return FHEMRENDERER_fatal("$gplot_pgm: $!");
|
|
my $gplot_script = join("", <FH>);
|
|
close(FH);
|
|
|
|
$gplot_script =~ s/<OUT>/$FHEMRENDERER_tmpfile$wl/g;
|
|
$gplot_script =~ s/<SIZE>/$__plotsize/g;
|
|
$gplot_script =~ s/<IN>/$path/g;
|
|
$gplot_script =~ s/<TL>/$file/g;
|
|
|
|
if($__devs{$wl} && $__devs{$wl}{ATTR}{fixedrange}) {
|
|
my $fr = $__devs{$wl}{ATTR}{fixedrange}{VAL};
|
|
$fr =~ s/ /\":\"/;
|
|
$fr = "set xrange [\"$fr\"]\n";
|
|
$gplot_script =~ s/(set timefmt ".*")/$1\n$fr/;
|
|
}
|
|
|
|
open(FH, "|gnuplot > /dev/null");# feed it to gnuplot
|
|
print FH $gplot_script;
|
|
close(FH);
|
|
|
|
} elsif($__plotmode eq "gnuplot-scroll") {
|
|
|
|
############################
|
|
# Read in the template gnuplot file. Digest the #FileLog lines. Replace
|
|
# the plot directive with our own, as we offer a file for each line
|
|
|
|
my (@filelog, @data, $plot);
|
|
open(FH, $gplot_pgm) || return FHEMRENDERER_fatal("$gplot_pgm: $!");
|
|
while(my $l = <FH>) {
|
|
if($l =~ m/^#FileLog (.*)$/) {
|
|
push(@filelog, $1);
|
|
} elsif($l =~ "^plot" || $plot) {
|
|
$plot .= $l;
|
|
} else {
|
|
push(@data, $l);
|
|
}
|
|
}
|
|
close(FH);
|
|
|
|
my $gplot_script = join("", @data);
|
|
$gplot_script =~ s/<OUT>/$FHEMRENDERER_tmpfile$wl/g;
|
|
$gplot_script =~ s/<SIZE>/$__plotsize/g;
|
|
$gplot_script =~ s/<TL>/$file/g;
|
|
|
|
my ($f,$t)=($__devs{$d}{from}, $__devs{$d}{to});
|
|
|
|
my @path = split(" ", FHEMRENDERER_fC("get $d $file $FHEMRENDERER_tmpfile$wl $f $t " .
|
|
join(" ", @filelog)));
|
|
my $i = 0;
|
|
$plot =~ s/\".*?using 1:[^ ]+ /"\"$path[$i++]\" using 1:2 "/gse;
|
|
my $xrange = "set xrange [\"$f\":\"$t\"]\n";
|
|
foreach my $p (@path) { # If the file is empty, write a 0 line
|
|
next if(!-z $p);
|
|
open(FH, ">$p");
|
|
print FH "$f 0\n";
|
|
close(FH);
|
|
}
|
|
|
|
open(FH, "|gnuplot > /dev/null");# feed it to gnuplot
|
|
print FH $gplot_script, $xrange, $plot;
|
|
close(FH);
|
|
foreach my $p (@path) {
|
|
unlink($p);
|
|
}
|
|
}
|
|
|
|
} #elsif($__plotmode eq "SVG") {
|
|
|
|
# my (@filelog, @data, $plot);
|
|
# open(FH, $gplot_pgm) || return FHEMRENDERER_fatal("$gplot_pgm: $!");
|
|
# while(my $l = <FH>) {
|
|
# if($l =~ m/^#FileLog (.*)$/) {
|
|
# push(@filelog, $1);
|
|
# } elsif($l =~ "^plot" || $plot) {
|
|
# $plot .= $l;
|
|
# } else {
|
|
# push(@data, $l);
|
|
# }
|
|
# }
|
|
# close(FH);
|
|
# my ($f,$t)=($__devs{$d}{from}, $__devs{$d}{to});
|
|
# $f = 0 if(!$f); # From the beginning of time...
|
|
# $t = 9 if(!$t); # till the end
|
|
#
|
|
# my $ret = FHEMRENDERER_fC("get $d $file INT $f $t " . join(" ", @filelog));
|
|
# SVG_render($file, $__plotsize, $f, $t, \@data, $internal_data, $plot);
|
|
#
|
|
# open (FH, ">$FHEMRENDERER_tmpfile$wl.svg");
|
|
# print FH $__RET;
|
|
# close (FH);
|
|
# }
|
|
}
|
|
|
|
|
|
|
|
##################
|
|
sub
|
|
FHEMRENDERER_fatal($)
|
|
{
|
|
my ($msg) = @_;
|
|
FHEMRENDERER_pO "<html><body>$msg</body></html>";
|
|
}
|
|
|
|
##################
|
|
# print formatted
|
|
sub
|
|
FHEMRENDERER_pF($@)
|
|
{
|
|
my $fmt = shift;
|
|
$__RET .= sprintf $fmt, @_;
|
|
}
|
|
|
|
##################
|
|
# print output
|
|
sub
|
|
FHEMRENDERER_pO(@)
|
|
{
|
|
$__RET .= shift;
|
|
}
|
|
|
|
##################
|
|
# fhem command
|
|
sub
|
|
FHEMRENDERER_fC($)
|
|
{
|
|
my ($cmd) = @_;
|
|
#Log 0, "Calling $cmd";
|
|
my $oll = $attr{global}{verbose};
|
|
$attr{global}{verbose} = 0 if($cmd ne "save");
|
|
my $ret = AnalyzeCommand(undef, $cmd);
|
|
$attr{global}{verbose} = $oll if($cmd !~ m/attr.*global.*verbose/);
|
|
return $ret;
|
|
}
|
|
|
|
##################
|
|
sub
|
|
FHEMRENDERER_getAttr($$)
|
|
{
|
|
my ($aname, $def) = @_;
|
|
if($attr{$__wname} && defined($attr{$__wname}{$aname})) {
|
|
return $attr{$__wname}{$aname};
|
|
} else {
|
|
CommandAttr (undef, $__wname . " $aname $def");
|
|
}
|
|
return $def;
|
|
}
|
|
|
|
##################
|
|
sub
|
|
FHEMRENDERER_setAttr($$)
|
|
{
|
|
my ($aname, $def) = @_;
|
|
CommandAttr (undef, $__wname . " $aname $def");
|
|
}
|
|
|
|
|
|
##################
|
|
# Calculate either the number of scrollable weblinks (for $d = undef) or
|
|
# for the device the valid from and to dates for the given zoom and offset
|
|
sub
|
|
FHEMRENDERER_calcWeblink($$)
|
|
{
|
|
my ($d,$wl) = @_;
|
|
|
|
return if($__plotmode eq "gnuplot");
|
|
my $now = time();
|
|
|
|
my $zoom = $__pos{zoom};
|
|
$zoom = "day" if(!$zoom);
|
|
|
|
if(!$d) {
|
|
foreach my $d (sort keys %__devs ) {
|
|
next if($__devs{$d}{type} ne "weblink");
|
|
next if(!$__room || ($__room ne "all" && !$__rooms{$__room}{$d}));
|
|
next if($__devs{$d}{ATTR} && $__devs{$d}{ATTR}{noscroll});
|
|
next if($__devs{$d}{ATTR} && $__devs{$d}{ATTR}{fixedrange});
|
|
$__scrolledweblinkcount++;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
# return if(!$__devs{$wl});
|
|
return if($__devs{$wl} && $__devs{$wl}{ATTR}{noscroll});
|
|
|
|
if($__devs{$wl} && $__devs{$wl}{ATTR}{fixedrange}) {
|
|
my @range = split(" ", $__devs{$wl}{ATTR}{fixedrange}{VAL});
|
|
$__devs{$d}{from} = $range[0];
|
|
$__devs{$d}{to} = $range[1];
|
|
return;
|
|
}
|
|
|
|
my $off = $__pos{$d};
|
|
$off = 0 if(!$off);
|
|
$off += $__pos{off} if($__pos{off});
|
|
|
|
if($zoom eq "qday") {
|
|
|
|
my $t = $now + $off*21600;
|
|
my @l = localtime($t);
|
|
$l[2] = int($l[2]/6)*6;
|
|
$__devs{$d}{from}
|
|
= sprintf("%04d-%02d-%02d_%02d",$l[5]+1900,$l[4]+1,$l[3],$l[2]);
|
|
$__devs{$d}{to}
|
|
= sprintf("%04d-%02d-%02d_%02d",$l[5]+1900,$l[4]+1,$l[3],$l[2]+6);
|
|
|
|
} elsif($zoom eq "day") {
|
|
|
|
my $t = $now + $off*86400;
|
|
my @l = localtime($t);
|
|
$__devs{$d}{from} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]);
|
|
$__devs{$d}{to} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]+1);
|
|
|
|
} elsif($zoom eq "week") {
|
|
|
|
my @l = localtime($now);
|
|
my $t = $now - ($l[6]*86400) + ($off*86400)*7;
|
|
@l = localtime($t);
|
|
$__devs{$d}{from} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]);
|
|
|
|
@l = localtime($t+7*86400);
|
|
$__devs{$d}{to} = sprintf("%04d-%02d-%02d",$l[5]+1900,$l[4]+1,$l[3]);
|
|
|
|
|
|
} elsif($zoom eq "month") {
|
|
|
|
my @l = localtime($now);
|
|
while($off < -12) {
|
|
$off += 12; $l[5]--;
|
|
}
|
|
$l[4] += $off;
|
|
$l[4] += 12, $l[5]-- if($l[4] < 0);
|
|
$__devs{$d}{from} = sprintf("%04d-%02d", $l[5]+1900, $l[4]+1);
|
|
|
|
$l[4]++;
|
|
$l[4] = 0, $l[5]++ if($l[4] == 12);
|
|
$__devs{$d}{to} = sprintf("%04d-%02d", $l[5]+1900, $l[4]+1);
|
|
|
|
} elsif($zoom eq "year") {
|
|
|
|
my @l = localtime($now);
|
|
$l[5] += $off;
|
|
$__devs{$d}{from} = sprintf("%04d", $l[5]+1900);
|
|
$__devs{$d}{to} = sprintf("%04d", $l[5]+1901);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
1; |