####################################################################### # DMX ArtNet UI for ESP32(C3/S2/S3) # ####################################################################### var artnet_ui = module('artnet_ui') ################################################################################# # ArtNet_UI # # WebUI ################################################################################# class ArtNet_UI def init() import persist if persist.find("artnet_autorun") == true # autorun end end # #################################################################################################### # Init web handlers # #################################################################################################### # Displays a "DMX ArtNet" button on the configuration page def web_add_config_button() import webserver webserver.content_send("

") end # #################################################################################################### # Get WS2812 gpios # # Returns an array of valid WS2812 gpios as defined in the template, or empty array # #################################################################################################### def get_ws2812_gpios() import gpio var ret = [] for p:0..31 if gpio.pin_used(gpio.WS2812, p) ret.push(p) end end return ret end static def read_persist() import persist var conf = dyn() conf.gpio = persist.find("artnet_gpio", 0) # gpio number from template conf.rows = persist.find("artnet_rows", 5) # number of rows (min: 1) conf.cols = persist.find("artnet_cols", 5) # number of columns (min: 1) conf.offs = persist.find("artnet_offs", 0) # offset in the led strip where the matrix starts (min: 0) conf.alt = persist.find("artnet_alt", false) # are the rows in alternate directions conf.univ = persist.find("artnet_univ", 0) # start universe # conf.addr = persist.find("artnet_addr", "uni") # listening mode, either 'uni' or 'multi' for multicast conf.port = persist.find("artnet_port", 6454) # UDP port number conf.auto = persist.find("artnet_auto", true) # autorun at startup return conf end def save_persist(conf) import persist persist.artnet_gpio = conf.gpio persist.artnet_rows = conf.rows persist.artnet_cols = conf.cols persist.artnet_offs = conf.offs persist.artnet_alt = conf.alt persist.artnet_univ = conf.univ # persist.artnet_addr = conf.addr persist.artnet_port = conf.port persist.artnet_auto = conf.auto persist.save() end ####################################################################### # Display the complete page on `/artnet_ui` ####################################################################### def page_artnet_ui() import webserver if !webserver.check_privileged_access() return nil end # read configuration var conf = self.read_persist() webserver.content_start("ArtNet") #- title of the web page -# webserver.content_send_style() #- send standard Tasmota styles -# # webserver.content_send("

Warning: actions below can brick your device.

") # webserver.content_send("

 (This feature requires an internet connection)

") webserver.content_send("
") webserver.content_send(format(" ArtNet configuration")) webserver.content_send("

") # WS2812 bus configuration webserver.content_send(format("

WS2812 configuration:

")) webserver.content_send(format( "" "") webserver.content_send(format("") webserver.content_send(format("") webserver.content_send(format("") webserver.content_send(format("") webserver.content_send("") webserver.content_send(format("") # description webserver.content_send("") webserver.content_send("
GPIO")) var ws2812_list = self.get_ws2812_gpios() var ws2812_gpio if size(ws2812_list) == 0 webserver.content_send("**Not configured**") else webserver.content_send("") end webserver.content_send("
Rows")) webserver.content_send(format("", conf.rows)) webserver.content_send("
Columns")) webserver.content_send(format("", conf.cols)) webserver.content_send("
Offset")) webserver.content_send(format("", conf.offs)) webserver.content_send("
Alternate rows")) webserver.content_send(format("

", conf.alt ? " checked" : "")) webserver.content_send("
 
DMX universe")) webserver.content_send(format("", conf.univ)) webserver.content_send("
") webserver.content_send("This this the universe number for
the first row, and gets incremented
for each row.") webserver.content_send("

") # IP configuration webserver.content_send(format("

IP listener:

")) webserver.content_send("") # "") webserver.content_send("") webserver.content_send("
IP mode")) # webserver.content_send("") # webserver.content_send("
Port") # webserver.content_send(format("
Port")) webserver.content_send(format("", conf.port)) webserver.content_send("

") # auto-run webserver.content_send(format("

Auto-run at boot:

", conf.auto ? " checked" : "")) # button webserver.content_send("") webserver.content_send("

") webserver.content_send("

") webserver.content_button(webserver.BUTTON_CONFIGURATION) webserver.content_stop() end ####################################################################### # Web Controller, called by POST to `/artnet_ui` ####################################################################### def page_artnet_ctl() import webserver if !webserver.check_privileged_access() return nil end import persist import introspect try if webserver.has_arg("artnetapply") # read argumments, sanity check and put in conf object var conf = dyn() # read gpio var ws2812_list = self.get_ws2812_gpios() var gp_ws2812 = int(webserver.arg("ws2812")) if ws2812_list.find(gp_ws2812) != nil conf.gpio = gp_ws2812 else conf.gpio = -1 end # read rows and cols var rows = int(webserver.arg("rows")) if rows < 1 || rows > 999 rows = 1 end conf.rows = rows var cols = int(webserver.arg("cols")) if cols < 1 || cols > 999 cols = 1 end conf.cols = cols # alternate conf.alt = webserver.arg("alt") == 'on' # offset var offs = int(webserver.arg("offs")) if offs < 0 || offs > 999 offs = 0 end conf.offs = offs # universe var univ = int(webserver.arg("univ")) if univ < 0 || univ > 999 univ = 0 end conf.univ = univ # universe var port = int(webserver.arg("port")) if port < 1 || port > 65535 port = 6454 end conf.port = port # autorun conf.auto = webserver.arg("auto") == 'on' self.save_persist(conf) artnet.stop_global() artnet.run_from_conf() # tasmota.log("BRY: conf=" + str(conf), 2); webserver.redirect("/cn?") else raise "value_error", "Unknown command" end except .. as e, m print(format("BRY: Exception> '%s' - %s", e, m)) #- display error page -# webserver.content_start("Parameter error") #- title of the web page -# webserver.content_send_style() #- send standard Tasmota styles -# webserver.content_send(format("

Exception:
'%s'
%s

", e, m)) webserver.content_button(webserver.BUTTON_CONFIGURATION) #- button back to management page -# webserver.content_stop() #- end of web page -# end end #- ---------------------------------------------------------------------- -# # respond to web_add_handler() event to register web listeners #- ---------------------------------------------------------------------- -# #- this is called at Tasmota start-up, as soon as Wifi/Eth is up and web server running -# def web_add_handler() import webserver #- we need to register a closure, not just a function, that captures the current instance -# webserver.on("/artnet_ui", / -> self.page_artnet_ui(), webserver.HTTP_GET) webserver.on("/artnet_ui", / -> self.page_artnet_ctl(), webserver.HTTP_POST) end end artnet_ui.ArtNet_UI = ArtNet_UI #- create and register driver in Tasmota -# if tasmota var artnet_ui_instance = artnet_ui.ArtNet_UI() tasmota.add_driver(artnet_ui_instance) ## can be removed if put in 'autoexec.bat' artnet_ui_instance.web_add_handler() end return artnet_ui #- Example import partition # read p = partition.Partition() print(p) -#