From a183a561cb82a1413dd31bcb19567ef511eb8fbb Mon Sep 17 00:00:00 2001 From: justme-1968 Date: Sun, 21 Dec 2014 20:25:45 +0000 Subject: [PATCH] 34_SWAP.pm: added flash command for panStamp NRG ota update (by mgehre) added internals and readings cleanup on ProductCode change (by mgehre) added createUnknownReadings attribute see also: http://forum.fhem.de/index.php/topic,30589.msg233658.html#msg233658 git-svn-id: https://svn.fhem.de/fhem/trunk@7295 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/34_SWAP.pm | 80 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 75 insertions(+), 5 deletions(-) diff --git a/fhem/FHEM/34_SWAP.pm b/fhem/FHEM/34_SWAP.pm index 39beb44ad..4a5855006 100755 --- a/fhem/FHEM/34_SWAP.pm +++ b/fhem/FHEM/34_SWAP.pm @@ -86,6 +86,7 @@ SWAP_Initialize($) $hash->{AttrFn} = "SWAP_Attr"; $hash->{AttrList} = "IODev". " ignore:1,0". + " createUnknownReadings:1,0". " $readingFnAttributes" . " ProductCode:".join(",", sort keys %{$products}); @@ -242,7 +243,7 @@ SWAP_Define($$) my @a = split("[ \t][ \t]*", $def); if(@a != 3 && @a != 4 ) { - my $msg = "wrong syntax: define SWAP [.] []"; + my $msg = "wrong syntax: define SWAP [.]"; Log3 undef, 2, $msg; return $msg; } @@ -299,6 +300,9 @@ SWAP_Define($$) $hash->{product} = $products->{$productcode} if( defined($productcode) && defined($products->{$productcode} ) ); + $hash->{DEF} = $hash->{addr}; + $hash->{DEF} .= $hash->{reg} if( $hash->{reg} ); + SWAP_Send($hash, $addr, QUERY, "00" ); return undef; @@ -624,7 +628,6 @@ SWAP_Set($@) } } - } elsif( $cmd eq "readDeviceXML" ) { my $productcode = $attr{$name}{ProductCode} if( defined($attr{$name}{ProductCode} ) ); if( defined($products->{$productcode} ) ) { @@ -633,9 +636,34 @@ SWAP_Set($@) } else { return "can't read deviceXML for unknown ProductCode"; } + } elsif( $cmd eq "clearUnconfirmed" ) { delete( $hash->{sentList} ); delete ($hash->{SWAP_Sent_unconfirmed}); + + } elsif( $cmd eq "flash" ) { + my $firmwareFolder = "./FHEM/firmware/"; + my $hexfile; + if ($cnt < 2) { + #No argument to flash + return "Device has no product code; you need to specify a firmeware to flash" if( !defined($attr{$name}{ProductCode} ) ); + $hexfile = $firmwareFolder . "SWAP_$attr{$name}{ProductCode}.hex"; + } else { + if ( substr($arg, 0, 1) eq "/" ) { + #absolute path provided + $hexfile = $arg; + } else { + #Product code provided + $hexfile = $firmwareFolder . "SWAP_$arg.hex"; + } + } + open FILE, $hexfile or return "Could not open $hexfile"; + Log3 $name, 1, "Flashing $hexfile to $name"; + my @a = ; + @a = map { substr $_, 3, -1 } @a; + $hash->{HEXFILE} = [ @a ]; + SWAP_Send($hash, $addr, COMMAND, "03", "05" ); #Set "System State" to "Flash" + } else { return SetExtensions($hash, $list, $name, @aa); return "Unknown argument $cmd, choose one of ".$list; @@ -840,7 +868,7 @@ SWAP_updateReadings($$$) readingsBulkUpdate($hash, "state", (substr($data,0,6) eq "000000"?"off":$data)) if( defined($attr{$name}{ProductCode}) && $attr{$name}{ProductCode} eq '0000002200000003' && $reg == 0x0B ); readingsBulkUpdate($hash, "state", $data) if( $hash->{reg} && hex($hash->{reg}) == $reg ); readingsEndUpdate($hash,1); - } else { + } elsif( AttrVal($name, "createUnknownReadings",0 ) ) { readingsBeginUpdate($hash); readingsBulkUpdate($hash, $rid, $data); readingsBulkUpdate($hash, "state", $data) if( $hash->{reg} && hex($hash->{reg}) == $reg ); @@ -924,6 +952,18 @@ SWAP_Parse($$) Log3 $name, 4, $sname ." -> ". $dname ." ($hop,$secu-$nonce): ". $function_codes{$func} . " ". $rname . " ". $regname . ($data?":":"") . $data; + if( $raddr eq "01" and $func == QUERY and $rid eq "0B" and length($data) == 4 ) { + #Uploading firmware + my $lineno = hex($data); + Log3 $name, 4, "Serving firmware request of $src for line no. $lineno"; + if (exists($shash->{HEXFILE})) { + SWAP_Send($shash, "00", STATUS, "0B", $data.$shash->{HEXFILE}[$lineno] ); + } else { + Log3 $name, 1, "SWAP device $src is in flash mode, but no hex file is configured. Use 'set $name flash HEXFILE'"; + } + } + + return $rname if( $raddr eq "01" ); return $rname if( $func == QUERY ); @@ -944,10 +984,11 @@ SWAP_Parse($$) #product code if( $reg == 0x00 ) { - my $first = !defined($rhash->{"SWAP_00-ProductCode"}); my $productcode = $data; - SWAP_Attr( "set", $rname, "ProductCode", $productcode ) if( !defined( $attr{$rname}{ProductCode} ) ); + my $first = !defined($rhash->{"SWAP_00-ProductCode"}) || $rhash->{"SWAP_00-ProductCode"} ne $productcode; + + SWAP_Attr( "set", $rname, "ProductCode", $productcode ) if( $first ); if( !defined($products->{$productcode}->{registers}) ){ SWAP_readDeviceXML( $rhash, $productcode ); @@ -1119,6 +1160,26 @@ SWAP_Attr(@) my $hash = $defs{$name}; my $productcode = $attrVal; + #Product code changed (due to flash of different firmware or switch of addresses) + if( defined( $attr{$name}{ProductCode} ) && $attr{$name}{ProductCode} ne $productcode) { + my $oldproductcode = "None"; + $oldproductcode = $attr{$name}{ProductCode} if( defined( $attr{$name}{ProductCode} ) ); + Log3 $name, 3, "Device $name changed product code from $oldproductcode to $productcode"; + #Delete all SWAP_HEX- + foreach my $key (keys %{$hash}) { + if ($key =~ "^SWAP_[0-9A-F][0-9A-F]-") { + Log3 $name, 5, "Deleting $key"; + delete $hash->{$key}; + } + } + + #Delete all readings + foreach my $key (keys %{$hash->{READINGS}}) { + Log3 $name, 5, "Deleting reading $key"; + delete $hash->{READINGS}{$key}; + } + } + if( !defined($products->{$productcode}->{registers}) ){ SWAP_readDeviceXML( $hash, $productcode ); } @@ -1230,6 +1291,12 @@ SWAP_Attr(@)
  • clearUnconfirmed
    clears the list of unconfirmed messages.

  • +
  • flash [<productCode>|<firmwareFile>]
    + will initiate an ota firmware update. only possible for panStamp NRG devices.
    + no params -> will use the SWAP_<current productCode>.hex file from the FHEM/firmware directory.
    + <productCode> -> will use the SWAP_<productCode>.hex file from the FHEM/firmware directory.
    + <firmwareFile> -> will use <firmwareFile> as the absolute file name of the hex file.
    +

  • @@ -1255,6 +1322,9 @@ SWAP_Attr(@) Attributes
      +
    • createUnknownReadings
      + Create readings for unknown registers, i.e. registers not defined in the device xml file. +

    • ProductCode
      ProductCode of the device. used to read the register configuration from the device definition file. hast to be set manualy for devices that are in sleep mode during definition.