';
+
+ foreach my $polyIndex (0..$#alternativesPoly){
+ $map .= '
';
+ }
+
$map .= '
' if $returnDebugPoly && decode_base64($returnDebugPoly);
$map .= '
@@ -250,23 +266,29 @@ sub TRAFFIC_GetMap($@){
var myLatlng = new google.maps.LatLng('.$GoogleMapsCenter.');
var myOptions = {
zoom: '.$GoogleMapsZoom.',
+ '.$GoogleMapsFixedMap.'
center: myLatlng,
'.$GoogleMapsDisableUI.'
mapTypeId: google.maps.MapTypeId.ROADMAP,
styles: '.$selectedGoogleMapsStyle.'
}
var map = new google.maps.Map(document.getElementById("map"), myOptions);
- var decodedPath = google.maps.geometry.encoding.decodePath(document.getElementById("path").value);
+ ';
+
+ foreach my $polyIndex (1..$#alternativesPoly){
+ $map .='var decodedPath = google.maps.geometry.encoding.decodePath(document.getElementById("path'.$polyIndex.'").value);
var decodedLevels = decodeLevels("");
var setRegion = new google.maps.Polyline({
path: decodedPath,
levels: decodedLevels,
- strokeColor: "'.$GoogleMapsStroke1Color.'",
- strokeOpacity: '.$GoogleMapsStroke1Opacity.',
- strokeWeight: '.$GoogleMapsStroke1Weight.',
+ strokeColor: "'.$GoogleMapsStrokeAColor.'",
+ strokeOpacity: '.$GoogleMapsStrokeAOpacity.',
+ strokeWeight: '.$GoogleMapsStrokeAWeight.',
map: map
- });';
-
+ });
+ ';
+ }
+
$map .= 'var decodedPathR = google.maps.geometry.encoding.decodePath(document.getElementById("pathR").value);
var decodedLevelsR = decodeLevels("");
var setRegionR = new google.maps.Polyline({
@@ -278,6 +300,17 @@ sub TRAFFIC_GetMap($@){
map: map
});' if $returnDebugPoly && decode_base64($returnDebugPoly );
+ $map .='var decodedPath = google.maps.geometry.encoding.decodePath(document.getElementById("path0").value);
+ var decodedLevels = decodeLevels("");
+ var setRegion = new google.maps.Polyline({
+ path: decodedPath,
+ levels: decodedLevels,
+ strokeColor: "'.$GoogleMapsStroke1Color.'",
+ strokeOpacity: '.$GoogleMapsStroke1Opacity.',
+ strokeWeight: '.$GoogleMapsStroke1Weight.',
+ map: map
+ });
+ ';
$map .= 'var trafficLayer = new google.maps.TrafficLayer();
trafficLayer.setMap(map);' if AttrVal($name, "GoogleMapsTrafficLayer", 0) eq 1;
@@ -461,7 +494,7 @@ sub TRAFFIC_StartUpdate($){
if(defined(AttrVal($name, "start_address", undef )) && defined(AttrVal($name, "end_address", undef ))){
BlockingCall("TRAFFIC_DoUpdate",$hash->{NAME}.';;;normal',"TRAFFIC_FinishUpdate",60,"TRAFFIC_AbortUpdate",$hash);
-
+
if(defined(AttrVal($name, "includeReturn", undef )) && AttrVal($name, "includeReturn", undef ) eq 1){
BlockingCall("TRAFFIC_DoUpdate",$hash->{NAME}.';;;return',"TRAFFIC_FinishUpdate",60,"TRAFFIC_AbortUpdate",$hash);
}
@@ -525,16 +558,19 @@ sub TRAFFIC_DoUpdate(){
}
}
- my $origin = AttrVal($name, "start_address", 0 );
- my $destination = AttrVal($name, "end_address", 0 );
- my $travelMode = AttrVal($name, "travelMode", 'driving' );
+ my $origin = AttrVal($name, "start_address", 0 );
+ my $destination = AttrVal($name, "end_address", 0 );
+ my $travelMode = AttrVal($name, "travelMode", 'driving' );
+ my $alternatives = 'false';
+ $alternatives = 'true' if (AttrVal($name, "alternatives", undef ));
if($direction eq "return"){
- $origin = AttrVal($name, "end_address", 0 );
- $destination = AttrVal($name, "start_address", 0 );
+ $origin = AttrVal($name, "end_address", 0 );
+ $destination = AttrVal($name, "start_address", 0 );
+ $alternatives = 'false';
}
- my $url = 'https://maps.googleapis.com/maps/api/directions/json?origin='.$origin.'&destination='.$destination.'&mode='.$travelMode.$TRlanguage.'&departure_time=now'.$TRwaypoints.'&key='.$hash->{APIKEY};
+ my $url = 'https://maps.googleapis.com/maps/api/directions/json?origin='.$origin.'&destination='.$destination.'&mode='.$travelMode.$TRlanguage.'&departure_time=now'.$TRwaypoints.'&key='.$hash->{APIKEY}.'&alternatives='.$alternatives;
Log3 $hash, 4, "TRAFFIC: ($name) using $url";
my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 } );
@@ -543,6 +579,7 @@ sub TRAFFIC_DoUpdate(){
# test json decode and catch error nicely
+
eval {
my $testJson = decode_json($body->decoded_content);
1;
@@ -550,14 +587,14 @@ sub TRAFFIC_DoUpdate(){
if($@) {
my $e = $@;
Log3 $hash, 1, "TRAFFIC: ($name) decode_json on googles return failed, cant continue";
- my %errorreturn = ('status' => 'API error');
- return "$name;;;$direction;;;".encode_json(\%errorreturn);
+ Log3 $hash, 5, "TRAFFIC: ($name) received: ".Dumper($body->decoded_content);
+ my %errorReturn = ('status' => 'API error','action' => 'retry');
+ #fixme: handle this and schedule a retry
+ return "$name;;;$direction;;;".encode_json(\%errorReturn);
};
my $json = decode_json($body->decoded_content);
-
-
my $duration_sec = $json->{'routes'}[0]->{'legs'}[0]->{'duration'}->{'value'} ;
my $duration_in_traffic_sec = $json->{'routes'}[0]->{'legs'}[0]->{'duration_in_traffic'}->{'value'};
@@ -567,10 +604,14 @@ sub TRAFFIC_DoUpdate(){
$returnJSON->{'READINGS'}->{'state'} = $json->{'status'};
$returnJSON->{'READINGS'}->{'status'} = $json->{'status'};
$returnJSON->{'READINGS'}->{'eta'} = FmtTime( gettimeofday() + $duration_in_traffic_sec ) if defined($duration_in_traffic_sec);
+ $returnJSON->{'READINGS'}->{'summary'} = $json->{'routes'}[0]->{'summary'};
- $returnJSON->{'HELPER'}->{'Poly'} = encode_base64 ($json->{'routes'}[0]->{overview_polyline}->{points});
- $returnJSON->{'HELPER'}->{'GoogleMapsCenter'} = $json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lat}.','.$json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lng};
+ # handling alternatives
+ $returnJSON->{'READINGS'}->{'alternatives'} = join( ", ", map { $_->{summary}.' - '.$_->{'legs'}[0]->{'duration_in_traffic'}->{'text'} } @{$json->{'routes'}} );
+ $returnJSON->{'HELPER'}->{'Poly'} = encode_base64 (join(',', map{ $_->{overview_polyline}->{points} } @{$json->{'routes'}} ));
+ $returnJSON->{'HELPER'}->{'GoogleMapsCenter'} = $json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lat}.','.$json->{'routes'}[0]->{'legs'}[0]->{start_location}->{lng};
+
if($duration_in_traffic_sec && $duration_sec){
$returnJSON->{'READINGS'}->{'delay'} = prettySeconds($duration_in_traffic_sec - $duration_sec) if AttrVal($name, "outputReadings", "" ) =~ m/text/;
Log3 $hash, 4, "TRAFFIC: ($name) delay in seconds = $duration_in_traffic_sec - $duration_sec";
@@ -628,9 +669,24 @@ sub TRAFFIC_FinishUpdate($){
my %sensors;
my $dotrigger = 1;
- Log3 $hash, 4, "TRAFFIC: ($name) TRAFFIC_FinishUpdate start";
my $json = decode_json($rawJson);
+
+ # before we update anything, check if the status contains error, if yes -> retry
+ if(defined($json->{'status'}) && $json->{'status'} =~ m/error/){
+ if ($json->{'action'} eq 'retry'){
+ Log3 $hash, 1, "TRAFFIC: ($name) TRAFFIC_doUpdate returned an error \"".$json->{'status'}. "\" will schedule a retry in 5 seconds";
+ RemoveInternalTimer ($hash);
+ my $nextTrigger = gettimeofday() + 5;
+ $hash->{TRIGGERTIME} = $nextTrigger;
+ $hash->{TRIGGERTIME_FMT} = FmtDateTime($nextTrigger);
+ InternalTimer($nextTrigger, "TRAFFIC_DoUpdate", $hash, 0);
+ }else{
+ Log3 $hash, 1, "TRAFFIC: ($name) TRAFFIC_doUpdate returned an error: ".$json->{'status'};
+ }
+ }else{
+
+ Log3 $hash, 4, "TRAFFIC: ($name) TRAFFIC_FinishUpdate start";
readingsBeginUpdate($hash);
my $readings = $json->{'READINGS'};
@@ -671,6 +727,7 @@ sub TRAFFIC_FinishUpdate($){
readingsEndUpdate($hash, $dotrigger);
Log3 $hash, 4, "TRAFFIC: ($name) TRAFFIC_FinishUpdate done";
Log3 $hash, 5, "TRAFFIC: ($name) Helper: ".Dumper($hash->{helper});
+ }# not an error
}
sub TRAFFIC_weblink{
@@ -713,9 +770,22 @@ sub prettySeconds {
}else{
return $time;
}
-
}
+sub minHex{ $_[0]<$_[1] ? $_[0] : $_[1] }
+
+sub degradeHex{
+ my ($rgb, $degr) = (hex(shift), pop);
+ $rgb -= minHex( $rgb&(0xff<<$_), $degr<<$_ ) for (0,8,16);
+ return '%06x', $rgb;
+}
+
+sub lightHex {
+ $_[0] =~ s/#//g;
+ return sprintf '%02x'x3,
+ map{ ($_ *= 1+$_[1]) > 0xff ? 0xff : $_ }
+ map hex, unpack 'A2'x3, $_[0];
+}
1;
@@ -785,6 +855,7 @@ sub prettySeconds {
"start_address" - Street, zipcode City (mandatory)
"end_address" - Street, zipcode City (mandatory)
"raw_data" - 0:1
+
"alternatives" - 0:1, include alternative routes into readings and Map
"language" - de, en etc.
"waypoints" - Lat, Long coordinates, separated by |
"returnWaypoints" - Lat, Long coordinates, separated by |
@@ -807,16 +878,18 @@ sub prettySeconds {
Readings:
- - delay
- - distance
- - duration
- - duration_in_traffic
- - state
- - eta
- - delay_min
- - duration_min
- - duration_in_traffic_min
- - error_message
+ - alternatives
+ - delay
+ - delay_min
+ - distance
+ - duration
+ - duration_in_traffic
+ - duration_in_traffic_min
+ - duration_min
+ - error_message
+ - eta
+ - state
+ - summary