diff --git a/fhem/CHANGED b/fhem/CHANGED
index ba5ed5164..f25a0e9a9 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,6 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - feature: 98_TRAFFIC: reverse waypoints, integrated map for visualization
- update: 77_UWZ: New Version 1.4.7 added headlines for weblinks
- update: 73_NUKIBridge,74_NUKIDevice: New Version 0.4.0
More Feature get,set ,Callback/Webhook Funktion
diff --git a/fhem/FHEM/98_TRAFFIC.pm b/fhem/FHEM/98_TRAFFIC.pm
index d9d141a01..aa0dc7918 100644
--- a/fhem/FHEM/98_TRAFFIC.pm
+++ b/fhem/FHEM/98_TRAFFIC.pm
@@ -17,6 +17,13 @@
# You should have received a copy of the GNU General Public License
# along with fhem. If not, see .
#
+# versioning: MAJOR.MINOR.PATCH, increment the:
+# MAJOR version when you make incompatible API changes
+# - includes changing CLI options, changing log-messages
+# MINOR version when you add functionality in a backwards-compatible manner
+# - includes adding new features and log-messages (as long as they don't break anything existing)
+# PATCH version when you make backwards-compatible bug fixes.
+#
##############################################################################
# Changelog:
#
@@ -30,18 +37,21 @@
# 2016-10-07 version 1.0, adding to SVN
# 2016-10-15 adding attribute updateSchedule to provide flexible updates, changed internal interval to INTERVAL
# 2016-12-13 adding travelMode, fixing stateReading with value 0
+# 2016-12-15 adding reverseWaypoints attribute, adding weblink with auto create route via gmaps on verbose 5
package main;
use strict;
use warnings;
-use Time::HiRes qw(gettimeofday);
use Data::Dumper;
+use Time::HiRes qw(gettimeofday);
use LWP::Simple qw($ua get);
-use JSON;
-use POSIX;
use Blocking;
+use POSIX;
+die "MIME::Base64 missing!" unless(eval{require MIME::Base64});
+die "JSON missing!" unless(eval{require JSON});
+
sub TRAFFIC_Initialize($);
sub TRAFFIC_Define($$);
@@ -53,7 +63,7 @@ sub TRAFFIC_GetUpdate($);
my %TRcmds = (
'update' => 'noArg',
);
-my $TRVersion = '1.1';
+my $TRVersion = '1.2';
sub TRAFFIC_Initialize($){
@@ -64,9 +74,11 @@ sub TRAFFIC_Initialize($){
$hash->{SetFn} = "TRAFFIC_Set";
$hash->{AttrFn} = "TRAFFIC_Attr";
$hash->{AttrList} =
- "disable:0,1 start_address end_address raw_data:0,1 language waypoints stateReading outputReadings travelMode:driving,walking,bicycling,transit includeReturn:0,1 updateSchedule " .
+ "disable:0,1 start_address end_address raw_data:0,1 language waypoints returnWaypoints stateReading outputReadings travelMode:driving,walking,bicycling,transit includeReturn:0,1 updateSchedule " .
$readingFnAttributes;
-
+ $data{FWEXT}{"/TRAFFIC"}{FUNC} = "TRAFFIC_debug";
+ $data{FWEXT}{"/TRAFFIC"}{FORKABLE} = 1;
+
}
sub TRAFFIC_Define($$){
@@ -85,7 +97,6 @@ sub TRAFFIC_Define($$){
$hash->{VERSION} = $TRVersion;
delete($hash->{BURSTCOUNT}) if $hash->{BURSTCOUNT};
delete($hash->{BURSTINTERVAL}) if $hash->{BURSTINTERVAL};
-
my $name = $hash->{NAME};
@@ -145,7 +156,19 @@ sub TRAFFIC_Attr(@){
if($attrName eq "disable" && $attrValue eq "1"){
readingsSingleUpdate( $hash, "state", "disabled", 1 );
}
- if($attrName eq "outputReadings" || $attrName eq "includeReturn"){
+
+ if($attrName eq "verbose" && $attrValue eq "5"){
+ if (!defined $defs{$name."_weblink"}) {
+ FW_fC("define ".$name."_weblink weblink htmlCode {TRAFFIC_weblink(\"".$name."\",0)}");
+ FW_fC("attr ".$name."_weblink room TRAFFIC_debug");
+ Log3 $hash, 5, "TRAFFIC: ($name) weblink created";
+ }
+ }elsif($attrName eq "verbose" && $attrValue < 5){
+ FW_fC("delete ".$name."_weblink");
+ }
+
+
+ if($attrName eq "outputReadings" || $attrName eq "includeReturn" || $attrName eq "verbose"){
#clear all readings
foreach my $clearReading ( keys %{$hash->{READINGS}}){
Log3 $hash, 5, "TRAFFIC: ($name) READING: $clearReading deleted";
@@ -201,7 +224,10 @@ sub TRAFFIC_Set($@){
InternalTimer($updateTrigger, "TRAFFIC_StartUpdate", $hash, 0);
return undef;
+ }elsif($set =~ m/debug/){
+ # TRAFFIC_widget();
}
+
}
@@ -325,13 +351,19 @@ sub TRAFFIC_DoUpdate(){
my $TRwaypoints = '';
if(defined(AttrVal($name,"waypoints",undef))){
$TRwaypoints = '&waypoints=via:' . join('|via:', split('\|', AttrVal($name,"waypoints",undef)));
-
- if($direction eq "return"){
- $TRwaypoints = '&waypoints=via:' . join('|via:', reverse split('\|', AttrVal($name,"waypoints",undef)));
- Log3 $hash, 5, "TRAFFIC: ($name) reversing waypoints";
- }
}else{
- Log3 $hash, 5, "TRAFFIC: ($name) no waypoints specified";
+ Log3 $hash, 3, "TRAFFIC: ($name) no waypoints specified";
+ }
+ if($direction eq "return"){
+ if(defined(AttrVal($name,"returnWaypoints",undef))){
+ $TRwaypoints = '&waypoints=via:' . join('|via:', split('\|', AttrVal($name,"returnWaypoints",undef)));
+ Log3 $hash, 3, "TRAFFIC: ($name) using returnWaypoints";
+ }elsif(defined(AttrVal($name,"waypoints",undef))){
+ $TRwaypoints = '&waypoints=via:' . join('|via:', reverse split('\|', AttrVal($name,"waypoints",undef)));
+ Log3 $hash, 3, "TRAFFIC: ($name) reversing waypoints";
+ }else{
+ Log3 $hash, 3, "TRAFFIC: ($name) no waypoints for return specified";
+ }
}
my $origin = AttrVal($name, "start_address", 0 );
@@ -361,6 +393,9 @@ sub TRAFFIC_DoUpdate(){
$returnJSON->{'status'} = $json->{'status'};
$returnJSON->{'eta'} = FmtTime( gettimeofday() + $duration_in_traffic_sec ) if defined($duration_in_traffic_sec);
+ $returnJSON->{'debugLocation'} = $json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lat}.','.$json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lng} if AttrVal($name, "verbose", 0 ) == 5;
+ $returnJSON->{'debugPoly'} = encode_base64 ($json->{'routes'}[0]->{overview_polyline}->{points}) if AttrVal($name, "verbose", 0 ) == 5;
+
if($duration_in_traffic_sec && $duration_sec){
$returnJSON->{'delay'} = prettySeconds($duration_in_traffic_sec - $duration_sec) if AttrVal($name, "outputReadings", "" ) =~ m/text/;
Log3 $hash, 3, "TRAFFIC: ($name) delay in seconds = $duration_in_traffic_sec - $duration_sec";
@@ -445,11 +480,86 @@ sub TRAFFIC_FinishUpdate($){
Log3 $hash, 1, "TRAFFIC: ($name) stateReading $stateReading not found";
}
}
-
readingsEndUpdate($hash, $dotrigger);
Log3 $hash, 3, "TRAFFIC: ($name) TRAFFIC_FinishUpdate done";
}
+sub TRAFFIC_weblink{
+ my $name = shift();
+ my $return = shift();
+ return "open Map for TRAFFIC $name
";
+}
+
+sub TRAFFIC_debug(){
+ my $name = $FW_webArgs{name};
+ my $return = $FW_webArgs{return};
+ return if(!defined($name));
+
+ $FW_RETTYPE = "text/html; charset=UTF-8";
+ $FW_RET="";
+
+ Log 1,"[traffic debug] called for $name";
+
+ my $debugPoly = 'debugPoly';
+ my $debugLocation = 'debugLocation';
+ if($return eq 1){
+ $debugPoly = 'return_'.$debugPoly;
+ $debugLocation = 'return_'.$debugLocation;
+ }
+
+ my $web = '
+';
+$web .= '' if decode_base64(ReadingsVal($name, "return_debugPoly", undef) );
+$web .= '
+
+
+';
+ FW_pO $web;
+ return ($FW_RETTYPE, $FW_RET);
+}
sub prettySeconds {
my $time = shift;
@@ -502,6 +612,7 @@ sub prettySeconds {
requirements:
perl JSON module
perl LWP::SIMPLE module
+ perl MIME::Base64 module
Google maps API key
Features:
@@ -523,6 +634,9 @@ sub prettySeconds {
configure the state-reading
optionally display the same route in return
one-time-burst, specify the amount and interval between updates
+ different Travel Modes (driving, walking, bicycling and transit)
+ flexible update schedule
+ integrated Map to visualize configured route at verbose 5
@@ -543,6 +657,7 @@ sub prettySeconds {
"raw_data" - 0:1
"language" - de, en etc.
"waypoints" - Lat, Long coordinates, separated by |
+ "returnWaypoints" - Lat, Long coordinates, separated by |
"disable" - 0:1
"stateReading" - name the reading which will be used in device state
"outputReadings" - define what kind of readings you want to get: text, min, sec, average