Compare commits
2 commits
91341b2d75
...
6517fae509
Author | SHA1 | Date | |
---|---|---|---|
|
6517fae509 | ||
|
236e85c209 |
4 changed files with 487 additions and 9 deletions
144
medium-display.yaml
Normal file
144
medium-display.yaml
Normal file
|
@ -0,0 +1,144 @@
|
|||
esphome:
|
||||
name: infodisplay
|
||||
|
||||
esp32:
|
||||
board: esp32-s3-devkitc-1
|
||||
variant: esp32s3
|
||||
flash_size: 16MB
|
||||
framework:
|
||||
type: esp-idf
|
||||
version: recommended
|
||||
sdkconfig_options:
|
||||
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240: "y"
|
||||
CONFIG_ESP32S3_DATA_CACHE_64KB: "y"
|
||||
CONFIG_ESP32S3_DATA_CACHE_LINE_64B: "y"
|
||||
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB: "y"
|
||||
|
||||
CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST: "y"
|
||||
CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY: "y"
|
||||
|
||||
CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC: "y"
|
||||
CONFIG_MBEDTLS_SSL_PROTO_TLS1_3: "y"
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
|
||||
# # Enable Home Assistant API
|
||||
# api:
|
||||
# password: ""
|
||||
|
||||
# ota:
|
||||
# - platform: esphome
|
||||
# password: ""
|
||||
|
||||
# wifi:
|
||||
# ssid: "Coyote's Baubles"
|
||||
# password: "internetofshit1"
|
||||
|
||||
# # Enable fallback hotspot (captive portal) in case wifi connection fails
|
||||
# ap:
|
||||
# ssid: "Infodisplay Fallback Hotspot"
|
||||
# password: "21MYOl2F9OpG"
|
||||
|
||||
# captive_portal:
|
||||
|
||||
# Pins to use for things
|
||||
# 4 - Display CS -
|
||||
# 5 - Display Reset
|
||||
# 6 - Display DC
|
||||
# 7 - MOSI
|
||||
# 15 - SCK
|
||||
# 16 - LED
|
||||
# 17 - MISO
|
||||
# 18 - T_CLK
|
||||
# 8 - T_CS
|
||||
# 3 - T_DIN
|
||||
# 46 - T_DO
|
||||
# 9 - T_IRQ
|
||||
|
||||
# i2c:
|
||||
# - id: internal_i2c
|
||||
# sda: GPIO5
|
||||
# scl: GPIO6
|
||||
# frequency: 400kHz
|
||||
|
||||
psram:
|
||||
mode: octal
|
||||
speed: 40MHz
|
||||
|
||||
spi:
|
||||
- id: display_spi
|
||||
clk_pin: GPIO15
|
||||
mosi_pin: GPIO7
|
||||
miso_pin: GPIO17
|
||||
interface: any
|
||||
- id: touch_spi
|
||||
clk_pin: GPIO18
|
||||
mosi_pin: GPIO3
|
||||
miso_pin: GPIO46
|
||||
interface: any
|
||||
|
||||
output:
|
||||
- platform: ledc
|
||||
pin: GPIO16
|
||||
id: backlight_pwm
|
||||
|
||||
light:
|
||||
- platform: monochromatic
|
||||
output: backlight_pwm
|
||||
name: "Display Backlight"
|
||||
id: back_light
|
||||
restore_mode: ALWAYS_ON
|
||||
|
||||
touchscreen:
|
||||
platform: xpt2046
|
||||
id: the_touchscreen
|
||||
spi_id: touch_spi
|
||||
display: the_display
|
||||
cs_pin: GPIO8
|
||||
interrupt_pin: GPIO9
|
||||
transform:
|
||||
swap_xy: true
|
||||
calibration:
|
||||
x_min: 350
|
||||
x_max: 3640
|
||||
y_min: 350
|
||||
y_max: 3750
|
||||
# on_touch:
|
||||
# - lambda: |-
|
||||
# ESP_LOGI("cal", "x=%d, y=%d, x_raw=%d, y_raw=%0d",
|
||||
# touch.x,
|
||||
# touch.y,
|
||||
# touch.x_raw,
|
||||
# touch.y_raw
|
||||
# );
|
||||
|
||||
color:
|
||||
- id: my_red
|
||||
red: 100%
|
||||
green: 3%
|
||||
blue: 5%
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: the_display
|
||||
model: ili9341
|
||||
spi_id: display_spi
|
||||
dc_pin: GPIO6
|
||||
reset_pin: GPIO5
|
||||
cs_pin: GPIO4
|
||||
invert_colors: false
|
||||
rotation: 90°
|
||||
dimensions:
|
||||
height: 320
|
||||
width: 240
|
||||
auto_clear_enabled: false
|
||||
update_interval: never
|
||||
# show_test_card: true
|
||||
# lambda: |-
|
||||
# auto touch = id(the_touchscreen)->get_touch();
|
||||
# if (touch) // or touch.has_value()
|
||||
# it.filled_circle(touch.value().x, touch.value().y, 10, id(my_red));
|
||||
|
||||
lvgl:
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
const source=new EventSource("/events");source.addEventListener("log",function(t){const e=document.getElementById("log");let n=[["[1;31m","e"],["[0;33m","w"],["[0;32m","i"],["[0;35m","c"],["[0;36m","d"],["[0;37m","v"]],o="";for(const e of n)t.data.startsWith(e[0])&&(o=e[1]);""==o&&(e.innerHTML+=t.data+"\n"),e.innerHTML+='<span class="'+o+'">'+t.data.substr(7,t.data.length-11)+"</span>\n"});const actions=[["switch",["toggle"]],["light",["toggle"]],["fan",["toggle"]],["cover",["open","close"]],["button",["press"]],["lock",["lock","unlock","open"]]];const multi_actions=[["select","option"],["number","value"]];source.addEventListener("state",function(t){const e=JSON.parse(t.data);document.getElementById(e.id).children[1].innerText=e.state});const states=document.getElementById("states");let row,i=0;for(;row=states.rows[i];i++)if(row.children[2].children.length){for(const t of actions)if(row.classList.contains(t[0])){let e=row.id.substr(t[0].length+1);for(let n=0;n<row.children[2].children.length&&n<t[1].length;n++)row.children[2].children[n].addEventListener("click",function(){const o=new XMLHttpRequest;o.open("POST","/"+t[0]+"/"+e+"/"+t[1][n],!0),o.send()})}for(const t of multi_actions)if(row.classList.contains(t[0])){let e=row.id.substr(t[0].length+1);row.children[2].children[0].addEventListener("change",function(){const n=new XMLHttpRequest;n.open("POST","/"+t[0]+"/"+e+"/set?"+t[1]+"="+encodeURIComponent(this.value),!0),n.send()})}}
|
||||
{let e,t,r,o,n,l,s,i,f,h,w,a,d,u,_,c,S,g,y,b,m,v,j,x,O;s=Object.getPrototypeOf,f={},h=s(i={isConnected:1}),w=s(s),a=(e,t,r,o)=>(e??(setTimeout(r,o),new Set)).add(t),d=(e,t,o)=>{let n=r;r=t;try{return e(o)}catch(e){return console.error(e),o}finally{r=n}},u=e=>e.filter(e=>e.t?.isConnected),_=e=>n=a(n,e,()=>{for(let e of n)e.o=u(e.o),e.l=u(e.l);n=l},1e3),c={get val(){return r?.i?.add(this),this.rawVal},get oldVal(){return r?.i?.add(this),this.h},set val(o){r?.u?.add(this),o!==this.rawVal&&(this.rawVal=o,this.o.length+this.l.length?(t?.add(this),e=a(e,this,x)):this.h=o)}},S=e=>({__proto__:c,rawVal:e,h:e,o:[],l:[]}),g=(e,t)=>{let r={i:new Set,u:new Set},n={f:e},l=o;o=[];let s=d(e,r,t);s=(s??document).nodeType?s:new Text(s);for(let e of r.i)r.u.has(e)||(_(e),e.o.push(n));for(let e of o)e.t=s;return o=l,n.t=s},y=(e,t=S(),r)=>{let n={i:new Set,u:new Set},l={f:e,s:t};l.t=r??o?.push(l)??i,t.val=d(e,n,t.rawVal);for(let e of n.i)n.u.has(e)||(_(e),e.l.push(l));return t},b=(e,...t)=>{for(let r of t.flat(1/0)){let t=s(r??0),o=t===c?g(()=>r.val):t===w?g(r):r;o!=l&&e.append(o)}return e},m=(e,t,...r)=>{let[{is:o,...n},...i]=s(r[0]??0)===h?r:[{},...r],a=e?document.createElementNS(e,t,{is:o}):document.createElement(t,{is:o});for(let[e,r]of Object.entries(n)){let o=t=>t?Object.getOwnPropertyDescriptor(t,e)??o(s(t)):l,n=t+","+e,i=f[n]??=o(s(a))?.set??0,h=e.startsWith("on")?(t,r)=>{let o=e.slice(2);a.removeEventListener(o,r),a.addEventListener(o,t)}:i?i.bind(a):a.setAttribute.bind(a,e),d=s(r??0);e.startsWith("on")||d===w&&(r=y(r),d=c),d===c?g(()=>(h(r.val,r.h),a)):h(r)}return b(a,i)},v=e=>({get:(t,r)=>m.bind(l,e,r)}),j=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),x=()=>{let r=0,o=[...e].filter(e=>e.rawVal!==e.h);do{t=new Set;for(let e of new Set(o.flatMap(e=>e.l=u(e.l))))y(e.f,e.s,e.t),e.t=l}while(++r<100&&(o=[...t]).length);let n=[...e].filter(e=>e.rawVal!==e.h);e=l;for(let e of new Set(n.flatMap(e=>e.o=u(e.o))))j(e.t,g(e.f,e.t)),e.t=l;for(let e of n)e.h=e.rawVal},O={tags:new Proxy(e=>new Proxy(m,v(e)),v()),hydrate:(e,t)=>j(e,g(t,e)),add:b,state:S,derive:y},window.van=O;}
|
||||
{let e,t,r,{fromEntries:o,entries:l,keys:n,hasOwn:f,getPrototypeOf:a}=Object,{get:i,set:y,deleteProperty:c,ownKeys:s}=Reflect,{state:m,derive:d,add:u}=van,b=1e3,w=Symbol(),A=Symbol(),S=Symbol(),_=Symbol(),g=Symbol(),p=Symbol(),P=e=>(e[A]=1,e),v=e=>e instanceof Object&&!(e instanceof Function)&&!e[p],h=e=>{if(e?.[A]){let t=m();return d(()=>{let r=e();v(t.rawVal)&&v(r)?B(t.rawVal,r):t.val=x(r)}),t}return m(x(e))},F=e=>{let t=Array.isArray(e)?[]:{__proto__:a(e)};for(let[r,o]of l(e))t[r]=h(o);return t[S]=[],t[_]=m(1),t},O={get:(e,t,r)=>t===w?e:f(e,t)?Array.isArray(e)&&"length"===t?(e[_].val,e.length):e[t].val:i(e,t,r),set:(e,o,l,n)=>f(e,o)?Array.isArray(e)&&"length"===o?(l!==e.length&&++e[_].val,e.length=l,1):(e[o].val=x(l),1):o in e?y(e,o,l,n):y(e,o,h(l))&&(++e[_].val,C(e).forEach(E.bind(t,n,o,e[o],r)),1),deleteProperty:(e,t)=>(c(e,t)&&R(e,t),++e[_].val),ownKeys:e=>(e[_].val,s(e))},x=e=>!v(e)||e[w]?e:new Proxy(F(e),O),D=e=>(e[p]=1,e),j=e=>e[w],K=a(m()),N=e=>new Proxy(e,{get:(e,t,r)=>a(e[t]??0)===K?{val:k(e[t].rawVal)}:i(e,t,r)}),k=e=>e?.[w]?new Proxy(N(e[w]),O):e,C=e=>e[S]=e[S].filter(e=>e.t.isConnected),E=(e,t,r,o,{t:l,f:f})=>{let a=Array.isArray(e),i=a?Number(t):t;u(l,()=>l[g][t]=f(r,()=>delete e[t],i)),a&&!o&&i!==e.length-1&&l.insertBefore(l.lastChild,l[g][n(e).find(e=>Number(e)>i)])},R=(e,t)=>{for(let r of C(e)){let e=r.t[g];e[t]?.remove(),delete e[t]}},T=r=>(e??(setTimeout(()=>(e.forEach(C),e=t),b),e=new Set)).add(r),q=(e,t,r)=>{let o={t:e instanceof Function?e():e,f:r},n=t[w];o.t[g]={},n[S].push(o),T(n);for(let[e,r]of l(n))E(t,e,r,1,o);return o.t},z=(e,t)=>{for(let[r,o]of l(t)){let t=e[r];v(t)&&v(o)?z(t,o):e[r]=o}for(let r in e)f(t,r)||delete e[r];let r=n(t),o=Array.isArray(e);if(o||n(e).some((e,t)=>e!==r[t])){let l=e[w];if(o)e.length=t.length;else{++l[_].val;let e={...l};for(let e of r)delete l[e];for(let t of r)l[t]=e[t]}for(let{t:e}of C(l)){let{firstChild:t,[g]:o}=e;for(let l of r)t===o[l]?t=t.nextSibling:e.insertBefore(o[l],t)}}return e},B=(e,n)=>{r=1;try{return z(e,n instanceof Function?Array.isArray(e)?n(e.filter(e=>1)):o(n(l(e))):n)}finally{r=t}},G=e=>Array.isArray(e)?e.filter(e=>1).map(G):v(e)?o(l(e).map(([e,t])=>[e,G(t)])):e;window.vanX={calc:P,reactive:x,noreactive:D,stateFields:j,raw:k,list:q,replace:B,compact:G}}
|
||||
function hex2tuya(hex){hex=hex.replace(/^#/,'');const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);const hsv=rgb2hsv(r,g,b);const h=Math.round(hsv.h).toString(16).padStart(4,"0");const s=Math.round(hsv.s*10).toString(16).padStart(4,"0");const v=Math.round(hsv.v*10).toString(16).padStart(4,"0");const tuyastr=h+s+v+"00000000";return tuyastr;}
|
||||
function rgb2hsv(r,g,b){let rabs,gabs,babs,rr,gg,bb,h,s,v,diff,diffc,percentRoundFn;rabs=r/255;gabs=g/255;babs=b/255;v=Math.max(rabs,gabs,babs),diff=v-Math.min(rabs,gabs,babs);diffc=c=>(v-c)/6/diff+1/2;percentRoundFn=num=>Math.round(num*100)/100;if(diff==0){h=s=0;}else{s=diff/v;rr=diffc(rabs);gg=diffc(gabs);bb=diffc(babs);if(rabs===v){h=bb-gg;}else if(gabs===v){h=(1/3)+rr-bb;}else if(babs===v){h=(2/3)+gg-rr;}
|
||||
if(h<0){h+=1;}else if(h>1){h-=1;}}
|
||||
return{h:Math.round(h*360),s:percentRoundFn(s*100),v:percentRoundFn(v*100)};}
|
||||
const{a,button,p,div,input,span,ul,li,select,option}=van.tags;const lightModes=["Fade","Flash","Music"];const lightPatterns=["Solid","Up","Down","Center","Stripe","Out","In","Rotate","Spiral"];const ColorPicker=()=>{const config=vanX.reactive({id:Math.round(Math.random()*30),mode:0,pattern:0,speed:10,colors:[{color:"#ffffff"}]});return div(div(span("ID: ",input({type:"number",min:0,max:30,required:true,value:config.id,oninput:e=>config.id=parseInt(e.target.value)}))),div(span("Mode: ",select({oninput:e=>config.mode=parseInt(e.target.value)},...lightModes.map((v,i)=>option({value:i.toString(),selected:i==config.mode},v))))),div(span("Pattern: ",select({oninput:e=>config.pattern=parseInt(e.target.value)},...lightPatterns.map((v,i)=>option({value:i.toString(),selected:i==config.pattern},v))))),div(span("Speed: ",()=>config.speed,input({type:'range',min:0,max:100,required:true,value:config.speed,oninput:e=>config.speed=parseInt(e.target.value)}))),div("Colors:",vanX.list(ul,config.colors,({val:v},deleter)=>li(span(a({onclick:deleter},"✖️"),input({type:"color",value:v.color,oninput:e=>v.color=e.target.value}),()=>`${v.color}`))),button({onclick:()=>config.colors.push({color:"#ffffff"})},"➕")),div(()=>{const id=config.id.toString(16).padStart(2,"0");const mode=config.mode.toString(16).padStart(2,"0");const pattern=config.pattern.toString(16).padStart(2,"0");const speed=config.speed.toString(16).padStart(2,"0");const colorString=config.colors.map(v=>hex2tuya(v.color)).join("")
|
||||
const configstring=`${id}${speed}${mode}${pattern}${colorString}`;return configstring;}));};setTimeout(() => van.add(document.body,ColorPicker()),1000);
|
||||
const source=new EventSource("/events");source.addEventListener("log",function(t){const e=document.getElementById("log");let n=[["[1;31m","e"],["[0;33m","w"],["[0;32m","i"],["[0;35m","c"],["[0;36m","d"],["[0;37m","v"]],o="";for(const e of n)t.data.startsWith(e[0])&&(o=e[1]);""==o&&(e.innerHTML+=t.data+"\n"),e.innerHTML+='<span class="'+o+'">'+t.data.substr(7,t.data.length-11)+"</span>\n"});const actions=[["switch",["toggle"]],["light",["toggle"]],["fan",["toggle"]],["cover",["open","close"]],["button",["press"]],["lock",["lock","unlock","open"]]];const multi_actions=[["select","option"],["number","value"]];source.addEventListener("state",function(t){const e=JSON.parse(t.data);document.getElementById(e.id).children[1].innerText=e.state});const states=document.getElementById("states");let row,i=0;for(;row=states.rows[i];i++)if(row.children[2].children.length){for(const t of actions)if(row.classList.contains(t[0])){let e=row.id.substr(t[0].length+1);for(let n=0;n<row.children[2].children.length&&n<t[1].length;n++)row.children[2].children[n].addEventListener("click",function(){const o=new XMLHttpRequest;o.open("POST","/"+t[0]+"/"+e+"/"+t[1][n],!0),o.send()})}for(const t of multi_actions)if(row.classList.contains(t[0])){let e=row.id.substr(t[0].length+1);row.children[2].children[0].addEventListener("change",function(){const n=new XMLHttpRequest;n.open("POST","/"+t[0]+"/"+e+"/set?"+t[1]+"="+encodeURIComponent(this.value),!0),n.send()})}}
|
||||
{let e,t,r,o,n,l,s,i,f,h,w,a,d,u,_,c,S,g,y,b,m,v,j,x,O;s=Object.getPrototypeOf,f={},h=s(i={isConnected:1}),w=s(s),a=(e,t,r,o)=>(e??(setTimeout(r,o),new Set)).add(t),d=(e,t,o)=>{let n=r;r=t;try{return e(o)}catch(e){return console.error(e),o}finally{r=n}},u=e=>e.filter(e=>e.t?.isConnected),_=e=>n=a(n,e,()=>{for(let e of n)e.o=u(e.o),e.l=u(e.l);n=l},1e3),c={get val(){return r?.i?.add(this),this.rawVal},get oldVal(){return r?.i?.add(this),this.h},set val(o){r?.u?.add(this),o!==this.rawVal&&(this.rawVal=o,this.o.length+this.l.length?(t?.add(this),e=a(e,this,x)):this.h=o)}},S=e=>({__proto__:c,rawVal:e,h:e,o:[],l:[]}),g=(e,t)=>{let r={i:new Set,u:new Set},n={f:e},l=o;o=[];let s=d(e,r,t);s=(s??document).nodeType?s:new Text(s);for(let e of r.i)r.u.has(e)||(_(e),e.o.push(n));for(let e of o)e.t=s;return o=l,n.t=s},y=(e,t=S(),r)=>{let n={i:new Set,u:new Set},l={f:e,s:t};l.t=r??o?.push(l)??i,t.val=d(e,n,t.rawVal);for(let e of n.i)n.u.has(e)||(_(e),e.l.push(l));return t},b=(e,...t)=>{for(let r of t.flat(1/0)){let t=s(r??0),o=t===c?g(()=>r.val):t===w?g(r):r;o!=l&&e.append(o)}return e},m=(e,t,...r)=>{let[{is:o,...n},...i]=s(r[0]??0)===h?r:[{},...r],a=e?document.createElementNS(e,t,{is:o}):document.createElement(t,{is:o});for(let[e,r]of Object.entries(n)){let o=t=>t?Object.getOwnPropertyDescriptor(t,e)??o(s(t)):l,n=t+","+e,i=f[n]??=o(s(a))?.set??0,h=e.startsWith("on")?(t,r)=>{let o=e.slice(2);a.removeEventListener(o,r),a.addEventListener(o,t)}:i?i.bind(a):a.setAttribute.bind(a,e),d=s(r??0);e.startsWith("on")||d===w&&(r=y(r),d=c),d===c?g(()=>(h(r.val,r.h),a)):h(r)}return b(a,i)},v=e=>({get:(t,r)=>m.bind(l,e,r)}),j=(e,t)=>t?t!==e&&e.replaceWith(t):e.remove(),x=()=>{let r=0,o=[...e].filter(e=>e.rawVal!==e.h);do{t=new Set;for(let e of new Set(o.flatMap(e=>e.l=u(e.l))))y(e.f,e.s,e.t),e.t=l}while(++r<100&&(o=[...t]).length);let n=[...e].filter(e=>e.rawVal!==e.h);e=l;for(let e of new Set(n.flatMap(e=>e.o=u(e.o))))j(e.t,g(e.f,e.t)),e.t=l;for(let e of n)e.h=e.rawVal},O={tags:new Proxy(e=>new Proxy(m,v(e)),v()),hydrate:(e,t)=>j(e,g(t,e)),add:b,state:S,derive:y},window.van=O;}
|
||||
{let e,t,r,{fromEntries:o,entries:l,keys:n,hasOwn:f,getPrototypeOf:a}=Object,{get:i,set:y,deleteProperty:c,ownKeys:s}=Reflect,{state:m,derive:d,add:u}=van,b=1e3,w=Symbol(),A=Symbol(),S=Symbol(),_=Symbol(),g=Symbol(),p=Symbol(),P=e=>(e[A]=1,e),v=e=>e instanceof Object&&!(e instanceof Function)&&!e[p],h=e=>{if(e?.[A]){let t=m();return d(()=>{let r=e();v(t.rawVal)&&v(r)?B(t.rawVal,r):t.val=x(r)}),t}return m(x(e))},F=e=>{let t=Array.isArray(e)?[]:{__proto__:a(e)};for(let[r,o]of l(e))t[r]=h(o);return t[S]=[],t[_]=m(1),t},O={get:(e,t,r)=>t===w?e:f(e,t)?Array.isArray(e)&&"length"===t?(e[_].val,e.length):e[t].val:i(e,t,r),set:(e,o,l,n)=>f(e,o)?Array.isArray(e)&&"length"===o?(l!==e.length&&++e[_].val,e.length=l,1):(e[o].val=x(l),1):o in e?y(e,o,l,n):y(e,o,h(l))&&(++e[_].val,C(e).forEach(E.bind(t,n,o,e[o],r)),1),deleteProperty:(e,t)=>(c(e,t)&&R(e,t),++e[_].val),ownKeys:e=>(e[_].val,s(e))},x=e=>!v(e)||e[w]?e:new Proxy(F(e),O),D=e=>(e[p]=1,e),j=e=>e[w],K=a(m()),N=e=>new Proxy(e,{get:(e,t,r)=>a(e[t]??0)===K?{val:k(e[t].rawVal)}:i(e,t,r)}),k=e=>e?.[w]?new Proxy(N(e[w]),O):e,C=e=>e[S]=e[S].filter(e=>e.t.isConnected),E=(e,t,r,o,{t:l,f:f})=>{let a=Array.isArray(e),i=a?Number(t):t;u(l,()=>l[g][t]=f(r,()=>delete e[t],i)),a&&!o&&i!==e.length-1&&l.insertBefore(l.lastChild,l[g][n(e).find(e=>Number(e)>i)])},R=(e,t)=>{for(let r of C(e)){let e=r.t[g];e[t]?.remove(),delete e[t]}},T=r=>(e??(setTimeout(()=>(e.forEach(C),e=t),b),e=new Set)).add(r),q=(e,t,r)=>{let o={t:e instanceof Function?e():e,f:r},n=t[w];o.t[g]={},n[S].push(o),T(n);for(let[e,r]of l(n))E(t,e,r,1,o);return o.t},z=(e,t)=>{for(let[r,o]of l(t)){let t=e[r];v(t)&&v(o)?z(t,o):e[r]=o}for(let r in e)f(t,r)||delete e[r];let r=n(t),o=Array.isArray(e);if(o||n(e).some((e,t)=>e!==r[t])){let l=e[w];if(o)e.length=t.length;else{++l[_].val;let e={...l};for(let e of r)delete l[e];for(let t of r)l[t]=e[t]}for(let{t:e}of C(l)){let{firstChild:t,[g]:o}=e;for(let l of r)t===o[l]?t=t.nextSibling:e.insertBefore(o[l],t)}}return e},B=(e,n)=>{r=1;try{return z(e,n instanceof Function?Array.isArray(e)?n(e.filter(e=>1)):o(n(l(e))):n)}finally{r=t}},G=e=>Array.isArray(e)?e.filter(e=>1).map(G):v(e)?o(l(e).map(([e,t])=>[e,G(t)])):e;window.vanX={calc:P,reactive:x,noreactive:D,stateFields:j,raw:k,list:q,replace:B,compact:G}}
|
||||
function hex2tuya(hex){hex=hex.replace(/^#/,'');const r=parseInt(hex.substring(0,2),16);const g=parseInt(hex.substring(2,4),16);const b=parseInt(hex.substring(4,6),16);const hsv=rgb2hsv(r,g,b);const h=Math.round(hsv.h).toString(16).padStart(4,"0");const s=Math.round(hsv.s*10).toString(16).padStart(4,"0");const v=Math.round(hsv.v*10).toString(16).padStart(4,"0");const tuyastr=h+s+v+"00000000";return tuyastr;}
|
||||
function rgb2hsv(r,g,b){let rabs,gabs,babs,rr,gg,bb,h,s,v,diff,diffc,percentRoundFn;rabs=r/255;gabs=g/255;babs=b/255;v=Math.max(rabs,gabs,babs),diff=v-Math.min(rabs,gabs,babs);diffc=c=>(v-c)/6/diff+1/2;percentRoundFn=num=>Math.round(num*100)/100;if(diff==0){h=s=0;}else{s=diff/v;rr=diffc(rabs);gg=diffc(gabs);bb=diffc(babs);if(rabs===v){h=bb-gg;}else if(gabs===v){h=(1/3)+rr-bb;}else if(babs===v){h=(2/3)+gg-rr;}
|
||||
if(h<0){h+=1;}else if(h>1){h-=1;}}
|
||||
return{h:Math.round(h*360),s:percentRoundFn(s*100),v:percentRoundFn(v*100)};}
|
||||
const{a,button,p,div,input,span,ul,li,select,option}=van.tags;const lightModes=["Fade","Flash","Music"];const lightPatterns=["Solid","Up","Down","Center","Stripe","Out","In","Rotate","Spiral"];const ColorPicker=()=>{const config=vanX.reactive({id:Math.round(Math.random()*30),mode:0,pattern:0,speed:10,colors:[{color:"#ffffff"}]});return div(div(span("ID: ",input({type:"number",min:0,max:30,required:true,value:config.id,oninput:e=>config.id=parseInt(e.target.value)}))),div(span("Mode: ",select({oninput:e=>config.mode=parseInt(e.target.value)},...lightModes.map((v,i)=>option({value:i.toString(),selected:i==config.mode},v))))),div(span("Pattern: ",select({oninput:e=>config.pattern=parseInt(e.target.value)},...lightPatterns.map((v,i)=>option({value:i.toString(),selected:i==config.pattern},v))))),div(span("Speed: ",()=>config.speed,input({type:'range',min:0,max:100,required:true,value:config.speed,oninput:e=>config.speed=parseInt(e.target.value)}))),div("Colors:",vanX.list(ul,config.colors,({val:v},deleter)=>li(span(a({onclick:deleter},"✖️"),input({type:"color",value:v.color,oninput:e=>v.color=e.target.value}),()=>`${v.color}`))),button({onclick:()=>config.colors.push({color:"#ffffff"})},"➕")),div(()=>{const id=config.id.toString(16).padStart(2,"0");const mode=config.mode.toString(16).padStart(2,"0");const pattern=config.pattern.toString(16).padStart(2,"0");const speed=config.speed.toString(16).padStart(2,"0");const colorString=config.colors.map(v=>hex2tuya(v.color)).join("")
|
||||
const configstring=`${id}${speed}${mode}${pattern}${colorString}`;return configstring;}));};setTimeout(() => van.add(document.body,ColorPicker()),1000);
|
||||
|
|
21
testdisp.yaml
Normal file
21
testdisp.yaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
esphome:
|
||||
name: testdisplay
|
||||
|
||||
host:
|
||||
logger:
|
||||
api:
|
||||
password: ""
|
||||
# ota:
|
||||
# wifi:
|
||||
# captive_portal:
|
||||
|
||||
display:
|
||||
- platform: sdl
|
||||
show_test_card: true
|
||||
# rotation: 90°
|
||||
dimensions:
|
||||
height: 240
|
||||
width: 320
|
||||
touchscreen:
|
||||
platform: sdl
|
||||
lvgl:
|
313
walkie.yaml
Normal file
313
walkie.yaml
Normal file
|
@ -0,0 +1,313 @@
|
|||
esphome:
|
||||
name: walkie
|
||||
# libraries:
|
||||
# - "SPI"
|
||||
# - "Ticker"
|
||||
# - "SX126x-Arduino"
|
||||
|
||||
esp32:
|
||||
board: esp32dev
|
||||
framework:
|
||||
type: arduino
|
||||
|
||||
# Enable logging
|
||||
logger:
|
||||
# baud_rate: 0
|
||||
|
||||
# Enable Home Assistant API
|
||||
# api:
|
||||
# password: ""
|
||||
|
||||
# ota:
|
||||
# platform: esphome
|
||||
packages:
|
||||
wifi: !include base/wifi.inc.yaml
|
||||
ota: !include base/ota.inc.yaml
|
||||
api: !include base/api.inc.yaml
|
||||
wifi:
|
||||
on_connect:
|
||||
- lvgl.widget.show: lbl_hastatus
|
||||
on_disconnect:
|
||||
- lvgl.widget.hide: lbl_hastatus
|
||||
|
||||
# external_components:
|
||||
# - source:
|
||||
# type: git
|
||||
# url: https://github.com/PaulSchulz/esphome-lora-sx126x
|
||||
# ref: main
|
||||
# components: ["lorawan_sx126x"]
|
||||
|
||||
output:
|
||||
- platform: ledc
|
||||
pin: GPIO32
|
||||
id: backlight_pwm
|
||||
inverted: true
|
||||
- platform: ledc
|
||||
pin: GPIO19
|
||||
id: spkr_pwm
|
||||
rtttl:
|
||||
output: spkr_pwm
|
||||
id: speaker_rtttl
|
||||
gain: 50%
|
||||
|
||||
light:
|
||||
- platform: monochromatic
|
||||
output: backlight_pwm
|
||||
name: "Display Backlight"
|
||||
id: back_light
|
||||
restore_mode: ALWAYS_ON
|
||||
|
||||
sn74hc165:
|
||||
- id: sn74hc165_hub
|
||||
clock_pin: GPIO22
|
||||
data_pin: GPIO23
|
||||
load_pin: GPIO21
|
||||
# clock_inhibit_pin: GPIOXX
|
||||
sr_count: 2
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
id: key_del
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 0
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_7
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 1
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_4
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 2
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_1
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 3
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_2
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 4
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_5
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 5
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_8
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 6
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_0
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 7
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_func
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 8
|
||||
inverted: true
|
||||
on_release:
|
||||
- if:
|
||||
condition: lvgl.is_paused
|
||||
then:
|
||||
- logger.log: "LVGL resuming"
|
||||
- lvgl.resume:
|
||||
- lvgl.widget.redraw:
|
||||
- light.turn_on: back_light
|
||||
- platform: gpio
|
||||
id: key_9
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 9
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_6
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 10
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_3
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 11
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_up
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 12
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_down
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 13
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_ok
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 14
|
||||
inverted: true
|
||||
- platform: gpio
|
||||
id: key_esc
|
||||
pin:
|
||||
sn74hc165: sn74hc165_hub
|
||||
number: 15
|
||||
inverted: true
|
||||
|
||||
sensor:
|
||||
- platform: adc
|
||||
pin: GPIO34
|
||||
name: "Battery Voltage"
|
||||
id: batt_volt
|
||||
accuracy_decimals: 2
|
||||
update_interval: 60s
|
||||
attenuation: 12dB
|
||||
samples: 10
|
||||
filters:
|
||||
- multiply: 6.0 # The voltage divider requires us to multiply by 2
|
||||
on_value:
|
||||
- lvgl.indicator.update:
|
||||
id: batt_needle
|
||||
value: !lambda "return x;"
|
||||
# - platform: lora-sx126x
|
||||
# id: lorarssi
|
||||
# name: lorarssi
|
||||
|
||||
spi:
|
||||
- id: display_bus
|
||||
clk_pin: GPIO27
|
||||
mosi_pin: GPIO26
|
||||
# - id: radio_bus
|
||||
# mosi_pin: GPIO5
|
||||
# miso_pin: GPIO17
|
||||
# clk_pin: GPIO16
|
||||
|
||||
# lorawan_sx126x:
|
||||
# # name: "LoRa Radio"
|
||||
# pin_lora_reset: -1
|
||||
# pin-lora_dio_1: GPIO18
|
||||
# pin_lora_busy: GPIO4
|
||||
# pin_lora_nss: GPIO14
|
||||
# pin_lora_sclk: GPIO16
|
||||
# pin_lora_miso: GPIO17
|
||||
# pin_lora_mosi: GPIO5
|
||||
# region: US915
|
||||
# subchannel: 2
|
||||
# device_type: CLASS_A
|
||||
# authentication: OTAA
|
||||
# app_eui: !secret lorawan_join_eui
|
||||
# app_key: !secret lorawan_app_key
|
||||
|
||||
# lora_sx126x:
|
||||
# name: "LoRa Radio"
|
||||
|
||||
# # # Interface to radio chip
|
||||
# pin_lora_reset: -1 # LoRa Reset
|
||||
# pin-lora_dio_1: GPIO18 # LoRa DIO_1
|
||||
# pin_lora_busy: GPIO4 # LoRa SPI Busy
|
||||
# pin_lora_nss: GPIO14 # LoRa SPI CS (Chip Select)
|
||||
# pin_lora_sclk: GPIO16 # LoRa SPI SCLK
|
||||
# pin_lora_miso: GPIO17 # LoRa SPI MISO (Master In, Slave Out)
|
||||
# pin_lora_mosi: GPIO5 # LoRa SPI MOSI (Master Out, Slave In)
|
||||
# # radio_txen: -1 # LoRa Antenna TX Enable, on some boards.
|
||||
# # radio_rxen: -1 # LoRa Antenna RX Enable, on some boards.
|
||||
|
||||
# # LoRa Options
|
||||
# # Setting these will enable the LoRa radio mode.
|
||||
# # tx_output_power: 22 # dBm
|
||||
# # lora_bandwidth: 0 # [0: 1 25 kHz, 1: 250 kHz, 2: 500 kHz, 3: Reserved]
|
||||
# # lora_spreading_factor: 7 # [SF7..SF12]
|
||||
# # lora_codingrate: 1 # [1: 4/5, 2: 4/6, 3: 4/7, 4: 4/8]
|
||||
# # lora_preamble_length: 8 # Same for Tx and Rx
|
||||
# # lora_symbol_timeout: 0 # Symbols
|
||||
# # lora_fx_length_payload_on: -1 # Default: -1 (False)
|
||||
# # lora_iq_inversion_on: -1 # Default: -1 (False)
|
||||
# # rx_timeout_value: 3000 # ms
|
||||
# # tx_timeout_value: 3000 # ms
|
||||
# rf_frequency: 915000000 # Hz - Manditory
|
||||
|
||||
display:
|
||||
- platform: ili9xxx
|
||||
id: my_display
|
||||
spi_id: display_bus
|
||||
model: ST7735
|
||||
dc_pin: GPIO33
|
||||
reset_pin: GPIO15
|
||||
# cs_pin: -1
|
||||
invert_colors: false
|
||||
dimensions:
|
||||
height: 160
|
||||
width: 128
|
||||
rotation: 90°
|
||||
# show_test_card: true
|
||||
auto_clear_enabled: false
|
||||
update_interval: never
|
||||
|
||||
lvgl:
|
||||
# encoders:
|
||||
# - enter_button: key_ok
|
||||
# sensor:
|
||||
# left_button: key_up
|
||||
# right_button: key_down
|
||||
keypads:
|
||||
- up: key_up
|
||||
down: key_down
|
||||
left: key_up
|
||||
right: key_up
|
||||
esc: key_esc
|
||||
backspace: key_del
|
||||
enter: key_ok
|
||||
home: key_2
|
||||
end: key_0
|
||||
next: key_6
|
||||
prev: key_4
|
||||
widgets:
|
||||
- meter:
|
||||
scales:
|
||||
range_from: 2.5
|
||||
range_to: 5.5
|
||||
ticks:
|
||||
count: 12
|
||||
angle_range: 180
|
||||
indicators:
|
||||
- arc:
|
||||
end_value: 5.5
|
||||
start_value: 2.5
|
||||
- line:
|
||||
id: batt_needle
|
||||
width: 2
|
||||
# r_mod: 3
|
||||
on_idle:
|
||||
- timeout: 30s
|
||||
then:
|
||||
- light.turn_off: back_light
|
||||
- lvgl.pause:
|
||||
top_layer:
|
||||
bg_color: 0x0033DD
|
||||
widgets:
|
||||
- label:
|
||||
text: "\uF1EB"
|
||||
id: lbl_hastatus
|
||||
hidden: true
|
||||
align: top_right
|
||||
x: -2
|
||||
y: 7
|
||||
text_align: right
|
||||
text_color: 0xFFFFFF
|
Loading…
Add table
Add a link
Reference in a new issue