diff --git a/fhem/CHANGED b/fhem/CHANGED
index dd90000cf..63c432a71 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,7 @@
# 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.
+ - bugfix: 74_AutomowerConnect: Common.pm, automowerconnect.js, fix promlem
+ with empty positions array
- feature: 74_AutomowerConnect: Common.pm, add additional API polling
- feature: 76_SMAInverter: bugfix DC-Power
- change: 74_AutomowerConnect: Common.pm, automowerconnect.js
diff --git a/fhem/lib/FHEM/Devices/AMConnect/Common.pm b/fhem/lib/FHEM/Devices/AMConnect/Common.pm
index de2eb249d..ee893e9d5 100644
--- a/fhem/lib/FHEM/Devices/AMConnect/Common.pm
+++ b/fhem/lib/FHEM/Devices/AMConnect/Common.pm
@@ -195,6 +195,7 @@ my $mapZonesTpl = '{
maxLat => -90,
imageHeight => 650,
imageWidthHeight => '350 650',
+ map_init_delay => 2,
mapdesign => $mapAttr,
mapZonesTpl => $mapZonesTpl,
posMinMax => "-180 90\n180 -90",
@@ -447,87 +448,82 @@ sub FW_detailFn {
my $type = $hash->{TYPE};
return '' if( AttrVal($name, 'disable', 0) || !AttrVal($name, 'showMap', 1) );
- if ( $hash->{helper} && $hash->{helper}{mower} && $hash->{helper}{mower}{attributes} && $hash->{helper}{mower}{attributes}{positions} && @{$hash->{helper}{mower}{attributes}{positions}} > 0 ) {
+ my $img = "$FW_ME/$type/$name/map";
+ my $zoom=AttrVal( $name,"mapImageZoom", 0.7 );
+ my $backgroundcolor = AttrVal($name, 'mapBackgroundColor','');
+ my $bgstyle = $backgroundcolor ? " background-color:$backgroundcolor;" : '';
+ my $design = AttrVal( $name, 'mapDesignAttributes', $hash->{helper}{mapdesign} );
+ my @adesign = split(/\R/,$design);
+ my $mapDesign = 'data-'.join("data-",@adesign);
- my $img = "$FW_ME/$type/$name/map";
- my $zoom=AttrVal( $name,"mapImageZoom", 0.7 );
- my $backgroundcolor = AttrVal($name, 'mapBackgroundColor','');
- my $bgstyle = $backgroundcolor ? " background-color:$backgroundcolor;" : '';
- my $design = AttrVal( $name, 'mapDesignAttributes', $hash->{helper}{mapdesign} );
- my @adesign = split(/\R/,$design);
- my $mapDesign = 'data-'.join("data-",@adesign);
+ my ($picx,$picy) = AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
+ $picx=int($picx*$zoom);
+ $picy=int($picy*$zoom);
- my ($picx,$picy) = AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
- $picx=int($picx*$zoom);
- $picy=int($picy*$zoom);
+ my ( $lonlo, $latlo, $dummy, $lonru, $latru ) = AttrVal( $name,"mapImageCoordinatesToRegister",$hash->{helper}{posMinMax} ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
+ my $mapx = $lonlo-$lonru;
+ my $mapy = $latlo-$latru;
- my ( $lonlo, $latlo, $dummy, $lonru, $latru ) = AttrVal( $name,"mapImageCoordinatesToRegister",$hash->{helper}{posMinMax} ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
- my $mapx = $lonlo-$lonru;
- my $mapy = $latlo-$latru;
+ AttrVal($name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude}) =~ /(-?\d+)\s+(-?\d+)/;
+ my $scalx = ( $lonru - $lonlo ) * $1;
+ my $scaly = ( $latlo - $latru ) * $2;
- AttrVal($name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude}) =~ /(-?\d+)\s+(-?\d+)/;
- my $scalx = ( $lonru - $lonlo ) * $1;
- my $scaly = ( $latlo - $latru ) * $2;
+ # CHARGING STATION POSITION
+ my $csimgpos = AttrVal( $name,"chargingStationImagePosition","right" );
+ my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
+ my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
- # CHARGING STATION POSITION
- my $csimgpos = AttrVal( $name,"chargingStationImagePosition","right" );
- my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
- my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
+ my ($cslo,$csla) = AttrVal( $name,"chargingStationCoordinates","$xm $ym" ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
+ my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
+ my $cslat = int(($latlo-$csla) * $picy / $mapy);
+ my $csdata = 'data-csimgpos="'.$csimgpos.'" data-cslon="'.$cslon.'" data-cslat="'.$cslat.'"';
- my ($cslo,$csla) = AttrVal( $name,"chargingStationCoordinates","$xm $ym" ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
- my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
- my $cslat = int(($latlo-$csla) * $picy / $mapy);
- my $csdata = 'data-csimgpos="'.$csimgpos.'" data-cslon="'.$cslon.'" data-cslat="'.$cslat.'"';
-
- # AREA LIMITS
- my $arealimits = AttrVal($name,'mowingAreaLimits','');
- my $limi = '';
- if ($arealimits) {
- my @lixy = (split(/\s|,|\R$/,$arealimits));
- $limi = int( ( $lonlo - $lixy[ 0 ] ) * $picx / $mapx ) . "," . int( ( $latlo - $lixy[ 1 ] ) * $picy / $mapy );
- for (my $i=2;$i<@lixy;$i+=2){
- $limi .= ",".int( ( $lonlo - $lixy[ $i ] ) * $picx / $mapx).",".int( ( $latlo-$lixy[$i+1] ) * $picy / $mapy);
- }
+ # AREA LIMITS
+ my $arealimits = AttrVal($name,'mowingAreaLimits','');
+ my $limi = '';
+ if ($arealimits) {
+ my @lixy = (split(/\s|,|\R$/,$arealimits));
+ $limi = int( ( $lonlo - $lixy[ 0 ] ) * $picx / $mapx ) . "," . int( ( $latlo - $lixy[ 1 ] ) * $picy / $mapy );
+ for (my $i=2;$i<@lixy;$i+=2){
+ $limi .= ",".int( ( $lonlo - $lixy[ $i ] ) * $picx / $mapx).",".int( ( $latlo-$lixy[$i+1] ) * $picy / $mapy);
}
- $limi = 'data-areaLimitsPath="'.$limi.'"';
-
- # PROPERTY LIMITS
- my $propertylimits = AttrVal($name,'propertyLimits','');
- my $propli = '';
- if ($propertylimits) {
- my @propxy = (split(/\s|,|\R$/,$propertylimits));
- $propli = int(($lonlo-$propxy[0]) * $picx / $mapx).",".int(($latlo-$propxy[1]) * $picy / $mapy);
- for (my $i=2;$i<@propxy;$i+=2){
- $propli .= ",".int(($lonlo-$propxy[$i]) * $picx / $mapx).",".int(($latlo-$propxy[$i+1]) * $picy / $mapy);
- }
- }
- $propli = 'data-propertyLimitsPath="'.$propli.'"';
-
- my $ret = "";
- $ret .= "";
- $ret .= "
";
- $ret .= "";
- $ret .= "";
- $ret .= "
";
- $hash->{helper}{detailFnFirst} = 1;
- InternalTimer( gettimeofday() + 2, \&FW_detailFn_Update, $hash, 0 );
-
- return $ret;
-
}
+ $limi = 'data-areaLimitsPath="'.$limi.'"';
- return '';
+ # PROPERTY LIMITS
+ my $propertylimits = AttrVal($name,'propertyLimits','');
+ my $propli = '';
+ if ($propertylimits) {
+ my @propxy = (split(/\s|,|\R$/,$propertylimits));
+ $propli = int(($lonlo-$propxy[0]) * $picx / $mapx).",".int(($latlo-$propxy[1]) * $picy / $mapy);
+ for (my $i=2;$i<@propxy;$i+=2){
+ $propli .= ",".int(($lonlo-$propxy[$i]) * $picx / $mapx).",".int(($latlo-$propxy[$i+1]) * $picy / $mapy);
+ }
+ }
+ $propli = 'data-propertyLimitsPath="'.$propli.'"';
+
+ my $ret = "";
+ $ret .= "";
+ $ret .= "";
+ $ret .= "";
+ $ret .= "";
+ $ret .= "
";
+ $hash->{helper}{detailFnFirst} = 1;
+ my $mid = $hash->{helper}{map_init_delay};
+ InternalTimer( gettimeofday() + $mid, \&FW_detailFn_Update, $hash, 0 );
+
+ return $ret;
}
@@ -2504,7 +2500,8 @@ sub wsCb {
my $name = $hash->{NAME};
my $type = $hash->{TYPE};
my $iam = "$type $name wsCb:";
- Log3 $name, 2, "$iam failed with error: $error" if( $error );
+ my $l = $hash->{devioLoglevel};
+ Log3 $name, ( $l ? $l : 1 ), "$iam failed with error: $error" if( $error );
return undef;
}
diff --git a/fhem/www/pgm2/automowerconnect.js b/fhem/www/pgm2/automowerconnect.js
index ea911f1e1..1ea200376 100644
--- a/fhem/www/pgm2/automowerconnect.js
+++ b/fhem/www/pgm2/automowerconnect.js
@@ -294,87 +294,79 @@ function AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, sca
"L" : "leavingPath",
"G" : "goingHomePath"
};
-// log('loop: Start '+ type+' '+dev );
- if (FW_urlParams.detail == dev || 1) {
- const canvas_0 = document.getElementById(type+'_'+dev+'_canvas_0');
- const canvas = document.getElementById(type+'_'+dev+'_canvas_1');
- const div = document.getElementById(type+'_'+dev+'_div');
+ const div = document.getElementById(type+'_'+dev+'_div');
+ const canvas_0 = document.getElementById(type+'_'+dev+'_canvas_0');
+ const canvas = document.getElementById(type+'_'+dev+'_canvas_1');
- if ( canvas && canvas_0 ) {
+ if ( div && canvas && canvas_0 ) {
-// log('loop: canvas && canvas_0 true '+ type+' '+dev + ' detailfnfirst '+detailfnfirst);
+// log('loop: div && canvas && canvas_0 true '+ type+' '+dev + ' detailfnfirst '+detailfnfirst);
- if ( detailfnfirst ) {
+ if ( detailfnfirst ) {
- const ctx0 = canvas_0.getContext( '2d' );
- ctx0.clearRect( 0, 0, canvas.width, canvas.height );
- const ctx = canvas.getContext( '2d' );
+ const ctx0 = canvas_0.getContext( '2d' );
+ ctx0.clearRect( 0, 0, canvas.width, canvas.height );
+ const ctx = canvas.getContext( '2d' );
- // draw area limits
- const lixy = div.getAttribute( 'data-areaLimitsPath' ).split(",");
- if ( lixy.length > 0 ) AutomowerConnectLimits( ctx0, div, lixy, 'area' );
+ // draw area limits
+ const lixy = div.getAttribute( 'data-areaLimitsPath' ).split(",");
+ if ( lixy.length > 0 ) AutomowerConnectLimits( ctx0, div, lixy, 'area' );
// log('pos.length '+pos.length+' lixy.length '+lixy.length+', scalx '+scalx );
- // draw property limits
- const plixy = div.getAttribute( 'data-propertyLimitsPath' ).split( "," );
- if ( plixy.length > 0 ) AutomowerConnectLimits( ctx0, div, plixy, 'property' );
+ // draw property limits
+ const plixy = div.getAttribute( 'data-propertyLimitsPath' ).split( "," );
+ if ( plixy.length > 0 ) AutomowerConnectLimits( ctx0, div, plixy, 'property' );
- // draw scale
- AutomowerConnectScale( ctx0, picx, picy, scalx );
+ // draw scale
+ AutomowerConnectScale( ctx0, picx, picy, scalx );
- // draw charging station
- var csx = div.getAttribute( 'data-cslon' );
- var csy = div.getAttribute( 'data-cslat' );
- var csrel = div.getAttribute( 'data-csimgpos' );
- AutomowerConnectIcon( ctx0, csx , csy, csrel, 'CS' );
+ // draw charging station
+ var csx = div.getAttribute( 'data-cslon' );
+ var csy = div.getAttribute( 'data-cslat' );
+ var csrel = div.getAttribute( 'data-csimgpos' );
+ AutomowerConnectIcon( ctx0, csx , csy, csrel, 'CS' );
- }
-
- const ctx = canvas.getContext( '2d' );
- ctx.clearRect( 0, 0, canvas.width, canvas.height );
-
- if ( pos.length > 3 ) {
-
- // draw mowing path color
- if ( div.getAttribute( 'data-mowingPathUseDots' ) ) {
-
- AutomowerConnectDrawDotColor ( ctx, div, pos, colorat );
-
- } else {
-
- AutomowerConnectDrawPathColor ( ctx, div, pos, colorat );
-
- }
-
- // draw start
- if ( div.getAttribute( 'data-mowingPathDisplayStart' ) ) {
- ctx.beginPath();
- ctx.setLineDash([]);
- ctx.lineWidth=3;
- ctx.strokeStyle = 'white';
- ctx.fillStyle= 'black';
- ctx.arc( parseInt( pos[ pos.length-3 ] ), parseInt( pos[ pos.length-2 ] ), 4, 0, 2 * Math.PI, false );
- ctx.fill();
- ctx.stroke();
- }
-
- // draw mower icon
- AutomowerConnectIcon( ctx, pos[0], pos[1], AutomowerConnectTor ( pos[3], pos[4], pos[0], pos[1] ), 'M' );
-
- }
-
- // draw error icon and path
- if ( errdesc[0] != '-' ) AutomowerConnectShowError( ctx, div, dev, picx, picy, errdesc, erray );
-
- } else {
- setTimeout(()=>{
-// log('loop: canvas false '+ type+' '+dev );
- AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, scalx, errdesc, pos, erray);
- }, 100);
}
+
+ const ctx = canvas.getContext( '2d' );
+ ctx.clearRect( 0, 0, canvas.width, canvas.height );
+
+ if ( pos.length > 3 ) {
+
+ // draw mowing path color
+ if ( div.getAttribute( 'data-mowingPathUseDots' ) ) {
+
+ AutomowerConnectDrawDotColor ( ctx, div, pos, colorat );
+
+ } else {
+
+ AutomowerConnectDrawPathColor ( ctx, div, pos, colorat );
+
+ }
+
+ // draw start
+ if ( div.getAttribute( 'data-mowingPathDisplayStart' ) ) {
+ ctx.beginPath();
+ ctx.setLineDash([]);
+ ctx.lineWidth=3;
+ ctx.strokeStyle = 'white';
+ ctx.fillStyle= 'black';
+ ctx.arc( parseInt( pos[ pos.length-3 ] ), parseInt( pos[ pos.length-2 ] ), 4, 0, 2 * Math.PI, false );
+ ctx.fill();
+ ctx.stroke();
+ }
+
+ // draw mower icon
+ AutomowerConnectIcon( ctx, pos[0], pos[1], AutomowerConnectTor ( pos[3], pos[4], pos[0], pos[1] ), 'M' );
+
+ }
+
+ // draw error icon and path
+ if ( errdesc[0] != '-' ) AutomowerConnectShowError( ctx, div, dev, picx, picy, errdesc, erray );
+
} else {
setTimeout(()=>{
-// log('loop: detail false '+ type+' '+dev );
+ log('AutomowerConnectUpdateDetail loop: div && canvas && canvas_0 false '+ type+' '+dev );
AutomowerConnectUpdateDetail (dev, type, detailfnfirst, picx, picy, scalx, errdesc, pos, erray);
}, 100);
}