defmod MyDownloader dummy
attr MyDownloader userattr Filepath
attr MyDownloader devStateIcon {\
#Lade mehrere Dinge herunter, füllt ggf. das Backlog:\
my $cmd = <<"CMD";;\
set $name job Filepath="/opt/fhem/www/tasmota.bin" https://ota.tasmota.com/tasmota/release/tasmota.bin;;\
set $name job Filepath="/opt/fhem/www/tasmota.bin.gz" https://ota.tasmota.com/tasmota/release/tasmota.bin.gz;;\
set $name job Filepath="/opt/fhem/www/tasmota-minimal.bin.gz" https://ota.tasmota.com/tasmota/release/tasmota-minimal.bin.gz;;\
set $name job Filepath="/opt/fhem/www/tasmota32-zbbrdgpro.bin" https://ota.tasmota.com/tasmota32/release/tasmota32-zbbrdgpro.bin\
CMD\
\
#verpacke das ganze sicher für den Transport als BASE64 und als RCE payload:\
$cmd = "{fhem(MIME::Base64::decode_base64('". encode_base64($cmd,'') ."'))}";;\
$cmd = urlEncode($cmd);;\
\
#Mit JS wird verhindert, dass der Browser navigiert:\
my $link = "<a href=\"#\" onclick=\"".\
"FW_cmd(FW_root + '?XHR=1&cmd=${cmd}', function(data){log('📂: ' + data)});; return false;;".\
"\">📂</a>";;\
\
return "<div>". ReadingsVal($name, "result", "???") ." $link</div>";;\
}
attr MyDownloader readingList job
attr MyDownloader setList job
attr MyDownloader userReadings result:job:.* {\
my $hash = $defs{$name};;\
my $job = ReadingsVal($name, "job", 'https://fhem.de/www/images/default/fhemicon.png');;\
my $path = AttrVal($name, "Filepath", "/opt/fhem/www/download.bin");;\
\
if ($job =~ s/(?:Filepath|Dateipfad)="(.*?)"//) {\
$path = $1;;\
}\
\
# Entferne Whitespaces:\
$job =~ s/^\s+|\s+$//g;;\
\
# Wenn busy aktiv ist, dann den Job ins Backlog schieben:\
if (ReadingsVal($name, "busy", 0) != 0) {\
my $backlog = ReadingsVal($name, "backlog", "");;\
$backlog .= "Filepath=\"${path}\" ${job}\n";;\
readingsBulkUpdate($hash, "backlog", $backlog, 1);;\
return "queued job ($job)";;\
}\
\
# ab hier sind wir busy mit dem request:\
readingsBulkUpdate($hash, "busy", 1, 1);;\
\
# definiere Callback:\
my $fnFct = sub {\
my ($param, $err, $data) = @_;;\
\
my $len = $data ? length($data) : 0;;\
my $fw_hash = {FileName => $path, ForceType => "file", NoNL => 1};;\
my $error = $err ? $err : FileWrite($fw_hash, $data);;\
\
readingsBeginUpdate($hash);;\
readingsBulkUpdate($hash, "result", "saved $len Bytes to $path", 1) if !$error;;\
readingsBulkUpdate($hash, "result", "ERROR ($error|$err|$path|$job)", 1) if $error;;\
\
# prüfe das Backlog:\
my $backlog = ReadingsVal($name, "backlog", "");;\
my @lines = grep { /\S/ } split(/\r?\n/, $backlog);;\
\
if (@lines) {\
my $next = shift @lines;; # ersten Job holen\
my $newbacklog = join("\n", @lines);;\
readingsBulkUpdate($hash, "backlog", $newbacklog, 1);;\
\
# Nächsten Job starten wenn diese Funktion endet,\
# deswegen über "@cmdList","%sleepers" in fhem.pl\
fhem("sleep 0.0;; set $name job $next");;\
}\
\
readingsBulkUpdate($hash, "busy", 0, 1);;\
readingsEndUpdate($hash, 1);;\
};;\
\
# prepare and call HttpUtils:\
my $param = {\
url => $job,\
timeout => 10,\
hash => $hash,\
method => "GET",\
callback => $fnFct\
};;\
HttpUtils_NonblockingGet($param);;\
\
return "download job started ($job)";;\
}
attr CN.Blaubrenner userReadings Bestellmenge {
my $tankvol = ReadingsNum($name,"Tankvolumen",0);
my $level = ReadingsNum($name,"appTanklevel",0);
my $min = ReadingsNum($name,"minOrderVolume",0);
my $bedarf = $tankvol - $level;
$bedarf = 0 if $bedarf < 0;
# Mindestbestellmenge anwenden
$bedarf = $bedarf < $min ? $min : $bedarf;
# Auf volle 100 l aufrunden
$bedarf = int(($bedarf + 99) / 100) * 100;
return $bedarf;
}
Zitat von: rabehd am 18 Dezember 2025, 13:51:23Grüße aus dem Kraichgau, längerfristig gernedurch das westliche Kraichgau würde ich eh fahren....

{
"connections" : [
{
"port" : "8084",
"filter" : "alexaName=..*",
"server" : "127.0.0.1",
"webname" : "fhem",
"name" : "FHEM",
"uid" : 0
}
],
"sshproxy" : {
"description" : "FHEM Connector",
"ssh" : "/usr/bin/ssh"
}
}
root@fhem:/# nodejs --version
v18.20.4
root@fhem:/# npm update -g alexa-fhem
up to date in 67ms
root@fhem:/# npm update -g alexa-fhem --verbose
npm verb cli /usr/bin/node /usr/bin/npm
npm info using npm@9.2.0
npm info using node@v18.20.4
npm verb title npm update alexa-fhem
npm verb argv "update" "--global" "alexa-fhem" "--loglevel" "verbose"
npm verb logfile logs-max:10 dir:/root/.npm/_logs/2025-12-18T22_10_14_735Z-
npm verb logfile /root/.npm/_logs/2025-12-18T22_10_14_735Z-debug-0.log
up to date in 71ms
npm verb exit 0
npm info ok
root@fhem:/#