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 --- KBWifi 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