mirror of https://github.com/arendst/Tasmota.git
Merge pull request #15447 from s-hadinger/OpenHASP-full-demo
OpenHASP full demo
This commit is contained in:
commit
850e25e305
Binary file not shown.
|
@ -0,0 +1,56 @@
|
||||||
|
# OpenHASP demo
|
||||||
|
# rm openhasp_demo.tapp ; zip -j -0 openhasp_demo.tapp openhasp_demo/* openhasp_core/openhasp.be
|
||||||
|
|
||||||
|
if !tasmota.memory().contains("psram")
|
||||||
|
print("HSP: Error: OpenHASP demo requires PSRAM")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
import lv_tasmota_log
|
||||||
|
import lv_tasmota_info
|
||||||
|
import lv_wifi_graph
|
||||||
|
|
||||||
|
import openhasp
|
||||||
|
openhasp.start(false, "openhasp_demo.tapp#pages.jsonl")
|
||||||
|
|
||||||
|
var prev_day = -1
|
||||||
|
def set_watch()
|
||||||
|
import global
|
||||||
|
var now = tasmota.rtc()
|
||||||
|
var time_raw = now['local']
|
||||||
|
var time = tasmota.time_dump(time_raw)
|
||||||
|
# set second
|
||||||
|
global.p5b13.angle = 60 * time['sec']
|
||||||
|
# set minutes
|
||||||
|
global.p5b12.angle = 60 * time['min']
|
||||||
|
# set hours
|
||||||
|
global.p5b11.angle = 300 * (time['hour'] % 12) + time['min'] * 5
|
||||||
|
# set day
|
||||||
|
if time['day'] != prev_day
|
||||||
|
global.p5b15.text = str(time['day'])
|
||||||
|
prev_day = time['day']
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run_watch()
|
||||||
|
set_watch()
|
||||||
|
tasmota.set_timer(100, run_watch)
|
||||||
|
end
|
||||||
|
run_watch()
|
||||||
|
|
||||||
|
def p5_in()
|
||||||
|
global.p0b101.bg_opa = 0
|
||||||
|
global.p0b102.bg_opa = 0
|
||||||
|
global.p0b103.bg_opa = 0
|
||||||
|
global.p0b11.bg_opa = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
def p5_out()
|
||||||
|
global.p0b101.bg_opa = 255
|
||||||
|
global.p0b102.bg_opa = 255
|
||||||
|
global.p0b103.bg_opa = 255
|
||||||
|
global.p0b11.bg_opa = 255
|
||||||
|
end
|
||||||
|
|
||||||
|
tasmota.add_rule("hasp#p5==in", p5_in)
|
||||||
|
tasmota.add_rule("hasp#p5==out", p5_out)
|
|
@ -0,0 +1,70 @@
|
||||||
|
# lv_tasmota_info class
|
||||||
|
|
||||||
|
class lv_tasmota_info : lv.label
|
||||||
|
var msg
|
||||||
|
var delay
|
||||||
|
|
||||||
|
def init(parent)
|
||||||
|
super(self).init(parent)
|
||||||
|
self.set_width(parent.get_width())
|
||||||
|
self.set_pos(0, 0)
|
||||||
|
|
||||||
|
self.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_bg_opa(100, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.move_background()
|
||||||
|
self.set_style_border_opa(255, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_radius(0, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_pad_all(2, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_color(lv.color(0x0099EE), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_width(1, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
|
||||||
|
self.set_style_text_color(lv.color(0xFFFFFF), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_long_mode(lv.LABEL_LONG_CLIP)
|
||||||
|
var lg_font = lv.font_montserrat(14)
|
||||||
|
self.set_style_text_font(lg_font, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
|
||||||
|
self.msg = "IP: - \nFree: - kB"
|
||||||
|
self.set_text(self.msg)
|
||||||
|
self.delay = 1
|
||||||
|
|
||||||
|
self.add_event_cb(/->self.before_del(), lv.EVENT_DELETE, 0) # register `before_del` to be called when object is deleted
|
||||||
|
tasmota.add_driver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update()
|
||||||
|
var wifi_ip = "IP: " + tasmota.wifi().find('ip', '') + " " + tasmota.eth().find('ip', '')
|
||||||
|
var tas_mem = tasmota.memory()
|
||||||
|
var mem_msg = "Free: " + str(tas_mem['heap_free']) + " kB"
|
||||||
|
if tas_mem.contains('psram_free')
|
||||||
|
mem_msg += " PSRam: " + str(tas_mem['psram_free']) + " kB"
|
||||||
|
end
|
||||||
|
var msg = wifi_ip + "\n" + mem_msg
|
||||||
|
|
||||||
|
if msg != self.msg
|
||||||
|
self.msg = msg
|
||||||
|
self.set_text(self.msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_second()
|
||||||
|
self.delay -= 1
|
||||||
|
if self.delay == 0
|
||||||
|
self.update()
|
||||||
|
self.delay = 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def before_del()
|
||||||
|
tasmota.remove_driver(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return lv_tasmota_info
|
||||||
|
|
||||||
|
#-
|
||||||
|
import lv_tasmota_info
|
||||||
|
var info = lv_tasmota_info(scr)
|
||||||
|
info.set_pos(0, stat_line.get_height())
|
||||||
|
info.set_size(hres - 80, 30)
|
||||||
|
tasmota.add_driver(info)
|
||||||
|
-#
|
|
@ -0,0 +1,101 @@
|
||||||
|
# lv_tasmota_log class
|
||||||
|
|
||||||
|
class lv_tasmota_log : lv.obj
|
||||||
|
var label # contains the sub lv_label object
|
||||||
|
var lines
|
||||||
|
var line_len
|
||||||
|
var log_reader
|
||||||
|
var log_level
|
||||||
|
|
||||||
|
def init(parent)
|
||||||
|
super(self).init(parent)
|
||||||
|
self.set_width(parent.get_width())
|
||||||
|
self.set_pos(0, 0)
|
||||||
|
|
||||||
|
self.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_bg_opa(255, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.move_background()
|
||||||
|
self.set_style_border_opa(255, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_radius(0, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_pad_all(2, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_color(lv.color(0x0099EE), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_width(1, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.refr_size()
|
||||||
|
self.refr_pos()
|
||||||
|
|
||||||
|
self.label = lv.label(self)
|
||||||
|
|
||||||
|
self.label.set_style_text_color(lv.color(0x00FF00), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.label.set_long_mode(lv.LABEL_LONG_CLIP)
|
||||||
|
self.label.set_text("") # bug, still displays "Text"
|
||||||
|
|
||||||
|
self.label.set_width(self.get_width() - 12)
|
||||||
|
self.label.set_height(self.get_height() - 6)
|
||||||
|
|
||||||
|
self.add_event_cb( / -> self._size_changed(), lv.EVENT_SIZE_CHANGED, 0)
|
||||||
|
self.add_event_cb( / -> self._size_changed(), lv.EVENT_STYLE_CHANGED, 0)
|
||||||
|
self.add_event_cb( / -> tasmota.remove_driver(self), lv.EVENT_DELETE, 0)
|
||||||
|
|
||||||
|
self.lines = []
|
||||||
|
self.line_len = 0
|
||||||
|
self.log_reader = tasmota_log_reader()
|
||||||
|
self.log_level = 2
|
||||||
|
self._size_changed()
|
||||||
|
|
||||||
|
tasmota.add_driver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_lines_count(line_len)
|
||||||
|
if line_len > self.line_len # increase lines
|
||||||
|
for i: self.line_len .. line_len-1
|
||||||
|
self.lines.insert(0, "")
|
||||||
|
end
|
||||||
|
elif line_len < self.line_len # decrease lines
|
||||||
|
for i: line_len .. self.line_len-1
|
||||||
|
self.lines.remove(0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self.line_len = line_len
|
||||||
|
end
|
||||||
|
|
||||||
|
def _size_changed(obj, evt)
|
||||||
|
# print(">>> lv.EVENT_SIZE_CHANGED")
|
||||||
|
var pad_hor = self.get_style_pad_left(lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
+ self.get_style_pad_right(lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
+ self.get_style_border_width(lv.PART_MAIN | lv.STATE_DEFAULT) * 2
|
||||||
|
+ 3
|
||||||
|
var pad_ver = self.get_style_pad_top(lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
+ self.get_style_pad_bottom(lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
+ self.get_style_border_width(lv.PART_MAIN | lv.STATE_DEFAULT) * 2
|
||||||
|
+ 3
|
||||||
|
var w = self.get_width() - pad_hor - 2
|
||||||
|
var h = self.get_height() - pad_ver
|
||||||
|
self.label.set_size(w, h)
|
||||||
|
# print("w",w,"h",h,"pad_hor",pad_hor,"pad_ver",pad_ver)
|
||||||
|
|
||||||
|
# compute how many lines should be displayed
|
||||||
|
var h_font = lv.font_get_line_height(self.label.get_style_text_font(0)) # current font's height
|
||||||
|
var lines_count = ((h * 2 / h_font) + 1 ) / 2
|
||||||
|
# print("h_font",h_font,"h",h,"lines_count",lines_count)
|
||||||
|
self.set_lines_count(lines_count)
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_second()
|
||||||
|
var dirty = false
|
||||||
|
for n:0..20
|
||||||
|
var line = self.log_reader.get_log(self.log_level)
|
||||||
|
if line == nil break end # no more logs
|
||||||
|
self.lines.remove(0) # remove first line
|
||||||
|
self.lines.push(line)
|
||||||
|
dirty = true
|
||||||
|
end
|
||||||
|
if dirty self.update() end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update()
|
||||||
|
var msg = self.lines.concat("\n")
|
||||||
|
self.label.set_text(msg)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return lv_tasmota_log
|
|
@ -0,0 +1,77 @@
|
||||||
|
# lv_wifi_graph class
|
||||||
|
|
||||||
|
class lv_wifi_graph : lv.chart
|
||||||
|
var ws_h
|
||||||
|
var ws_w
|
||||||
|
var ser1
|
||||||
|
var wsl
|
||||||
|
var delay
|
||||||
|
|
||||||
|
def init(parent)
|
||||||
|
super(self).init(parent)
|
||||||
|
|
||||||
|
self.set_style_bg_color(lv.color(0x000000), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_bg_opa(100, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_color(lv.color(0x0099EE), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_border_width(1, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
#self.set_style_border_opa(200, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_radius(0, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.set_style_pad_all(2, lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
|
||||||
|
self.set_range(lv.CHART_AXIS_PRIMARY_Y, 0, 100)
|
||||||
|
self.set_div_line_count(0,0) # no lines
|
||||||
|
self.set_type(lv.CHART_TYPE_LINE)
|
||||||
|
|
||||||
|
self.set_style_size(0, lv.PART_INDICATOR) # don't show dots
|
||||||
|
self.set_style_line_rounded(true, lv.PART_ITEMS)
|
||||||
|
self.set_style_line_width(2, lv.PART_ITEMS) # don't show dots
|
||||||
|
self.set_update_mode(lv.CHART_UPDATE_MODE_SHIFT)
|
||||||
|
|
||||||
|
self.set_point_count(40)
|
||||||
|
|
||||||
|
self.ser1 = self.add_series(lv.color(0xEE4444), lv.CHART_AXIS_PRIMARY_Y)
|
||||||
|
|
||||||
|
self.wsl = lv.label(self)
|
||||||
|
self.wsl.set_style_text_color(lv.color(0xFFFFFF), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.wsl.set_text("wifi")
|
||||||
|
self.wsl.set_style_text_font(lv.font_montserrat(10), lv.PART_MAIN | lv.STATE_DEFAULT)
|
||||||
|
self.wsl.set_align(lv.ALIGN_BOTTOM_MID)
|
||||||
|
|
||||||
|
self.delay = 1
|
||||||
|
|
||||||
|
self.add_event_cb(/->self.before_del(), lv.EVENT_DELETE, 0) # register `before_del` to be called when object is deleted
|
||||||
|
tasmota.add_driver(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_wifi_point()
|
||||||
|
var wifi = tasmota.wifi()
|
||||||
|
var quality = wifi.find("quality")
|
||||||
|
if quality != nil
|
||||||
|
self.set_next_value(self.ser1, quality)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def every_second()
|
||||||
|
self.delay -= 1
|
||||||
|
if self.delay == 0
|
||||||
|
self.add_wifi_point()
|
||||||
|
self.delay = 2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def before_del()
|
||||||
|
tasmota.remove_driver(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return lv_wifi_graph
|
||||||
|
|
||||||
|
#-
|
||||||
|
import lv_wifi_graph
|
||||||
|
ws_h = 40
|
||||||
|
ws_w = 80
|
||||||
|
ws = lv_wifi_graph(scr)
|
||||||
|
ws.set_size(ws_w,ws_h)
|
||||||
|
ws.set_pos(hres-ws_w, stat_line.get_height())
|
||||||
|
tasmota.add_driver(ws)
|
||||||
|
-#
|
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
|
@ -0,0 +1,52 @@
|
||||||
|
{"page":0,"comment":"---------- Upper stat line ----------"}
|
||||||
|
{"id":0,"text_color":"#FFFFFF"}
|
||||||
|
{"id":11,"obj":"label","x":0,"y":0,"w":320,"pad_right":90,"h":22,"bg_color":"#D00000","bg_opa":255,"radius":0,"border_side":0,"text":"Tasmota","text_font":"montserrat-20"}
|
||||||
|
|
||||||
|
{"id":15,"obj":"lv_wifi_arcs","x":291,"y":0,"w":29,"h":22,"radius":0,"border_side":0,"bg_color":"#000000","line_color":"#FFFFFF"}
|
||||||
|
{"id":16,"obj":"lv_clock","x":232,"y":3,"w":55,"h":16,"radius":0,"border_side":0}
|
||||||
|
|
||||||
|
{"comment":"---------- Bottom buttons - prev/home/next ----------"}
|
||||||
|
{"id":101,"obj":"btn","x":20,"y":210,"w":80,"h":25,"action":"prev","bg_color":"#1fa3ec","radius":10,"border_side":1,"text":"\uF053","text_font":"montserrat-20"}
|
||||||
|
{"id":102,"obj":"btn","x":120,"y":210,"w":80,"h":25,"action":"back","bg_color":"#1fa3ec","radius":10,"border_side":1,"text":"\uF015","text_font":"montserrat-20"}
|
||||||
|
{"id":103,"obj":"btn","x":220,"y":210,"w":80,"h":25,"action":"next","bg_color":"#1fa3ec","radius":10,"border_side":1,"text":"\uF054","text_font":"montserrat-20"}
|
||||||
|
|
||||||
|
{"page":2,"comment":"---------- Page 2 ----------"}
|
||||||
|
{"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"}
|
||||||
|
|
||||||
|
{"comment":"---------- Wifi status ----------"}
|
||||||
|
{"id":20,"obj":"lv_wifi_graph","x":257,"y":25,"w":60,"h":40,"radius":0}
|
||||||
|
{"id":21,"obj":"lv_tasmota_info","x":3,"y":25,"w":251,"h":40,"radius":0}
|
||||||
|
{"id":22,"obj":"lv_tasmota_log","x":3,"y":68,"w":314,"h":90,"radius":0,"text_font":12}
|
||||||
|
|
||||||
|
{"page":1,"comment":"---------- Page 1 ----------"}
|
||||||
|
{"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"}
|
||||||
|
|
||||||
|
{"id":2,"obj":"arc","x":20,"y":65,"w":80,"h":100,"border_side":0,"type":0,"rotation":0,"start_angle":180,"end_angle":0,"start_angle1":180,"value_font":12,"value_ofs_x":0,"value_ofs_y":-14,"bg_opa":0,"text":"--.-°C","min":200,"max":800,"val":0,"val_rule":"ESP32#Temperature","val_rule_formula":"val * 10","text_rule":"ESP32#Temperature","text_rule_format":"%2.1f °C"}
|
||||||
|
|
||||||
|
{"id":5,"obj":"label","x":2,"y":35,"w":120,"text":"Temperature","align":1}
|
||||||
|
|
||||||
|
{"id":10,"obj":"label","x":172,"y":35,"w":140,"text":"MPU","align":0}
|
||||||
|
{"id":11,"obj":"label","x":172,"y":55,"w":140,"text":"x=","align":0,"text_rule":"MPU9250#AX","text_rule_format":"x=%6.3f","text_rule_formula":"val / 1000"}
|
||||||
|
{"id":12,"obj":"label","x":172,"y":75,"w":140,"text":"y=","align":0,"text_rule":"MPU9250#AY","text_rule_format":"y=%6.3f","text_rule_formula":"val / 1000"}
|
||||||
|
{"id":13,"obj":"label","x":172,"y":95,"w":140,"text":"z=","align":0,"text_rule":"MPU9250#AZ","text_rule_format":"z=%6.3f","text_rule_formula":"val / 1000"}
|
||||||
|
|
||||||
|
{"page":3,"comment":"---------- Page 3 - qrcode ----------"}
|
||||||
|
{"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"}
|
||||||
|
{"id":1,"obj":"qrcode","qr_text":"https://github.com/arendst/Tasmota","x":85,"y":40,"qr_size":150}
|
||||||
|
|
||||||
|
{"page":4,"comment":"---------- Page 4 - fan animation ----------"}
|
||||||
|
{"id":0,"bg_color":"#0000A0","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#FFFFFF"}
|
||||||
|
{"id":11,"obj":"img","src":"A:/openhasp_demo.tapp#noun_Fan_35097_140.png","auto_size":1,"w":140,"h":140,"x":50,"y":50,"image_recolor":"#0080FF","image_recolor_opa":150}
|
||||||
|
{"id":12,"obj":"spinner","parentid":11,"x":7,"y":6,"w":126,"h":126,"bg_opa":0,"border_width":0,"line_width":7,"line_width1":7,"type":2,"angle":120,"speed":1000,"value_str":3,"value_font":24}
|
||||||
|
|
||||||
|
{"page":5,"comment":"---------- Page 5 - fancy watch ----------"}
|
||||||
|
{"id":0,"bg_color":"#000000","bg_grad_color":"#000000","bg_grad_dir":1,"text_color":"#000000"}
|
||||||
|
|
||||||
|
{"id":10,"obj":"img","src":"A:/openhasp_demo.tapp#watch_ren_back_240.png","x":40,"y":0,"w":240,"h":240}
|
||||||
|
{"id":11,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_hour_240.png","auto_size":1,"x":110,"y":45}
|
||||||
|
{"id":12,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_min_240.png","auto_size":1}
|
||||||
|
{"id":13,"obj":"img","parentid":10,"src":"A:/openhasp_demo.tapp#watch_ren_sec_240.png","auto_size":1,"x":110,"y":10}
|
||||||
|
{"id":15,"obj":"label","parentid":10,"x":184,"y":112,"w":18,"h":16,"text":"","align":1,"text_font":"montserrat-14"}
|
||||||
|
|
||||||
|
|
||||||
|
{"comment":"--- Trigger sensors every 2 seconds ---","berry_run":"tasmota.add_cron('*/2 * * * * *', def () tasmota.publish_rule(tasmota.read_sensors()) end, 'oh_every_5_s')"}
|
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 5.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.1 KiB |
Loading…
Reference in New Issue