mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 09:16:53 +00:00
AutomowerConnect(Device): add features getter, reduce readings
git-svn-id: https://svn.fhem.de/fhem/trunk@27151 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
eb52154588
commit
8a2106c257
@ -1,12 +1,15 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# 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.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- feature: 74_AutomowerConnect: reduce readings, new getter for error codes
|
||||||
|
and internal data, show mower path without registered image
|
||||||
|
- feature: 75_AutomowerConnectDevice: same as AutomowerConnect
|
||||||
- feature: 72_FB_CALLMONITOR: tellows.de integriert
|
- feature: 72_FB_CALLMONITOR: tellows.de integriert
|
||||||
kleinere Korrekturen
|
kleinere Korrekturen
|
||||||
commandRef überarbeitet / ergänzt
|
commandRef überarbeitet / ergänzt
|
||||||
- feature: 59_Weather: mod packages, add new modul path in to pre-commit
|
- feature: 59_Weather: mod packages, add new modul path in to pre-commit
|
||||||
- bugfix: 00_KNXIO: PBP fixes
|
- bugfix: 00_KNXIO: PBP fixes
|
||||||
- bugfix: 10_KNX: fix define-parsing problem, PBP fixes
|
- bugfix: 10_KNX: fix define-parsing problem, PBP fixes
|
||||||
- bugfix: 74_AutomowerConnect: improved error handling, fix missig password bug
|
- bugfix: 74_AutomowerConnect: improved error handling, fix missig passwd bug
|
||||||
- feature: 74_AutomowerConnect: add disabledForIntervals, Internal MODEL
|
- feature: 74_AutomowerConnect: add disabledForIntervals, Internal MODEL
|
||||||
- feature: 75_AutomowerConnectDevice: add disabledForIntervals, Internal MODEL
|
- feature: 75_AutomowerConnectDevice: add disabledForIntervals, Internal MODEL
|
||||||
- bugfix: 98_WeekdayTimer: !$we handling
|
- bugfix: 98_WeekdayTimer: !$we handling
|
||||||
|
@ -50,6 +50,8 @@ BEGIN {
|
|||||||
IsDisabled
|
IsDisabled
|
||||||
Log3
|
Log3
|
||||||
Log
|
Log
|
||||||
|
minNum
|
||||||
|
maxNum
|
||||||
readingFnAttributes
|
readingFnAttributes
|
||||||
readingsBeginUpdate
|
readingsBeginUpdate
|
||||||
readingsBulkUpdate
|
readingsBulkUpdate
|
||||||
@ -147,6 +149,14 @@ sub Define{
|
|||||||
mowerNumber => $mowerNumber,
|
mowerNumber => $mowerNumber,
|
||||||
scaleToMeterLongitude => 67425,
|
scaleToMeterLongitude => 67425,
|
||||||
scaleToMeterLatitude => 108886,
|
scaleToMeterLatitude => 108886,
|
||||||
|
minLon => 180,
|
||||||
|
maxLon => -180,
|
||||||
|
minLat => 90,
|
||||||
|
maxLat => -90,
|
||||||
|
imageHeight => 650,
|
||||||
|
imageWidthHeight => '350 650',
|
||||||
|
posMinMax => "-180 90\n 180 -90",
|
||||||
|
newdatasets => 0,
|
||||||
client_id => $client_id,
|
client_id => $client_id,
|
||||||
grant_type => 'client_credentials',
|
grant_type => 'client_credentials',
|
||||||
MAP_PATH => '',
|
MAP_PATH => '',
|
||||||
@ -175,7 +185,7 @@ sub Define{
|
|||||||
},
|
},
|
||||||
CHARGING => {
|
CHARGING => {
|
||||||
arrayName => 'cspos',
|
arrayName => 'cspos',
|
||||||
maxLength => 500,
|
maxLength => 100,
|
||||||
callFn => \&ChargingStationPosition
|
callFn => \&ChargingStationPosition
|
||||||
},
|
},
|
||||||
LEAVING => {
|
LEAVING => {
|
||||||
@ -185,7 +195,7 @@ sub Define{
|
|||||||
},
|
},
|
||||||
PARKED_IN_CS => {
|
PARKED_IN_CS => {
|
||||||
arrayName => 'cspos',
|
arrayName => 'cspos',
|
||||||
maxLength => 50,
|
maxLength => 100,
|
||||||
callFn => \&ChargingStationPosition
|
callFn => \&ChargingStationPosition
|
||||||
},
|
},
|
||||||
STOPPED_IN_GARDEN => {
|
STOPPED_IN_GARDEN => {
|
||||||
@ -196,13 +206,10 @@ sub Define{
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
# my $helper = retrieve( $name.'_helper' );
|
|
||||||
# my $hashhelper = $hash->{helper};
|
|
||||||
# %$hashhelper = (%$helper, %$hashhelper);
|
|
||||||
|
|
||||||
my $errorjson = <<'EOF';
|
my $errorjson = <<'EOF';
|
||||||
{"23":"Wheel drive problem, left","24":"Cutting system blocked","123":"Destination not reachable","710":"SIM card locked","50":"Guide 1 not found","717":"SMS could not be sent","108":"Folding cutting deck sensor defect","4":"Loop sensor problem, front","15":"Lifted","29":"Slope too steep","1":"Outside working area","45":"Cutting height problem, dir","52":"Guide 3 not found","28":"Memory circuit problem","95":"Folding sensor activated","9":"Trapped","114":"Too high discharge current","103":"Cutting drive motor 2 defect","65":"Temporary battery problem","119":"Zone generator problem","6":"Loop sensor problem, left","82":"Wheel motor blocked, rear right","714":"Geofence problem","703":"Connectivity problem","708":"SIM card locked","75":"Connection changed","7":"Loop sensor problem, right","35":"Wheel motor overloaded, right","3":"Wrong loop signal","117":"High internal power loss","0":"Unexpected error","80":"Cutting system imbalance - Warning","110":"Collision sensor error","100":"Ultrasonic Sensor 3 defect","79":"Invalid battery combination - Invalid combination of different battery types.","724":"Communication circuit board SW must be updated","86":"Wheel motor overloaded, rear right","81":"Safety function faulty","78":"Slipped - Mower has Slipped.Situation not solved with moving pattern","107":"Docking sensor defect","33":"Mower tilted","69":"Alarm! Mower switched off","68":"Temporary battery problem","34":"Cutting stopped - slope too steep","127":"Battery problem","73":"Alarm! Mower in motion","74":"Alarm! Outside geofence","713":"Geofence problem","87":"Wheel motor overloaded, rear left","120":"Internal voltage error","39":"Cutting motor problem","704":"Connectivity problem","63":"Temporary battery problem","109":"Loop sensor defect","38":"Electronic problem","64":"Temporary battery problem","113":"Complex working area","93":"No accurate position from satellites","104":"Cutting drive motor 3 defect","709":"SIM card not found","94":"Reference station communication problem","43":"Cutting height problem, drive","13":"No drive","44":"Cutting height problem, curr","118":"Charging system problem","14":"Mower lifted","57":"Guide calibration failed","707":"SIM card requires PIN","99":"Ultrasonic Sensor 2 defect","98":"Ultrasonic Sensor 1 defect","51":"Guide 2 not found","56":"Guide calibration accomplished","49":"Ultrasonic problem","2":"No loop signal","124":"Destination blocked","25":"Cutting system blocked","19":"Collision sensor problem, front","18":"Collision sensor problem, rear","48":"No response from charger","105":"Lift Sensor defect","111":"No confirmed position","10":"Upside down","40":"Limited cutting height range","716":"Connectivity problem","27":"Settings restored","90":"No power in charging station","21":"Wheel motor blocked, left","26":"Invalid sub-device combination","92":"Work area not valid","702":"Connectivity settings restored","125":"Battery needs replacement","5":"Loop sensor problem, rear","12":"Empty battery","55":"Difficult finding home","42":"Limited cutting height range","30":"Charging system problem","72":"Alarm! Mower tilted","85":"Wheel drive problem, rear left","8":"Wrong PIN code","62":"Temporary battery problem","102":"Cutting drive motor 1 defect","116":"High charging power loss","122":"CAN error","60":"Temporary battery problem","705":"Connectivity problem","711":"SIM card locked","70":"Alarm! Mower stopped","32":"Tilt sensor problem","37":"Charging current too high","89":"Invalid system configuration","76":"Connection NOT changed","71":"Alarm! Mower lifted","88":"Angular sensor problem","701":"Connectivity problem","715":"Connectivity problem","61":"Temporary battery problem","66":"Battery problem","106":"Collision sensor defect","67":"Battery problem","112":"Cutting system major imbalance","83":"Wheel motor blocked, rear left","84":"Wheel drive problem, rear right","126":"Battery near end of life","77":"Com board not available","36":"Wheel motor overloaded, left","31":"STOP button problem","17":"Charging station blocked","54":"Weak GPS signal","47":"Cutting height problem","53":"GPS navigation problem","121":"High internal temerature","97":"Left brush motor overloaded","712":"SIM card locked","20":"Wheel motor blocked, right","91":"Switch cord problem","96":"Right brush motor overloaded","58":"Temporary battery problem","59":"Temporary battery problem","22":"Wheel drive problem, right","706":"Poor signal quality","41":"Unexpected cutting height adj","46":"Cutting height blocked","11":"Low battery","16":"Stuck in charging station","101":"Ultrasonic Sensor 4 defect","115":"Too high internal current"}
|
{"23":"Wheel drive problem, left","24":"Cutting system blocked","123":"Destination not reachable","710":"SIM card locked","50":"Guide 1 not found","717":"SMS could not be sent","108":"Folding cutting deck sensor defect","4":"Loop sensor problem, front","15":"Lifted","29":"Slope too steep","1":"Outside working area","45":"Cutting height problem, dir","52":"Guide 3 not found","28":"Memory circuit problem","95":"Folding sensor activated","9":"Trapped","114":"Too high discharge current","103":"Cutting drive motor 2 defect","65":"Temporary battery problem","119":"Zone generator problem","6":"Loop sensor problem, left","82":"Wheel motor blocked, rear right","714":"Geofence problem","703":"Connectivity problem","708":"SIM card locked","75":"Connection changed","7":"Loop sensor problem, right","35":"Wheel motor overloaded, right","3":"Wrong loop signal","117":"High internal power loss","0":"Unexpected error","80":"Cutting system imbalance - Warning","110":"Collision sensor error","100":"Ultrasonic Sensor 3 defect","79":"Invalid battery combination - Invalid combination of different battery types.","724":"Communication circuit board SW must be updated","86":"Wheel motor overloaded, rear right","81":"Safety function faulty","78":"Slipped - Mower has Slipped.Situation not solved with moving pattern","107":"Docking sensor defect","33":"Mower tilted","69":"Alarm! Mower switched off","68":"Temporary battery problem","34":"Cutting stopped - slope too steep","127":"Battery problem","73":"Alarm! Mower in motion","74":"Alarm! Outside geofence","713":"Geofence problem","87":"Wheel motor overloaded, rear left","120":"Internal voltage error","39":"Cutting motor problem","704":"Connectivity problem","63":"Temporary battery problem","109":"Loop sensor defect","38":"Electronic problem","64":"Temporary battery problem","113":"Complex working area","93":"No accurate position from satellites","104":"Cutting drive motor 3 defect","709":"SIM card not found","94":"Reference station communication problem","43":"Cutting height problem, drive","13":"No drive","44":"Cutting height problem, curr","118":"Charging system problem","14":"Mower lifted","57":"Guide calibration failed","707":"SIM card requires PIN","99":"Ultrasonic Sensor 2 defect","98":"Ultrasonic Sensor 1 defect","51":"Guide 2 not found","56":"Guide calibration accomplished","49":"Ultrasonic problem","2":"No loop signal","124":"Destination blocked","25":"Cutting system blocked","19":"Collision sensor problem, front","18":"Collision sensor problem, rear","48":"No response from charger","105":"Lift Sensor defect","111":"No confirmed position","10":"Upside down","40":"Limited cutting height range","716":"Connectivity problem","27":"Settings restored","90":"No power in charging station","21":"Wheel motor blocked, left","26":"Invalid sub-device combination","92":"Work area not valid","702":"Connectivity settings restored","125":"Battery needs replacement","5":"Loop sensor problem, rear","12":"Empty battery","55":"Difficult finding home","42":"Limited cutting height range","30":"Charging system problem","72":"Alarm! Mower tilted","85":"Wheel drive problem, rear left","8":"Wrong PIN code","62":"Temporary battery problem","102":"Cutting drive motor 1 defect","116":"High charging power loss","122":"CAN error","60":"Temporary battery problem","705":"Connectivity problem","711":"SIM card locked","70":"Alarm! Mower stopped","32":"Tilt sensor problem","37":"Charging current too high","89":"Invalid system configuration","76":"Connection NOT changed","71":"Alarm! Mower lifted","88":"Angular sensor problem","701":"Connectivity problem","715":"Connectivity problem","61":"Temporary battery problem","66":"Battery problem","106":"Collision sensor defect","67":"Battery problem","112":"Cutting system major imbalance","83":"Wheel motor blocked, rear left","84":"Wheel drive problem, rear right","126":"Battery near end of life","77":"Com board not available","36":"Wheel motor overloaded, left","31":"STOP button problem","17":"Charging station blocked","54":"Weak GPS signal","47":"Cutting height problem","53":"GPS navigation problem","121":"High internal temerature","97":"Left brush motor overloaded","712":"SIM card locked","20":"Wheel motor blocked, right","91":"Switch cord problem","96":"Right brush motor overloaded","58":"Temporary battery problem","59":"Temporary battery problem","22":"Wheel drive problem, right","706":"Poor signal quality","41":"Unexpected cutting height adj","46":"Cutting height blocked","11":"Low battery","16":"Stuck in charging station","101":"Ultrasonic Sensor 4 defect","115":"Too high internal current"}
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
my $errortable = eval { decode_json ($errorjson) };
|
my $errortable = eval { decode_json ($errorjson) };
|
||||||
if ($@) {
|
if ($@) {
|
||||||
return "$iam $@";
|
return "$iam $@";
|
||||||
@ -434,11 +441,11 @@ sub getMowerResponse {
|
|||||||
}
|
}
|
||||||
Log3 $name, 5, "$iam found $foundMower ";
|
Log3 $name, 5, "$iam found $foundMower ";
|
||||||
|
|
||||||
if ( defined ($hash->{helper}{mower}{id}) ){
|
if ( defined ($hash->{helper}{mower}{id}) ){ # update dataset
|
||||||
|
|
||||||
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mower} );
|
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mower} );
|
||||||
|
|
||||||
} else {
|
} else { # first data set
|
||||||
|
|
||||||
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mowers}[$mowerNumber] );
|
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mowers}[$mowerNumber] );
|
||||||
|
|
||||||
@ -451,9 +458,17 @@ sub getMowerResponse {
|
|||||||
$hash->{helper}{cspos} = [ dclone( $hash->{helper}{mowerold}{attributes}{positions}[0] ), dclone( $hash->{helper}{mowerold}{attributes}{positions}[1] ) ];
|
$hash->{helper}{cspos} = [ dclone( $hash->{helper}{mowerold}{attributes}{positions}[0] ), dclone( $hash->{helper}{mowerold}{attributes}{positions}[1] ) ];
|
||||||
$hash->{helper}{cspos}[0]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
$hash->{helper}{cspos}[0]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
||||||
$hash->{helper}{cspos}[1]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp} - 600000;
|
$hash->{helper}{cspos}[1]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp} - 600000;
|
||||||
|
|
||||||
|
if ( AttrVal( $name, 'mapImageCoordinatesToRegister', '' ) eq '' ) {
|
||||||
|
posMinMax( $hash, $hash->{helper}{mowerold}{attributes}{positions} );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash->{helper}{mower} = dclone( $hash->{helper}{mowers}[$mowerNumber] );
|
$hash->{helper}{mower} = dclone( $hash->{helper}{mowers}[$mowerNumber] );
|
||||||
|
# add alignment data set to the end
|
||||||
|
push( @{ $hash->{helper}{mower}{attributes}{positions} }, @{ dclone( $hash->{helper}{searchpos} ) } );
|
||||||
|
|
||||||
my $storediff = $hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
my $storediff = $hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
||||||
if ($storediff) {
|
if ($storediff) {
|
||||||
|
|
||||||
@ -510,8 +525,7 @@ sub getMowerResponse {
|
|||||||
readingsBulkUpdateIfChanged($hash, $pref."_TimestampDiff", $storediff/1000 );
|
readingsBulkUpdateIfChanged($hash, $pref."_TimestampDiff", $storediff/1000 );
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_TimestampOld", FmtDateTime( $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp}/1000 ));
|
readingsBulkUpdateIfChanged($hash, $pref."_TimestampOld", FmtDateTime( $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp}/1000 ));
|
||||||
$pref = 'positions';
|
$pref = 'positions';
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_lastLatitude", $hash->{helper}{mower}{attributes}{$pref}[0]{latitude} );
|
readingsBulkUpdateIfChanged($hash, $pref."_lastLonLat", $hash->{helper}{mower}{attributes}{$pref}[0]{longitude} . ' ' . $hash->{helper}{mower}{attributes}{$pref}[0]{latitude} );
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_lastLongitude", $hash->{helper}{mower}{attributes}{$pref}[0]{longitude} );
|
|
||||||
readingsBulkUpdateIfChanged($hash, 'state', 'connected' );
|
readingsBulkUpdateIfChanged($hash, 'state', 'connected' );
|
||||||
|
|
||||||
my @time = localtime();
|
my @time = localtime();
|
||||||
@ -684,9 +698,24 @@ sub Get {
|
|||||||
Log3 $name, 4, "$iam called with $setName " . ($setVal ? $setVal : "");
|
Log3 $name, 4, "$iam called with $setName " . ($setVal ? $setVal : "");
|
||||||
|
|
||||||
if ( $setName eq 'html' ) {
|
if ( $setName eq 'html' ) {
|
||||||
|
|
||||||
my $ret = '<html>' . FW_detailFn( undef, $name, undef, undef) . '</html>';
|
my $ret = '<html>' . FW_detailFn( undef, $name, undef, undef) . '</html>';
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
|
} elsif ( $setName eq 'listErrorCodes' ) {
|
||||||
|
|
||||||
|
my $ret = listErrorCodes($hash);
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
} elsif ( $setName eq 'listInternalData' ) {
|
||||||
|
|
||||||
|
my $ret = listInternalData($hash);
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return "Unknown argument $setName, choose one of listErrorCodes:noArg listInternalData:noArg ";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -710,7 +739,8 @@ sub Set {
|
|||||||
|
|
||||||
} elsif ( $setName eq 'chargingStationPositionToAttribute' ) {
|
} elsif ( $setName eq 'chargingStationPositionToAttribute' ) {
|
||||||
|
|
||||||
my ($xm, $ym, $n) = split(/,\s/,ReadingsVal($name,'status_calcChargingStationPositionXYn','10.1165, 51.28, 0'));
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
|
||||||
CommandAttr($hash,"$name chargingStationCoordinates $xm $ym");
|
CommandAttr($hash,"$name chargingStationCoordinates $xm $ym");
|
||||||
return undef;
|
return undef;
|
||||||
|
|
||||||
@ -774,12 +804,12 @@ sub FW_detailFn {
|
|||||||
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my $type = $hash->{TYPE};
|
my $type = $hash->{TYPE};
|
||||||
return undef if( AttrVal($name, 'disable', 0) || !AttrVal($name, 'showMap', 1) );
|
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 ) {
|
if ( $hash->{helper} && $hash->{helper}{mower} && $hash->{helper}{mower}{attributes} && $hash->{helper}{mower}{attributes}{positions} && @{$hash->{helper}{mower}{attributes}{positions}} > 0 ) {
|
||||||
my $img = "./fhem/$type/$name/map";
|
my $img = "./fhem/$type/$name/map";
|
||||||
my $zoom=AttrVal($name,"mapImageZoom",0.7);
|
my $zoom=AttrVal( $name,"mapImageZoom", 0.7 );
|
||||||
|
|
||||||
AttrVal($name,"mapImageWidthHeight",'100 200') =~ /(\d+)\s(\d+)/;
|
AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
|
||||||
my ($picx,$picy) = ($1, $2);
|
my ($picx,$picy) = ($1, $2);
|
||||||
|
|
||||||
$picx=int($picx*$zoom);
|
$picx=int($picx*$zoom);
|
||||||
@ -794,7 +824,7 @@ sub FW_detailFn {
|
|||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
return undef;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
@ -806,17 +836,16 @@ sub FW_detailFn_Update {
|
|||||||
|
|
||||||
my @pos = ();
|
my @pos = ();
|
||||||
my @posc = ();
|
my @posc = ();
|
||||||
# @pos = @{$hash->{helper}{mower}{attributes}{positions}}; # developement mode
|
|
||||||
@pos = @{$hash->{helper}{areapos}}; # operational mode
|
@pos = @{$hash->{helper}{areapos}}; # operational mode
|
||||||
@posc =@{$hash->{helper}{cspos}}; # maybe operational mode
|
@posc =@{$hash->{helper}{cspos}}; # maybe operational mode
|
||||||
my $img = "./fhem/$type/$name/map";
|
my $img = "./fhem/$type/$name/map";
|
||||||
|
|
||||||
AttrVal($name,"mapImageCoordinatesToRegister","0 90\n90 0") =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,"mapImageCoordinatesToRegister",$hash->{helper}{posMinMax} ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|-?\s)(\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ( $lonlo, $latlo, $lonru, $latru ) = ($1, $2, $4, $5);
|
my ( $lonlo, $latlo, $lonru, $latru ) = ( $1, $2, $4, $5 );
|
||||||
|
|
||||||
my $zoom = AttrVal($name,"mapImageZoom",0.7);
|
my $zoom = AttrVal( $name,"mapImageZoom", 0.7 );
|
||||||
|
|
||||||
AttrVal($name,"mapImageWidthHeight",'100 200') =~ /(\d+)\s(\d+)/;
|
AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
|
||||||
my ($picx,$picy) = ($1, $2);
|
my ($picx,$picy) = ($1, $2);
|
||||||
|
|
||||||
AttrVal($name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude}) =~ /(\d+)\s+(\d+)/;
|
AttrVal($name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude}) =~ /(\d+)\s+(\d+)/;
|
||||||
@ -833,17 +862,15 @@ sub FW_detailFn_Update {
|
|||||||
use strict "refs";
|
use strict "refs";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $csimgpos = AttrVal($name,"chargingStationImagePosition","right");
|
my $csimgpos = AttrVal( $name,"chargingStationImagePosition","right" );
|
||||||
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
|
||||||
|
|
||||||
AttrVal($name,"chargingStationCoordinates",'10.1165 51.28') =~ /(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,"chargingStationCoordinates","$xm $ym" ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ($cslo,$csla) = ($1, $2);
|
my ($cslo,$csla) = ($1, $2);
|
||||||
|
|
||||||
my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
|
my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
|
||||||
my $cslat = int(($latlo-$csla) * $picy / $mapy);
|
my $cslat = int(($latlo-$csla) * $picy / $mapy);
|
||||||
# my $lon = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx);
|
|
||||||
# my $lat = int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
|
||||||
# my $lastx = int(($lonlo-$pos[$#pos]{longitude}) * $picx / $mapx);
|
|
||||||
# my $lasty = int(($latlo-$pos[$#pos]{latitude}) * $picy / $mapy);
|
|
||||||
|
|
||||||
# MOWING PATH
|
# MOWING PATH
|
||||||
my $posxy = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx).",".int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
my $posxy = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx).",".int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
||||||
@ -977,10 +1004,10 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
if ( AttrVal( $name,'mapImageCoordinatesToRegister', '' ) && $attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/ ) {
|
if ( AttrVal( $name,'mapImageCoordinatesToRegister', '' ) && $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ ) {
|
||||||
|
|
||||||
my ( $x1, $y1, $x2, $y2 ) = ( $1, $2, $4, $5 );
|
my ( $x1, $y1, $x2, $y2 ) = ( $1, $2, $4, $5 );
|
||||||
AttrVal( $name,'mapImageCoordinatesToRegister', '' ) =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,'mapImageCoordinatesToRegister', '' ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ( $lo1, $la1, $lo2, $la2 ) = ( $1, $2, $4, $5 );
|
my ( $lo1, $la1, $lo2, $la2 ) = ( $1, $2, $4, $5 );
|
||||||
my $scx = int( ( $x1 - $x2) / ( $lo1 - $lo2 ) );
|
my $scx = int( ( $x1 - $x2) / ( $lo1 - $lo2 ) );
|
||||||
my $scy = int( ( $y1 - $y2 ) / ( $la1 - $la2 ) );
|
my $scy = int( ( $y1 - $y2 ) / ( $la1 - $la2 ) );
|
||||||
@ -1001,7 +1028,7 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use linewise pairs <floating point longitude><one space character><floating point latitude>" unless($attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/);
|
return "$iam $attrName has a wrong format use linewise pairs <floating point longitude><one space character><floating point latitude>" unless( $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
@ -1014,7 +1041,7 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use <floating point longitude><one space character><floating point latitude>" unless($attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)/);
|
return "$iam $attrName has a wrong format use <floating point longitude><one space character><floating point latitude>" unless( $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
@ -1027,7 +1054,7 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless($attrVal =~ /(\d+)\s(\d+)/);
|
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless( $attrVal =~ /(\d+)\s(\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
@ -1040,7 +1067,7 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless($attrVal =~ /(\d+)\s(\d+)/);
|
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless( $attrVal =~ /(\d+)\s(\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
@ -1124,13 +1151,13 @@ sub AlignArray {
|
|||||||
my $activity = $hash->{helper}{mower}{attributes}{mower}{activity};
|
my $activity = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||||
my $arrayName = $hash->{helper}{$activity}{arrayName};
|
my $arrayName = $hash->{helper}{$activity}{arrayName};
|
||||||
my $maxLength = $hash->{helper}{$activity}{maxLength};
|
my $maxLength = $hash->{helper}{$activity}{maxLength};
|
||||||
for ( $i = 0; $i < $poslen-1; $i++ ) {
|
for ( $i = 0; $i < $poslen-3; $i++ ) { # 3 instead of 1 due to new alignment
|
||||||
if ( $searchposlon[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{longitude}
|
if ( $searchposlon[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{longitude}
|
||||||
&& $searchposlat[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{latitude}
|
&& $searchposlat[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{latitude}
|
||||||
&& $searchposlon[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{longitude}
|
&& $searchposlon[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{longitude}
|
||||||
&& $searchposlat[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{latitude}
|
&& $searchposlat[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{latitude} ) {
|
||||||
|| $i == $poslen-2 ) {
|
# || $i == $poslen-2 ) { # not nessecary due to new alignment
|
||||||
$i++ if ($i == $poslen-2);
|
# $i++ if ( $i == $poslen-2 ); # not nessecary due to new alignment
|
||||||
# timediff per step
|
# timediff per step
|
||||||
my $dt = 0;
|
my $dt = 0;
|
||||||
$dt = int(($hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{$arrayName}[0]{statusTimestamp})/$i) if ($i);
|
$dt = int(($hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{$arrayName}[0]{statusTimestamp})/$i) if ($i);
|
||||||
@ -1142,16 +1169,29 @@ sub AlignArray {
|
|||||||
|
|
||||||
unshift (@{$hash->{helper}{searchpos}}, dclone($hash->{helper}{mower}{attributes}{positions}[ $k ]) );
|
unshift (@{$hash->{helper}{searchpos}}, dclone($hash->{helper}{mower}{attributes}{positions}[ $k ]) );
|
||||||
pop (@{$hash->{helper}{searchpos}}) if (@{$hash->{helper}{searchpos}} > $searchlen);
|
pop (@{$hash->{helper}{searchpos}}) if (@{$hash->{helper}{searchpos}} > $searchlen);
|
||||||
|
|
||||||
|
my @temp = ();
|
||||||
|
unshift ( @temp, dclone( $hash->{helper}{mower}{attributes}{positions}[ $k ] ) );
|
||||||
|
posMinMax( $hash, \@temp );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#callFn if present
|
#callFn if present
|
||||||
if ($hash->{helper}{$activity}{callFn}) {
|
if ($hash->{helper}{$activity}{callFn}) {
|
||||||
|
|
||||||
$hash->{helper}{$activity}{cnt} = $i;
|
$hash->{helper}{$activity}{cnt} = $i;
|
||||||
no strict "refs";
|
no strict "refs";
|
||||||
&{$hash->{helper}{$activity}{callFn}}($hash);
|
&{$hash->{helper}{$activity}{callFn}}($hash);
|
||||||
use strict "refs";
|
use strict "refs";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash->{helper}{newdatasets} = $i;
|
||||||
|
readingsSingleUpdate($hash, "statistics_newGeoDataSets", $i, 1);
|
||||||
last;
|
last;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1166,13 +1206,11 @@ sub ChargingStationPosition {
|
|||||||
my $ym = 0;
|
my $ym = 0;
|
||||||
map { $ym += $_->{latitude} } @{$hash->{helper}{cspos}};
|
map { $ym += $_->{latitude} } @{$hash->{helper}{cspos}};
|
||||||
$ym = $ym/$n;
|
$ym = $ym/$n;
|
||||||
$hash->{helper}{chargingStation}{longitude} = $xm;
|
$hash->{helper}{chargingStation}{longitude} = sprintf("%.8f",$xm);
|
||||||
$hash->{helper}{chargingStation}{latitude} = $ym;
|
$hash->{helper}{chargingStation}{latitude} = sprintf("%.8f",$ym);
|
||||||
readingsSingleUpdate($hash, "statistics_ChargingStationPositionXYn", (int($xm * 10000000 + 0.5) / 10000000).", ".(int($ym * 10000000 + 0.5) / 10000000).", ".$n, 0);
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
sub AreaStatistics {
|
sub AreaStatistics {
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
@ -1192,7 +1230,7 @@ sub AreaStatistics {
|
|||||||
}
|
}
|
||||||
$asum = $lsum * AttrVal($name,'mowerCuttingWidth',0.24);
|
$asum = $lsum * AttrVal($name,'mowerCuttingWidth',0.24);
|
||||||
my $td = $xyarr[ 0 ]{storedTimestamp} - $xyarr[ $k ]{storedTimestamp};
|
my $td = $xyarr[ 0 ]{storedTimestamp} - $xyarr[ $k ]{storedTimestamp};
|
||||||
$vm = int($lsum / $td * 1000000 + 0.5)/1000 if ($td);
|
$vm = sprintf( '%.6f', $lsum / $td ) * 1000 if ($td);
|
||||||
$lsum += int( ReadingsNum( $name, 'statistics_currentDayTrack', 0 ) );
|
$lsum += int( ReadingsNum( $name, 'statistics_currentDayTrack', 0 ) );
|
||||||
$asum += int( ReadingsNum( $name, 'statistics_currentDayArea', 0 ) );
|
$asum += int( ReadingsNum( $name, 'statistics_currentDayArea', 0 ) );
|
||||||
readingsBeginUpdate($hash);
|
readingsBeginUpdate($hash);
|
||||||
@ -1275,6 +1313,114 @@ sub readMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub posMinMax {
|
||||||
|
my ($hash, $poshash) = @_;
|
||||||
|
my $minLon = $hash->{helper}{minLon};
|
||||||
|
my $maxLon = $hash->{helper}{maxLon};
|
||||||
|
my $minLat = $hash->{helper}{minLat};
|
||||||
|
my $maxLat = $hash->{helper}{maxLat};
|
||||||
|
|
||||||
|
for ( @{$poshash} ) {
|
||||||
|
$minLon = minNum( $minLon,$_->{longitude} );
|
||||||
|
$maxLon = maxNum( $maxLon,$_->{longitude} );
|
||||||
|
$minLat = minNum( $minLat,$_->{latitude} );
|
||||||
|
$maxLat = maxNum( $maxLat,$_->{latitude} );
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{helper}{minLon} = $minLon;
|
||||||
|
$hash->{helper}{maxLon} = $maxLon;
|
||||||
|
$hash->{helper}{minLat} = $minLat;
|
||||||
|
$hash->{helper}{maxLat} = $maxLat;
|
||||||
|
$hash->{helper}{posMinMax} = "$minLon $maxLat\n$maxLon $minLat";
|
||||||
|
$hash->{helper}{imageWidthHeight} = int($hash->{helper}{imageHeight} * ($maxLon-$minLon) / ($maxLat-$minLat)) . ' ' . $hash->{helper}{imageHeight} if ($maxLon-$minLon);
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub listInternalData {
|
||||||
|
my ( $hash ) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $rowCount = 1;
|
||||||
|
my $ret = '<html><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Calculated Coordinates For Automatic Registration</b></caption><tbody>';
|
||||||
|
|
||||||
|
$hash->{helper}{posMinMax} =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|-?\s)(\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
|
|
||||||
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 0;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 0;
|
||||||
|
my $csnr = scalar @{$hash->{helper}{cspos}};
|
||||||
|
my $csnrmax = $hash->{helper}{PARKED_IN_CS}{maxLength};
|
||||||
|
my $arnr = 0;
|
||||||
|
$arnr = scalar @{$hash->{helper}{areapos}} if( scalar @{$hash->{helper}{areapos}} > 2 );
|
||||||
|
my $arnrmax = $hash->{helper}{MOWING}{maxLength};
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Data Sets ( max ) </td><td> Corner </td><td> Longitude </td><td> Latitude </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td rowspan="2" style="vertical-align:middle;" > ' . ($csnr + $arnr) . ' ( ' . ($csnrmax + $arnrmax) . ' ) </td><td> Upper Left </td><td> ' . $1 . ' </td><td> ' . $2 . ' </td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td> Lower Right </td><td> ' . $4 . ' </td><td> ' . $5 . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table><p>';
|
||||||
|
$ret .= '<table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Calculated Charging Station Coordinates</b></caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Data Sets (max) </td><td> Longitude </td><td> Latitude </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td> ' . $csnr . ' ( ' . $csnrmax . ' ) </td><td> ' . $xm . ' </td><td> ' . $ym . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table><p>';
|
||||||
|
$ret .= '<table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Way Point Stacks</b></caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Used For Action </td><td> Stack Name </td><td> Current Size </td><td> Max Size </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td>PARKED_IN_CS, CHARGING </td><td> cspos </td><td> ' . $csnr . ' </td><td> ' . $csnrmax . ' </td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td>MOWING </td><td> areapos </td><td> ' . $arnr . ' </td><td> ' . $arnrmax . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table>';
|
||||||
|
if ( $hash->{TYPE} eq 'AutomowerConnect' ) {
|
||||||
|
|
||||||
|
$ret .= '<p><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Access Token</b> ( expires: ' . ReadingsVal( $name, 'api_token_expires', 'none') . ' ) </caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="column odd"><td style="word-wrap:break-word; max-width:40em">' . ReadingsVal( $name, '.access_token', 'none') . '</td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table>';
|
||||||
|
|
||||||
|
}
|
||||||
|
$ret .= '</html>';
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub listErrorCodes {
|
||||||
|
my ( $hash ) = @_;
|
||||||
|
my $rowCount = 1;
|
||||||
|
my %ec = ();
|
||||||
|
my $ec = \%ec;
|
||||||
|
for ( keys %{$hash->{helper}{errortable}} ) {
|
||||||
|
$ec->{sprintf("%03d",$_)} = $hash->{helper}{errortable}{$_} ;
|
||||||
|
}
|
||||||
|
my $ret = '<html><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>API-Response Status Codes</b></caption><tbody>';
|
||||||
|
$ret .= '<tr class="column odd"><td>200, 201, 202<br>204</td><td>response o.k.</td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td>400, 401, 402<br>403, 404, 415<br>500, 503</td><td>error, detailed information see logfile</td></tr>';
|
||||||
|
$ret .= '</tbody></table><p><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Mower Error Table</b></caption><tbody>';
|
||||||
|
for (sort keys %{$ec}) {
|
||||||
|
$ret .= '<tr class="column ';
|
||||||
|
$ret .= ( $rowCount % 2 ? "odd" : "even" );
|
||||||
|
$ret .= '"><td>';
|
||||||
|
$ret .= $_;
|
||||||
|
$ret .= '</td><td>';
|
||||||
|
$ret .= $ec->{$_};
|
||||||
|
$ret .= '</td></tr>';
|
||||||
|
$rowCount++;
|
||||||
|
}
|
||||||
|
$ret .= '</tbody></table></html>';
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
1;
|
1;
|
||||||
@ -1397,8 +1543,16 @@ sub readMap {
|
|||||||
<b>Get</b>
|
<b>Get</b>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a id='AutomowerConnect-get-html'>html</a><br>
|
<li><a id='AutomowerConnect-get-html'>html</a><br>
|
||||||
<code>get <name> html </code><br>
|
<code>get <name> html</code><br>
|
||||||
Returns the mower area image as html code. For use in uiTable, TabletUI, Floorplan, readingsGroup, weblink etc.</li>
|
Returns the mower area image as html code. For use in uiTable, TabletUI, Floorplan, readingsGroup, weblink etc.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listInternalData'>listInternalData</a><br>
|
||||||
|
<code>get <name> listInternalData</code><br>
|
||||||
|
Lists some device internal data</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listErrorCodes'>listErrorCodes</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Lists API response status codes and mower error codes</li>
|
||||||
<br><br>
|
<br><br>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
@ -1502,13 +1656,12 @@ sub readMap {
|
|||||||
<li>planner_nextStart - next start time</li>
|
<li>planner_nextStart - next start time</li>
|
||||||
<li>planner_restrictedReason - reason for parking NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
<li>planner_restrictedReason - reason for parking NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
||||||
<li>planner_overrideAction - reason for override a planned action NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
<li>planner_overrideAction - reason for override a planned action NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
||||||
<li>positions_lastLatitude - last known position (latitude)</li>
|
<li>positions_lastLonLat - last known position (longitude latitude)</li>
|
||||||
<li>positions_lastLongitude - last known position (longitude)</li>
|
|
||||||
<li>state - status of connection FHEM to Husqvarna Cloud API and device state(e.g. defined, authorization, authorized, connected, error, update)</li>
|
<li>state - status of connection FHEM to Husqvarna Cloud API and device state(e.g. defined, authorization, authorized, connected, error, update)</li>
|
||||||
<li>status_statusTimestampOld - local time of second last change of the API content</li>
|
<li>status_statusTimestampOld - local time of second last change of the API content</li>
|
||||||
<li>settings_cuttingHeight - actual cutting height from API</li>
|
<li>settings_cuttingHeight - actual cutting height from API</li>
|
||||||
<li>settings_headlight - actual headlight mode from API</li>
|
<li>settings_headlight - actual headlight mode from API</li>
|
||||||
<li>statistics_ChargingStationPositionXYn - calculated position of the carging station (longitude, latitude, number of datasets) during mower_activity PARKED_IN_CS and CHARGING</li>
|
<li>statistics_newGeoDataSets - number of new data sets between the last two different time stamps</li>
|
||||||
<li>statistics_numberOfChargingCycles - number of charging cycles</li>
|
<li>statistics_numberOfChargingCycles - number of charging cycles</li>
|
||||||
<li>statistics_numberOfCollisions - number of collisions</li>
|
<li>statistics_numberOfCollisions - number of collisions</li>
|
||||||
<li>statistics_totalChargingTime - total charging time in hours</li>
|
<li>statistics_totalChargingTime - total charging time in hours</li>
|
||||||
@ -1648,6 +1801,14 @@ sub readMap {
|
|||||||
<li><a id='AutomowerConnect-get-html'>html</a><br>
|
<li><a id='AutomowerConnect-get-html'>html</a><br>
|
||||||
<code>get <name> html </code><br>
|
<code>get <name> html </code><br>
|
||||||
Gibt das Bild des Mäherbereiches html kodiert zurück, zur Verwendung in uiTable, TabletUI, Floorplan, readingsGroup, weblink usw.</li>
|
Gibt das Bild des Mäherbereiches html kodiert zurück, zur Verwendung in uiTable, TabletUI, Floorplan, readingsGroup, weblink usw.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listErrorCodes'>listErrorCodes</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Listet die Statuscode der API-Anfrage und die Fehlercodes des Mähroboters auf.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listInternalData'>listInternalData</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Listet einige Daten des FHEM-Gerätes auf.</li>
|
||||||
<br><br>
|
<br><br>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
@ -1757,12 +1918,11 @@ sub readMap {
|
|||||||
<li>planner_nextStart - nächste Startzeit</li>
|
<li>planner_nextStart - nächste Startzeit</li>
|
||||||
<li>planner_restrictedReason - Grund für Parken NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
<li>planner_restrictedReason - Grund für Parken NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
||||||
<li>planner_overrideAction - Grund für vorrangige Aktion NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
<li>planner_overrideAction - Grund für vorrangige Aktion NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
||||||
<li>positions_lastLatitude - letzte bekannte Position (Breitengrad)</li>
|
<li>positions_lastLonLat - letzte bekannte Position (Längengrad Breitengrad)</li>
|
||||||
<li>positions_lastLongitude - letzte bekannte Position (Längengrad)</li>
|
<li>state - Status der Verbindung des FHEM-Gerätes zur Husqvarna Cloud API (defined, authentification, authentified, connected, error, update).</li>
|
||||||
<li>state - Status der Verbindung des FHEM-Gerätes zur Husqvarna Cloud API (defined, authorization, authorized, connected, error, update).</li>
|
|
||||||
<li>settings_cuttingHeight - aktuelle Schnitthöhe aus der API</li>
|
<li>settings_cuttingHeight - aktuelle Schnitthöhe aus der API</li>
|
||||||
<li>settings_headlight - aktueller Scheinwerfermode aus der API</li>
|
<li>settings_headlight - aktueller Scheinwerfermode aus der API</li>
|
||||||
<li>statistics_ChargingStationPositionXYn - berechnete Position der Ladestation mit den Werten Longitude, Latitude und Anzahl der verwendeten Datensätze wähend der Mower_activity PARKED_IN_CS und CHARGING</li>
|
<li>statistics_newGeoDataSets - Anzahl der neuen Datensätze zwischen den letzten zwei unterschiedlichen Zeitstempeln</li>
|
||||||
<li>statistics_numberOfChargingCycles - Anzahl der Ladezyklen</li>
|
<li>statistics_numberOfChargingCycles - Anzahl der Ladezyklen</li>
|
||||||
<li>statistics_numberOfCollisions - Anzahl der Kollisionen</li>
|
<li>statistics_numberOfCollisions - Anzahl der Kollisionen</li>
|
||||||
<li>statistics_totalChargingTime - Gesamtladezeit in Stunden</li>
|
<li>statistics_totalChargingTime - Gesamtladezeit in Stunden</li>
|
||||||
|
@ -46,6 +46,8 @@ BEGIN {
|
|||||||
InternalVal
|
InternalVal
|
||||||
IsDisabled
|
IsDisabled
|
||||||
Log3
|
Log3
|
||||||
|
minNum
|
||||||
|
maxNum
|
||||||
readingFnAttributes
|
readingFnAttributes
|
||||||
readingsBeginUpdate
|
readingsBeginUpdate
|
||||||
readingsBulkUpdate
|
readingsBulkUpdate
|
||||||
@ -76,7 +78,6 @@ my $missingModul = "";
|
|||||||
|
|
||||||
eval "use JSON;1" or $missingModul .= "JSON ";
|
eval "use JSON;1" or $missingModul .= "JSON ";
|
||||||
require HttpUtils;
|
require HttpUtils;
|
||||||
|
|
||||||
use constant AUTHURL => 'https://api.authentication.husqvarnagroup.dev/v1';
|
use constant AUTHURL => 'https://api.authentication.husqvarnagroup.dev/v1';
|
||||||
use constant APIURL => 'https://api.amc.husqvarna.dev/v1';
|
use constant APIURL => 'https://api.amc.husqvarna.dev/v1';
|
||||||
|
|
||||||
@ -141,6 +142,14 @@ sub Define{
|
|||||||
mowerNumber => $mowerNumber,
|
mowerNumber => $mowerNumber,
|
||||||
scaleToMeterLongitude => 67425,
|
scaleToMeterLongitude => 67425,
|
||||||
scaleToMeterLatitude => 108886,
|
scaleToMeterLatitude => 108886,
|
||||||
|
minLon => 180,
|
||||||
|
maxLon => -180,
|
||||||
|
minLat => 90,
|
||||||
|
maxLat => -90,
|
||||||
|
imageHeight => 650,
|
||||||
|
imageWidthHeight => '350 650',
|
||||||
|
posMinMax => "-180 90\n 180 -90",
|
||||||
|
newdatasets => 0,
|
||||||
MAP_PATH => '',
|
MAP_PATH => '',
|
||||||
MAP_MIME => '',
|
MAP_MIME => '',
|
||||||
MAP_CACHE => '',
|
MAP_CACHE => '',
|
||||||
@ -167,7 +176,7 @@ sub Define{
|
|||||||
},
|
},
|
||||||
CHARGING => {
|
CHARGING => {
|
||||||
arrayName => 'cspos',
|
arrayName => 'cspos',
|
||||||
maxLength => 500,
|
maxLength => 100,
|
||||||
callFn => \&ChargingStationPosition
|
callFn => \&ChargingStationPosition
|
||||||
},
|
},
|
||||||
LEAVING => {
|
LEAVING => {
|
||||||
@ -177,7 +186,7 @@ sub Define{
|
|||||||
},
|
},
|
||||||
PARKED_IN_CS => {
|
PARKED_IN_CS => {
|
||||||
arrayName => 'cspos',
|
arrayName => 'cspos',
|
||||||
maxLength => 50,
|
maxLength => 100,
|
||||||
callFn => \&ChargingStationPosition
|
callFn => \&ChargingStationPosition
|
||||||
},
|
},
|
||||||
STOPPED_IN_GARDEN => {
|
STOPPED_IN_GARDEN => {
|
||||||
@ -202,7 +211,7 @@ EOF
|
|||||||
$errortable = undef;
|
$errortable = undef;
|
||||||
|
|
||||||
$hash->{MODEL} = '';
|
$hash->{MODEL} = '';
|
||||||
$attr{$name}{room} = $type if( !defined( $attr{$name}{room} ) );
|
$attr{$name}{room} = 'AutomowerConnect' if( !defined( $attr{$name}{room} ) );
|
||||||
$attr{$name}{icon} = 'automower' if( !defined( $attr{$name}{icon} ) );
|
$attr{$name}{icon} = 'automower' if( !defined( $attr{$name}{icon} ) );
|
||||||
if (::AnalyzeCommandChain(undef,"version 75_AutomowerConnectDevice.pm noheader") =~ "^75_AutomowerConnectDevice.pm (.*)Z") {
|
if (::AnalyzeCommandChain(undef,"version 75_AutomowerConnectDevice.pm noheader") =~ "^75_AutomowerConnectDevice.pm (.*)Z") {
|
||||||
$hash->{VERSION}=$1;
|
$hash->{VERSION}=$1;
|
||||||
@ -255,11 +264,11 @@ sub Notify {
|
|||||||
|
|
||||||
my $mowerhash = $hosthash->{helper}{mowers}[$mowerNumber];
|
my $mowerhash = $hosthash->{helper}{mowers}[$mowerNumber];
|
||||||
my $myMower = dclone( $mowerhash );
|
my $myMower = dclone( $mowerhash );
|
||||||
if ( defined ($hash->{helper}{mower}{id}) ){
|
if ( defined ($hash->{helper}{mower}{id}) ){ # update dataset
|
||||||
|
|
||||||
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mower} );
|
$hash->{helper}{mowerold} = dclone( $hash->{helper}{mower} );
|
||||||
|
|
||||||
} else {
|
} else { # first data set
|
||||||
|
|
||||||
$hash->{helper}{mowerold} = $myMower;
|
$hash->{helper}{mowerold} = $myMower;
|
||||||
|
|
||||||
@ -272,9 +281,17 @@ sub Notify {
|
|||||||
$hash->{helper}{cspos} = [ dclone( $hash->{helper}{mowerold}{attributes}{positions}[0] ), dclone( $hash->{helper}{mowerold}{attributes}{positions}[1] ) ];
|
$hash->{helper}{cspos} = [ dclone( $hash->{helper}{mowerold}{attributes}{positions}[0] ), dclone( $hash->{helper}{mowerold}{attributes}{positions}[1] ) ];
|
||||||
$hash->{helper}{cspos}[0]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
$hash->{helper}{cspos}[0]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
||||||
$hash->{helper}{cspos}[1]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp} - 600000;
|
$hash->{helper}{cspos}[1]{statusTimestamp} = $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp} - 600000;
|
||||||
|
|
||||||
|
if ( AttrVal( $name, 'mapImageCoordinatesToRegister', '' ) eq '' ) {
|
||||||
|
posMinMax( $hash, $hash->{helper}{mowerold}{attributes}{positions} );
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash->{helper}{mower} = $myMower;
|
$hash->{helper}{mower} = $myMower;
|
||||||
|
# add alignment data set to the end
|
||||||
|
push( @{ $hash->{helper}{mower}{attributes}{positions} }, @{ dclone( $hash->{helper}{searchpos} ) } );
|
||||||
|
|
||||||
my $storediff = $hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
my $storediff = $hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp};
|
||||||
if ($storediff) {
|
if ($storediff) {
|
||||||
AlignArray( $hash );
|
AlignArray( $hash );
|
||||||
@ -330,8 +347,7 @@ sub Notify {
|
|||||||
readingsBulkUpdateIfChanged($hash, $pref."_TimestampDiff", $storediff/1000 );
|
readingsBulkUpdateIfChanged($hash, $pref."_TimestampDiff", $storediff/1000 );
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_TimestampOld", FmtDateTime( $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp}/1000 ));
|
readingsBulkUpdateIfChanged($hash, $pref."_TimestampOld", FmtDateTime( $hash->{helper}{mowerold}{attributes}{metadata}{statusTimestamp}/1000 ));
|
||||||
$pref = 'positions';
|
$pref = 'positions';
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_lastLatitude", $hash->{helper}{mower}{attributes}{$pref}[0]{latitude} );
|
readingsBulkUpdateIfChanged($hash, $pref."_lastLonLat", $hash->{helper}{mower}{attributes}{$pref}[0]{longitude} . ' ' . $hash->{helper}{mower}{attributes}{$pref}[0]{latitude} );
|
||||||
readingsBulkUpdateIfChanged($hash, $pref."_lastLongitude", $hash->{helper}{mower}{attributes}{$pref}[0]{longitude} );
|
|
||||||
readingsBulkUpdateIfChanged($hash, 'state', 'connected' );
|
readingsBulkUpdateIfChanged($hash, 'state', 'connected' );
|
||||||
|
|
||||||
my @time = localtime();
|
my @time = localtime();
|
||||||
@ -500,9 +516,23 @@ sub Get {
|
|||||||
Log3 $name, 4, "$iam called with $setName " . ($setVal ? $setVal : "");
|
Log3 $name, 4, "$iam called with $setName " . ($setVal ? $setVal : "");
|
||||||
|
|
||||||
if ( $setName eq 'html' ) {
|
if ( $setName eq 'html' ) {
|
||||||
|
|
||||||
my $ret = '<html>' . FW_detailFn( undef, $name, undef, undef) . '</html>';
|
my $ret = '<html>' . FW_detailFn( undef, $name, undef, undef) . '</html>';
|
||||||
return $ret;
|
return $ret;
|
||||||
|
|
||||||
|
} elsif ( $setName eq 'listErrorCodes' ) {
|
||||||
|
|
||||||
|
my $ret = listErrorCodes($hash);
|
||||||
|
return $ret;
|
||||||
|
|
||||||
|
} elsif ( $setName eq 'listInternalData' ) {
|
||||||
|
|
||||||
|
my $ret = listInternalData($hash);
|
||||||
|
return $ret;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
return "Unknown argument $setName, choose one of listInternalData:noArg listErrorCodes:noArg ";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,9 +548,11 @@ sub Set {
|
|||||||
Log3 $name, 4, "$iam set called with $setName " . ($setVal ? $setVal : "") if ($setName !~ /^\?$/);
|
Log3 $name, 4, "$iam set called with $setName " . ($setVal ? $setVal : "") if ($setName !~ /^\?$/);
|
||||||
|
|
||||||
if ( $setName eq 'chargingStationPositionToAttribute' ) {
|
if ( $setName eq 'chargingStationPositionToAttribute' ) {
|
||||||
my ($xm, $ym, $n) = split(/,\s/,ReadingsVal($name,'status_calcChargingStationPositionXYn','10.1165, 51.28, 0'));
|
|
||||||
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
|
||||||
CommandAttr($hash,"$name chargingStationCoordinates $xm $ym");
|
CommandAttr($hash,"$name chargingStationCoordinates $xm $ym");
|
||||||
return undef;
|
return undef;
|
||||||
|
|
||||||
################
|
################
|
||||||
} elsif ( ReadingsVal( $name, 'state', 'defined' ) !~ /defined|initialized/ && $setName eq 'mowerScheduleToAttribute' ) {
|
} elsif ( ReadingsVal( $name, 'state', 'defined' ) !~ /defined|initialized/ && $setName eq 'mowerScheduleToAttribute' ) {
|
||||||
@ -563,12 +595,12 @@ sub FW_detailFn {
|
|||||||
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
my ($FW_wname, $name, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my $type = $hash->{TYPE};
|
my $type = $hash->{TYPE};
|
||||||
return undef if( IsDisabled($name) || !AttrVal($name, 'showMap', 1) );
|
return '' if( IsDisabled($name) || !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 ) {
|
if ( $hash->{helper} && $hash->{helper}{mower} && $hash->{helper}{mower}{attributes} && $hash->{helper}{mower}{attributes}{positions} && @{$hash->{helper}{mower}{attributes}{positions}} > 0 ) {
|
||||||
my $img = "./fhem/$type/$name/map";
|
my $img = "./fhem/$type/$name/map";
|
||||||
my $zoom=AttrVal($name,"mapImageZoom",0.7);
|
my $zoom=AttrVal( $name,"mapImageZoom", 0.7 );
|
||||||
|
|
||||||
AttrVal($name,"mapImageWidthHeight",'100 200') =~ /(\d+)\s(\d+)/;
|
AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
|
||||||
my ($picx,$picy) = ($1, $2);
|
my ($picx,$picy) = ($1, $2);
|
||||||
|
|
||||||
$picx=int($picx*$zoom);
|
$picx=int($picx*$zoom);
|
||||||
@ -583,7 +615,7 @@ sub FW_detailFn {
|
|||||||
|
|
||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
return undef;
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
@ -595,20 +627,19 @@ sub FW_detailFn_Update {
|
|||||||
|
|
||||||
my @pos = ();
|
my @pos = ();
|
||||||
my @posc = ();
|
my @posc = ();
|
||||||
# @pos = @{$hash->{helper}{mower}{attributes}{positions}}; # developement mode
|
|
||||||
@pos = @{$hash->{helper}{areapos}}; # operational mode
|
@pos = @{$hash->{helper}{areapos}}; # operational mode
|
||||||
@posc =@{$hash->{helper}{cspos}}; # maybe operational mode
|
@posc =@{$hash->{helper}{cspos}}; # maybe operational mode
|
||||||
my $img = "./fhem/$type/$name/map";
|
my $img = "./fhem/$type/$name/map";
|
||||||
|
|
||||||
AttrVal($name,"mapImageCoordinatesToRegister","0 90\n90 0") =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,"mapImageCoordinatesToRegister",$hash->{helper}{posMinMax} ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|-?\s)(\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ( $lonlo, $latlo, $lonru, $latru ) = ($1, $2, $4, $5);
|
my ( $lonlo, $latlo, $lonru, $latru ) = ($1, $2, $4, $5);
|
||||||
|
|
||||||
my $zoom = AttrVal($name,"mapImageZoom",0.7);
|
my $zoom = AttrVal( $name,"mapImageZoom",0.7 );
|
||||||
|
|
||||||
AttrVal($name,"mapImageWidthHeight",'100 200') =~ /(\d+)\s(\d+)/;
|
AttrVal( $name,"mapImageWidthHeight", $hash->{helper}{imageWidthHeight} ) =~ /(\d+)\s(\d+)/;
|
||||||
my ($picx,$picy) = ($1, $2);
|
my ($picx,$picy) = ($1, $2);
|
||||||
|
|
||||||
AttrVal($name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude}) =~ /(\d+)\s+(\d+)/;
|
AttrVal( $name,'scaleToMeterXY', $hash->{helper}{scaleToMeterLongitude} . ' ' .$hash->{helper}{scaleToMeterLatitude} ) =~ /(\d+)\s+(\d+)/;
|
||||||
my $scalx = ($lonru-$lonlo) * $1;
|
my $scalx = ($lonru-$lonlo) * $1;
|
||||||
|
|
||||||
$picx = int($picx*$zoom);
|
$picx = int($picx*$zoom);
|
||||||
@ -618,21 +649,19 @@ sub FW_detailFn_Update {
|
|||||||
|
|
||||||
if ( ($hash->{helper}{PARKED_IN_CS}{callFn} || $hash->{helper}{CHARGING}{callFn}) && (!$hash->{helper}{chargingStation}{longitude} || !$hash->{helper}{chargingStation}{latitude}) ) {
|
if ( ($hash->{helper}{PARKED_IN_CS}{callFn} || $hash->{helper}{CHARGING}{callFn}) && (!$hash->{helper}{chargingStation}{longitude} || !$hash->{helper}{chargingStation}{latitude}) ) {
|
||||||
no strict "refs";
|
no strict "refs";
|
||||||
&{$hash->{helper}{PARKED_IN_CS}{callFn}}($hash);
|
&{$hash->{helper}{PARKED_IN_CS}{callFn}}( $hash );
|
||||||
use strict "refs";
|
use strict "refs";
|
||||||
}
|
}
|
||||||
|
|
||||||
my $csimgpos = AttrVal($name,"chargingStationImagePosition","right");
|
my $csimgpos = AttrVal( $name,"chargingStationImagePosition","right" );
|
||||||
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 10.1165;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 51.28;
|
||||||
|
|
||||||
AttrVal($name,"chargingStationCoordinates",'10.1165 51.28') =~ /(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,"chargingStationCoordinates","$xm $ym" ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ($cslo,$csla) = ($1, $2);
|
my ($cslo,$csla) = ($1, $2);
|
||||||
|
|
||||||
my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
|
my $cslon = int(($lonlo-$cslo) * $picx / $mapx);
|
||||||
my $cslat = int(($latlo-$csla) * $picy / $mapy);
|
my $cslat = int(($latlo-$csla) * $picy / $mapy);
|
||||||
# my $lon = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx);
|
|
||||||
# my $lat = int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
|
||||||
# my $lastx = int(($lonlo-$pos[$#pos]{longitude}) * $picx / $mapx);
|
|
||||||
# my $lasty = int(($latlo-$pos[$#pos]{latitude}) * $picy / $mapy);
|
|
||||||
|
|
||||||
# MOWING PATH
|
# MOWING PATH
|
||||||
my $posxy = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx).",".int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
my $posxy = int(($lonlo-$pos[0]{longitude}) * $picx / $mapx).",".int(($latlo-$pos[0]{latitude}) * $picy / $mapy);
|
||||||
@ -758,10 +787,10 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
if ( AttrVal( $name,'mapImageCoordinatesToRegister', '' ) && $attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/ ) {
|
if ( AttrVal( $name,'mapImageCoordinatesToRegister', '' ) && $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ ) {
|
||||||
|
|
||||||
my ( $x1, $y1, $x2, $y2 ) = ( $1, $2, $4, $5 );
|
my ( $x1, $y1, $x2, $y2 ) = ( $1, $2, $4, $5 );
|
||||||
AttrVal( $name,'mapImageCoordinatesToRegister', '' ) =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/;
|
AttrVal( $name,'mapImageCoordinatesToRegister', '' ) =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
my ( $lo1, $la1, $lo2, $la2 ) = ( $1, $2, $4, $5 );
|
my ( $lo1, $la1, $lo2, $la2 ) = ( $1, $2, $4, $5 );
|
||||||
my $scx = int( ( $x1 - $x2) / ( $lo1 - $lo2 ) );
|
my $scx = int( ( $x1 - $x2) / ( $lo1 - $lo2 ) );
|
||||||
my $scy = int( ( $y1 - $y2 ) / ( $la1 - $la2 ) );
|
my $scy = int( ( $y1 - $y2 ) / ( $la1 - $la2 ) );
|
||||||
@ -774,7 +803,7 @@ sub Attr {
|
|||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
|
|
||||||
Log3 $name, 3, "$iam $cmd $attrName and set default 0 90<Line feed>90 0";
|
Log3 $name, 3, "$iam $cmd $attrName and set default";
|
||||||
|
|
||||||
}
|
}
|
||||||
##########
|
##########
|
||||||
@ -782,12 +811,12 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use linewise pairs <floating point longitude><one space character><floating point latitude>" unless($attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)(\R|\s)(\d*\.?\d+)\s(\d*\.?\d+)/);
|
return "$iam $attrName has a wrong format use linewise pairs <floating point longitude><one space character><floating point latitude>" unless( $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|\s)(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
|
|
||||||
Log3 $name, 3, "$iam $cmd $attrName and set default 0 90<Line feed>90 0";
|
Log3 $name, 3, "$iam $cmd $attrName and set default";
|
||||||
|
|
||||||
}
|
}
|
||||||
##########
|
##########
|
||||||
@ -795,12 +824,12 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use <floating point longitude><one space character><floating point latitude>" unless($attrVal =~ /(\d*\.?\d+)\s(\d*\.?\d+)/);
|
return "$iam $attrName has a wrong format use <floating point longitude><one space character><floating point latitude>" unless( $attrVal =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
|
|
||||||
Log3 $name, 3, "$iam $cmd $attrName and set default 10.1165 51.28";
|
Log3 $name, 3, "$iam $cmd $attrName and set default";
|
||||||
|
|
||||||
}
|
}
|
||||||
##########
|
##########
|
||||||
@ -808,12 +837,12 @@ sub Attr {
|
|||||||
|
|
||||||
if( $cmd eq "set" ) {
|
if( $cmd eq "set" ) {
|
||||||
|
|
||||||
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless($attrVal =~ /(\d+)\s(\d+)/);
|
return "$iam $attrName has a wrong format use <integer longitude><one space character><integer latitude>" unless( $attrVal =~ /(\d+)\s(\d+)/ );
|
||||||
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
Log3 $name, 3, "$iam $cmd $attrName $attrVal";
|
||||||
|
|
||||||
} elsif( $cmd eq "del" ) {
|
} elsif( $cmd eq "del" ) {
|
||||||
|
|
||||||
Log3 $name, 3, "$iam $cmd $attrName and set default 100 200";
|
Log3 $name, 3, "$iam $cmd $attrName and set default";
|
||||||
|
|
||||||
}
|
}
|
||||||
##########
|
##########
|
||||||
@ -879,13 +908,13 @@ sub AlignArray {
|
|||||||
my $activity = $hash->{helper}{mower}{attributes}{mower}{activity};
|
my $activity = $hash->{helper}{mower}{attributes}{mower}{activity};
|
||||||
my $arrayName = $hash->{helper}{$activity}{arrayName};
|
my $arrayName = $hash->{helper}{$activity}{arrayName};
|
||||||
my $maxLength = $hash->{helper}{$activity}{maxLength};
|
my $maxLength = $hash->{helper}{$activity}{maxLength};
|
||||||
for ( $i = 0; $i < $poslen-1; $i++ ) {
|
for ( $i = 0; $i < $poslen-3; $i++ ) { # 3 instead of 1 due to new alignment
|
||||||
if ( $searchposlon[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{longitude}
|
if ( $searchposlon[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{longitude}
|
||||||
&& $searchposlat[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{latitude}
|
&& $searchposlat[0] == $hash->{helper}{mower}{attributes}{positions}[ $i ]{latitude}
|
||||||
&& $searchposlon[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{longitude}
|
&& $searchposlon[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{longitude}
|
||||||
&& $searchposlat[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{latitude}
|
&& $searchposlat[1] == $hash->{helper}{mower}{attributes}{positions}[ $i+1 ]{latitude} ) {
|
||||||
|| $i == $poslen-2 ) {
|
# || $i == $poslen-2 ) { # not nessecary due to new alignment
|
||||||
$i++ if ($i == $poslen-2);
|
# $i++ if ( $i == $poslen-2 ); # not nessecary due to new alignment
|
||||||
# timediff per step
|
# timediff per step
|
||||||
my $dt = 0;
|
my $dt = 0;
|
||||||
$dt = int(($hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{$arrayName}[0]{statusTimestamp})/$i) if ($i);
|
$dt = int(($hash->{helper}{mower}{attributes}{metadata}{statusTimestamp} - $hash->{helper}{$arrayName}[0]{statusTimestamp})/$i) if ($i);
|
||||||
@ -897,15 +926,27 @@ sub AlignArray {
|
|||||||
|
|
||||||
unshift (@{$hash->{helper}{searchpos}}, dclone($hash->{helper}{mower}{attributes}{positions}[ $k ]) );
|
unshift (@{$hash->{helper}{searchpos}}, dclone($hash->{helper}{mower}{attributes}{positions}[ $k ]) );
|
||||||
pop (@{$hash->{helper}{searchpos}}) if (@{$hash->{helper}{searchpos}} > $searchlen);
|
pop (@{$hash->{helper}{searchpos}}) if (@{$hash->{helper}{searchpos}} > $searchlen);
|
||||||
|
|
||||||
|
my @temp = ();
|
||||||
|
unshift ( @temp, dclone( $hash->{helper}{mower}{attributes}{positions}[ $k ] ) );
|
||||||
|
posMinMax( $hash, \@temp );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#callFn if present
|
#callFn if present
|
||||||
if ($hash->{helper}{$activity}{callFn}) {
|
if ($hash->{helper}{$activity}{callFn}) {
|
||||||
|
|
||||||
$hash->{helper}{$activity}{cnt} = $i;
|
$hash->{helper}{$activity}{cnt} = $i;
|
||||||
no strict "refs";
|
no strict "refs";
|
||||||
&{$hash->{helper}{$activity}{callFn}}($hash);
|
&{$hash->{helper}{$activity}{callFn}}($hash);
|
||||||
use strict "refs";
|
use strict "refs";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$hash->{helper}{newdatasets} = $i;
|
||||||
|
readingsSingleUpdate($hash, "statistics_newGeoDataSets", $i, 1);
|
||||||
last;
|
last;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -921,9 +962,8 @@ sub ChargingStationPosition {
|
|||||||
my $ym = 0;
|
my $ym = 0;
|
||||||
map { $ym += $_->{latitude} } @{$hash->{helper}{cspos}};
|
map { $ym += $_->{latitude} } @{$hash->{helper}{cspos}};
|
||||||
$ym = $ym/$n;
|
$ym = $ym/$n;
|
||||||
$hash->{helper}{chargingStation}{longitude} = $xm;
|
$hash->{helper}{chargingStation}{longitude} = int($xm * 10000000 + 0.5) / 10000000;
|
||||||
$hash->{helper}{chargingStation}{latitude} = $ym;
|
$hash->{helper}{chargingStation}{latitude} = int($ym * 10000000 + 0.5) / 10000000;
|
||||||
readingsSingleUpdate($hash, "statistics_ChargingStationPositionXYn", (int($xm * 10000000 + 0.5) / 10000000).", ".(int($ym * 10000000 + 0.5) / 10000000).", ".$n, 0);
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1031,6 +1071,114 @@ sub readMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub posMinMax {
|
||||||
|
my ($hash, $poshash) = @_;
|
||||||
|
my $minLon = $hash->{helper}{minLon};
|
||||||
|
my $maxLon = $hash->{helper}{maxLon};
|
||||||
|
my $minLat = $hash->{helper}{minLat};
|
||||||
|
my $maxLat = $hash->{helper}{maxLat};
|
||||||
|
|
||||||
|
for ( @{$poshash} ) {
|
||||||
|
$minLon = minNum( $minLon,$_->{longitude} );
|
||||||
|
$maxLon = maxNum( $maxLon,$_->{longitude} );
|
||||||
|
$minLat = minNum( $minLat,$_->{latitude} );
|
||||||
|
$maxLat = maxNum( $maxLat,$_->{latitude} );
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{helper}{minLon} = $minLon;
|
||||||
|
$hash->{helper}{maxLon} = $maxLon;
|
||||||
|
$hash->{helper}{minLat} = $minLat;
|
||||||
|
$hash->{helper}{maxLat} = $maxLat;
|
||||||
|
$hash->{helper}{posMinMax} = "$minLon $maxLat\n$maxLon $minLat";
|
||||||
|
$hash->{helper}{imageWidthHeight} = int($hash->{helper}{imageHeight} * ($maxLon-$minLon) / ($maxLat-$minLat)) . ' ' . $hash->{helper}{imageHeight} if ($maxLon-$minLon);
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub listInternalData {
|
||||||
|
my ( $hash ) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $rowCount = 1;
|
||||||
|
my $ret = '<html><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Calculated Coordinates For Automatic Registration</b></caption><tbody>';
|
||||||
|
|
||||||
|
$hash->{helper}{posMinMax} =~ /(-?\d*\.?\d+)\s(-?\d*\.?\d+)(\R|-?\s)(\d*\.?\d+)\s(-?\d*\.?\d+)/;
|
||||||
|
|
||||||
|
my $xm = $hash->{helper}{chargingStation}{longitude} // 0;
|
||||||
|
my $ym = $hash->{helper}{chargingStation}{latitude} // 0;
|
||||||
|
my $csnr = scalar @{$hash->{helper}{cspos}};
|
||||||
|
my $csnrmax = $hash->{helper}{PARKED_IN_CS}{maxLength};
|
||||||
|
my $arnr = 0;
|
||||||
|
$arnr = scalar @{$hash->{helper}{areapos}} if( scalar @{$hash->{helper}{areapos}} > 2 );
|
||||||
|
my $arnrmax = $hash->{helper}{MOWING}{maxLength};
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Data Sets ( max ) </td><td> Corner </td><td> Longitude </td><td> Latitude </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td rowspan="2" style="vertical-align:middle;" > ' . ($csnr + $arnr) . ' ( ' . ($csnrmax + $arnrmax) . ' ) </td><td> Upper Left </td><td> ' . $1 . ' </td><td> ' . $2 . ' </td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td> Lower Right </td><td> ' . $4 . ' </td><td> ' . $5 . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table><p>';
|
||||||
|
$ret .= '<table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Calculated Charging Station Coordinates</b></caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Data Sets (max) </td><td> Longitude </td><td> Latitude </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td> ' . $csnr . ' ( ' . $csnrmax . ' ) </td><td> ' . $xm . ' </td><td> ' . $ym . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table><p>';
|
||||||
|
$ret .= '<table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Way Point Stacks</b></caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="col_header"><td> Used For Action </td><td> Stack Name </td><td> Current Size </td><td> Max Size </td></tr>';
|
||||||
|
$ret .= '<tr class="column odd"><td>PARKED_IN_CS, CHARGING </td><td> cspos </td><td> ' . $csnr . ' </td><td> ' . $csnrmax . ' </td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td>MOWING </td><td> areapos </td><td> ' . $arnr . ' </td><td> ' . $arnrmax . ' </td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table>';
|
||||||
|
if ( $hash->{TYPE} eq 'AutomowerConnect' ) {
|
||||||
|
|
||||||
|
$ret .= '<p><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Access Token</b> ( expires: ' . ReadingsVal( $name, 'api_token_expires', 'none') . ' ) </caption><tbody>';
|
||||||
|
|
||||||
|
$ret .= '<tr class="column odd"><td style="word-wrap:break-word; max-width:40em">' . ReadingsVal( $name, '.access_token', 'none') . '</td></tr>';
|
||||||
|
|
||||||
|
$ret .= '</tbody></table>';
|
||||||
|
|
||||||
|
}
|
||||||
|
$ret .= '</html>';
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#########################
|
||||||
|
sub listErrorCodes {
|
||||||
|
my ( $hash ) = @_;
|
||||||
|
my $rowCount = 1;
|
||||||
|
my %ec = ();
|
||||||
|
my $ec = \%ec;
|
||||||
|
for ( keys %{$hash->{helper}{errortable}} ) {
|
||||||
|
$ec->{sprintf("%03d",$_)} = $hash->{helper}{errortable}{$_} ;
|
||||||
|
}
|
||||||
|
my $ret = '<html><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>API-Response Status Codes</b></caption><tbody>';
|
||||||
|
$ret .= '<tr class="column odd"><td>200, 201, 202<br>204</td><td>response o.k.</td></tr>';
|
||||||
|
$ret .= '<tr class="column even"><td>400, 401, 402<br>403, 404, 415<br>500, 503</td><td>error, detailed information see logfile</td></tr>';
|
||||||
|
$ret .= '</tbody></table><p><table class="block wide">';
|
||||||
|
$ret .= '<caption><b>Mower Error Table</b></caption><tbody>';
|
||||||
|
for (sort keys %{$ec}) {
|
||||||
|
$ret .= '<tr class="column ';
|
||||||
|
$ret .= ( $rowCount % 2 ? "odd" : "even" );
|
||||||
|
$ret .= '"><td>';
|
||||||
|
$ret .= $_;
|
||||||
|
$ret .= '</td><td>';
|
||||||
|
$ret .= $ec->{$_};
|
||||||
|
$ret .= '</td></tr>';
|
||||||
|
$rowCount++;
|
||||||
|
}
|
||||||
|
$ret .= '</tbody></table></html>';
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
##############################################################
|
##############################################################
|
||||||
|
|
||||||
1;
|
1;
|
||||||
@ -1130,6 +1278,14 @@ sub readMap {
|
|||||||
<li><a id='AutomowerConnectDevice-get-html'>html</a><br>
|
<li><a id='AutomowerConnectDevice-get-html'>html</a><br>
|
||||||
<code>get <name> html </code><br>
|
<code>get <name> html </code><br>
|
||||||
Returns the mower area image as html code. For use in uiTable, TabletUI, Floorplan, readingsGroup, weblink etc.</li>
|
Returns the mower area image as html code. For use in uiTable, TabletUI, Floorplan, readingsGroup, weblink etc.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listInternalData'>listInternalData</a><br>
|
||||||
|
<code>get <name> listInternalData</code><br>
|
||||||
|
Lists some device internal data</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listErrorCodes'>listErrorCodes</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Lists API response status codes and mower error codes</li>
|
||||||
<br><br>
|
<br><br>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
@ -1227,13 +1383,12 @@ sub readMap {
|
|||||||
<li>planner_nextStart - next start time</li>
|
<li>planner_nextStart - next start time</li>
|
||||||
<li>planner_restrictedReason - reason for parking NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
<li>planner_restrictedReason - reason for parking NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
||||||
<li>planner_overrideAction - reason for override a planned action NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
<li>planner_overrideAction - reason for override a planned action NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
||||||
<li>positions_lastLatitude - last known position (latitude)</li>
|
<li>positions_lastLonLat - last known position (longitude latitude)</li>
|
||||||
<li>positions_lastLongitude - last known position (longitude)</li>
|
<li>state - status of connection FHEM to Husqvarna Cloud API and device state(e.g. defined, connected, error)</li>
|
||||||
<li>state - status of connection FHEM to Husqvarna Cloud API and device state(e.g. defined, authorization, authorized, connected, error, update)</li>
|
|
||||||
<li>status_statusTimestampOld - local time of second last change of the API content</li>
|
<li>status_statusTimestampOld - local time of second last change of the API content</li>
|
||||||
<li>settings_cuttingHeight - actual cutting height from API</li>
|
<li>settings_cuttingHeight - actual cutting height from API</li>
|
||||||
<li>settings_headlight - actual headlight mode from API</li>
|
<li>settings_headlight - actual headlight mode from API</li>
|
||||||
<li>statistics_ChargingStationPositionXYn - calculated position of the carging station (longitude, latitude, number of datasets) during mower_activity PARKED_IN_CS and CHARGING</li>
|
<li>statistics_newGeoDataSets - number of new data sets between the last two different time stamps</li>
|
||||||
<li>statistics_numberOfChargingCycles - number of charging cycles</li>
|
<li>statistics_numberOfChargingCycles - number of charging cycles</li>
|
||||||
<li>statistics_numberOfCollisions - number of collisions</li>
|
<li>statistics_numberOfCollisions - number of collisions</li>
|
||||||
<li>statistics_totalChargingTime - total charging time in hours</li>
|
<li>statistics_totalChargingTime - total charging time in hours</li>
|
||||||
@ -1350,6 +1505,14 @@ sub readMap {
|
|||||||
<li><a id='AutomowerConnectDevice-get-html'>html</a><br>
|
<li><a id='AutomowerConnectDevice-get-html'>html</a><br>
|
||||||
<code>get <name> html </code><br>
|
<code>get <name> html </code><br>
|
||||||
Gibt das Bild des Mäherbereiches html kodiert zurück, zur Verwendung in uiTable, TabletUI, Floorplan, readingsGroup, weblink usw.</li>
|
Gibt das Bild des Mäherbereiches html kodiert zurück, zur Verwendung in uiTable, TabletUI, Floorplan, readingsGroup, weblink usw.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listErrorCodes'>listErrorCodes</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Listet die Statuscode der API-Anfrage und die Fehlercodes des Mähroboters auf.</li>
|
||||||
|
|
||||||
|
<li><a id='AutomowerConnect-get-listInternalData'>listInternalData</a><br>
|
||||||
|
<code>get <name> listErrorCodes</code><br>
|
||||||
|
Listet einige Daten des FHEM-Gerätes auf.</li>
|
||||||
<br><br>
|
<br><br>
|
||||||
</ul>
|
</ul>
|
||||||
<br>
|
<br>
|
||||||
@ -1457,12 +1620,11 @@ sub readMap {
|
|||||||
<li>planner_nextStart - nächste Startzeit</li>
|
<li>planner_nextStart - nächste Startzeit</li>
|
||||||
<li>planner_restrictedReason - Grund für Parken NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
<li>planner_restrictedReason - Grund für Parken NONE, WEEK_SCHEDULE, PARK_OVERRIDE, SENSOR, DAILY_LIMIT, FOTA, FROST</li>
|
||||||
<li>planner_overrideAction - Grund für vorrangige Aktion NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
<li>planner_overrideAction - Grund für vorrangige Aktion NOT_ACTIVE, FORCE_PARK, FORCE_MOW</li>
|
||||||
<li>positions_lastLatitude - letzte bekannte Position (Breitengrad)</li>
|
<li>positions_lastLonLat - letzte bekannte Position (Längengrad Breitengrad)</li>
|
||||||
<li>positions_lastLongitude - letzte bekannte Position (Längengrad)</li>
|
<li>state - Status der Verbindung des FHEM-Gerätes zur Husqvarna Cloud API (defined, connected, error).</li>
|
||||||
<li>state - Status der Verbindung des FHEM-Gerätes zur Husqvarna Cloud API (defined, connected).</li>
|
|
||||||
<li>settings_cuttingHeight - aktuelle Schnitthöhe aus der API</li>
|
<li>settings_cuttingHeight - aktuelle Schnitthöhe aus der API</li>
|
||||||
<li>settings_headlight - aktueller Scheinwerfermode aus der API</li>
|
<li>settings_headlight - aktueller Scheinwerfermode aus der API</li>
|
||||||
<li>statistics_ChargingStationPositionXYn - berechnete Position der Ladestation mit den Werten Longitude, Latitude und Anzahl der verwendeten Datensätze wähend der Mower_activity PARKED_IN_CS und CHARGING</li>
|
<li>statistics_newGeoDataSets - Anzahl der neuen Datensätze zwischen den letzten zwei unterschiedlichen Zeitstempeln</li>
|
||||||
<li>statistics_numberOfChargingCycles - Anzahl der Ladezyklen</li>
|
<li>statistics_numberOfChargingCycles - Anzahl der Ladezyklen</li>
|
||||||
<li>statistics_numberOfCollisions - Anzahl der Kollisionen</li>
|
<li>statistics_numberOfCollisions - Anzahl der Kollisionen</li>
|
||||||
<li>statistics_totalChargingTime - Gesamtladezeit in Stunden</li>
|
<li>statistics_totalChargingTime - Gesamtladezeit in Stunden</li>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user