ich lasse mir manchmal ein list eines devices über email senden.
heute habe ich festgestellt, dass es mit einigen devices nicht funktioniert. anscheinend ist der inhalt des list dafür verantwortlich. die emal bleibt dann leer und erzeugt folgende einträge in fhem.log:
sh: syntax error: unexpected redirection
rm: can't remove 'fhem_nachricht.txt': No such file or directory
ein anderes list
sh: can't open div: no such file
rm: can't remove 'fhem_nachricht.txt': No such file or directory
zum testen für die fhem-eingabezeile nutze ich:
{my $email_text = fhem("list refRoom");;FB_mail('xxx@yyy.de',"test",$email_text)}
hier das nicht funktionierende list der 1. fehlermeldung
Internals:
NAME refRoom
NR 548
STATE <div style="text-align:left"><form name="configHeatingControl" action="" method="get"><fieldset><legend>Heizung</legend><pre>Kommunikation: [?HZG_BETRIEB=03] => no problem<br>Zeitpunkt: 2015-12-11 08:53:09<br><br>Kommunikation: [?HZG1_KOMF=18.0] => no problem<br>Zeitpunkt: 2015-12-11 15:52:28<br><br>Kommunikation: [?HZG1_RAUM=16.8] => no problem<br>Zeitpunkt: 2015-12-11 16:51:31<br><br> | Modus | Tkomf | Traum | Hyst- | Hyst+ | Tmodus |
-----------------------------------------------------------------
<b id="com2broetje" style="color:lightgray">-></b> |<b style="color:lightgreen"> komf </b>|<b style="color:lightgreen"> 18.0 °C </b>|<b style="color:lightgreen"> 16.8 °C </b>|<select id="hystDown"><option>0.0</option><option>0.1</option><option>0.2</option><option>0.3</option><option>0.4</option><option>0.5</option></select>|<select id="hystUp"><option>0.0</option><option>0.1</option><option>0.2</option><option>0.3</option><option>0.4</option><option>0.5</option></select>|<select id="refTistModus"><option>min</option><option>avg</option><option>max</option></select>|<br> <- |<b style="color:lightgreen"> komf </b>|<b style="color:lightgreen"> 18.0 °C </b>|<b style="color:lightgreen"> 16.8 °C </b>|<br></pre></fieldset></form><form name="selectRefRooms" action="" method="get"><fieldset><legend>Referenzräume</legend><pre> Raum | Modus | Tsoll | Tist | Vsoll | Vist | PID | err/lost/day |
------------------------------------------------------------------------------
<label for="roomWZ"><input type="checkbox" name="checkRefRooms" value="WZ" id="roomWZ"><b style="color:red"> WZ </b>|<b style="color:red"> demand </b>|<b style="color:red"> 18.0 °C </b>|<b style="color:red"> 17.7 °C </b>|<b style="color:red"> 99 % </b>|<b style="color:red"> 99 % </b>|<b style="color:red"> stop </b>|<b style="color:red"> 84/ 2/ 3.1 </b>|</label><br><label for="roomKueche"><input type="checkbox" name="checkRefRooms" value="Kueche" id="roomKueche"><b style="color:lightgray"> Kueche </b>|<b style="color:lightgray"> idle </b>|<b style="color:lightgray"> 18.5 °C </b>|<b style="color:lightgray"> 18.5 °C </b>|<b style="color:lightgray"> 26 % </b>|<b style="color:lightgray"> 26 % </b>|<b style="color:lightgray"> start </b>|<b style="color:lightgray"> 77/ 2/ 2.8 </b>|</label><br><label for="roomBad"><input type="checkbox" name="checkRefRooms" value="Bad" id="roomBad"><b style="color:lightgray"> Bad </b>|<b style="color:lightgray"> idle </b>|<b style="color:lightgray"> 18.0 °C </b>|<b style="color:lightgray"> 18.7 °C </b>|<b style="color:lightgray"> 22 % </b>|<b style="color:lightgray"> 22 % </b>|<b style="color:lightgray"> start </b>|<b style="color:lightgray"> 100/ 1/ 3.7 </b>|</label><br><label for="roomAZ"><input type="checkbox" name="checkRefRooms" value="AZ" id="roomAZ"><b style="color:lightgray"> AZ </b>|<b style="color:lightgray"> idle </b>|<b style="color:lightgray"> 18.0 °C </b>|<b style="color:lightgray"> 18.7 °C </b>|<b style="color:lightgray"> 06 % </b>|<b style="color:lightgray"> 08 % </b>|<b style="color:lightgray"> start </b>|<b style="color:lightgray"> 159/ 0/ 5.9 </b>|</label><br><label for="roomSZ"><input type="checkbox" name="checkRefRooms" value="SZ" id="roomSZ"><b style="color:lightgray"> SZ </b>|<b style="color:lightgray"> demand </b>|<b style="color:lightgray"> 17.5 °C </b>|<b style="color:lightgray"> 15.8 °C </b>|<b style="color:lightgray"> 99 % </b>|<b style="color:lightgray"> 99 % </b>|<b style="color:lightgray"> start </b>|<b style="color:lightgray"> 89/ 1/ 3.3 </b>|</label><br></pre></fieldset></form></div><script>hystDown.options[4].selected=true;hystUp.options[0].selected=true;refTistModus.options[1].selected=true;roomWZ.checked=true;roomKueche.checked=true;roomBad.checked=true;roomSZ.checked=true;document.getElementById("hystDown").addEventListener("change", syncAttr);document.getElementById("hystUp").addEventListener("change", syncAttr);document.getElementById("refTistModus").addEventListener("change", syncAttr);document.getElementById("roomWZ").addEventListener("change", syncReading);document.getElementById("roomKueche").addEventListener("change", syncReading);document.getElementById("roomBad").addEventListener("change", syncReading);document.getElementById("roomAZ").addEventListener("change", syncReading);document.getElementById("roomSZ").addEventListener("change", syncReading);function syncAttr(ev) { var attr = ev.target.options[ev.target.selectedIndex].text; FW_cmd("/fhem?XHR=1&cmd=attr refRoom "+ev.target.id+" "+attr); }function syncReading() { var rooms = document.getElementsByName("checkRefRooms"); var reading = "WZ,Kueche,Bad,AZ,SZ:"; for (i = 0; i < rooms.length; i++) { if(rooms[i].checked == true) { if(reading.charAt(reading.length-1) == ":") { reading += rooms[i].value; } else { reading += ","+rooms[i].value; } } } FW_cmd("/fhem?XHR=1&cmd=setreading refRoom refRooms "+reading); }</script>
TYPE dummy
Readings:
2015-12-11 12:11:07 Thermostat.AZ idle
2015-12-11 08:52:09 Thermostat.AZ_PIDstat start
2015-12-11 16:28:27 Thermostat.AZ_Tist 18.7
2015-12-11 09:16:07 Thermostat.AZ_Tsoll 18.0
2015-12-11 16:47:27 Thermostat.AZ_Vist 8
2015-12-11 16:53:27 Thermostat.AZ_Vsoll 6
2015-12-11 14:51:07 Thermostat.Bad idle
2015-12-11 08:52:09 Thermostat.Bad_PIDstat start
2015-12-11 16:10:27 Thermostat.Bad_Tist 18.7
2015-12-11 09:08:07 Thermostat.Bad_Tsoll 18.0
2015-12-11 16:48:27 Thermostat.Bad_Vist 22
2015-12-11 16:54:27 Thermostat.Bad_Vsoll 22
2015-12-11 15:50:27 Thermostat.Kueche idle
2015-12-11 15:50:29 Thermostat.Kueche_PIDstat start
2015-12-11 16:33:27 Thermostat.Kueche_Tist 18.5
2015-12-11 09:07:08 Thermostat.Kueche_Tsoll 18.5
2015-12-11 16:40:27 Thermostat.Kueche_Vist 26
2015-12-11 16:33:27 Thermostat.Kueche_Vsoll 26
2015-12-11 08:52:07 Thermostat.SZ demand
2015-12-11 09:07:10 Thermostat.SZ_PIDstat start
2015-12-11 15:56:27 Thermostat.SZ_Tist 15.8
2015-12-10 21:15:07 Thermostat.SZ_Tsoll 17.5
2015-12-11 10:05:07 Thermostat.SZ_Vist 99
2015-12-11 09:57:08 Thermostat.SZ_Vsoll 99
2015-12-11 09:07:07 Thermostat.WZ demand
2015-12-11 15:50:28 Thermostat.WZ_PIDstat stop
2015-12-11 16:31:27 Thermostat.WZ_Tist 17.7
2015-12-11 09:07:07 Thermostat.WZ_Tsoll 18.0
2015-12-11 15:58:27 Thermostat.WZ_Vist 99
2015-12-11 15:50:28 Thermostat.WZ_Vsoll 99
2015-12-11 08:52:08 demandHzg 3
2015-12-11 08:53:09 httpErrBetrieb [?HZG_BETRIEB=03] => no problem
2015-12-11 15:52:28 httpErrKomf [?HZG1_KOMF=18.0] => no problem
2015-12-11 16:51:31 httpErrRaum [?HZG1_RAUM=16.8] => no problem
2015-12-11 07:51:08 lock off
2015-12-11 15:50:27 refRoom WZ
2015-12-08 23:27:29 refRooms WZ,Kueche,Bad,AZ,SZ:WZ,Kueche,Bad,SZ
2015-12-11 16:31:27 refTist 16.8
2015-12-11 15:50:27 refTsoll 18.0
2015-12-10 07:45:50 state 0_all_off
Attributes:
[object HTMLSelectElement] 0.0
event-on-change-reading .*
event-on-update-reading httpErr,state
group Heizung
hystDown 0.4
hystUp 0.0
refTistModus avg
room 03_Test,80_HZG,98_Ventile
setList state:0_all_off,1_all_min,2_all_max,3_all_15,4_all_18
stateFormat { my $defaultRooms = "WZ,Kueche,Bad,AZ,SZ"; my $defaultRefRooms = "WZ,Kueche,Bad,AZ,SZ"; my (undef,$refRooms) = split(':',ReadingsVal("refRoom","refRooms",$defaultRooms.":".$defaultRefRooms)); my @allRooms = split(',',$defaultRooms); my @refRooms = split(',',$refRooms); my $refRoom = ReadingsVal("refRoom","refRoom",""); my $demandHzg = ReadingsVal("refRoom","demandHzg",0); my $demandHzgTxt = ($demandHzg > 0)?"komf":"frost"; my $demandHzgIst = ReadingsVal("Broetje","hkBetrModus",0); my $demandHzgIstTxt = ($demandHzgIst > 0)?"komf":"frost"; my $lock = ReadingsVal("refRoom","lock","on"); my $refTistModus = AttrVal("refRoom","refTistModus","avg"); my $demandRoom; my $Tkomf = ReadingsVal("Broetje","hkTkomf",15); my $Traum = ReadingsVal("Broetje","hkTraum",0); my $refTist = ReadingsVal("refRoom","refTist",0); my $refTsoll = ReadingsVal("refRoom","refTsoll",15); my $Tsoll; my $Tist; my $hystUp = AttrVal("refRoom","hystUp",0.1); my $hystDown = AttrVal("refRoom","hystDown",0.3); my $Vsoll; my $Vist; my $PID; my $day; my $lost; my $err; my $colorHzgModus = ($demandHzgIst == $demandHzg)?"lightgreen":"red"; my $colorTkomf = (sprintf("%.1f",$Tkomf) == $refTsoll)?"lightgreen":"red"; my $colorTraum = (sprintf("%.1f",$Traum) == $refTist)?"lightgreen":"red"; my $colorRefRoom; my $colorDemandRoom; my $colorComModus; my $errComModus = ReadingsVal("refRoom","httpErrBetrieb","?"); if($errComModus =~ m/^\[\?HZG_BETRIEB=0\d\] => send/) { $colorComModus = "yellow"; } elsif($errComModus =~ m/^\[\?HZG_BETRIEB=0\d\] => no problem/) { $colorComModus = "lightgreen"; } else { $colorComModus = "red"; } my $colorComTkomf; my $errComTkomf = ReadingsVal("refRoom","httpErrKomf","?"); if($errComTkomf =~ m/^\[\?HZG1_KOMF=\d+\.\d\] => send/) { $colorComTkomf = "yellow"; } elsif($errComTkomf =~ m/^\[\?HZG1_KOMF=\d+\.\d\] => no problem/) { $colorComTkomf = "lightgreen"; } else { $colorComTkomf = "red"; } my $colorComTraum; my $errComTraum = ReadingsVal("refRoom","httpErrRaum","?"); if($errComTraum =~ m/^\[\?HZG1_RAUM=\d+\.\d\] => send/) { $colorComTraum = "yellow"; } elsif($errComTraum =~ m/^\[\?HZG1_RAUM=\d+\.\d\] => no problem/) { $colorComTraum = "lightgreen"; } else { $colorComTraum = "red"; } my $colorCom = ($colorComModus eq "yellow" || $colorComTkomf eq "yellow" || $colorComTraum eq "yellow")?"yellow":"lightgray"; my $ret = '<div style="text-align:left">'; $ret .= '<form name="configHeatingControl" action="" method="get">'; $ret .= '<fieldset><legend>Heizung</legend><pre>'; $ret .= 'Kommunikation: '.ReadingsVal("refRoom","httpErrBetrieb","???").'<br>'; $ret .= 'Zeitpunkt: '.ReadingsTimestamp("refRoom","httpErrBetrieb","???").'<br><br>'; $ret .= 'Kommunikation: '.ReadingsVal("refRoom","httpErrKomf","???").'<br>'; $ret .= 'Zeitpunkt: '.ReadingsTimestamp("refRoom","httpErrKomf","???").'<br><br>'; $ret .= 'Kommunikation: '.ReadingsVal("refRoom","httpErrRaum","???").'<br>'; $ret .= 'Zeitpunkt: '.ReadingsTimestamp("refRoom","httpErrRaum","???").'<br><br>'; $ret .= " | Modus | Tkomf | Traum | Hyst- | Hyst+ | Tmodus |\n"; $ret .= " -----------------------------------------------------------------\n"; $ret .= " "; $ret .= '<b id="com2broetje" style="color:'.$colorCom.'">'; $ret .= "->"; $ret .= '</b>'; $ret .= " "; $ret .= "|"; $ret .= '<b style="color:'.$colorComModus.'">'; $ret .= sprintf(" %5s ",$demandHzgTxt); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorComTkomf.'">'; $ret .= sprintf(" %4.1f °C ",$refTsoll); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorComTraum.'">'; $ret .= sprintf(" %4.1f °C ",$refTist); $ret .= '</b>'; $ret .= "|"; $ret .= '<select id="hystDown">'; $ret .= '<option>0.0</option>'; $ret .= '<option>0.1</option>'; $ret .= '<option>0.2</option>'; $ret .= '<option>0.3</option>'; $ret .= '<option>0.4</option>'; $ret .= '<option>0.5</option>'; $ret .= '</select>'; $ret .= "|"; $ret .= '<select id="hystUp">'; $ret .= '<option>0.0</option>'; $ret .= '<option>0.1</option>'; $ret .= '<option>0.2</option>'; $ret .= '<option>0.3</option>'; $ret .= '<option>0.4</option>'; $ret .= '<option>0.5</option>'; $ret .= '</select>'; $ret .= "|"; $ret .= '<select id="refTistModus">'; $ret .= '<option>min</option>'; $ret .= '<option>avg</option>'; $ret .= '<option>max</option>'; $ret .= '</select>'; $ret .= "|"; $ret .= '<br>'; $ret .= " <- "; $ret .= "|"; $ret .= '<b style="color:'.$colorHzgModus.'">'; $ret .= sprintf(" %5s ",$demandHzgIstTxt); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorTkomf.'">'; $ret .= sprintf(" %4.1f °C ",$Tkomf); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorTraum.'">'; $ret .= sprintf(" %4.1f °C ",$Traum); $ret .= '</b>'; $ret .= "|"; $ret .= '<br>'; $ret .= '</pre></fieldset>'; $ret .= '</form>'; $ret .= '<form name="selectRefRooms" action="" method="get">'; $ret .= '<fieldset><legend>Referenzräume</legend><pre>'; $ret .= " Raum | Modus | Tsoll | Tist | Vsoll | Vist | PID | err/lost/day |\n"; $ret .= " ------------------------------------------------------------------------------\n"; foreach my $room (@allRooms) { if(($room eq $refRoom) && $demandHzg) { $colorRefRoom = "red"; } elsif (($room eq $refRoom) && !$demandHzg) { $colorRefRoom = "dodgerblue"; } else { $colorRefRoom = "lightgray"; } $Tist = ReadingsVal("refRoom","Thermostat.".$room."_Tist",0); $Tsoll = ReadingsVal("refRoom","Thermostat.".$room."_Tsoll",0); $Vsoll = ReadingsVal("refRoom","Thermostat.".$room."_Vsoll","???"); $Vist = ReadingsVal("refRoom","Thermostat.".$room."_Vist","???"); $PID = ReadingsVal("refRoom","Thermostat.".$room."_PIDstat","???"); $err = ReadingsVal("VentilControler.".(($room eq "AZ")?"AZ.Nord":$room)."_Btn1","errorCtr",0); $lost = ReadingsVal("VentilControler.".(($room eq "AZ")?"AZ.Nord":$room)."_Btn1","lostCtr",0); $day = ReadingsVal("VentilControler.".(($room eq "AZ")?"AZ.Nord":$room)."_Btn1","errorAvg",0); $demandRoom = ReadingsVal("refRoom","Thermostat.".$room,"idle"); if(($demandRoom eq "demand") && ($lock eq "on") && ($refRooms =~ m/$room/)) { $demandRoom = "locked"; $colorDemandRoom = "red"; } else { $colorDemandRoom = $colorRefRoom; } $ret .= '<label for="room'.$room.'">'; $ret .= '<input type="checkbox" name="checkRefRooms" value="'.$room.'" id="room'.$room.'">'; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %-6s ",$room); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorDemandRoom.'">'; $ret .= sprintf(" %6s ",$demandRoom); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %4.1f °C ",$Tsoll); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %4.1f °C ",$Tist); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %02d %% ",$Vsoll); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %02d %% ",$Vist); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %5s ",$PID); $ret .= '</b>'; $ret .= "|"; $ret .= '<b style="color:'.$colorRefRoom.'">'; $ret .= sprintf(" %4d/%2d/%4.1f ",$err,$lost,$day); $ret .= '</b>'; $ret .= "|"; $ret .= '</label><br>'; } $ret .= '</pre></fieldset>'; $ret .= '</form>'; $ret .= '</div>'; $ret .= '<script>'; $ret .= 'hystDown.options['.int($hystDown*10).'].selected=true;'; $ret .= 'hystUp.options['.int($hystUp*10).'].selected=true;'; my $idx; if($refTistModus eq "min") { $idx = 0; } elsif($refTistModus eq "avg") { $idx = 1; } else { $idx = 2; } $ret .= 'refTistModus.options['.$idx.'].selected=true;'; foreach (@refRooms) { $ret .= 'room'.$_.'.checked=true;'; } $ret .= 'document.getElementById("hystDown").addEventListener("change", syncAttr);'; $ret .= 'document.getElementById("hystUp").addEventListener("change", syncAttr);'; $ret .= 'document.getElementById("refTistModus").addEventListener("change", syncAttr);'; foreach (@allRooms) { $ret .= 'document.getElementById("room'.$_.'").addEventListener("change", syncReading);'; } $ret .= 'function syncAttr(ev) { var attr = ev.target.options[ev.target.selectedIndex].text; FW_cmd("/fhem?XHR=1&cmd=attr refRoom "+ev.target.id+" "+attr); }'; $ret .= 'function syncReading() { var rooms = document.getElementsByName("checkRefRooms"); var reading = "'.$defaultRooms.":".'"; for (i = 0; i < rooms.length; i++) { if(rooms[i].checked == true) { if(reading.charAt(reading.length-1) == ":") { reading += rooms[i].value; } else { reading += ","+rooms[i].value; } } } FW_cmd("/fhem?XHR=1&cmd=setreading refRoom refRooms "+reading); }'; $ret .= '</script>'; return $ret; }
userattr refTistModus:avg,max,min hystUp:0.0,0.1,0.2,0.3,0.4,0.5 hystDown:0.0,0.1,0.2,0.3,0.4,0.5
webCmd state
bei den bisherigen nicht funktionierenden devices ist html-code im text vorhanden. könnte das die ursache sein?
wie könnte ich die fehler "umgehen"?
die emals werden von einer fritzbox erzeugt/versendet.
hier die email funktion für die fritzbox:
sub
FB_mail($$$)
{
my ($rcpt, $subject, $text) = @_;
my $tmpfile = "fhem_nachricht.txt";
system("/bin/echo \'$text\' > \'$tmpfile\' ");
system("/sbin/mailer send -i \"$tmpfile\" -s \"$subject\" -t \"$rcpt\"");
system("rm \"$tmpfile\"");
Log 3, "Mail sent to $rcpt";
}
da gemeldet wird, dass die datei nicht gelöscht werden kann, weil sie nicht existiert, wird wohl das erstellen scheitern. also funktioniert dann dieser befehl nicht:
system("/bin/echo \'$text\' > \'$tmpfile\' ");
aber warum ist das inhaltsabhängig? oder gibt es ein limit für die länge von text?
das Problem sind die spitzen Klammern um HTML Tags, die werden bei der Ausführung unter Linux auf der Kommandozeile interpretiert, wenn Du sie in system() übergibst.
http://www.linux-praxis.de/lpic1/lpi101/1.103.4.html
"nur" die spitzen klammern sind es leider nicht.
ich habe mal einen test dummy mit folgendem list definiert, das aber einwandfrei gemailt wird.
Internals:
CFGFN
NAME d_test
NR 625
STATE <div style="text-align:left">settings:</div>
TYPE dummy
Readings:
Attributes:
room 04_Test
stateFormat <div style="text-align:left">settings:</div>
wahrscheinlich ist eine kombination mit single-quotes schuld.
nach der erweiterung des stateformat um 2 single-quotes im folgenden list:
Internals:
CFGFN
NAME d_test
NR 625
STATE <div style="color:yellow">'<(.*)>'</div>
TYPE dummy
Readings:
Attributes:
room 04_Test
stateFormat <div style="color:yellow">'<(.*)>'</div>
gab es diese fehlermeldung und die email blieb leer.
sh: syntax error: unexpected "("
rm: can't remove 'fhem_nachricht.txt': No such file or directory
ich denke, jetzt habe ich endlich die "quote-logik" in dieser codezeile verstanden.
system("/bin/echo \'$text\' > \'$tmpfile\' ");
das problem sind dann wirklich nur zusätzliche single-quotes, die in $text enthalten sind, wodurch der von perl an die shell übergebene string ('$text') quasi "gesplittet" wird. ab dem ersten zusätzlichen single quote versucht die shell dann zu interpretieren und erzeugt fehler, wenn dann "problemzeichen" folgen.
mein workaround besteht im augenblick darin, dass ich alle single-quotes in $text durch double-quotes ersetze.
am besten wäre es sicherlich, den system-aufruf in der sub FB_mail($$$) aus FritzBoxUtils.pm durch perl-code zu ersetzen. dann könnten wahrscheinlich auch single-quotes gemailt werden, aber vor allem kann es keinen versehentlichen supergau auf betriebssystem-ebene geben.
zumindestens sollte der inhalt von $text auf single-quotes untersucht und entsprechend behandelt werden. das wenigste wäre eine deutliche warnung in der beschreibung zur sub.
# warning: single-quotes in email-text can damage your fritzbox
gruss frank