mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-09 20:57:11 +00:00
36_LaCrosseGateway: flash and nextion upload non blocking
git-svn-id: https://svn.fhem.de/fhem/trunk@13515 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
44be045253
commit
f26213c2f0
@ -43,6 +43,7 @@ sub LaCrosseGateway_Initialize($) {
|
||||
." ownSensors:dispatch,readings,both"
|
||||
." mode:USB,WiFi,Cable"
|
||||
." usbFlashCommand"
|
||||
." filter"
|
||||
." $readingFnAttributes";
|
||||
|
||||
}
|
||||
@ -92,6 +93,8 @@ sub LaCrosseGateway_Undef($$) {
|
||||
my ($hash, $arg) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
|
||||
|
||||
foreach my $d (sort keys %defs) {
|
||||
if(defined($defs{$d}) && defined($defs{$d}{IODev}) && $defs{$d}{IODev} == $hash) {
|
||||
my $lev = ($reread_active ? 4 : 2);
|
||||
@ -111,6 +114,209 @@ sub LaCrosseGateway_RemoveLaCrossePair($) {
|
||||
delete($hash->{LaCrossePair});
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_LogOTA($) {
|
||||
my($text) = @_;
|
||||
BlockingInformParent("DoTrigger", ["global", " $text"], 0);
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_StartUpload($) {
|
||||
my ($string) = @_;
|
||||
my ($name, $argument) = split("\\|", $string);
|
||||
my $hash = $defs{$name};
|
||||
|
||||
sleep(2);
|
||||
LaCrosseGateway_LogOTA("Started not blocking");
|
||||
|
||||
my @deviceName = split('@', $hash->{DeviceName});
|
||||
my $port = $deviceName[0];
|
||||
my $logFile = AttrVal("global", "logdir", "./log") . "/LaCrosseGatewayFlash.log";
|
||||
my $hexFile = "./FHEM/firmware/JeeLink_LaCrosseGateway.bin";
|
||||
|
||||
if(!-e $hexFile) {
|
||||
LaCrosseGateway_LogOTA("The file '$hexFile' does not exist");
|
||||
return $name;
|
||||
}
|
||||
|
||||
LaCrosseGateway_LogOTA("flashing LaCrosseGateway $name");
|
||||
LaCrosseGateway_LogOTA("hex file: $hexFile");
|
||||
|
||||
if(AttrVal($name, "mode", "WiFi") eq "WiFi") {
|
||||
eval "use LWP::UserAgent";
|
||||
if($@) {
|
||||
LaCrosseGateway_LogOTA("ERROR: Please install LWP::UserAgent");
|
||||
return $name;
|
||||
}
|
||||
eval "use HTTP::Request::Common";
|
||||
if($@) {
|
||||
LaCrosseGateway_LogOTA("ERROR: Please install HTTP::Request::Common");
|
||||
return $name;
|
||||
}
|
||||
|
||||
LaCrosseGateway_LogOTA("Mode is LaCrosseGateway OTA-update");
|
||||
DevIo_CloseDev($hash);
|
||||
readingsSingleUpdate($hash, "state", "disconnected", 1);
|
||||
LaCrosseGateway_LogOTA("$name closed");
|
||||
|
||||
my @spl = split(':', $hash->{DeviceName});
|
||||
my $targetIP = $spl[0];
|
||||
my $targetURL = "http://" . $targetIP . "/ota/firmware.bin";
|
||||
LaCrosseGateway_LogOTA("target: $targetURL");
|
||||
|
||||
my $request = POST($targetURL, Content_Type => 'multipart/form-data', Content => [ file => [$hexFile, "firmware.bin"] ]);
|
||||
my $userAgent = LWP::UserAgent->new;
|
||||
$userAgent->timeout(120);
|
||||
LaCrosseGateway_LogOTA("Upload started, please wait a minute or two ...");
|
||||
my $response = $userAgent->request($request);
|
||||
if ($response->is_success) {
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("--- LGW reports ---------------------------------------------------------------------------");
|
||||
my @lines = split /\r\n|\n|\r/, $response->decoded_content;
|
||||
foreach (@lines) {
|
||||
LaCrosseGateway_LogOTA($_);
|
||||
}
|
||||
LaCrosseGateway_LogOTA("----------------------------------------------------------------------------------------------------");
|
||||
|
||||
}
|
||||
else {
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("ERROR: " . $response->code);
|
||||
my @lines = split /\r\n|\n|\r/, $response->decoded_content;
|
||||
foreach (@lines) {
|
||||
LaCrosseGateway_LogOTA($_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LaCrosseGateway_LogOTA("Mode is LaCrosseGateway USB-update");
|
||||
my $usbFlashCommand = AttrVal($name, "usbFlashCommand", "");
|
||||
|
||||
if ($usbFlashCommand ne "") {
|
||||
my $command = $usbFlashCommand;
|
||||
$command =~ s/\Q[PORT]\E/$port/g;
|
||||
$command =~ s/\Q[BINFILE]\E/$hexFile/g;
|
||||
$command =~ s/\Q[LOGFILE]\E/$logFile/g;
|
||||
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("Upload started, please wait a minute or two ...");
|
||||
`$command`;
|
||||
|
||||
if (-e $logFile) {
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("--- esptool ---------------------------------------------------------------------------------");
|
||||
local $/ = undef;
|
||||
open FILE, $logFile;
|
||||
my $content = <FILE>;
|
||||
my @lines = split /\r\n|\n|\r/, $content;
|
||||
foreach (@lines) {
|
||||
LaCrosseGateway_LogOTA($_);
|
||||
}
|
||||
LaCrosseGateway_LogOTA("--- esptool ---------------------------------------------------------------------------------");
|
||||
LaCrosseGateway_LogOTA("");
|
||||
}
|
||||
else {
|
||||
LaCrosseGateway_LogOTA("WARNING: esptool created no log file");
|
||||
}
|
||||
}
|
||||
else {
|
||||
LaCrosseGateway_LogOTA("No usbFlashCommand found. Please define this attribute.");
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_UploadDone($) {
|
||||
my ($name) = @_;
|
||||
return unless(defined($name));
|
||||
my $hash = $defs{$name};
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
delete($hash->{helper}{FLASHING});
|
||||
|
||||
LaCrosseGateway_Connect($hash);
|
||||
LaCrosseGateway_LogOTA("$name opened");
|
||||
|
||||
LaCrosseGateway_LogOTA("Finshed");
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_UploadError($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
delete($hash->{helper}{FLASHING});
|
||||
LaCrosseGateway_LogOTA("Upload failed");
|
||||
LaCrosseGateway_Connect($hash);
|
||||
LaCrosseGateway_LogOTA("$name opened");
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_StartNextion($) {
|
||||
my ($string) = @_;
|
||||
my ($name, $argument) = split("\\|", $string);
|
||||
my $hash = $defs{$name};
|
||||
|
||||
sleep(2);
|
||||
LaCrosseGateway_LogOTA("Started not blocking");
|
||||
|
||||
my @deviceName = split('@', $hash->{DeviceName});
|
||||
my $port = $deviceName[0];
|
||||
my $logFile = AttrVal("global", "logdir", "./log") . "/NextionUpload.log";
|
||||
my $tftFile = AttrVal($name, "tftFile", "./FHEM/firmware/nextion.tft");
|
||||
|
||||
if(!-e $tftFile) {
|
||||
LaCrosseGateway_LogOTA("The file '$tftFile' does not exist");
|
||||
return $name;
|
||||
}
|
||||
|
||||
LaCrosseGateway_LogOTA("upload Nextion firmware to $name");
|
||||
LaCrosseGateway_LogOTA("tft file: $tftFile");
|
||||
|
||||
eval "use LWP::UserAgent";
|
||||
if($@) {
|
||||
LaCrosseGateway_LogOTA("ERROR: Please install LWP::UserAgent");
|
||||
return $name;
|
||||
}
|
||||
eval "use HTTP::Request::Common";
|
||||
if($@) {
|
||||
LaCrosseGateway_LogOTA("ERROR: Please install HTTP::Request::Common");
|
||||
return $name;
|
||||
}
|
||||
|
||||
my @spl = split(':', $hash->{DeviceName});
|
||||
my $targetIP = $spl[0];
|
||||
my $targetURL = "http://" . $targetIP . "/ota/nextion";
|
||||
LaCrosseGateway_LogOTA("target: $targetURL");
|
||||
|
||||
my $request = POST($targetURL, Content_Type => 'multipart/form-data', Content => [ file => [$tftFile, "nextion.tft"] ]);
|
||||
my $userAgent = LWP::UserAgent->new;
|
||||
$userAgent->timeout(900);
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("Upload started, this can take 10 minutes or more ...");
|
||||
my $response = $userAgent->request($request);
|
||||
if ($response->is_success) {
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("--- LGW reports ---------------------------------------------------------------------------");
|
||||
my @lines = split /\r\n|\n|\r/, $response->decoded_content;
|
||||
foreach (@lines) {
|
||||
LaCrosseGateway_LogOTA($_);
|
||||
}
|
||||
LaCrosseGateway_LogOTA("----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
else {
|
||||
LaCrosseGateway_LogOTA("");
|
||||
LaCrosseGateway_LogOTA("ERROR: " . $response->code);
|
||||
my @lines = split /\r\n|\n|\r/, $response->decoded_content;
|
||||
foreach (@lines) {
|
||||
LaCrosseGateway_LogOTA($_);
|
||||
}
|
||||
}
|
||||
|
||||
return $name;
|
||||
}
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_Set($@) {
|
||||
my ($hash, @a) = @_;
|
||||
@ -126,123 +332,20 @@ sub LaCrosseGateway_Set($@) {
|
||||
LaCrosseGateway_SimpleWrite($hash, $arg);
|
||||
}
|
||||
elsif ($cmd eq "flash") {
|
||||
my @args = split(' ', $arg);
|
||||
my $log = "";
|
||||
my @deviceName = split('@', $hash->{DeviceName});
|
||||
my $port = $deviceName[0];
|
||||
my $logFile = AttrVal("global", "logdir", "./log") . "/LaCrosseGatewayFlash.log";
|
||||
my $hexFile = "./FHEM/firmware/JeeLink_LaCrosseGateway.bin";
|
||||
|
||||
return "The file '$hexFile' does not exist" if(!-e $hexFile);
|
||||
|
||||
$log .= "flashing LaCrosseGateway $name\n";
|
||||
$log .= "hex file: $hexFile\n";
|
||||
|
||||
if(AttrVal($name, "mode", "WiFi") eq "WiFi") {
|
||||
eval "use LWP::UserAgent";
|
||||
return "\nERROR: Please install LWP::UserAgent" if($@);
|
||||
|
||||
eval "use HTTP::Request::Common";
|
||||
return "\nERROR: Please install HTTP::Request::Common" if($@);
|
||||
|
||||
$log .= "Mode is LaCrosseGateway OTA-update\n";
|
||||
DevIo_CloseDev($hash);
|
||||
readingsSingleUpdate($hash, "state", "disconnected", 1);
|
||||
$log .= "$name closed\n";
|
||||
|
||||
my @spl = split(':', $hash->{DeviceName});
|
||||
my $targetIP = $spl[0];
|
||||
my $targetURL = "http://" . $targetIP . "/ota/firmware.bin";
|
||||
$log .= "target: $targetURL\n";
|
||||
|
||||
my $request = POST($targetURL, Content_Type => 'multipart/form-data', Content => [ file => [$hexFile, "firmware.bin"] ]);
|
||||
my $userAgent = LWP::UserAgent->new;
|
||||
$userAgent->timeout(60);
|
||||
my $response = $userAgent->request($request);
|
||||
if ($response->is_success) {
|
||||
$log .= "\n\nSketch reports:\n";
|
||||
$log .= $response->decoded_content;
|
||||
}
|
||||
else {
|
||||
$log .= "\nERROR: " . $response->code . " " . $response->decoded_content;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$log .= "Mode is LaCrosseGateway USB-update\n";
|
||||
my $usbFlashCommand = AttrVal($name, "usbFlashCommand", "");
|
||||
|
||||
if ($usbFlashCommand ne "") {
|
||||
if (-e $logFile) {
|
||||
unlink $logFile;
|
||||
}
|
||||
|
||||
my $command = $usbFlashCommand;
|
||||
$command =~ s/\Q[PORT]\E/$port/g;
|
||||
$command =~ s/\Q[BINFILE]\E/$hexFile/g;
|
||||
$command =~ s/\Q[LOGFILE]\E/$logFile/g;
|
||||
|
||||
$log .= "command: $command\n\n";
|
||||
`$command`;
|
||||
|
||||
local $/ = undef;
|
||||
if (-e $logFile) {
|
||||
open FILE, $logFile;
|
||||
my $logText = <FILE>;
|
||||
close FILE;
|
||||
$log .= "--- esptool ---------------------------------------------------------------------------------\n";
|
||||
$log .= $logText;
|
||||
$log .= "--- esptool ---------------------------------------------------------------------------------\n\n";
|
||||
}
|
||||
else {
|
||||
$log .= "WARNING: esptool created no log file\n\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
$log .= "\n\nNo usbFlashCommand found. Please define this attribute.\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
LaCrosseGateway_Connect($hash);
|
||||
$log .= "$name opened\n";
|
||||
|
||||
return $log;
|
||||
CallFn("WEB", "ActivateInformFn", $hash, "global");
|
||||
DevIo_CloseDev($hash);
|
||||
readingsSingleUpdate($hash, "state", "disconnected", 1);
|
||||
$hash->{helper}{FLASHING} = 1;
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("LaCrosseGateway_StartUpload", $name . "|" . $arg, "LaCrosseGateway_UploadDone", 300, "LaCrosseGateway_UploadError", $hash);
|
||||
return undef;
|
||||
}
|
||||
elsif ($cmd eq "nextionUpload") {
|
||||
my $log = "";
|
||||
my @deviceName = split('@', $hash->{DeviceName});
|
||||
my $port = $deviceName[0];
|
||||
my $logFile = AttrVal("global", "logdir", "./log") . "/NextionUpload.log";
|
||||
my $tftFile = AttrVal($name, "tftFile", "./FHEM/firmware/nextion.tft");
|
||||
|
||||
return "The file '$tftFile' does not exist" if(!-e $tftFile);
|
||||
|
||||
$log .= "upload Nextion firmware to $name\n";
|
||||
$log .= "tft file: $tftFile\n";
|
||||
|
||||
eval "use LWP::UserAgent";
|
||||
return "\nERROR: Please install LWP::UserAgent" if($@);
|
||||
|
||||
eval "use HTTP::Request::Common";
|
||||
return "\nERROR: Please install HTTP::Request::Common" if($@);
|
||||
|
||||
my @spl = split(':', $hash->{DeviceName});
|
||||
my $targetIP = $spl[0];
|
||||
my $targetURL = "http://" . $targetIP . "/ota/nextion";
|
||||
$log .= "target: $targetURL\n";
|
||||
|
||||
my $request = POST($targetURL, Content_Type => 'multipart/form-data', Content => [ file => [$tftFile, "nextion.tft"] ]);
|
||||
my $userAgent = LWP::UserAgent->new;
|
||||
$userAgent->timeout(300);
|
||||
my $response = $userAgent->request($request);
|
||||
if ($response->is_success) {
|
||||
$log .= "\n\nLGW reports:\n";
|
||||
$log .= $response->decoded_content;
|
||||
}
|
||||
else {
|
||||
$log .= "\nERROR: " . $response->code . " " . $response->decoded_content;
|
||||
}
|
||||
|
||||
return $log;
|
||||
CallFn("WEB", "ActivateInformFn", $hash, "global");
|
||||
DevIo_CloseDev($hash);
|
||||
readingsSingleUpdate($hash, "state", "disconnected", 1);
|
||||
$hash->{helper}{FLASHING} = 1;
|
||||
$hash->{helper}{RUNNING_PID} = BlockingCall("LaCrosseGateway_StartNextion", $name . "|" . $arg, "LaCrosseGateway_UploadDone", 1200, "LaCrosseGateway_UploadError", $hash);
|
||||
return undef;
|
||||
}
|
||||
elsif ($cmd eq "LaCrossePairForSec") {
|
||||
my @args = split(' ', $arg);
|
||||
@ -267,8 +370,7 @@ sub LaCrosseGateway_Set($@) {
|
||||
$po->rts_active(1);
|
||||
$po->dtr_active(1);
|
||||
}
|
||||
|
||||
|
||||
LaCrosseGateway_Connect($hash);
|
||||
}
|
||||
elsif ($cmd eq "parse") {
|
||||
LaCrosseGateway_Parse($hash, $hash, $name, $arg);
|
||||
@ -293,7 +395,7 @@ sub LaCrosseGateway_DoInit($) {
|
||||
my $hash = shift;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $enabled = AttrVal($name, "disable", "0") != "1";
|
||||
my $enabled = AttrVal($name, "disable", "0") != "1" && !defined($hash->{helper}{FLASHING});
|
||||
if($enabled) {
|
||||
readingsSingleUpdate($hash, "state", "opened", 1);
|
||||
if(AttrVal($name, "mode", "") ne "USB") {
|
||||
@ -377,6 +479,15 @@ sub LaCrosseGateway_HandleKVP($$) {
|
||||
if($kvp =~ m/FramesPerMinute=(.*?)(\,|\ ,)/) {
|
||||
readingsBulkUpdate($hash, "FramesPerMinute", $1);
|
||||
}
|
||||
if($kvp =~ m/ReceivedFrames=(.*?)(\,|\ ,)/) {
|
||||
readingsBulkUpdate($hash, "ReceivedFrames", $1);
|
||||
}
|
||||
if($kvp =~ m/FreeHeap=(.*?)(\,|\ ,)/) {
|
||||
readingsBulkUpdate($hash, "FreeHeap", $1);
|
||||
}
|
||||
if($kvp =~ m/OLED=(.*?)(\,|\ ,)/) {
|
||||
readingsBulkUpdate($hash, "OLED", $1);
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, 1);
|
||||
}
|
||||
@ -442,16 +553,19 @@ sub LaCrosseGateway_HandleAnalogData($$) {
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#=======================================================================================
|
||||
sub LaCrosseGateway_Parse($$$$) {
|
||||
my ($hash, $iohash, $name, $msg) = @_;
|
||||
|
||||
next if (!$msg || length($msg) < 1);
|
||||
return if ($msg =~ m/^\*\*\*CLEARLOG/);
|
||||
|
||||
return if ($msg =~ m/[^\x20-\x7E]/);
|
||||
|
||||
|
||||
my $filter = AttrVal($name, "filter", undef);
|
||||
if(defined($filter)) {
|
||||
return if ($msg =~ m/$filter/);
|
||||
}
|
||||
|
||||
if ($msg =~ m/^LGW/) {
|
||||
if ($msg =~ /ALIVE/) {
|
||||
@ -550,7 +664,7 @@ sub LaCrosseGateway_Connect($;$) {
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
$mode = 0 if!($mode);
|
||||
my $enabled = AttrVal($name, "disable", "0") != "1";
|
||||
my $enabled = AttrVal($name, "disable", "0") != "1" && !defined($hash->{helper}{FLASHING});
|
||||
if($enabled) {
|
||||
my $ret = DevIo_OpenDev($hash, $mode, "LaCrosseGateway_DoInit");
|
||||
return $ret;
|
||||
@ -590,7 +704,7 @@ sub LaCrosseGateway_OnConnectTimer($) {
|
||||
|
||||
InternalTimer(gettimeofday() + $interval, "LaCrosseGateway_OnConnectTimer", $hash, 0);
|
||||
|
||||
if(AttrVal($name, "disable", "0") != "1") {
|
||||
if(AttrVal($name, "disable", "0") != "1" && !defined($hash->{helper}{FLASHING})) {
|
||||
my ($date, $time, $year, $month, $day, $hour, $min, $sec, $timestamp, $alive);
|
||||
if($useOldMethod) {
|
||||
$alive = InternalVal($name, "${name}_TIME", "2000-01-01 00:00:00");
|
||||
@ -819,6 +933,18 @@ sub LaCrosseGateway_Attr(@) {
|
||||
<li>tftFile<br>
|
||||
defines the .tft file that shall be used by the Nextion firmware upload (set nextionUpload)
|
||||
</li><br>
|
||||
|
||||
<li>filter<br>
|
||||
defines a filter (regular expression) that is applied to the incoming data. If the regex matches, the data will be discarded.<br>
|
||||
This allows to suppress sensors, for example those of the neighbour.<br>
|
||||
The data of different kinds of sensors starts with (where xx is the ID):<br>
|
||||
LaCrosse sensor: OK 9 xx<br>
|
||||
EnergyCount 3000: OK 22 xx xx<br>
|
||||
EMT7110: OK EMT7110 xx xx<br>
|
||||
LevelSender: OK LS xx<br>
|
||||
Example: set lgw filter ^OK 22 117 196|^OK 9 49<br>
|
||||
will filter the LaCrosse sensor with ID "49" and the EC3000 with ID "117 196"
|
||||
</li><br>
|
||||
|
||||
</ul>
|
||||
<br>
|
||||
|
Loading…
x
Reference in New Issue
Block a user