mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
MQTT2_CLIENT/MQTT2_SERVER: add "Show MQTT traffic"
git-svn-id: https://svn.fhem.de/fhem/trunk@25943 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
1ba6839dd3
commit
ff078b9f9b
@ -12,6 +12,8 @@ sub MQTT2_CLIENT_Undef($@);
|
|||||||
sub MQTT2_CLIENT_doPublish($@);
|
sub MQTT2_CLIENT_doPublish($@);
|
||||||
sub MQTT2_CLIENT_Disco($;$$);
|
sub MQTT2_CLIENT_Disco($;$$);
|
||||||
|
|
||||||
|
use vars qw(%FW_id2inform);
|
||||||
|
|
||||||
# See also:
|
# See also:
|
||||||
# http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
# http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||||
|
|
||||||
@ -57,6 +59,7 @@ MQTT2_CLIENT_Initialize($)
|
|||||||
);
|
);
|
||||||
use warnings 'qw';
|
use warnings 'qw';
|
||||||
$hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
|
$hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
|
||||||
|
$hash->{FW_detailFn} = "MQTT2_CLIENT_fhemwebFn";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
@ -536,6 +539,7 @@ MQTT2_CLIENT_Read($@)
|
|||||||
DoTrigger($name, "$tp:$val") if($re && $tp =~ m/$re/);
|
DoTrigger($name, "$tp:$val") if($re && $tp =~ m/$re/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MQTT2_CLIENT_feedTheList($hash, $tp, $val, 1);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log 1, "M2: Unhandled packet $cpt, disconneting $name";
|
Log 1, "M2: Unhandled packet $cpt, disconneting $name";
|
||||||
@ -592,7 +596,8 @@ MQTT2_CLIENT_doPublish($@)
|
|||||||
length($pi)).
|
length($pi)).
|
||||||
pack("n", length($topic)).
|
pack("n", length($topic)).
|
||||||
$topic.$pi.$val;
|
$topic.$pi.$val;
|
||||||
MQTT2_CLIENT_send($hash, $msg, $immediate)
|
MQTT2_CLIENT_send($hash, $msg, $immediate);
|
||||||
|
MQTT2_CLIENT_feedTheList($hash, $topic, $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
@ -687,6 +692,65 @@ MQTT2_CLIENT_getStr($$)
|
|||||||
return ($r, $off+2+$l);
|
return ($r, $off+2+$l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
MQTT2_CLIENT_fhemwebFn()
|
||||||
|
{
|
||||||
|
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||||
|
|
||||||
|
return '' if($pageHash);
|
||||||
|
|
||||||
|
return << "JSEND"
|
||||||
|
<div id="m2s_cons"><a href="#">Show MQTT traffic</a></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
\$(document).ready(function() {
|
||||||
|
\$("#m2s_cons a")
|
||||||
|
.click(function(e){
|
||||||
|
loadScript("pgm2/console.js", function() {
|
||||||
|
cons4dev('#m2s_cons', '^\$', 'MQTT2_CLIENT_addToFeedList', '$d');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
JSEND
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
MQTT2_CLIENT_addToFeedList($$)
|
||||||
|
{
|
||||||
|
my ($name, $turnOn) = @_;
|
||||||
|
my $hash = $defs{$name};
|
||||||
|
return if(!$hash);
|
||||||
|
|
||||||
|
my $fwid = $FW_chash->{FW_ID};
|
||||||
|
$hash->{".feedList"} = () if(!$hash->{".feedList"});
|
||||||
|
if($turnOn) {
|
||||||
|
$hash->{".feedList"}{$fwid} = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
delete($hash->{".feedList"}{$fwid});
|
||||||
|
delete($hash->{".feedList"}) if(!keys %{$hash->{".feedList"}});
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
MQTT2_CLIENT_feedTheList($$$)
|
||||||
|
{
|
||||||
|
my ($server, $tp, $val, $cid) = @_;
|
||||||
|
my $fl = $server->{".feedList"};
|
||||||
|
if($fl) {
|
||||||
|
foreach my $fwid (keys %{$fl}) {
|
||||||
|
my $cl = $FW_id2inform{$fwid};
|
||||||
|
if(!$cl || !$cl->{inform}{filter} || $cl->{inform}{filter} ne '^$') {
|
||||||
|
delete($fl->{$fwid});
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
FW_AsyncOutput($cl, "",
|
||||||
|
defined($cid) ? "RCVD: $tp $val<br>" : "SENT: $tp $val<br>");
|
||||||
|
}
|
||||||
|
delete($server->{".feedList"}) if(!keys %{$fl});
|
||||||
|
}
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
|
||||||
=pod
|
=pod
|
||||||
|
@ -12,6 +12,7 @@ sub MQTT2_SERVER_Write($$$);
|
|||||||
sub MQTT2_SERVER_Undef($@);
|
sub MQTT2_SERVER_Undef($@);
|
||||||
sub MQTT2_SERVER_doPublish($$$$;$);
|
sub MQTT2_SERVER_doPublish($$$$;$);
|
||||||
|
|
||||||
|
use vars qw(%FW_id2inform);
|
||||||
|
|
||||||
# See also:
|
# See also:
|
||||||
# http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
# http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html
|
||||||
@ -50,6 +51,7 @@ MQTT2_SERVER_Initialize($)
|
|||||||
);
|
);
|
||||||
use warnings 'qw';
|
use warnings 'qw';
|
||||||
$hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
|
$hash->{AttrList} = join(" ", @attrList)." ".$readingFnAttributes;
|
||||||
|
$hash->{FW_detailFn} = "MQTT2_SERVER_fhemwebFn";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
@ -564,6 +566,20 @@ MQTT2_SERVER_doPublish($$$$;$)
|
|||||||
my $re = AttrVal($serverName, "rawEvents", undef);
|
my $re = AttrVal($serverName, "rawEvents", undef);
|
||||||
DoTrigger($server->{NAME}, "$tp:$val") if($re && $tp =~ m/$re/);
|
DoTrigger($server->{NAME}, "$tp:$val") if($re && $tp =~ m/$re/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $fl = $server->{".feedList"};
|
||||||
|
if($fl) {
|
||||||
|
foreach my $fwid (keys %{$fl}) {
|
||||||
|
my $cl = $FW_id2inform{$fwid};
|
||||||
|
if(!$cl || !$cl->{inform}{filter} || $cl->{inform}{filter} ne '^$') {
|
||||||
|
delete($fl->{$fwid});
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
FW_AsyncOutput($cl, "",
|
||||||
|
defined($cid) ? "RCVD: $tp $val<br>" : "SENT: $tp $val<br>");
|
||||||
|
}
|
||||||
|
delete($server->{".feedList"}) if(!keys %{$fl});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
######################################
|
######################################
|
||||||
@ -665,6 +681,47 @@ MQTT2_SERVER_getStr($$$)
|
|||||||
return ($r, $off+2+$l);
|
return ($r, $off+2+$l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
MQTT2_SERVER_fhemwebFn()
|
||||||
|
{
|
||||||
|
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||||
|
|
||||||
|
return '' if($pageHash);
|
||||||
|
|
||||||
|
return << "JSEND"
|
||||||
|
<div id="m2s_cons"><a href="#">Show MQTT traffic</a></div>
|
||||||
|
<script type="text/javascript">
|
||||||
|
\$(document).ready(function() {
|
||||||
|
\$("#m2s_cons a")
|
||||||
|
.click(function(e){
|
||||||
|
loadScript("pgm2/console.js", function() {
|
||||||
|
cons4dev('#m2s_cons', '^\$', 'MQTT2_SERVER_addToFeedList', '$d');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
JSEND
|
||||||
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
MQTT2_SERVER_addToFeedList($$)
|
||||||
|
{
|
||||||
|
my ($name, $turnOn) = @_;
|
||||||
|
my $hash = $defs{$name};
|
||||||
|
return if(!$hash);
|
||||||
|
|
||||||
|
my $fwid = $FW_chash->{FW_ID};
|
||||||
|
$hash->{".feedList"} = () if(!$hash->{".feedList"});
|
||||||
|
if($turnOn) {
|
||||||
|
$hash->{".feedList"}{$fwid} = 1;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
delete($hash->{".feedList"}{$fwid});
|
||||||
|
delete($hash->{".feedList"}) if(!keys %{$hash->{".feedList"}});
|
||||||
|
}
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
# {MQTT2_SERVER_ReadDebug("m2s", '0(12)(0)(5)HelloWorld')}
|
# {MQTT2_SERVER_ReadDebug("m2s", '0(12)(0)(5)HelloWorld')}
|
||||||
sub
|
sub
|
||||||
MQTT2_SERVER_ReadDebug($$)
|
MQTT2_SERVER_ReadDebug($$)
|
||||||
|
@ -92,6 +92,7 @@ use vars qw(@FW_httpheader); # HTTP header, line by line
|
|||||||
use vars qw(%FW_httpheader); # HTTP header, as hash
|
use vars qw(%FW_httpheader); # HTTP header, as hash
|
||||||
use vars qw($FW_userAgent); # user agent string
|
use vars qw($FW_userAgent); # user agent string
|
||||||
use vars qw($FW_addJs); # Only for helper like AttrTemplate
|
use vars qw($FW_addJs); # Only for helper like AttrTemplate
|
||||||
|
use vars qw(%FW_id2inform);
|
||||||
|
|
||||||
$FW_formmethod = "post";
|
$FW_formmethod = "post";
|
||||||
|
|
||||||
@ -101,7 +102,6 @@ my $FW_lastWebName = ""; # Name of last FHEMWEB instance, for caching
|
|||||||
my $FW_lastHashUpdate = 0;
|
my $FW_lastHashUpdate = 0;
|
||||||
my $FW_httpRetCode = "";
|
my $FW_httpRetCode = "";
|
||||||
my %FW_csrfTokenCache;
|
my %FW_csrfTokenCache;
|
||||||
my %FW_id2inform;
|
|
||||||
|
|
||||||
#########################
|
#########################
|
||||||
# As we are _not_ multithreaded, it is safe to use global variables.
|
# As we are _not_ multithreaded, it is safe to use global variables.
|
||||||
@ -360,7 +360,7 @@ FW_Read($$)
|
|||||||
my $buf;
|
my $buf;
|
||||||
my $ret = sysread($c, $buf, 1024);
|
my $ret = sysread($c, $buf, 1024);
|
||||||
$buf = Encode::decode($hash->{encoding}, $buf)
|
$buf = Encode::decode($hash->{encoding}, $buf)
|
||||||
if($unicodeEncoding && $hash->{encoding});
|
if($unicodeEncoding && $hash->{encoding} && !$hash->{websocket});
|
||||||
|
|
||||||
if(!defined($ret) && $! == EWOULDBLOCK ){
|
if(!defined($ret) && $! == EWOULDBLOCK ){
|
||||||
$hash->{wantWrite} = 1
|
$hash->{wantWrite} = 1
|
||||||
@ -750,9 +750,9 @@ FW_addToWritebuffer($$@)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
FW_AsyncOutput($$)
|
FW_AsyncOutput($$;$)
|
||||||
{
|
{
|
||||||
my ($hash, $ret) = @_;
|
my ($hash, $ret, $directData) = @_;
|
||||||
|
|
||||||
return if(!$hash || !$hash->{FW_ID});
|
return if(!$hash || !$hash->{FW_ID});
|
||||||
if( $ret =~ m/^<html>(.*)<\/html>$/s ) {
|
if( $ret =~ m/^<html>(.*)<\/html>$/s ) {
|
||||||
@ -766,6 +766,7 @@ FW_AsyncOutput($$)
|
|||||||
|
|
||||||
my $data = FW_longpollInfo('JSON',
|
my $data = FW_longpollInfo('JSON',
|
||||||
"#FHEMWEB:$FW_wname","FW_okDialog('$ret')","");
|
"#FHEMWEB:$FW_wname","FW_okDialog('$ret')","");
|
||||||
|
$data = $directData if($directData);
|
||||||
|
|
||||||
# find the longpoll connection with the same fw_id as the page that was the
|
# find the longpoll connection with the same fw_id as the page that was the
|
||||||
# origin of the get command
|
# origin of the get command
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
FW_version["console.js"] = "$Id$";
|
FW_version["console.js"] = "$Id$";
|
||||||
|
|
||||||
var consConn;
|
var consConn;
|
||||||
var debug;
|
var consName="#console";
|
||||||
|
|
||||||
var consFilter, oldFilter, consFType="";
|
var consFilter, oldFilter, consFType="";
|
||||||
var consLastIndex = 0;
|
var consLastIndex = 0;
|
||||||
@ -77,14 +77,14 @@ consUpdate(evt)
|
|||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
var isTa = $("#console").is("textarea"); // 102773
|
var isTa = $(consName).is("textarea"); // 102773
|
||||||
var ncA = new_content.split(/<br>[\r\n]/);
|
var ncA = new_content.split(/<br>[\r\n]/);
|
||||||
for(var i1=0; i1<ncA.length; i1++)
|
for(var i1=0; i1<ncA.length; i1++)
|
||||||
ncA[i1] = ncA[i1].replace(/[<> ]/g, function(a){return rTab[a]});
|
ncA[i1] = ncA[i1].replace(/[<> ]/g, function(a){return rTab[a]});
|
||||||
$("#console").append(logContent+ncA.join(isTa?"\n":"<br>"));
|
$(consName).append(logContent+ncA.join(isTa?"\n":"<br>"));
|
||||||
|
|
||||||
if(mustScroll)
|
if(mustScroll)
|
||||||
$("#console").scrollTop($("#console")[0].scrollHeight);
|
$(consName).scrollTop($(consName)[0].scrollHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
function
|
function
|
||||||
@ -98,6 +98,7 @@ consFill()
|
|||||||
var query = "?XHR=1"+
|
var query = "?XHR=1"+
|
||||||
"&inform=type=raw;withLog="+withLog+";filter="+
|
"&inform=type=raw;withLog="+withLog+";filter="+
|
||||||
encodeURIComponent(consFilter)+consFType+
|
encodeURIComponent(consFilter)+consFType+
|
||||||
|
"&fw_id="+$("body").attr('fw_id')+
|
||||||
"×tamp="+new Date().getTime();
|
"×tamp="+new Date().getTime();
|
||||||
query = addcsrf(query);
|
query = addcsrf(query);
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ consFill()
|
|||||||
|
|
||||||
consLastIndex = 0;
|
consLastIndex = 0;
|
||||||
if(oldFilter != consFilter) // only clear, when filter changes
|
if(oldFilter != consFilter) // only clear, when filter changes
|
||||||
$("#console").html("");
|
$(consName).html("");
|
||||||
|
|
||||||
oldFilter = consFilter;
|
oldFilter = consFilter;
|
||||||
}
|
}
|
||||||
@ -137,9 +138,11 @@ consFill()
|
|||||||
function
|
function
|
||||||
consStart()
|
consStart()
|
||||||
{
|
{
|
||||||
var el = document.getElementById("console");
|
if($(consName).length != 1)
|
||||||
|
return;
|
||||||
|
|
||||||
consFilter = $("a#eventFilter").html();
|
if($("a#eventFilter").length)
|
||||||
|
consFilter = $("a#eventFilter").html();
|
||||||
if(consFilter == undefined)
|
if(consFilter == undefined)
|
||||||
consFilter = ".*";
|
consFilter = ".*";
|
||||||
oldFilter = consFilter;
|
oldFilter = consFilter;
|
||||||
@ -148,7 +151,7 @@ consStart()
|
|||||||
|
|
||||||
$("#eventReset").click(function(evt){ // Event Monitor Reset
|
$("#eventReset").click(function(evt){ // Event Monitor Reset
|
||||||
log("Console resetted by user");
|
log("Console resetted by user");
|
||||||
$("#console").html("");
|
$(consName).html("");
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#eventFilter").click(function(evt){ // Event-Filter Dialog
|
$("#eventFilter").click(function(evt){ // Event-Filter Dialog
|
||||||
@ -192,10 +195,10 @@ consStart()
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$("#console").scroll(function() { // autoscroll check
|
$(consName).scroll(function() { // autoscroll check
|
||||||
|
|
||||||
if($("#console")[0].scrollHeight - $("#console").scrollTop() <=
|
if($(consName)[0].scrollHeight - $(consName).scrollTop() <=
|
||||||
$("#console").outerHeight() + 2) {
|
$(consName).outerHeight() + 2) {
|
||||||
if(!mustScroll) {
|
if(!mustScroll) {
|
||||||
mustScroll = 1;
|
mustScroll = 1;
|
||||||
log("Console autoscroll restarted");
|
log("Console autoscroll restarted");
|
||||||
@ -337,4 +340,51 @@ consAddRegexpPart()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function
|
||||||
|
cons4dev(screenId, filter, feedFn, devName)
|
||||||
|
{
|
||||||
|
$(screenId).find("a")
|
||||||
|
.blur() // remove focus, so return wont open/close it
|
||||||
|
.unbind("click")
|
||||||
|
.click(toggleOpen);
|
||||||
|
|
||||||
|
consName = screenId+">div.console";
|
||||||
|
consFilter = filter;
|
||||||
|
var opened;
|
||||||
|
|
||||||
|
function
|
||||||
|
toggleOpen()
|
||||||
|
{
|
||||||
|
$(this).blur();
|
||||||
|
var cmd = FW_root+"?cmd="+encodeURIComponent("{"+feedFn+"('"+devName+"',"+
|
||||||
|
(opened ? 0 : 1)+")}")+"&XHR=1";
|
||||||
|
if(!opened) {
|
||||||
|
$(screenId).append('<div class="console block"></div>');
|
||||||
|
$(consName)
|
||||||
|
.width( $("#content").width()-40)
|
||||||
|
.height($("#content").height()/2-20)
|
||||||
|
.css({overflow:"auto"});
|
||||||
|
$(screenId+">a").html($(screenId+">a").html().replace("Show", "Hide"));
|
||||||
|
FW_closeConn();
|
||||||
|
consStart();
|
||||||
|
// Leave time for establishing the connection, else the "feeder" may
|
||||||
|
// clear the flag
|
||||||
|
setTimeout(function(){ FW_cmd(cmd) }, 100);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
FW_cmd(cmd);
|
||||||
|
$(consName).remove();
|
||||||
|
$(screenId+">a").html($(screenId+">a").html().replace("Hide", "Show"));
|
||||||
|
if(consConn) {
|
||||||
|
consConn.onclose = undefined;
|
||||||
|
cons_closeConn();
|
||||||
|
}
|
||||||
|
FW_longpoll();
|
||||||
|
}
|
||||||
|
opened = !opened;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleOpen();
|
||||||
|
}
|
||||||
|
|
||||||
window.onload = consStart;
|
window.onload = consStart;
|
||||||
|
Loading…
Reference in New Issue
Block a user