From 01e1a0df6708aeab4364bbcaada81d008a9b0ab0 Mon Sep 17 00:00:00 2001 From: Ellert <> Date: Sun, 25 Jun 2023 11:44:25 +0000 Subject: [PATCH] 74_AutomowerConnect: Common.pm, automowerconnect.js, fix problem with empty positions array, java script cleanup git-svn-id: https://svn.fhem.de/fhem/trunk@27706 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 2 + fhem/lib/FHEM/Devices/AMConnect/Common.pm | 143 +++++++++++----------- fhem/www/pgm2/automowerconnect.js | 128 +++++++++---------- 3 files changed, 132 insertions(+), 141 deletions(-) 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); }