MYSENSORS (_DEVICE): update cref; OTA-related changes, #120942

git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@24446 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
Beta-User 2021-05-15 14:04:30 +00:00
parent 20424a5c29
commit ab9f8471a8
2 changed files with 150 additions and 131 deletions

View File

@ -40,13 +40,13 @@ use GPUtils qw(:all);
sub main::MYSENSORS_Initialize { goto &Initialize };
my %sets = (
"connect" => [],
"disconnect" => [],
"inclusion-mode" => [qw(on off)],
connect => [qw(noArg)],
disconnect => [qw(noArg)],
'inclusion-mode' => [qw(on off)],
);
my %gets = (
"version" => ""
version => ''
);
my @clients = qw(
@ -58,7 +58,7 @@ sub Initialize {
my $hash = shift // return;
# Provider
$hash->{Clients} = join (':',@clients);
$hash->{Clients} = join q{:}, @clients;
$hash->{ReadyFn} = \&Ready;
$hash->{ReadFn} = \&Read;
@ -73,13 +73,13 @@ sub Initialize {
qw(
autocreate:1
requestAck:1
first-sensorid
last-sensorid
first-sensorid:selectnumbers,1,1,255,0,lin
last-sensorid:selectnumbers,2,1,255,0,lin
stateFormat
OTA_firmwareConfig
)
);
$hash->{AttrList} = $hash->{AttrList} = join(" ", @attrList);
$hash->{AttrList} = $hash->{AttrList} = join q{ }, @attrList;
return;
}
@ -103,6 +103,7 @@ BEGIN { GP_Import(
Log3
FileRead
IsDisabled
looks_like_number
)
)
};
@ -417,15 +418,15 @@ sub Set {
.join ',', @{$sets{$_}} : $_} sort keys %sets)
if !defined($sets{$command});
if ($command eq "connect") {
if ($command eq 'connect') {
return Start($hash);
}
if ($command eq "disconnect") {
if ($command eq 'disconnect') {
return Stop($hash);
}
if ($command eq "inclusion-mode") {
if ($command eq 'inclusion-mode') {
sendMessage($hash,
radioId => 0,
childId => 0,
@ -447,7 +448,7 @@ sub Attr {
my $value = shift;
my $hash = $defs{$name};
if ($attribute eq "autocreate" && $init_done) {
if ($attribute eq 'autocreate' && $init_done) {
my $mode = $command eq "set" ? 1 : 0;
$hash->{'inclusion-mode'} = $mode;
return sendMessage($hash,
@ -459,8 +460,8 @@ sub Attr {
);
}
if ($attribute eq "requestAck") {
if ($command eq "set") {
if ($attribute eq 'requestAck') {
if ($command eq 'set') {
$hash->{ack} = 1;
} else {
$hash->{ack} = 0;
@ -470,12 +471,17 @@ sub Attr {
return;
}
if ($attribute eq "OTA_firmwareConfig") {
return;
if ($attribute eq 'OTA_firmwareConfig') {
if ($command eq 'set') {
return getFirmwareTypes($hash, 'set', $value);
} else {
delete $hash->{'.fwList'};
return;
}
}
if ($attribute eq "disable") {
return Stop($hash) if $command eq "set" && $value;
InternalTimer(time(), "MYSENSORS::Start", $hash,0);
if ($attribute eq 'disable') {
return Stop($hash) if $command eq 'set' && $value;
InternalTimer(time, "MYSENSORS::Start", $hash,0);
return;
}
return;
@ -485,9 +491,10 @@ sub Start {
my $hash = shift // return;
my ($dev) = split m{\s+}xms, $hash->{DEF};
$hash->{DeviceName} = $dev;
if (!AttrVal($hash->{NAME},"stateFormat",0)) {
if (!AttrVal($hash->{NAME},'stateFormat',0)) {
CommandAttr(undef, "$hash->{NAME} stateFormat connection")
}
getFirmwareTypes($hash, 'start');
return if IsDisabled( $hash->{NAME} );
DevIo_CloseDev($hash);
return DevIo_OpenDev($hash, 0, "MYSENSORS::Init");
@ -497,13 +504,13 @@ sub Stop {
my $hash = shift // return;
DevIo_CloseDev($hash);
RemoveInternalTimer($hash);
readingsSingleUpdate($hash,"connection","disconnected",1);
readingsSingleUpdate($hash,'connection','disconnected',1);
return;
}
sub Ready {
my $hash = shift // return;
return DevIo_OpenDev($hash, 1, "MYSENSORS::Init") if($hash->{STATE} eq "disconnected");
return DevIo_OpenDev($hash, 1, "MYSENSORS::Init") if($hash->{STATE} eq 'disconnected');
if(defined($hash->{USBDev})) {
my $po = $hash->{USBDev};
my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;
@ -515,8 +522,8 @@ sub Ready {
sub Init {
my $hash = shift // return;
my $name = $hash->{NAME};
$hash->{'inclusion-mode'} = AttrVal($name,"autocreate",0);
$hash->{ack} = AttrVal($name,"requestAck",0);
$hash->{'inclusion-mode'} = AttrVal($name,'autocreate',0);
$hash->{ack} = AttrVal($name,'requestAck',0);
$hash->{outstandingAck} = 0;
if ($hash->{ack}) {
GP_ForallClients($hash,sub {
@ -529,7 +536,7 @@ sub Init {
};
});
}
readingsSingleUpdate($hash,"connection","connected",1);
readingsSingleUpdate($hash,'connection','connected',1);
return sendMessage($hash,
radioId => 0,
childId => 0,
@ -699,7 +706,7 @@ sub onInternalMsg {
if ($type == I_HEARTBEAT_RESPONSE) {
RemoveInternalTimer($hash,"MYSENSORS::Start"); ## Reset reconnect because timeout was not reached
readingsSingleUpdate($hash, "heartbeat", "alive", 0);
readingsSingleUpdate($hash, 'heartbeat', 'alive', 0);
if ($client = matchClient($hash,$msg)){
return if IsDisabled( $client->{NAME} );
MYSENSORS::DEVICE::onInternalMessage($client,$msg)
@ -794,25 +801,34 @@ sub onAcknowledge {
sub getFirmwareTypes {
my $hash = shift;
my $mode = shift // 0;
my $filename = shift // AttrVal($hash->{NAME}, 'OTA_firmwareConfig', undef);
my $name = $hash->{NAME};
return @{$hash->{'.fwList'}} if !$mode && defined $hash->{'.fwList'};
return 'OTA_firmwareConfig_not_set_in_gateway' if !$mode && !defined $hash->{'.fwList'};
my @fwTypes = ();
my $filename = AttrVal($name, "OTA_firmwareConfig", undef);
if (defined($filename)) {
my ($err, @lines) = FileRead({FileName => "./FHEM/firmware/" . $filename,
ForceType => "file"});
if (defined($err) && $err) {
my ($err, @lines) = FileRead({FileName => "./FHEM/firmware/$filename",
ForceType => 'file'});
if ( defined $err && $err ) {
Log3($name, 2, "$name: could not read MySensor firmware configuration file - $err");
} else {
for (my $i = 0; $i < @lines ; $i++) {
chomp(my $row = $lines[$i]);
if (index($row, "#") != 0) {
my @tokens = split(",", $row);
push(@fwTypes, $tokens[0]);
}
return $err if $mode eq 'set' && $init_done;
return @fwTypes;
}
for (@lines) {
chomp($_);
if (index($_, "#") != 0) {
my @tokens = split m{,}xms, $_;
push @fwTypes, $tokens[0] if looks_like_number($tokens[0]);
}
}
$hash->{'.fwList'} = [@fwTypes];
}
delete $hash->{'.fwList'} if !@fwTypes;
Log3($name, 5, "$name: getFirmwareTypes - list contains: @fwTypes");
return if $mode eq 'set' && @fwTypes;
return 'file contains no valid data' if $mode eq 'set' && !@fwTypes;
return @fwTypes;
}
@ -820,22 +836,22 @@ sub getLatestFirmware {
my $hash = shift;
my $type = shift // return;
my $name = $hash->{NAME};
my $cfgfilename = AttrVal($name, "OTA_firmwareConfig", undef);
my $cfgfilename = AttrVal($name, 'OTA_firmwareConfig', undef);
my $version = undef;
$name = undef;
my $filename = undef;
if (defined($cfgfilename)) {
my ($err, @lines) = FileRead({FileName => "./FHEM/firmware/" . $cfgfilename,
ForceType => "file"});
my ($err, @lines) = FileRead({FileName => "./FHEM/firmware/$cfgfilename",
ForceType => 'file'});
if (defined($err) && $err) {
Log3($name, 2, "$name: could not read MySensor firmware configuration file - $err");
} else {
for (my $i = 0; $i < @lines ; $i++) {
chomp(my $row = $lines[$i]);
if (index($row, "#") != 0) {
my @tokens = split(",", $row);
for (@lines) {
chomp($_);
if (index($_, '#') != 0) {
my @tokens = split m{,}xms, $_;
if ($tokens[0] eq $type) {
if ((not defined $version) || ($tokens[2] > $version)) {
if ( !defined $version || $tokens[2] > $version ) {
$name = $tokens[1];
$version = $tokens[2];
$filename = $tokens[3];
@ -916,12 +932,10 @@ sub matchChan76GWClient {
if ( defined( $defs{$d} )
&& defined( $defs{$d}{radioId} )
&& $defs{$d}{radioId} == $radioId ) {
#my $clientname = $defs{$d}->{NAME};
#$found = $defs{$d} if AttrVal($clientname,"OTA_Chan76_IODev","") eq
$found = $defs{$d} if AttrVal($d,"OTA_Chan76_IODev","") eq $name;
$found = $defs{$d} if AttrVal($d,'OTA_Chan76_IODev','') eq $name;
}
}
Log3($hash, 4, "$name: matched firmware config request to IO-name $found->{NAME}") if $found;
return $found;
}
@ -939,6 +953,7 @@ sub parseMsg {
(?<type> [0-9]{1,2});
(?<payload> .*)
\z}xms);
#my $payload = $+{payload} // q{};
return {
radioId => $+{nodeid}, # docs speak of "nodeId"
@ -1014,18 +1029,19 @@ __END__
<a id="MYSENSORS-set"></a>
<h4>Set</h4>
<ul>
<li>
<p><a id="MYSENSORS-set-connect"></a><b>connect</b></p>
<li><a id="MYSENSORS-set-connect"></a>
<p><b>connect</b></p>
<p><code>set &lt;name&gt; connect</code></p>
<p>(re-)connects the MYSENSORS-device to the MYSENSORS-gateway</p>
<p>Can also be used to reload the <i>OTA_firmwareConfig</i> file after editing.</p>
</li>
<li>
<p><a id="MYSENSORS-set-disconnect"></a><b>disconnect</b></p>
<li><a id="MYSENSORS-set-disconnect"></a>
<p><b>disconnect</b></p>
<p><code>set &lt;name&gt; disconnect</code></p>
<p>disconnects the MYSENSORS-device from the MYSENSORS-gateway</p>
</li>
<li>
<p><a id="MYSENSORS-set-inclusion-mode"></a><b>inclusion-mode</b></p>
<li><a id="MYSENSORS-set-inclusion-mode"></a>
<p><b>inclusion-mode</b></p>
<p><code>set &lt;name&gt; inclusion-mode on|off</code></p>
<p>turns the gateways inclusion-mode on or off</p>
</li>
@ -1034,26 +1050,26 @@ __END__
<a id="MYSENSORS-attr"></a>
<h4>Attributes</h4>
<ul>
<li>
<p><a id="MYSENSORS-attr-autocreate"></a><b>autocreate</b></p>
<li><a id="MYSENSORS-attr-autocreate"></a>
<p><b>autocreate</b></p>
<p><code>attr &lt;name&gt; autocreate</code></p>
<p>enables auto-creation of MYSENSOR_DEVICE-devices on receival of presentation-messages</p>
</li>
<li>
<p><a id="MYSENSORS-attr-requestack"></a><b>requestAck</b></p>
<li><a id="MYSENSORS-attr-requestAck"></a>
<p><b>requestAck</b></p>
<p><code>attr &lt;name&gt; requestAck</code></p>
<p>request acknowledge from nodes.</p>
<p>if set the Readings of nodes are updated not before requested acknowledge is received<br>
if not set the Readings of nodes are updated immediatly (not awaiting the acknowledge).</p>
<p>May also be configured for individual nodes if not set for gateway.</p>
</li>
<li>
<p><a id="MYSENSORS-attr-first-sensorid"></a><b>first-sensorid</b></p>
<p><code>attr &lt;name&gt; first-sensorid &lt;number &lt;h;255&gt;&gt;</code></p>
<li><a id="MYSENSORS-attr-first-sensorid"></a>
<p><b>first-sensorid</b></p>
<p><code>attr &lt;name&gt; first-sensorid &lt;number &lt; 255&gt;</code></p>
<p>configures the lowest node-id assigned to a mysensor-node on request (defaults to 20)</p>
</li>
<li>
<p><a id="MYSENSORS-attr-ota_firmwareconfig"></a><b>OTA_firmwareConfig</b></p>
<li><a id="MYSENSORS-attr-OTA_firmwareConfig"></a>
<p><b>OTA_firmwareConfig</b></p>
<p><code>attr &lt;name&gt; OTA_firmwareConfig &lt;filename&gt;</code></p>
<p>specifies a configuration file for the <a href="https://www.mysensors.org/about/fota">FOTA</a>
(firmware over the air - wireless programming of the nodes) configuration. It must be stored
@ -1074,6 +1090,7 @@ __END__
<dt><code>Comments</code></dt>
<dd>a description / comment for the firmware</dd>
</dl>
<p>Note: Firmware config file by default only is read at startup. If you change it later, just issue a <i>connect</i> command to update also Internal values.</p>
</li>
</ul>

View File

@ -231,15 +231,15 @@ sub Define {
my $hash = shift;
my $def = shift // return;
return $@ unless ( FHEM::Meta::SetInternals($hash) );
my ($name, $type, $radioId) = split m{\s+}xms, $def; # split("[ \t]+", $def);
return "requires 1 parameter!" if (!defined $radioId || $radioId eq "");
my ($name, $type, $radioId) = split m{\s+}xms, $def;
return 'requires 1 parameter!' if (!defined $radioId || $radioId eq '');
$hash->{radioId} = $radioId;
$hash->{sets} = {
'time' => "noArg",
'reboot' => "noArg",
'clear' => "noArg",
'flash' => "noArg",
'fwType' => "",
time => 'noArg',
reboot => 'noArg',
clear => 'noArg',
flash => 'noArg',
fwType => '',
};
$hash->{ack} = 0;
@ -261,17 +261,17 @@ sub Set {
return "At least one parameter is needed!" if !defined $command;
return "Node is disabled!" if IsDisabled( $hash->{NAME} );
if(!defined($hash->{sets}->{$command})) {
$hash->{sets}->{fwType} = join(",", MYSENSORS::getFirmwareTypes($hash->{IODev}));
my $list = join(" ", map {
$hash->{sets}->{$_} ne "" ? "$_:$hash->{sets}->{$_}"
$hash->{sets}->{fwType} = join q{,}, MYSENSORS::getFirmwareTypes( $hash->{IODev} );
my $list = join( q{ }, map {
$hash->{sets}->{$_} ne '' ? "$_:$hash->{sets}->{$_}"
: $_
} sort keys %{$hash->{sets}});
$hash->{sets}->{fwType} = "";
$hash->{sets}->{fwType} = q{};
return SetExtensions($hash, $list, $name, $command, @values);
}
if ($command =~ m{\A(time|reboot|clear|flash|fwType)\z}xms) {
if ($command eq "time") {
if ($command eq 'time') {
my $t = timegm_nocheck(localtime(time));
return sendClientMessage($hash,
childId => 255,
@ -282,8 +282,8 @@ sub Set {
);
}
if ($command eq "reboot") {
(AttrVal($name, "OTA_BL_Type", 0) or ReadingsVal($name, "BL_VERSION", 0))
if ($command eq 'reboot') {
(AttrVal($name, 'OTA_BL_Type', 0) or ReadingsVal($name, 'BL_VERSION', 0))
? return sendClientMessage($hash,
childId => 255,
cmd => C_INTERNAL,
@ -293,7 +293,7 @@ sub Set {
: return;
}
if ($command eq "clear") {
if ($command eq 'clear') {
Log3 ($name,3,"MYSENSORS_DEVICE $name: clear");
return sendClientMessage($hash,
childId => 255,
@ -304,25 +304,25 @@ sub Set {
);
}
if ($command eq "flash") {
my $blVersion = ReadingsVal($name, "BL_VERSION", "");
my $blType = AttrVal($name, "OTA_BL_Type", "");
my $fwType = ReadingsNum($name, "FW_TYPE", -1);
if ($command eq 'flash') {
my $blVersion = ReadingsVal($name, 'BL_VERSION', '');
my $blType = AttrVal($name, 'OTA_BL_Type', '');
my $fwType = ReadingsNum($name, 'FW_TYPE', -1);
if ($fwType == -1) {
Log3 ($name,3,"Firmware type not defined (FW_TYPE) for $name, update not started");
return "$name: Firmware type not defined (FW_TYPE)";
}
if ($blVersion eq "3.0" or $blType eq "Optiboot") {
Log3 ($name,4,"Startet flashing Firmware: Optiboot method");
if ($blVersion eq '3.0' or $blType eq 'Optiboot') {
Log3 ($name,4,'Startet flashing Firmware: Optiboot method');
return flashFirmware($hash, $fwType);
}
if ($blType eq "MYSBootloader") {
if ($blType eq 'MYSBootloader') {
$hash->{OTA_requested} = 1;
Log3 ($name,4,"Send reboot command to MYSBootloader node to start update");
return sendClientMessage($hash,
childId => 255,
cmd => C_INTERNAL,
ack => 1,
ack => 0,
subType => I_REBOOT
);
} else {
@ -335,7 +335,8 @@ sub Set {
if ($command eq 'fwType') {
my $type = shift @values // return;
return "fwType must be numeric, but got >$type<." if ($type !~ m{^[0-9]{2,20}$}xms);
return readingsSingleUpdate($hash, 'FW_TYPE', $type, 1);
readingsSingleUpdate($hash, 'FW_TYPE', $type, 1);
return;
}
}
@ -1352,38 +1353,38 @@ __END__
<a id="MYSENSORS_DEVICE-set"></a>
<h4>Set</h4>
<ul>
<li>
<p><a id="MYSENSORS_DEVICE-set-update"></a><b>AttrTemplate</b></p>
<li><a id="MYSENSORS_DEVICE-set-attrTemplate"></a>
<p><b>AttrTemplate</b></p>
<p>Helps to easily configure your devices. Just get a list of all available attrTremplates by issuing<br>
<code>set &lt;name&gt; attrTemplate ?</code></p>
<p>Have a look at the descriptions and choose a suitable one. Then use the drop-down list and click "set" or use<br>
<code>set &lt;name&gt; attrTemplate A_02a_atmospheric_pressure</code></p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-set-clear"></a><b>clear</b></p>
<li><a id="MYSENSORS_DEVICE-set-clear"></a>
<p><b>clear</b></p>
<p><code>set &lt;name&gt; clear</code></p>
<p>clears MySensors EEPROM area and reboot (i.e. &quot;factory&quot; reset) - requires MY_SPECIAL_DEBUG</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-set-flash"></a><b>flash</b></p>
<li><a id="MYSENSORS_DEVICE-set-flash"></a>
<p><b>flash</b></p>
<p><code>set &lt;name&gt; flash</code></p>
<p>Checks whether a newer firmware version is available. If a newer firmware version is
available the flash procedure is started. The sensor node must support FOTA for
this.</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-set-fwType"></a><b>fwType</b></p>
<li><a id="MYSENSORS_DEVICE-set-fwType"></a>
<p><b>fwType</b></p>
<p><code>set &lt;name&gt; fwType &lt;value&gt;</code></p>
<p>assigns a firmware type to this node (must be a numeric value in the range 0 .. 65536).<br>
Should be contained in the <a href="#MYSENSORS-attr-ota_firmwareconfig">FOTA configuration file</a>.</p>
Should be contained in the <a href="#MYSENSORS-attr-ota_firmwareconfig">FOTA configuration file</a></p>. <p>Note: Firmware config file by default only is read at startup. If you change it later, just issue a <i>connect</i> command to the GW to update also Internal values.</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-set-time"></a><b>time</b></p>
<li><a id="MYSENSORS_DEVICE-set-time"></a>
<p><b>time</b></p>
<p><code>set &lt;name&gt; time</code></p>
<p>sets time for nodes (that support it)</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-set-reboot"></a><b>reboot</b></p>
<li><a id="MYSENSORS_DEVICE-set-reboot"></a>
<p><b>reboot</b></p>
<p><code>set &lt;name&gt; reboot</code></p>
<p>reboots a node (requires a bootloader that supports it).<br/>Attention: Nodes that run the standard arduino-bootloader will enter a bootloop!<br/>Dis- and reconnect the nodes power to restart in this case.</p>
</li>
@ -1392,20 +1393,20 @@ __END__
<a id="MYSENSORS_DEVICE-get"></a>
<h4>Get</h4>
<ul>
<li>
<p><a id="MYSENSORS_DEVICE-get-extended_debug"></a><b>Extended_DEBUG</b></p>
<li><a id="MYSENSORS_DEVICE-get-Extended_DEBUG"></a>
<p><b>Extended_DEBUG</b></p>
<p><code>get &lt;name&gt; Extended_DEBUG</code></p>
<p>requires MY_SPECIAL_DEBUG<br>
retrieves the CPU frequency, CPU voltage and free memory of the sensor</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-get-readingsfromcomment"></a><b>ReadingsFromComment</b></p>
<li><a id="MYSENSORS_DEVICE-get-ReadingsFromComment"></a>
<p><b>ReadingsFromComment</b></p>
<p><code>get &lt;name&gt; ReadingsFromComment</code></p>
<p>rebuild reding names from comments of presentation messages if available<br>
After issuing this get check the log for changes.</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-get-rssi"></a><b>RSSI</b></p>
<li><a id="MYSENSORS_DEVICE-get-RSSI"></a>
<p><b>RSSI</b></p>
<p><code>get &lt;name&gt; RSSI</code></p>
<p>requires MY_SIGNAL_REPORT_ENABLED, not supported by all transportation layers<br>
delievers a set of Signal Quality information.</p>
@ -1415,38 +1416,38 @@ __END__
<a id="MYSENSORS_DEVICE-attr"></a>
<h4>Attributes</h4>
<ul>
<li>
<p><a id="MYSENSORS_DEVICE-attr-config"></a><b>config</b></p>
<li><a id="MYSENSORS_DEVICE-attr-config"></a>
<p><b>config</b></p>
<p><code>attr &lt;name&gt; config [&lt;M|I&gt;]</code></p>
<p>configures metric (M) or inch (I). Defaults to 'M'</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-ota_autoUpdate"></a><b>OTA_autoUpdate</b></p>
<li><a id="MYSENSORS_DEVICE-attr-OTA_autoUpdate"></a>
<p><b>OTA_autoUpdate</b></p>
<p><code>attr &lt;name&gt; OTA_autoUpdate [&lt;0|1&gt;]</code></p>
<p>specifies whether an automatic update of the sensor node should be performed (1) during startup of the node or not (0). Defaults to 0</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-setcommands"></a><b>setCommands</b></p>
<li><a id="MYSENSORS_DEVICE-attr-setCommands">
<p></a><b>setCommands</b></p>
<p><code>attr &lt;name&gt; setCommands [&lt;command:reading:value&gt;]*</code></p>
<p>configures one or more commands that can be executed by set.</p>
<p>e.g.:<br>
<code>attr &lt;name&gt; setCommands on:switch_1:on off:switch_1:off</code></p>
<p>if list of commands contains both 'on' and 'off' <a href="#setExtensions">set extensions</a> are supported</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-setreading"></a><b>setReading_&lt;reading&gt;</b></p>
<li><a id="MYSENSORS_DEVICE-attr-setReading_ " data-pattern="setReading_.*"></a>
<p><b>setReading_&lt;reading&gt;</b></p>
<p><code>attr &lt;name&gt; setReading_&lt;reading&gt; [&lt;value&gt;]*</code></p>
<p>configures a reading that can be modified by set-command</p>
<p>e.g.:<br>
<code>attr &lt;name&gt; setReading_switch_1 on,off</code></p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-setextensionsevent"></a><b>setExtensionsEvent</b></p>
<li><a id="MYSENSORS_DEVICE-attr-setExtensionsEvent"></a>
<p><b>setExtensionsEvent</b></p>
<p><code>attr &lt;name&gt; setExtensionsEvent</code></p>
<p>If set, the event will contain the command implemented by SetExtensions (e.g. on-for-timer 10), else the executed command (e.g. on).</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-mapreading"></a><b>mapReading_&lt;reading&gt;</b></p>
<li><a id="MYSENSORS_DEVICE-attr-mapReading_" data-pattern="mapReading_.*"></a>
<p><b>mapReading_&lt;reading&gt;</b></p>
<p><code>attr &lt;name&gt; mapReading_&lt;reading&gt; &lt;childId&gt; &lt;readingtype&gt; [&lt;value&gt;:&lt;mappedvalue&gt;]*</code></p>
<p>configures the reading-name for a given childId and sensortype</p>
<p>e.g.:<br>
@ -1454,39 +1455,40 @@ __END__
<code>attr xxx mapReading_leftwindow 10 status 1:closed 0:open</code></p>
<p>See also mapReadingType for setting defaults for types without predefined defaults</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-requestack"></a><b>requestAck</b></p>
<li><a id="MYSENSORS_DEVICE-attr-requestAck"></a>
<p><b>requestAck</b></p>
<p><code>attr &lt;name&gt; requestAck</code></p>
<p>request acknowledge from nodes.<br>
if set the Readings of nodes are updated not before requested acknowledge is received<br>
if not set the Readings of nodes are updated immediatly (not awaiting the acknowledge).<br>
May also be configured on the gateway for all nodes at once</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-mapreadingtype"></a><b>mapReadingType_&lt;reading&gt;</b></p>
<li><a id="MYSENSORS_DEVICE-attr-mapReadingType_" data-pattern="mapReadingType_.*"></a>
<p><b>mapReadingType_&lt;reading&gt;</b></p>
<p><code>attr &lt;name&gt; mapReadingType_&lt;reading&gt; &lt;new reading name&gt; [&lt;value&gt;:&lt;mappedvalue&gt;]*</code></p>
<p>configures reading type names that should be used instead of technical names</p>
<p>e.g.:<br>
<code>attr xxx mapReadingType_LIGHT switch 0:on 1:off</code></p>
<p>to be used for mysensor Variabletypes that have no predefined defaults (yet)</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-ota_bl_type"></a><b>OTA_BL_Type</b></p>
<li><a id="MYSENSORS_DEVICE-attr-OTA_BL_Type"></a>
<p><b>OTA_BL_Type</b></p>
<p><code>attr &lt;name&gt; OTA_BL_Type &lt;either Optiboot or MYSBootloader&gt;*</code></p>
<p>For other bootloaders than Optiboot V3.0 OTA updates will only work if bootloader type is specified - MYSBootloader will reboot node if firmware update is started, so make sure, node will really recover</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-ota_chan76_iodev"></a><b>OTA_Chan76_IODev</b></p>
<li><a id="MYSENSORS_DEVICE-attr-OTA_Chan76_IODev">
<p></a><b>OTA_Chan76_IODev</b></p>
<p><code>attr &lt;name&gt; OTA_Chan76_IODev </code></p>
<p>As MYSBootloader per default uses nRF24 channel 76, you may specify a different IODev for OTA data using channel 76</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-timeoutack"></a><b>timeoutAck</b></p>
<li><a id="MYSENSORS_DEVICE-attr-timeoutAck"></a>
<p><b>timeoutAck</b></p>
<p><code>attr &lt;name&gt; timeoutAck &lt;time in seconds&gt;*</code></p>
<p>configures timeout to set device state to NACK in case not all requested acks are received</p>
</li>
<li>
<p><a id="MYSENSORS_DEVICE-attr-timeoutalive"></a><b>timeoutAlive</b></p>
<li><a id="MYSENSORS_DEVICE-attr-timeoutAlive"></a>
<p><b>timeoutAlive</b></p>
<p><code>attr &lt;name&gt; timeoutAlive &lt;time in seconds&gt;*</code></p>
<p>configures timeout to set device state to alive or dead. If messages from node are received within timout spec, state will be alive, otherwise dead. If state is NACK (in case timeoutAck is also set), state will only be changed to alive, if there are no outstanding messages to be sent.</p>
</li>