diff --git a/CHANGELOG.md b/CHANGELOG.md
index e0221235e..9a55c1550 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ All notable changes to this project will be documented in this file.
- Berry GPIO viewer initial version using async webserver (#20416)
- Berry add `string` to `bytes()` (#20420)
- Berry button to dynamically load GPIO Viewer with Berry backend (#20424)
+- Berry `debug_panel.tapp` to display real-time heap and wifi rssi
### Breaking Changed
diff --git a/tasmota/berry/gpio_viewer/autoexec.be b/tasmota/berry/gpio_viewer/autoexec.be
new file mode 100644
index 000000000..d61c44313
--- /dev/null
+++ b/tasmota/berry/gpio_viewer/autoexec.be
@@ -0,0 +1,18 @@
+# demo for debug panel
+#
+# rm debug_panel.tapp; zip -j -0 debug_panel.tapp webserver_async.be debug_panel.be autoexec.be
+import webserver_async
+import debug_panel
+
+if tasmota.version() >= 0xD030002
+ if !tasmota.wifi()['up']
+ tasmota.add_rule("Wifi#Connected", def ()
+ global._debug_panel = debug_panel(5550)
+ tasmota.remove_rule("Wifi#Connected", "debug_panel_start")
+ end, "debug_panel_start")
+ else
+ global._debug_panel = debug_panel(5550)
+ end
+else
+ log("BRY: 'debug_panel' requires Tasmota v13.3.0.2")
+end
diff --git a/tasmota/berry/gpio_viewer/debug_panel.be b/tasmota/berry/gpio_viewer/debug_panel.be
new file mode 100644
index 000000000..12f7c1c2f
--- /dev/null
+++ b/tasmota/berry/gpio_viewer/debug_panel.be
@@ -0,0 +1,179 @@
+#
+# debug_panel.be - implements a small panel on top of the Tasmota UI to view real-time information
+#
+# Copyright (C) 2023 Stephan Hadinger & Theo Arends
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+class debug_panel
+ var port
+ var web
+ var sampling_interval
+ #
+ var payload1, payload2 # temporary object bytes() to avoid reallocation
+
+ static var SAMPLING = 100
+ static var HTML_HEAD1 =
+ "
"
+ static var HTML_URL_F =
+ ""
+ static var HTML_HEAD2 =
+ ""
+ ""
+ ""
+ static var HTML_CONTENT =
+ ''
+ 'Free Heap --- KB | '
+ 'Wifi RSSI | | '
+ '
'
+ static var HTML_END =
+ ""
+
+ def init(port)
+ self.port = port
+ self.web = webserver_async(port)
+ self.sampling_interval = self.SAMPLING
+ self.payload1 = bytes(100) # reserve 100 bytes by default
+ self.payload2 = bytes(100) # reserve 100 bytes by default
+
+ self.web.set_chunked(true)
+ self.web.set_cors(true)
+ self.web.on("/info_feed", self, self.send_info_feed)
+ self.web.on("/info", self, self.send_info_page)
+
+ tasmota.add_driver(self)
+ end
+
+ def close()
+ tasmota.remove_driver(self)
+ self.web.close()
+ end
+
+ def send_info_page(cnx, uri, verb)
+ import string
+
+ var host = cnx.header_host
+ var host_split = string.split(host, ':') # need to make it stronger
+ var ip = host_split[0]
+ var port = 80
+ if size(host_split) > 1
+ port = int(host_split[1])
+ end
+
+ cnx.send(200, "text/html")
+ cnx.write(self.HTML_HEAD1)
+ cnx.write(format(self.HTML_URL_F, ip, port))
+ cnx.write(self.HTML_HEAD2)
+ cnx.write(self.HTML_CONTENT)
+ cnx.write(self.HTML_END)
+
+ cnx.content_stop()
+ end
+
+ def send_info_feed(cnx, uri, verb)
+ cnx.set_chunked(false) # no chunking since we use EventSource
+ cnx.send(200, "text/event-stream")
+ self.send_info_tick(cnx)
+ end
+
+ def send_info_tick(cnx)
+ if cnx.buf_out_empty()
+ # if out buffer is not empty, do not send any new information
+ var payload
+ # send free heap
+ payload = f"id:{tasmota.millis()}\r\n"
+ "event:free_heap\r\n"
+ "data:{tasmota.memory().find('heap_free', 0)} KB\r\n\r\n"
+ cnx.write(payload)
+
+ # send wifi rssi
+ payload = f"id:{tasmota.millis()}\r\n"
+ "event:wifi_rssi\r\n"
+ "data:{tasmota.wifi().find('quality', '--')}%\r\n\r\n"
+ cnx.write(payload)
+ end
+
+ tasmota.set_timer(self.sampling_interval, def () self.send_info_tick(cnx) end)
+ end
+
+ # Add button 'GPIO Viewer' redirects to '/part_wiz?'
+ def web_add_console_button()
+ self.send_iframe_code()
+ end
+ def web_add_main_button()
+ self.send_iframe_code()
+ end
+ def web_add_management_button()
+ self.send_iframe_code()
+ end
+ def web_add_config_button()
+ self.send_iframe_code()
+ end
+
+ def send_iframe_code()
+ import webserver
+ var ip = tasmota.wifi().find('ip')
+ if (ip == nil)
+ ip = tasmota.eth().find('ip')
+ end
+ if (ip != nil)
+ webserver.content_send(
+ f''
+ ''
+ '
'
+ '')
+ # f"")
+ end
+ end
+
+end
+
+return debug_panel
+
+# if tasmota
+# global.debug_panel = Debug_panel(8887)
+# end
+
+# return global.debug_panel
diff --git a/tasmota/berry/gpio_viewer/debug_panel.tapp b/tasmota/berry/gpio_viewer/debug_panel.tapp
new file mode 100644
index 000000000..31c2f9fc4
Binary files /dev/null and b/tasmota/berry/gpio_viewer/debug_panel.tapp differ
diff --git a/tasmota/berry/gpio_viewer/webserver_async.be b/tasmota/berry/gpio_viewer/webserver_async.be
index 640f79d30..2801484ed 100644
--- a/tasmota/berry/gpio_viewer/webserver_async.be
+++ b/tasmota/berry/gpio_viewer/webserver_async.be
@@ -198,7 +198,7 @@ class Webserver_async_cnx
# pre: self.buf_in is not empty
# post: self.buf_in has made progress (smaller or '')
def parse()
- tasmota.log(f"WEB: incoming {bytes().fromstring(self.buf_in).tohex()}", 3)
+ # tasmota.log(f"WEB: incoming {bytes().fromstring(self.buf_in).tohex()}", 3)
if self.phase == 0
self.parse_http_req_line()
elif self.phase == 1
@@ -274,7 +274,7 @@ class Webserver_async_cnx
#
# Received header
def event_http_header(header_key, header_value)
- tasmota.log(f"WEB: header key '{header_key}' = '{header_value}'")
+ # tasmota.log(f"WEB: header key '{header_key}' = '{header_value}'")
if (header_key == "Host")
self.header_host = header_value
@@ -291,7 +291,7 @@ class Webserver_async_cnx
#############################################################
# parse incoming payload (if any)
def parse_http_payload()
- tasmota.log(f"WEB: parsing payload '{bytes().fromstring(self.buf_in).tohex()}'")
+ # tasmota.log(f"WEB: parsing payload '{bytes().fromstring(self.buf_in).tohex()}'")
# dispatch request before parsing payload
self.server.dispatch(self, self.req_uri, self.req_verb)
end
@@ -538,7 +538,7 @@ class webserver_async
end
-#return webserver_async
+return webserver_async
#- Test