commit e3f3858d1e5edf94b9ba561cc350d7d71ac7001d
Author: joBr99 i&&s.push(r(n,i,d));let{value:h}=c[u];s.push(t(n,{start:d,end:i=m,value:h}))}return i{let o=n.data;switch(o.type){case 1:na.value=!0;break;case 3:typeof o.data.pagination.prev<"u"?it.value=He(H({},it.value),{pagination:o.data.pagination,items:[...it.value.items,...o.data.items]}):(it.value=o.data,ao(0));break}},qt(()=>{lr.value&&r.postMessage({type:0,data:lr.value})}),qt(()=>{na.value&&r.postMessage({type:2,data:Se.value})})}var oa={container:"p",hidden:"m"};function Mu(e){return z("div",{class:zt(oa.container,{[oa.hidden]:e.hidden}),onClick:()=>Dt()})}var ia={container:"r",disabled:"c"};function so(e){return z("button",{class:zt(ia.container,{[ia.disabled]:!e.onClick}),onClick:e.onClick,children:e.children})}var aa=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),ku=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,r,n)=>n?n.toUpperCase():r.toLowerCase()),sa=e=>{let t=ku(e);return t.charAt(0).toUpperCase()+t.slice(1)},Au=(...e)=>e.filter((t,r,n)=>!!t&&t.trim()!==""&&n.indexOf(t)===r).join(" ").trim(),Cu={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},Hu=c=>{var l=c,{color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:n,children:o,iconNode:i,class:a=""}=l,s=gr(l,["color","size","strokeWidth","absoluteStrokeWidth","children","iconNode","class"]);return Wt("svg",H(He(H({},Cu),{width:String(t),height:t,stroke:e,"stroke-width":n?Number(r)*24/Number(t):r,class:["lucide",a].join(" ")}),s),[...i.map(([u,p])=>Wt(u,p)),...Cr(o)])},bo=(e,t)=>{let r=a=>{var s=a,{class:n="",children:o}=s,i=gr(s,["class","children"]);return Wt(Hu,He(H({},i),{iconNode:t,class:Au(`lucide-${aa(sa(e))}`,`lucide-${aa(e)}`,n)}),o)};return r.displayName=sa(e),r},$u=bo("corner-down-left",[["path",{d:"M20 4v7a4 4 0 0 1-4 4H4",key:"6o5b7l"}],["path",{d:"m9 10-5 5 5 5",key:"1kshq7"}]]),Pu=bo("list-filter",[["path",{d:"M2 5h20",key:"1fs1ex"}],["path",{d:"M6 12h12",key:"8npq4p"}],["path",{d:"M9 19h6",key:"456am0"}]]),Iu=bo("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]),Yx=ml(dl(),1);function Ru({threshold:e=0,root:t=null,rootMargin:r="0%",freezeOnceVisible:n=!1,initialIsIntersecting:o=!1,onChange:i}={}){var a;let[s,c]=ro(null),[l,u]=ro(()=>({isIntersecting:o,entry:void 0})),p=Vt();p.current=i;let d=((a=l.entry)==null?void 0:a.isIntersecting)&&n;St(()=>{if(!s||!("IntersectionObserver"in window)||d)return;let v,S=new IntersectionObserver(x=>{let w=Array.isArray(S.thresholds)?S.thresholds:[S.thresholds];x.forEach(_=>{let de=_.isIntersecting&&w.some(be=>_.intersectionRatio>=be);u({isIntersecting:de,entry:_}),p.current&&p.current(de,_),de&&n&&v&&(v(),v=void 0)})},{threshold:e,root:t,rootMargin:r});return S.observe(s),()=>{S.disconnect()}},[s,JSON.stringify(e),t,r,d,n]);let m=Vt(null);St(()=>{var v;!s&&(v=l.entry)!=null&&v.target&&!n&&!d&&m.current!==l.entry.target&&(m.current=l.entry.target,u({isIntersecting:o,entry:void 0}))},[s,l.entry,n,d,o]);let h=[c,!!l.isIntersecting,l.entry];return h.ref=h[0],h.isIntersecting=h[1],h.entry=h[2],h}var lt={container:"n",hidden:"l",content:"u",pop:"d",badge:"y",sidebar:"i",controls:"w",results:"k",loadmore:"z"};function ju(e){let{isIntersecting:t,ref:r}=Ru({threshold:0});St(()=>{t&&au()},[t]);let n=Vt(null);St(()=>{n.current&&typeof Se.value.page>"u"&&n.current.scrollTo({top:0,behavior:"smooth"})},[Se.value]);let o=za();return z("div",{class:zt(lt.container,{[lt.hidden]:e.hidden}),children:[z("div",{class:lt.content,children:[z("div",{class:lt.controls,children:[z(so,{onClick:Dt,children:z(Iu,{})}),z(Uu,{focus:!e.hidden}),z(so,{onClick:Wa,children:[z(Pu,{}),o.length>0&&z("span",{class:lt.badge,children:o.length})]})]}),z("div",{class:lt.results,ref:n,children:[z(Nu,{keyboard:!e.hidden}),z("div",{class:lt.loadmore,ref:r})]})]}),z("div",{class:zt(lt.sidebar,{[lt.hidden]:fu()}),children:z(Fu,{})})]})}var Et={container:"X",list:"j",heading:"F",title:"I",item:"o",active:"g",value:"R",count:"q"};function Fu(e){let t=pu();return t.sort((r,n)=>n.node.count-r.node.count),z("div",{class:Et.container,children:[z("h3",{class:Et.heading,children:"Filters"}),z("h4",{class:Et.title,children:"Tags"}),z("ol",{class:Et.list,children:t.map(r=>z("li",{class:zt(Et.item,{[Et.active]:su(r.node.value)}),onClick:()=>cu(r.node.value),children:[z("span",{class:Et.value,children:r.node.value}),z("span",{class:Et.count,children:r.node.count})]}))})]})}var ca={container:"f"};function Uu(e){let t=Vt(null);return St(()=>{var r,n;e.focus?(r=t.current)==null||r.focus():(n=t.current)==null||n.blur()},[e.focus]),z("div",{class:ca.container,children:z("input",{ref:t,type:"text",class:ca.content,value:hn(vo()),onInput:r=>Va(_u(r.currentTarget.value)),autocapitalize:"off",autocomplete:"off",autocorrect:"off",placeholder:"Search",spellcheck:!1,role:"combobox"})})}var ut={container:"b",heading:"A",item:"a",active:"h",wrapper:"B",actions:"s",title:"x",path:"t"};function Nu(e){var a;let t=iu(),r=lu(),n=dn(),o=Vt([]);St(()=>{let s=o.current[n];s&&s.scrollIntoView({block:"center",behavior:"smooth"})},[n]),Aa(e.keyboard,s=>{let c=dn();s.key==="ArrowDown"?(s.preventDefault(),ao(Math.min(c+1,r.length-1))):s.key==="ArrowUp"&&(s.preventDefault(),ao(Math.max(c-1,0)))},[e.keyboard]);let i=(a=uu())!=null?a:0;return z(ft,{children:[r.length>0&&z("h3",{class:ut.heading,children:[z("span",{class:ut.bubble,children:new Intl.NumberFormat("en-US").format(i)})," ","results"]}),z("ol",{class:ut.container,children:r.map((s,c)=>{var d;let l=Ka(t[s.id].title,s.matches.find(({field:m})=>m==="title")),u=Lu((d=t[s.id].path)!=null?d:[],s.matches.find(({field:m})=>m==="path")),p=t[s.id].location;if(mu()){let m=encodeURIComponent(vo()),[h,v]=p.split("#",2);p=`${h}?h=${m.replace(/%20/g,"+")}`,typeof v<"u"&&(p+=`#${v}`)}return z("li",{children:z("a",{ref:m=>{o.current[c]=m},href:p,onClick:()=>Dt(),class:zt(ut.item,{[ut.active]:c===dn()}),children:[z("div",{class:ut.wrapper,children:[z("h2",{class:ut.title,children:l}),z("menu",{class:ut.path,children:u.map(m=>z("li",{children:m}))})]}),z("nav",{class:ut.actions,children:z(so,{children:z($u,{})})})]})})})})]})}var Du={container:"e"};function Wu(e){return Aa(!0,t=>{var r,n,o;if((t.metaKey||t.ctrlKey)&&t.key==="k")t.preventDefault(),Dt();else if((t.metaKey||t.ctrlKey)&&t.key==="j")document.body.classList.toggle("dark");else if(t.key==="Enter"&&!sr()){t.preventDefault(),Dt();let i=dn(),a=(n=(r=it.value)==null?void 0:r.items[i])==null?void 0:n.id;(o=lr.value)!=null&&o.items[a].location&&(window.location.href=lr.value.items[a].location)}else t.key==="Escape"&&!sr()&&(t.preventDefault(),Dt())},[]),z("div",{class:Du.container,children:[z(Mu,{hidden:sr()}),z(ju,{hidden:sr()})]})}function Ya(e,t){ou(e),xl(z(Wu,{}),t)}function go(){Dt()}function Vu(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function zu(){return R(b(window,"compositionstart").pipe(f(()=>!0)),b(window,"compositionend").pipe(f(()=>!1))).pipe(J(!1))}function Ga(){let e=b(window,"keydown").pipe(f(t=>({mode:sr()?"global":"search",type:t.key,meta:t.ctrlKey||t.metaKey,claim(){t.preventDefault(),t.stopPropagation()}})),L(({mode:t,type:r})=>{if(t==="global"){let n=yt();if(typeof n!="undefined")return!Vu(n,r)}return!0}),xe());return zu().pipe(g(t=>t?y:e))}function Ye(){return new URL(location.href)}function mt(e,t=!1){if(X("navigation.instant")&&!t){let r=A("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function Ja(){return new I}function Xa(){return location.hash.slice(1)}function Za(e){let t=A("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function _o(e){return R(b(window,"hashchange"),e).pipe(f(Xa),J(Xa()),L(t=>t.length>0),se(1))}function Qa(e){return _o(e).pipe(f(t=>Le(`[id="${t}"]`)),L(t=>typeof t!="undefined"))}function Ir(e){let t=matchMedia(e);return an(r=>t.addListener(()=>r(t.matches))).pipe(J(t.matches))}function es(){let e=matchMedia("print");return R(b(window,"beforeprint").pipe(f(()=>!0)),b(window,"afterprint").pipe(f(()=>!1))).pipe(J(e.matches))}function yo(e,t){return e.pipe(g(r=>r?t():y))}function xo(e,t){return new U(r=>{let n=new XMLHttpRequest;return n.open("GET",`${e}`),n.responseType="blob",n.addEventListener("load",()=>{n.status>=200&&n.status<300?(r.next(n.response),r.complete()):r.error(new Error(n.statusText))}),n.addEventListener("error",()=>{r.error(new Error("Network error"))}),n.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(n.addEventListener("progress",o=>{var i;if(o.lengthComputable)t.progress$.next(o.loaded/o.total*100);else{let a=(i=n.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(o.loaded/+a*100)}}),t.progress$.next(5)),n.send(),()=>n.abort()})}function et(e,t){return xo(e,t).pipe(g(r=>r.text()),f(r=>JSON.parse(r)),se(1))}function xn(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/html")),se(1))}function ts(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/xml")),se(1))}var wo={drawer:G("[data-md-toggle=drawer]"),search:G("[data-md-toggle=search]")};function Eo(e,t){wo[e].checked!==t&&wo[e].click()}function wn(e){let t=wo[e];return b(t,"change").pipe(f(()=>t.checked),J(t.checked))}function rs(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function ns(){return R(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(f(rs),J(rs()))}function os(){return{width:innerWidth,height:innerHeight}}function is(){return b(window,"resize",{passive:!0}).pipe(f(os),J(os()))}function as(){return re([ns(),is()]).pipe(f(([e,t])=>({offset:e,size:t})),se(1))}function En(e,{viewport$:t,header$:r}){let n=t.pipe(fe("size")),o=re([n,r]).pipe(f(()=>xt(e)));return re([r,t,o]).pipe(f(([{height:i},{offset:a,size:s},{x:c,y:l}])=>({offset:{x:a.x-c,y:a.y-l+i},size:s})))}var qu=G("#__config"),mr=JSON.parse(qu.textContent);mr.base=`${new URL(mr.base,Ye())}`;function Ue(){return mr}function X(e){return mr.features.includes(e)}function Bt(e,t){return typeof t!="undefined"?mr.translations[e].replace("#",t.toString()):mr.translations[e]}function dt(e,t=document){return G(`[data-md-component=${e}]`,t)}function Ee(e,t=document){return P(`[data-md-component=${e}]`,t)}function Ku(e){let t=G(".md-typeset > :first-child",e);return b(t,"click",{once:!0}).pipe(f(()=>G(".md-typeset",e)),f(r=>({hash:__md_hash(r.innerHTML)})))}function ss(e){if(!X("announce.dismiss")||!e.childElementCount)return y;if(!e.hidden){let t=G(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return j(()=>{let t=new I;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Ku(e).pipe($(r=>t.next(r)),V(()=>t.complete()),f(r=>H({ref:e},r)))})}function Bu(e,{target$:t}){return t.pipe(f(r=>({hidden:r!==e})))}function cs(e,t){let r=new I;return r.subscribe(({hidden:n})=>{e.hidden=n}),Bu(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))}function To(e,t){return t==="inline"?A("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"})):A("div",{class:"md-tooltip",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"}))}function Tn(...e){return A("div",{class:"md-tooltip2",role:"dialog"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function ls(...e){return A("div",{class:"md-tooltip2",role:"tooltip"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function us(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("a",{href:r,class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}else return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("span",{class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}function ps(e){return A("button",{class:"md-code__button",title:Bt("clipboard.copy"),"data-clipboard-target":`#${e} > code`,"data-md-type":"copy"})}function fs(){return A("button",{class:"md-code__button",title:"Toggle line selection","data-md-type":"select"})}function ms(){return A("nav",{class:"md-code__nav"})}var Ju=_r(So());function hs(e){return A("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>A("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?Li(r):r)))}function Oo(e){let t=`tabbed-control tabbed-control--${e}`;return A("div",{class:t,hidden:!0},A("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function vs(e){return A("div",{class:"md-typeset__scrollwrap"},A("div",{class:"md-typeset__table"},e))}function Xu(e){var n;let t=Ue(),r=new URL(`../${e.version}/`,t.base);return A("li",{class:"md-version__item"},A("a",{href:`${r}`,class:"md-version__link"},e.title,((n=t.version)==null?void 0:n.alias)&&e.aliases.length>0&&A("span",{class:"md-version__alias"},e.aliases[0])))}function bs(e,t){var n;let r=Ue();return e=e.filter(o=>{var i;return!((i=o.properties)!=null&&i.hidden)}),A("div",{class:"md-version"},A("button",{class:"md-version__current","aria-label":Bt("select.version")},t.title,((n=r.version)==null?void 0:n.alias)&&t.aliases.length>0&&A("span",{class:"md-version__alias"},t.aliases[0])),A("ul",{class:"md-version__list"},e.map(Xu)))}var Zu=0;function Qu(e,t=250){let r=re([ir(e),Ft(e,t)]).pipe(f(([o,i])=>o||i),ie()),n=j(()=>Ai(e)).pipe(oe(Ut),Lr(1),Ze(r),f(()=>Ci(e)));return r.pipe(Sr(o=>o),g(()=>re([r,n])),f(([o,i])=>({active:o,offset:i})),xe())}function Rr(e,t,r=250){let{content$:n,viewport$:o}=t,i=`__tooltip2_${Zu++}`;return j(()=>{let a=new I,s=new jn(!1);a.pipe(he(),ye(!1)).subscribe(s);let c=s.pipe(Tr(u=>Ve(+!u*250,Nn)),ie(),g(u=>u?n:y),$(u=>u.id=i),xe());re([a.pipe(f(({active:u})=>u)),c.pipe(g(u=>Ft(u,250)),J(!1))]).pipe(f(u=>u.some(p=>p))).subscribe(s);let l=s.pipe(L(u=>u),pe(c,o),f(([u,p,{size:d}])=>{let m=e.getBoundingClientRect(),h=m.width/2;if(p.role==="tooltip")return{x:h,y:8+m.height};if(m.y>=d.height/2){let{height:v}=Ae(p);return{x:h,y:-16-v}}else return{x:h,y:16+m.height}}));return re([c,a,l]).subscribe(([u,{offset:p},d])=>{u.style.setProperty("--md-tooltip-host-x",`${p.x}px`),u.style.setProperty("--md-tooltip-host-y",`${p.y}px`),u.style.setProperty("--md-tooltip-x",`${d.x}px`),u.style.setProperty("--md-tooltip-y",`${d.y}px`),u.classList.toggle("md-tooltip2--top",d.y<0),u.classList.toggle("md-tooltip2--bottom",d.y>=0)}),s.pipe(L(u=>u),pe(c,(u,p)=>p),L(u=>u.role==="tooltip")).subscribe(u=>{let p=Ae(G(":scope > *",u));u.style.setProperty("--md-tooltip-width",`${p.width}px`),u.style.setProperty("--md-tooltip-tail","0px")}),s.pipe(ie(),Ie(je),pe(c)).subscribe(([u,p])=>{p.classList.toggle("md-tooltip2--active",u)}),re([s.pipe(L(u=>u)),c]).subscribe(([u,p])=>{p.role==="dialog"?(e.setAttribute("aria-controls",i),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",i)}),s.pipe(L(u=>!u)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Qu(e,r).pipe($(u=>a.next(u)),V(()=>a.complete()),f(u=>H({ref:e},u)))})}function Ge(e,{viewport$:t},r=document.body){return Rr(e,{content$:new U(n=>{let o=e.title,i=ls(o);return n.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",o)}}),viewport$:t},0)}function ep(e,t){let r=j(()=>re([Hi(e),Ut(t)])).pipe(f(([{x:n,y:o},i])=>{let{width:a,height:s}=Ae(e);return{x:n-i.x+a/2,y:o-i.y+s/2}}));return ir(e).pipe(g(n=>r.pipe(f(o=>({active:n,offset:o})),Me(+!n||1/0))))}function gs(e,t,{target$:r}){let[n,o]=Array.from(e.children);return j(()=>{let i=new I,a=i.pipe(he(),ye(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),wt(e).pipe(Q(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),R(i.pipe(L(({active:s})=>s)),i.pipe(Be(250),L(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(n):n.remove()},complete(){e.prepend(n)}}),i.pipe(Xe(16,je)).subscribe(({active:s})=>{n.classList.toggle("md-tooltip--active",s)}),i.pipe(Lr(125,je),L(()=>!!e.offsetParent),f(()=>e.offsetParent.getBoundingClientRect()),f(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),b(o,"click").pipe(Q(a),L(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),b(o,"mousedown").pipe(Q(a),pe(i)).subscribe(([s,{active:c}])=>{var l;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(c){s.preventDefault();let u=e.parentElement.closest(".md-annotation");u instanceof HTMLElement?u.focus():(l=yt())==null||l.blur()}}),r.pipe(Q(a),L(s=>s===n),It(125)).subscribe(()=>e.focus()),ep(e,t).pipe($(s=>i.next(s)),V(()=>i.complete()),f(s=>H({ref:e},s)))})}function tp(e){let t=Ue();if(e.tagName!=="CODE")return[e];let r=[".c",".c1",".cm"];if(t.annotate){let n=e.closest("[class|=language]");if(n)for(let o of Array.from(n.classList)){if(!o.startsWith("language-"))continue;let[,i]=o.split("-");i in t.annotate&&r.push(...t.annotate[i])}}return P(r.join(", "),e)}function rp(e){let t=[];for(let r of tp(e)){let n=[],o=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=o.nextNode();i;i=o.nextNode())n.push(i);for(let i of n){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,c]=a;if(typeof c=="undefined"){let l=i.splitText(a.index);i=l.splitText(s.length),t.push(l)}else{i.textContent=s,t.push(i);break}}}}return t}function _s(e,t){t.append(...Array.from(e.childNodes))}function Sn(e,t,{target$:r,print$:n}){let o=t.closest("[id]"),i=o==null?void 0:o.id,a=new Map;for(let s of rp(t)){let[,c]=s.textContent.match(/\((\d+)\)/);Le(`:scope > li:nth-child(${c})`,e)&&(a.set(c,us(c,i)),s.replaceWith(a.get(c)))}return a.size===0?y:j(()=>{let s=new I,c=s.pipe(he(),ye(!0)),l=[];for(let[u,p]of a)l.push([G(".md-typeset",p),G(`:scope > li:nth-child(${u})`,e)]);return n.pipe(Q(c)).subscribe(u=>{e.hidden=!u,e.classList.toggle("md-annotation-list",u);for(let[p,d]of l)u?_s(p,d):_s(d,p)}),R(...[...a].map(([,u])=>gs(u,t,{target$:r}))).pipe(V(()=>s.complete()),xe())})}function ys(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return ys(t)}}function xs(e,t){return j(()=>{let r=ys(e);return typeof r!="undefined"?Sn(r,e,t):y})}var Es=_r(Mo());var np=0,ws=R(b(window,"keydown").pipe(f(()=>!0)),R(b(window,"keyup"),b(window,"contextmenu")).pipe(f(()=>!1))).pipe(J(!1),se(1));function Ts(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Ts(t)}}function op(e){return Re(e).pipe(f(({width:t})=>({scrollable:Mr(e).width>t})),fe("scrollable"))}function Ss(e,t){let{matches:r}=matchMedia("(hover)"),n=j(()=>{let o=new I,i=o.pipe(Bn(1));o.subscribe(({scrollable:m})=>{m&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[],s=e.closest("pre"),c=s.closest("[id]"),l=c?c.id:np++;s.id=`__code_${l}`;let u=[],p=e.closest(".highlight");if(p instanceof HTMLElement){let m=Ts(p);if(typeof m!="undefined"&&(p.classList.contains("annotate")||X("content.code.annotate"))){let h=Sn(m,e,t);u.push(Re(p).pipe(Q(i),f(({width:v,height:S})=>v&&S),ie(),g(v=>v?h:y)))}}let d=P(":scope > span[id]",e);if(d.length&&(e.classList.add("md-code__content"),e.closest(".select")||X("content.code.select")&&!e.closest(".no-select"))){let m=+d[0].id.split("-").pop(),h=fs();a.push(h),X("content.tooltips")&&u.push(Ge(h,{viewport$}));let v=b(h,"click").pipe(Or(M=>!M,!1),$(()=>h.blur()),xe());v.subscribe(M=>{h.classList.toggle("md-code__button--active",M)});let S=me(d).pipe(oe(M=>Ft(M).pipe(f(O=>[M,O]))));v.pipe(g(M=>M?S:y)).subscribe(([M,O])=>{let N=Le(".hll.select",M);if(N&&!O)N.replaceWith(...Array.from(N.childNodes));else if(!N&&O){let ee=document.createElement("span");ee.className="hll select",ee.append(...Array.from(M.childNodes).slice(1)),M.append(ee)}});let x=me(d).pipe(oe(M=>b(M,"mousedown").pipe($(O=>O.preventDefault()),f(()=>M)))),w=v.pipe(g(M=>M?x:y),pe(ws),f(([M,O])=>{var ee;let N=d.indexOf(M)+m;if(O===!1)return[N,N];{let le=P(".hll",e).map(ce=>d.indexOf(ce.parentElement)+m);return(ee=window.getSelection())==null||ee.removeAllRanges(),[Math.min(N,...le),Math.max(N,...le)]}})),_=_o(y).pipe(L(M=>M.startsWith(`__codelineno-${l}-`)));_.subscribe(M=>{let[,,O]=M.split("-"),N=O.split(":").map(le=>+le-m+1);N.length===1&&N.push(N[0]);for(let le of P(".hll:not(.select)",e))le.replaceWith(...Array.from(le.childNodes));let ee=d.slice(N[0]-1,N[1]);for(let le of ee){let ce=document.createElement("span");ce.className="hll",ce.append(...Array.from(le.childNodes).slice(1)),le.append(ce)}}),_.pipe(Me(1),Ie(ge)).subscribe(M=>{if(M.includes(":")){let O=document.getElementById(M.split(":")[0]);O&&setTimeout(()=>{let N=O,ee=-64;for(;N!==document.body;)ee+=N.offsetTop,N=N.offsetParent;window.scrollTo({top:ee})},1)}});let be=me(P('a[href^="#__codelineno"]',p)).pipe(oe(M=>b(M,"click").pipe($(O=>O.preventDefault()),f(()=>M)))).pipe(Q(i),pe(ws),f(([M,O])=>{let ee=+G(`[id="${M.hash.slice(1)}"]`).parentElement.id.split("-").pop();if(O===!1)return[ee,ee];{let le=P(".hll",e).map(ce=>+ce.parentElement.id.split("-").pop());return[Math.min(ee,...le),Math.max(ee,...le)]}}));R(w,be).subscribe(M=>{let O=`#__codelineno-${l}-`;M[0]===M[1]?O+=M[0]:O+=`${M[0]}:${M[1]}`,history.replaceState({},"",O),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+O,oldURL:window.location.href}))})}if(Es.default.isSupported()&&(e.closest(".copy")||X("content.code.copy")&&!e.closest(".no-copy"))){let m=ps(s.id);a.push(m),X("content.tooltips")&&u.push(Ge(m,{viewport$}))}if(a.length){let m=ms();m.append(...a),s.insertBefore(m,e)}return op(e).pipe($(m=>o.next(m)),V(()=>o.complete()),f(m=>H({ref:e},m)),Rt(R(...u).pipe(Q(i))))});return X("content.lazy")?wt(e).pipe(L(o=>o),Me(1),g(()=>n)):n}function ip(e,{target$:t,print$:r}){let n=!0;return R(t.pipe(f(o=>o.closest("details:not([open])")),L(o=>e===o),f(()=>({action:"open",reveal:!0}))),r.pipe(L(o=>o||!n),$(()=>n=e.open),f(o=>({action:o?"open":"close"}))))}function Os(e,t){return j(()=>{let r=new I;return r.subscribe(({action:n,reveal:o})=>{e.toggleAttribute("open",n==="open"),o&&e.scrollIntoView()}),ip(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))})}var Ls=0,Ms=new Map;function ap(e){let t=document.createElement("h3");t.innerHTML=e.innerHTML;let r=[t],n=e.nextElementSibling;for(;n&&!(n instanceof HTMLHeadingElement);)r.push(n.cloneNode(!0)),n=n.nextElementSibling;return r}function sp(e,t){for(let r of P("[href], [src]",e))for(let n of["href","src"]){let o=r.getAttribute(n);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){r[n]=new URL(r.getAttribute(n),t).toString();break}}for(let r of P("[name^=__], [for]",e))for(let n of["id","for","name"]){let o=r.getAttribute(n);o&&r.setAttribute(n,`${o}$preview_${Ls}`)}return Ls++,Y(e)}function cp(e){let t=Ms.get(e.toString());return t?Y(t):xn(e).pipe(g(r=>sp(r,e)),f(r=>(Ms.set(e.toString(),r),r)))}function ks(e,t){let{sitemap$:r}=t;if(!(e instanceof HTMLAnchorElement))return y;if(!(X("navigation.instant.preview")||e.hasAttribute("data-preview")))return y;e.removeAttribute("title");let n=re([ir(e),Ft(e).pipe(ke(1))]).pipe(f(([i,a])=>i||a),ie(),L(i=>i));return $t([r,n]).pipe(g(([i])=>{let a=new URL(e.href);return a.search=a.hash="",i.has(`${a}`)?Y(a):y}),g(i=>cp(i)),g(i=>{let a=e.hash?`article [id="${e.hash.slice(1)}"]`:"article h1",s=Le(a,i);return typeof s=="undefined"?y:Y(ap(s))})).pipe(g(i=>{let a=new U(s=>{let c=Tn(...i);return s.next(c),document.body.append(c),()=>c.remove()});return Rr(e,H({content$:a},t))}))}var As=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color)}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs marker.marker.composition.class path,defs marker.marker.dependency.class path,defs marker.marker.extension.class path{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs marker.marker.aggregation.class path{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}[id^=entity] path,[id^=entity] rect{fill:var(--md-default-bg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs .marker.oneOrMore.er *,defs .marker.onlyOne.er *,defs .marker.zeroOrMore.er *,defs .marker.zeroOrOne.er *{stroke:var(--md-mermaid-edge-color)!important}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var ko,up=0;function pp(){return typeof mermaid=="undefined"||mermaid instanceof Element?ar("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):Y(void 0)}function Cs(e){return e.classList.remove("mermaid"),ko||(ko=pp().pipe($(()=>mermaid.initialize({startOnLoad:!1,themeCSS:As,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),f(()=>{}),se(1))),ko.subscribe(()=>Uo(null,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${up++}`,r=A("div",{class:"mermaid"}),n=e.textContent,{svg:o,fn:i}=yield mermaid.render(t,n),a=r.attachShadow({mode:"closed"});a.innerHTML=o,e.replaceWith(r),i==null||i(a)})),ko.pipe(f(()=>({ref:e})))}var Hs=A("table");function $s(e){return e.replaceWith(Hs),Hs.replaceWith(vs(e)),Y({ref:e})}function fp(e){let t=e.find(r=>r.checked)||e[0];return R(...e.map(r=>b(r,"change").pipe(f(()=>G(`label[for="${r.id}"]`))))).pipe(J(G(`label[for="${t.id}"]`)),f(r=>({active:r})))}function Ps(e,{viewport$:t,target$:r}){let n=G(".tabbed-labels",e),o=P(":scope > input",e),i=Oo("prev");e.append(i);let a=Oo("next");return e.append(a),j(()=>{let s=new I,c=s.pipe(he(),ye(!0));re([s,Re(e),wt(e)]).pipe(Q(c),Xe(1,je)).subscribe({next([{active:l},u]){let p=xt(l),{width:d}=Ae(l);e.style.setProperty("--md-indicator-x",`${p.x}px`),e.style.setProperty("--md-indicator-width",`${d}px`);let m=ln(n);(p.x List of supported config keys of this card: List of supported config keys of this card: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: The first two entities are shown in the middle of the card, all other entities are used around it. Any entity overrides (e.g. icon, color) in the first entity apply to the middle of the card. List of supported config keys of this card: List of supported entitiy types for this page: N.B. Negative values will likely be truncated and not display gracefully. For this reason, when measuring energy you should use the same inputs as you use on the Home Assistant Energy Dashboard (i.e. separate grid import and grid export) and similarly when measuring power. Some details about speed: Speed expects an integer input between It is possible to calculate the speed through a Home Assistant template, this allows to calculate the speed in relation to other data in Home Assistant. This template will calculate a speed setting based on the amount of power drawn on a device as a fraction of the total power usage.
+ List of supported config keys of this card: List of supported entitiy types for this page: The qrCode value is evaluated as a homeassistant Template, so it is possible to get values from HomeAssistant within the qrCode. Can be used to navigate to create pin locked navigation to a hidden card. List of supported config keys of this card: This page compares the legacy AppDaemon For the full rewrite docs, including full key descriptions, see: Old AppDaemon version: Standalone rewrite: Old ( New ( If you are migrating now, use the standalone migration page for the complete mapping: To confiure your NSPanel to your needs, you need to edit the If you've sucessfully set up mqtt, you should already have a configuration looking like this: You can continue from this point adding configuration for the weather forcecast on the screensaver, configuring a schedule for the brightness of the screensaver and your first cards. This is the full list of configuration options supported for the config key: It is possible to schedule a brightness change for the screen at specific times. It is also possible to use a static value or an input_number/sensor with the range between 0 and 100 as value for sleepBrightness/screenBrightness: The config option The config option The following example configuration is turning off the screen after sunset, but in case the bedroom light is on the NSPanel brightness will be 20 instead of 0. In case you need to change the OTA URLs to do automatic updates without internet access for tasmota, you can modify the OTA URLs: Example for the a screensaver config with custom entities/overrides: Using a 6th entity will automatically activate the alternative layout. You can use override the options described on the entities documentation page to override colors, names or values of the entities. With Version 4.0.0 there is another alternative layout for the screensaver: Configuration is similar, you just need to add Specify colours as red green and blue values from 0-255 e.g. Example for the theme config: It is possible to increase the size of the font used for the icons by adding Configure your MQTT Server in Tasmota.
+See Tasmota MQTT Documentation for more details. Please leave the Full Topic as it is in default configuration (and on the screenshot). Change the topic to something unique for your panel, you will need this topic later in the configuration of your panel in appdaemon / apps.yaml The configuration has been moved out of the config folder from homeassistant. This is how you can access it with the VSCode Addon. For the app to work you need a working MQTT Configuration in AppDaemon. Please add the configuration of your mqtt server, user and password to your existing You will find this file in the following location: Please add the following minimal configuration to your apps.yaml, which is located in Note: You need to move your Please adjust If your configuration is correct you should get the following screens on your panel: Entities are mainly used on cardEntities and cardGrid. It is possible to overwrite and configure varrious things on Entities. To overwrite Icons or Names of entities you can configure an icon and/or name in your configuration, please see the following example.
+Only the icons listed in the Icon Cheatsheet are useable. It is also possible to configure different icon overwrites per state: It is also possible to configure different color overwrites per state: It is also possible to use text instead of icons with Note: State Overrides are working with all state values, not only with "on" and "off". To insert dynamic values from a homeassistant template, like a temperature you can also use If you want to display icons from a template you can put them between This sensor will only be shown on the card if it's state is equal to This sensor will only be shown on the card if it's state is not equal to The template must evaluate to The following example shows how to call services directly, this enables you to call services on entities not (yet) supported by the backend and also to pass data to services. You have most likely an error in your MQTT configuration somewhere. To find the error follow theese steps: Check the location of your apps.yaml
+With the AppDaemon Addon >= 15 the config dir has been moved.
+It's required to configure the location back to the old one, this is done by the Check your appdaemon log. (Settings > Add-ons > AppDaemon > Log)
+You should see something like this:
+ Check MQTT Configuration of Tasmota.
+Your Tasmota device needs to connect sucessfully to your MQTT Broker, if you are in the waiting for content screen, the panel will send periodic messages to it's mqtt topic. Note that there is a minimum password length of 5 chars for the MQTT Connection in Tasmota. Make sure that you are using the same topic in apps.yaml and in your tasmota configuration.
+The examples in the docs (MQTT Config) are an valid example (tasmota<>apps.yaml). If you are still in the waiting for content screen please share the following items, with the Waiting for Content Issue type on the Github Issues Page HACS will show you that there is an update avalible and ask you to update. It is important to restart the AppDaemon Container afterwards. You should get an notification on the screen, asking you to update the firmware. In case you want to update manually you can use the following commands. EU Version: US Version Portrait: US Version Landscape: You should get an notification on the screen, asking you to update the driver, if an update is needed. You can update the berry driver directly from the Tasmota Console with the following command. Click redownload in the menu of the app in HACS. Select main version. !!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!! !!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!! Click download. Restart AppDaemon Flash current Development Firmware in Tasmota Console. DO NOT USE THIS VERSION/URLS IF YOUR ARE NOT ON THE DEVELOPMENT VERSION EU VERSION: Development happens in the EU version, so it is possible that the US Version isn't up to date with the current development version of the EU firmware, the lastet US versions are still downloadable with the following links: US LANDSCAPE: US PORTRAIT: The HMI Project of this project is only used to display stuff, navigation ist mostly up to the backend. This allows to be way more flexible. Messages to the Panel can be send through the Command On startup the panel will send You can answer this message in many different ways, but in general the goal is to navigate way from the startup page. In the following example we will navigate to the screensaver page. Send the following messages to the CustomSend Topic. (You can also send them on tasmota console for testing) Send this every minute: Send this at least once at midnight: Send theese message once after receiving the startup event (parameters will be explained later): After sending this command you should already see the time and date.
+To also show weather data you have to send them with weatherUpdate, but we will skip this for now. Touching the panel on the screensaver will result in this MQTT Message on the result topic: You can answer this by sending theese commands to the CustomSend Topic. set brightness of screensaver and active-brightness: set current time: set current date: set screensaver timeout (set time in sec~ max 65): change the page type: Structure (Category): Possible entities on cardEntities/cardGrid: cardGrid is using the exact same messageformat like cardEntities does. The only difference is, it ignores the information supplied in optionalValue, because it isn't needed for cardGrid. Example without icons in bottom row: Serial Protocol of cardThermo is about to change; table will be completed later Example: options are ? seperated editable is 0 or 1 action fields are in the answer on the button press in case action is empty the button will be hidden Payload length contains the number of bytes of the payload. CRC is "CRC-16 (MODBUS) Big Endian" calculated over the whole message This protocol does not try to implement broken JSON Commands with a specified type (lol).
+Instead the commands are plain text commands with parameters. This message has to be generated for the Message "1337" (1337 is not a valid command~ this is just an example) Thanks to aderusha for this great nextion font: Generate-HASP-Fonts
+ Deprecated icons will be removed in a future major release.
+ If you like this project consider buying me a pizza 🍕 NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in the Design of HomeAssistant's Lovelace UI Design. EU Model and US Model supported (in portrait and landscape orientation) Content of the screen is controlled by a AppDaemon Python Script installed on your HomeAssistant Instance. Or an TypeScript on your ioBroker Instance in case you are an ioBroker User. NsPanel needs to be flashed with Tasmota (or with the 3rd Party ESPHome Component from @sairon) Localization (currently 40 languages) Everything is dynamically configurable by a yaml config, no need to code or touch Nextion Editor It works with Tasmota and MQTT.
+To control the panel and update it with content from HomeAssistant there is an AppDaemon App. See the following picture to get an idea of the look of this firmware for NSPanel. Some (not all) screenshots from the US Portrait Version: The Backend for ioBroker is maintained by britzelpuf and armilar See the wiki for documentation around setting lovelace-ui up with ioBroker Also see the Readme in the ioBroker Folder.
+iobroker ReadMe There are two notification types, that can be triggered by sending a command over mqtt to the panel here are examples for homeassistant scripts: This is the notification used by the backend for updates, opening it requires to the following commands to the CustomSend Topic: Alternative Layout with Icon: You need to use the acual char for the icon instead of the icon name which is used in the configuration. You can get the char of the icon from the cheatsheet. https://docs.nspanel.pky.eu/icon-cheatsheet.html It is possible to exit from the page by sending If you want to add newlines to your message add this string for the newline Send Message to the Panel combined with a buzzer sound: Send Message to the Panel: The screensaver can display Notifications by sending this command to the CustomSend topic: Send Message to the Screensaver combined with a buzzer sound: Send Message to the Screensaver: See Tasmota Buzzer for commands. It might be necessary to enable the buzzer with:
+ Decimal RGB565: 0 You can configure the buttons to mimic an UI element on the screen by configuring tasmota rules. The following rule will change the behaviour of the two buttons to do page navigation. If you do not want your NSPanel physical buttons to trigger the relays and prefer to have them as software configurable buttons, open the Tasmota console of your NSPanel and enter the following: Your relays will now appear as switches in HomeAssistant and you can control your buttons by using automations: You may reverse this change by entering the following in the Tasmota console of your NSPanel: Please note: Doing this will mean that if HomeAssistant is not working for any reason your buttons will not function correctly. The backend application for HomeAssistant is written in a python for AppDaemon.
+This means it requires a working and running installation of AppDaemon. The easiest way to install it is through Home Assistant's Supervisor Add-on Store, it will be automaticly connected to your Home Assistant Instance. For localisation (date in your local language) you need to add the python package babel to your AppDaemon Installation. You will need a way to edit the HACS is the Home Assistant Community Store and allows for community integrations and
+automations to be updated easily from the Home Assistant web user interface.
+You will be notified of updates, and they can be installed by a click on a button. To install Lovelace UI Backend App with HACS, you will need to make sure that you enabled
+AppDaemon automations in HACS, as these are not enabled by default: Now, to install NSPanel Lovelace UI Backend with HACS, follow these steps: You need to connect to your NSPanel via serial and flash Tasmota using tasmota32-nspanel.bin. Check out Blakadder's Template Repo for more information on flashing. Do not use the autoexec.be from that page. If you prefer ESPHome over Tasmota, you can use this third-party ESPHome component, which replaces Tasmota and the Berry driver used in this project. Configure the NSPanel template for Tasmota. (Go to Configuration > Configure Other, paste the template there, and make sure to tick the Activate checkbox.) You can use the following template or copy the one from the Tasmota Template Repo Site: {"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"} After a reboot of Tasmota, your screen will light up with the stock display firmware. Go to Consoles > Console in Tasmota and execute the following command: Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0; Restart 1 This downloads the autoexec.be file from the repository and restarts Tasmota. Note: This command also disables Matter to free up memory, as it's unlikely to be used by most Home Assistant users. (Matter can cause memory issues during flashing of the Nextion screen, but you can re-enable it later if needed.) Due to the limitations of Berry, it's not possible to download the TFT file directly from GitHub. A small server is available to download the file via HTTP. Use one of the following commands in the Tasmota console (not the Berry console) to flash the latest release from this repository: EU Version: US Version Portrait: US Version Landscape: After sending the command, the screen should show a progress bar. The flashing process takes around 5 minutes. Note for US users: You'll need to add the model config option to your apps.yaml later. More details can be found on the config overview page. You need to connect to your nspanel via serial and flash tasmota tasmota32-nspanel.bin to your NSPanel.
+You can use the Tasmota Web Installer to do so. Tasmota Web Installer Checkout Blakadders Template Repo for more information on flashing, do not use the autoexec.be from this page.
+NSPanel Page of the Tasmota Template Repository If you prefer EspHome over Tasmota, you can use this thrid party esphome component, which is replacing tasmota and the berry driver of this project.
+ESPHome component Configure the NSPanel template for Tasmota. (Go to Configuration and Configure Other and paste the template there, make sure to tick the activate checkbox) You can use the following template or copy the one on the Tasmota Template Repo Site. After a reboot of tasmota your screen will light up with the stock display firmware. Go to Due the limitations of Berry, it's not possible to download the tft file directly from github, so I'm also renting a small server where you can download the file via HTTP. Use the one following commands to flash the latest release from this repository, just execute the following Command in Tasmota: EU Version: US Version Portrait: US Version Landscape: If you like this project consider buying me a pizza 🍕 NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in the Design of HomeAssistant's Lovelace UI Design. EU Model and US Model supported (in portrait and landscape orientation) Content of the screen is controlled by a AppDaemon Python Script installed on your HomeAssistant Instance. Or an TypeScript on your ioBroker Instance in case you are an ioBroker User. NsPanel needs to be flashed with Tasmota (or with the 3rd Party ESPHome Component from @sairon) Localization (currently 40 languages) Everything is dynamically configurable by a yaml config, no need to code or touch Nextion Editor It works with Tasmota and MQTT. To control the panel and update it with content from HomeAssistant there is an AppDaemon App. See the following picture to get an idea of the look of this firmware for NSPanel. Some (not all) screenshots from the US Portrait Version: List of supported config keys of this card: List of supported config keys of this card: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: The first two entities are shown in the middle of the card, all other entities are used around it. Any entity overrides (e.g. icon, color) in the first entity apply to the middle of the card. List of supported config keys of this card: List of supported entitiy types for this page: N.B. Negative values will likely be truncated and not display gracefully. For this reason, when measuring energy you should use the same inputs as you use on the Home Assistant Energy Dashboard (i.e. separate grid import and grid export) and similarly when measuring power. Some details about speed: Speed expects an integer input between It is possible to calculate the speed through a Home Assistant template, this allows to calculate the speed in relation to other data in Home Assistant. This template will calculate a speed setting based on the amount of power drawn on a device as a fraction of the total power usage. List of supported config keys of this card: List of supported entitiy types for this page: The qrCode value is evaluated as a homeassistant Template, so it is possible to get values from HomeAssistant within the qrCode. Can be used to navigate to create pin locked navigation to a hidden card. List of supported config keys of this card: This page compares the legacy AppDaemon For the full rewrite docs, including full key descriptions, see: Old AppDaemon version: Standalone rewrite: Old ( New ( If you are migrating now, use the standalone migration page for the complete mapping: To confiure your NSPanel to your needs, you need to edit the If you've sucessfully set up mqtt, you should already have a configuration looking like this: You can continue from this point adding configuration for the weather forcecast on the screensaver, configuring a schedule for the brightness of the screensaver and your first cards. This is the full list of configuration options supported for the config key: It is possible to schedule a brightness change for the screen at specific times. It is also possible to use a static value or an input_number/sensor with the range between 0 and 100 as value for sleepBrightness/screenBrightness: The config option The config option The following example configuration is turning off the screen after sunset, but in case the bedroom light is on the NSPanel brightness will be 20 instead of 0. In case you need to change the OTA URLs to do automatic updates without internet access for tasmota, you can modify the OTA URLs: Example for the a screensaver config with custom entities/overrides: Using a 6th entity will automatically activate the alternative layout. You can use override the options described on the entities documentation page to override colors, names or values of the entities. With Version 4.0.0 there is another alternative layout for the screensaver: Configuration is similar, you just need to add Specify colours as red green and blue values from 0-255 e.g. Example for the theme config: It is possible to increase the size of the font used for the icons by adding Configure your MQTT Server in Tasmota. See Tasmota MQTT Documentation for more details. Please leave the Full Topic as it is in default configuration (and on the screenshot). Change the topic to something unique for your panel, you will need this topic later in the configuration of your panel in appdaemon / apps.yaml The configuration has been moved out of the config folder from homeassistant. This is how you can access it with the VSCode Addon. For the app to work you need a working MQTT Configuration in AppDaemon. Please add the configuration of your mqtt server, user and password to your existing You will find this file in the following location: Please add the following minimal configuration to your apps.yaml, which is located in Note: You need to move your Please adjust If your configuration is correct you should get the following screens on your panel: Entities are mainly used on cardEntities and cardGrid. It is possible to overwrite and configure varrious things on Entities. To overwrite Icons or Names of entities you can configure an icon and/or name in your configuration, please see the following example. Only the icons listed in the Icon Cheatsheet are useable. It is also possible to configure different icon overwrites per state: It is also possible to configure different color overwrites per state:404 - Not found
+
+ =t.count.fields)return{documents:r,terms:l};let o=t.shards[n];return e.forEach(a=>{let{occurrences:s}=o.terms[a];for(let u=0;uAlarm Card¶
+
cards:
+ - type: cardAlarm
+ title: Alarm Test 1
+ entity: alarm_control_panel.alarmo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+entityFalse
+string
+
+Nonecontains the entity of the current card
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+alarmControlTrue
+complex
+
+Noneoverwrites the action executed on pressing the left bottom icon, by default this button is used to show a list of open sensors on a failed attempt to arm.
+
+
+
+
+supportedModesTrue
+list
+
+NoneSupply list of arm modes if you want to limit the modes on the card. Example
+['arm_away', 'arm_night']Climate/Thermo Card¶
+
cards:
+ - type: cardThermo
+ title: HeatPump
+ entity: climate.heatpump
+ - type: cardThermo
+ title: HvaC
+ entity: climate.hvac
+ - type: cardThermo
+ title: ecobee
+ entity: climate.ecobee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entityFalse
+string
+
+Nonecontains the entitiy of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+temperatureUnitTrue
+string
+
+celsiusset this to fahrenheit to change the temperatureUnit on the page
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+supportedModesTrue
+list
+
+NoneSupply list of heat actions if you want to limit the actions on the card. Example
+['heat', 'off']Entities Page¶
+
cards:
+ - type: cardEntities
+ title: Test Entities Card
+ entities:
+ - entity: light.bed_light
+ - entity: switch.decorative_lights
+ - entity: cover.hall_window
+ - entity: sensor.outside_temperature
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Grid Page¶
+
cards:
+ - type: cardGrid
+ title: Test Grid Card
+ entities:
+ - entity: light.bed_light
+ - entity: switch.decorative_lights
+ - entity: sensor.outside_temperature
+ name: Outside Temp
+ - entity: sensor.carbon_monoxide
+ - entity: light.entrance_color_white_lights
+ name: Entrance
+ - entity: light.office_rgbw_lights
+ name: Office RGBW
+ icon: mdi:office-building
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Media Card¶
+
cards:
+ - type: cardMedia
+ entity: media_player.spotify
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+entityFalse
+string
+
+Nonecontains the entity of the current card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities shown in the bottom row, supports all entities supported by cardGrid
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+Example with configured Entities
+
+ - type: cardMedia
+ title: Kitchen
+ entity: media_player.kitchen
+ entities:
+ - entity: light.bed_light
+ - entity: light.ceiling_lights
+ - entity: light.entrance_color_white_lights
+ - entity: light.kitchen_lights
+ - entity: light.living_room_rgbww_lights
+Example with action on upper left media icon
+
+ - type: cardMedia
+ title: Kitchen
+ entity: input_select.test123
+ status: media_player.kitchen
+Example with moved spaker selection
+
+The icon for speaker selection is automatically appended to the end of the list and can be moved with entities in the list.
+With 6 entities it is possible to remove it entirely.
+ - type: cardMedia
+ title: Kitchen
+ entity: media_player.kitchen
+ entities:
+ - entity: delete
+ - entity: delete
+Power Card (v3.9 and higher)¶
+
cards:
+ - type: cardPower
+ title: Power Test
+ entities:
+ - entity: sensor.power_consumption
+ icon: mdi:home
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:car
+ speed: -20
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:battery
+ speed: 20
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:solar-panel
+ color: [255, 255, 0]
+ speed: 30
+ - entity: sensor.today_energy
+ speed: -40
+ icon: mdi:help
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains entities of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+cooldownTrue
+float
+
+NoneRate Limit for Entity Updates to the card in Seconds (
+cooldown: 0.5)
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+-100 and 100. speed: >-
+ {% set entity_power = states('sensor.appliance_water_heater_power') |float | round(3)%}
+ {% set total_power = states('sensor.ams_power_active') | float | round(3) %}
+ {% set entity_usage = (entity_power / total_power * 100) | float %}
+ {{ (entity_usage | round()) * -1 }}
+ {{ (entity_usage | round()) }}
+WiFi / QR Card¶
+
cards:
+ - type: cardQR
+ title: Guest Wifi
+ qrCode: "WIFI:S:test_ssid;T:WPA;P:test_pw;;"
+ entities:
+ - entity: iText.test_ssid
+ name: Name
+ icon: mdi:wifi
+ - entity: iText.test_pw
+ name: Password
+ icon: mdi:key
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains entities of the card, only valid on cardEntities and cardGrid and cardQR
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+
+qrCodeFalse
+string
+
+NoneValue of the qrCode
+
+
+"WIFI:S:{{states('input_text.test_ssid')}};T:WPA;P:{{states('input_text.test_pw')}};;"Unlock Card (v4.0 and higher)¶
+
cards:
+ - type: cardUnlock
+ pin: 1234
+ title: Admin Page
+ destination: navigate.adminpage
+ hiddenCards:
+ - type: cardGrid
+ title: Admin Page
+ key: adminpage
+ entities:
+ - entity: light.schreibtischlampe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+destinationFalse
+string
+
+Nonecontains the navigation entity this card should navigate to on unlock
+
+
+
+pinFalse
+string
+3830
+pin to unlock
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+Migration to Standalone Rewrite Config¶
+apps.yaml config with the standalone rewrite panels.yaml config.High-level differences¶
+
+
+apps.yaml with module / class / configappdaemon.yaml)
+
+/config/panels.yamlnspanelsMinimal before/after example¶
+apps.yaml):nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+panels.yaml):home_assistant_address: "http://supervisor"
+home_assistant_token: "YOUR_TOKEN"
+
+nspanels:
+ panel-1:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+ locale: en_US
+ timeZone: "Europe/Berlin"
+ timeFormat: "%H:%M"
+ dateFormat: "full"
+ screensaver:
+ entities:
+ - entity: weather.home
+ cards:
+ - type: cardEntities
+ title: Main
+ entities:
+ - entity: light.kitchen
+Important key changes¶
+
+
+
+
+
+
+
+Legacy key/concept
+Rewrite key/concept
+Notes
+
+
+
+module, class, config wrapperremoved
+Rewrite uses
+nspanels.<panel_name> directly.
+
+
+timezone
+timeZoneCasing changed.
+
+
+
+dateFormatBabel
+dateFormatUse
+dateFormat in rewrite.
+
+
+temperatureUnit (legacy card-level usage)
+temp_unit (panel-level)Rewrite reads
+temp_unit from panel settings.
+
+brightness schedule lists
+not supported
+Rewrite supports integer or entity id for brightness values.
+
+
+
+
+updateMode / OTA URL override keysnot supported
+Legacy update behavior is not part of rewrite config.
+Configuration¶
+apps.yaml inside of your Appdaemon config folder and add card and entities you want to display on the screen.---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+ sleepTimeout: 20
+ sleepBrightness:
+ - time: "7:00:00"
+ value: 10
+ - time: "23:00:00"
+ value: 0
+ locale: "de_DE"
+ screensaver:
+ entity: weather.k3ll3r
+ cards:
+ - type: cardEntities
+ entities:
+ - entity: switch.example_item
+ - entity: light.example_item
+ title: Example 1
+ - type: cardGrid
+ entities:
+ - entity: switch.example_item
+ - entity: light.example_item
+ title: Example 2
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+panelRecvTopicFalse
+string
+
+tele/tasmota_your_mqtt_topic/RESULTThe mqtt topic used to receive messages.
+
+
+
+panelSendTopicFalse
+string
+
+cmnd/tasmota_your_mqtt_topic/CustomSendThe mqtt topic used to send messages.
+
+
+
+updateModeTrue
+string
+
+auto-notifyUpdate Mode for flashing of the nextion display firmware, by default it is showing a message asking for the update after updating the backend app in HACS; Possible values: "auto", "auto-notify", "manual"
+
+
+
+modelTrue
+string
+
+euModel; Possible values: "eu", "us-l" and "us-p"
+
+
+
+sleepTimeoutTrue
+integer
+
+20Timeout for the screen to enter screensaver, to disable screensaver use 0
+
+
+
+sleepBrightnessTrue
+integer/complex
+
+20Brightness for the screen on the screensaver, see example below for complex/scheduled config.
+
+
+
+screenBrightnessTrue
+integer/complex
+
+100Brightness for the screen during usage, config format is the same as sleepBrightness.
+
+
+
+sleepTrackingTrue
+string
+None
+Forces screensaver brightness to 0 in case entity state is not_home or off, can be a group, person or device_tracker entity.
+
+
+
+sleepTrackingZonesTrue
+list
+
+["not_home", "off"]Allows you to set your own states for sleepTracking
+
+
+
+sleepOverrideTrue
+complex
+None
+Allows overriding of the sleepBrightness if entity state is on, true or home. Overrides sleepBrightness but sleepTracking takes precedence.
+
+
+
+localeTrue
+string
+
+en_USUsed by babel to determinante Date format on screensaver, also used for localization.
+
+
+
+dateFormatBabelTrue
+string
+
+fullformatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
+
+
+
+timeFormatTrue
+string
+
+%H:%MTime Format on screensaver. Substring after
+? is displayed in a seperate smaller textbox. Useful for 12h time format with AM/PM "%I:%M ?%p"
+
+
+dateAdditionalTemplateTrue
+string
+
+""Addional Text dispayed after Date, can contain a Homeassistant Template Example
+" - {{ states('sun.sun') }}"
+
+
+timeAdditionalTemplateTrue
+string
+
+""Addional Text dispayed below Time, can contain a Homeassistant Template
+
+
+
+dateFormatTrue
+string
+
+%A, %d. %B %Ydate format used if babel is not installed
+
+
+
+timezoneTrue
+string
+""
+Timezone for the time on the panel:
+Europe/Berlin - See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of TZ Identifiers (supported from upcoming version v4.4)
+
+
+defaultBackgroundColorTrue
+string
+ha-dark
+backgroud color of all cards, valid values:
+black, ha-dark
+
+
+cardsFalse
+complex
+
+ configuration for cards that are displayed on panel; see docs for cards
+
+
+
+screensaverTrue
+complex
+
+ configuration for screensaver; see docs for screensaver
+
+
+
+
+hiddenCardsTrue
+complex
+
+ configuration for cards that can be accessed though navigate items; see docs for cards
+Details on sleepBrightness/screenBrightness and other configs related to screen brightness¶
+ sleepBrightness:
+ - time: "7:00:00"
+ value: 10
+ - time: "23:00:00"
+ value: 0
+ sleepBrightness:
+ - time: "sunrise"
+ value: 10
+ - time: "sunset + 1:00:00"
+ value: 0
+ sleepBrightness: input_number.brightness_nspanel
+ sleepBrightness: 50
+sleepTracking overrides this setting and sets the brightness to 0 if the state of the configured Home Assistant entity is off or not_home. You may also use a Home Assistant group to track multiple entities.sleepOverride overrides sleepBrightness but does not take precedence over sleepTracking. This is useful if, for example, you want your NSPanel to be brighter than usual if your light is on or if you want to override a panel dimming if you are in the room. sleepBrightness:
+ - time: "sunrise"
+ value: 20
+ - time: "sunset"
+ value: 0
+ sleepOverride:
+ entity: light.bedroomlight
+ brightness: 20
+Supported keys for locale config¶
+
+
+
+
+
+
+
+Language Code
+Language
+
+
+
+af_ZAAfrikaans
+
+
+
+ar_SYArabic
+
+
+
+bg_BGBulgarian
+
+
+
+ca_ESCatalan
+
+
+
+cs_CZCzech
+
+
+
+da_DKDanish
+
+
+
+de_DEGerman
+
+
+
+el_GRGreek
+
+
+
+en_USEnglish
+
+
+
+es_ESSpanish
+
+
+
+et_EEEstonian
+
+
+
+fa_IRPersian
+
+
+
+fi_FIFinnish
+
+
+
+fr_FRFrench
+
+
+
+he_ILHebrew
+
+
+
+hr_xxCroatian
+
+
+
+hu_HUHungarian
+
+
+
+hy_AMArmenian
+
+
+
+id_IDIndonesian
+
+
+
+is_ISIcelandic
+
+
+
+it_ITItalian
+
+
+
+lb_xxLuxembourgish
+
+
+
+lt_LTLithuanian
+
+
+
+lv_LVLatvian
+
+
+
+nb_NONorwegian
+
+
+
+nl_NLDutch
+
+
+
+nn_NONorwegian
+
+
+
+pl_PLPolish
+
+
+
+pt_PTPortuguese
+
+
+
+ro_RORomanian
+
+
+
+ru_RURussian
+
+
+
+sk_SKSlovak
+
+
+
+sl_SISlovenian
+
+
+
+sv_SESwedish
+
+
+
+th_THThai
+
+
+
+tr_TRTurkish
+
+
+
+uk_UAUkrainian
+
+
+
+vi_VNVietnamese
+
+
+
+zh_CNSimplified Chinese
+
+
+
+
+zh_TWTraditional Chinese
+Customize OTA URLs¶
+ config:
+ displayURL-US-L: "http://example.com/us-l.tft"
+ displayURL-US-P: "http://example.com/us-l.tft"
+ displayURL-EU: "http://example.com/us-l.tft"
+ berryURL: "http://exampe.com/autoexec.be"
+Config screensaver
+
+Possible configuration values for screensaver config¶
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+entityTrue
+string
+
+weather.exampleweather entity from homeassistant
+
+
+
+entitiesTrue
+string
+
+Nonecontains a list of entities of this card (will be used instead of entity)
+
+
+
+statusIcon1True
+complex
+
+Nonestatus icon left to the date string, config similar to weatherOverride
+
+
+
+statusIcon2True
+complex
+
+Nonestatus icon right to the date string, config similar to weatherOverride
+
+
+
+doubleTapToUnlockTrue
+boolean
+
+Falserequires to tap screensaver two times
+
+
+
+themeTrue
+complex
+
+ configuration for theme
+
+
+
+defaultCardTrue
+string
+
+Nonedefault page after exiting screensaver; only works with top level cards defined in cards; needs to be a navigation item, see subpages (navigate.type_key) This config option will also be evaluated as a HomeAssistant Template.
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+
+typeTrue
+string
+
+screensaver
+screensaver or screensaver2 screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ - entity: weather.demo_weather_north
+ type: 1
+ - entity: weather.demo_weather_north
+ type: 2
+ - entity: sensor.energy_usage
+
screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ - entity: weather.demo_weather_north
+ type: 1
+ - entity: sensor.energy_usage
+ - entity: delete
+ - entity: sensor.indoor_temp
+ icon: mdi:home-thermometer-outline
+type: screensaver2 to switch the layout.
screensaver:
+ type: screensaver2
+ entities:
+ - entity: weather.demo_weather_north
+Possible configuration values for screensaver theme config (only normal screensaver layout not screensaver2)¶
+
+
+
+
+
+
+
+key
+option
+type
+default
+description
+
+
+
+backgroundTrue
+list
+Black
+
+[R, G, B]
+
+
+timeTrue
+list
+White
+
+[R, G, B]
+
+
+timeAMPMTrue
+list
+White
+
+[R, G, B]
+
+
+dateTrue
+list
+White
+
+[R, G, B]
+
+
+tMainTextTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast1True
+list
+White
+
+[R, G, B]
+
+
+tForecast2True
+list
+White
+
+[R, G, B]
+
+
+tForecast3True
+list
+White
+
+[R, G, B]
+
+
+tForecast4True
+list
+White
+
+[R, G, B]
+
+
+tForecast1ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast2ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast3ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast4ValTrue
+list
+White
+
+[R, G, B]
+
+
+barTrue
+list
+White
+
+[R, G, B]
+
+
+tMainTextAlt2True
+list
+White
+
+[R, G, B]
+
+
+
+tTimeAddTrue
+list
+White
+
+[R, G, B][255, 0, 0] for red or [0, 0, 255] for blue. These are translated internally to RGB565 (note that this has lower color depth so the colours may not appear the same). Also note that the screen has a low contrast ratio, so colors look sigificantly different at full display brightness and lowest brightness. screensaver:
+ theme:
+ date: [255, 0, 0]
+Config Example for configured statusIcons
+
+ screensaver:
+ entity: weather.k3ll3r
+ statusIcon1:
+ entity: switch.example_item
+ statusIcon2:
+ entity: binary_sensor.example_item
+altFont: True to the statusIcon configuration. Icon/Color Overrides are also possible like on any other Entity.Config Example for configured statusIcons with increased size of the icons
+
+ screensaver:
+ entity: weather.k3ll3r
+ statusIcon1:
+ entity: switch.example_item
+ altFont: True
+ statusIcon2:
+ entity: binary_sensor.example_item
+ altFont: True
+Config Example for all white icons on screensaver
+
+ screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 1
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 2
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 3
+ color: [255,255,255]
+Config Example for a custom date format on forecast
+
+ screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ name: "%a %-d/%-m"
+ - entity: weather.demo_weather_north
+ type: 1
+ name: "%a %-d/%-m"
+ - entity: weather.demo_weather_north
+ name: "%a %-d/%-m"
+ type: 2
+ - entity: weather.demo_weather_north
+ name: "%a %-d/%-m"
+ type: 3
+Configure MQTT on Tasmota¶
+
Note for Appdeamon Addon Version >= 15¶
+Configure MQTT Connection on AppDaemon¶
+appdaemon.yaml Restart your AppDaemon Container (not HomeAssistant) after adding the MQTT Configuration./addon_configs/a0d7b954_appdaemon/appdeamon.yaml---
+secrets: /homeassistant/secrets.yaml
+appdaemon:
+ latitude: 52.0
+ longitude: 4.0
+ elevation: 2
+ time_zone: Europe/Berlin
+ app_dir: /homeassistant/appdaemon/apps/ # !!! This is really important for AppDaemon HA Addon >= 15
+ plugins:
+ HASS:
+ type: hass
+ MQTT:
+ type: mqtt
+ namespace: mqtt
+ client_id: "appdaemon"
+ client_host: core-mosquitto.local.hass.io # This should work if you are using supervised HomeAssistant; if not use the IP Address instead.
+ #client_host: 192.168.75.30
+ client_port: 1883
+ client_user: "mqttuser"
+ client_password: "mqttpassword"
+ client_topics: NONE
+http:
+ url: http://127.0.0.1:5050
+admin:
+api:
+hadashboard:
+Configure NsPanel on AppDaemon¶
+config/appdaemon/apps/apps.yamlapps.yaml to this location if it isn't there.---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+tasmota_your_mqtt_topic to the topic used in Tasmota MQTT Configuration.
Note: You can add multiple panels to this configuration:
+
+---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/first-nspanel-topic/RESULT"
+ panelSendTopic: "cmnd/first-nspanel-topic/CustomSend"
+nspanel-2:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/second-nspanel-topic/RESULT"
+ panelSendTopic: "cmnd/second-nspanel-topic/CustomSend"
+Entities¶
+Possible configuration values for entities key:¶
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+entityFalse
+string
+
+Nonename of ha entity
+
+
+
+nameTrue
+string
+
+NoneUsed to override names (supports home assistant templates)
+
+
+
+valueTrue
+string
+
+NoneUsed to override the value (supports home assistant templates)
+
+
+
+iconTrue
+string
+
+NoneUsed to override icons
+
+
+
+colorTrue
+array
+
+NoneOverwrite color of entity
+color: [255, 0, 0]
+
+
+stateTrue
+string
+
+NoneOnly displayed if Entity state is equal to this value
+
+
+
+state_notTrue
+string
+
+NoneOnly displayed if Entity state is unequal to this value
+
+
+
+statusTrue
+string
+
+NoneOnly valid for navigate and service items, adds a entity to track state for the icon
+
+
+
+assumed_stateTrue
+string
+
+NoneOnly for cover items, up, down and stop buttons are always shown
+
+
+
+action_nameTrue
+string
+
+NoneOnly valid for script; Button label
+
+
+
+fontTrue
+string
+
+NoneUsed to change the font for cardGrid Icons; valid values are (
+small, medium-icon and medium). Currently only supported for homeassistant entities and not for internal ones.
+
+
+
+effectListTrue
+string
+
+NoneOnly valid for light; for example
+[Android, Aurora (fav list for effects)Override Icons or Names¶
+ entities:
+ - entity: light.test_item
+ name: NameOverride
+ icon: mdi:lightbulb
+ icon:
+ "on": mdi:lightbulb
+ "off": mdi:lightbulb
+ color:
+ "on": [255,0,0]
+ "off": [0,0,255]
+ color: '{{iif(states("binary_sensor.test")=="on", "[0,255,0]", "[255,165,0]")}}'
+text:X icon:
+ "on": mdi:lightbulb
+ "off": "text:"
+ha: which will be rendered as homeassistant template.
+There probably not much cases where this is needed, but here is an exmaple to show the current temperature on the status icon of the screensaver: statusIcon2:
+ entity: climate.wohnzimmer_boden
+ icon: 'ha:{{ state_attr("climate.wohnzimmer_boden","current_temperature")}}'
+<I></I> icon: 'ha:{{ iif(is_state('light.kitchen', 'on'), '<I>mdi:flashlight</I>', '<I>mdi:flashlight-off</I>') }}'
+Hide item based on state¶
+off - entity: binary_sensor.sensor_bad_contact
+ state: "off"
+on - entity: binary_sensor.sensor_kueche_contact
+ state_not: "on"
+Hide item based on HA Template¶
+true for the entity to hide. - entity: binary_sensor.sensor_kueche_contact
+ state_template: '{{ state_attr("sun.sun","azimuth") < 200 }}'
+Calling service directly as button¶
+ - entity: service.light.turn_on
+ data:
+ entity_id: light.schreibtischlampe
+ color_name: "green"
+FAQ - Frequently Asked Questions¶
+Waiting for content - This is taking longer than usual on the screen¶
+
+
+app_dir line in your appdaemon.yaml.
+This also requires you to move your apps.yaml to this location. Please make sure your apps.yaml is at /config/appdaemon/apps/apps.yaml and move it otherwise.INFO MQTT: MQTT Plugin initialization complete
+If you are seeing Messages like this:
+CRITICAL MQTT: Could not complete MQTT Plugin initialization, for Connection was refused due to Not Authorised
+Your appdaemon mqtt config is wrong, check your appdaemon.yaml.
+The log of your mqtt broker might give you additional information.
+Please don't modify the Full Topic in your Tasmota Config, unless you know the implications, changing the Full Topic will result in diffent Send and Receive Channels, that have to be correct in your apps.yaml.
+
+How to update¶
+Update AppDaemon Script¶
+Update Display Firmware¶
+FlashNextion http://nspanel.pky.eu/lui-release.tftFlashNextion http://nspanel.pky.eu/lui-us-p-release.tftFlashNextion http://nspanel.pky.eu/lui-us-l-release.tftUpdate Tasmota Berry Driver¶
+UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.beHow to upgrade from a release to the current development version¶
+
+
+
+
+FlashNextion http://nspanel.pky.eu/lui.tftFlashNextion http://nspanel.pky.eu/lui-us-l.tftFlashNextion http://nspanel.pky.eu/lui-us-p.tftNSPanel Lovelace UI¶
+CustomSend, which is implemented in the berry driver.
+You can issue this command through MQTT by sending messages to the cmnd/XXX/CustomSend Topic.
+Messages from the Panel are send to the tele/XXX/RESULT Topic, encoded in json {"CustomRecv":"message_from_screen"}Table of contents¶
+
+
+Startup¶
+{"CustomRecv":"event,startup,39,eu"} every few seconds.event, #Every message from the screen will start with `event`
+startup, #Startup Event
+39, #Current HMI Project Version
+eu #Current HMI Project Model
+Some preperation before we are acually navigating away:¶
+time~18:17date~Donnerstag, 25. August 2022timeout~20dimmode~10~100~6371Navigate from the startup page to the screensaver, by sending this command to the CustomSend Topic.¶
+pageType~screensaverExit Screensaver¶
+event,buttonPress2,screensaver,bExit,1pageType~cardEntitiesentityUpd~test~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~light~light.schreibtischlampe~X~17299~Schreibtischlampe~0~text~sensor.server_energy_power~Y~17299~Server ENERGY Power~155 W~shutter~cover.rolladenfenster_cover_1~Z~17299~Fenster Eingang~A|B|C|disable|enable|enable~switch~switch.bad~D~63142~Bad~1Messages to Nextion Display¶
+General Commands, implemented on all pages¶
+dimmode~0~100 - (screen off)dimmode~100~100 - (screen on with full brightness)time~22:26date~Di 24. Februartimeout~15 - timeout after 15 secondstimeout~0 - disable screensaverpageType~pageStartuppageType~cardEntitiespageType~cardThermopageType~cardMediapageType~popupLight~Schreibtischlampe~light.schreibtischlampepageType~popupNotifypageType~screensaverscreensaver page¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ weatherupdate
+
+
+
+ 1
+
+ Main Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 2
+
+ intNameEntity
+ ignored
+
+
+ 3
+
+ icon
+
+
+
+ 4
+
+ iconColor
+
+
+
+ 5
+
+ displayName
+ ignored
+
+
+ 6
+
+ optionalValue
+
+
+
+ 7
+
+ First Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 8
+
+ intNameEntity
+ ignored
+
+
+ 9
+
+ icon
+
+
+
+ 10
+
+ iconColor
+
+
+
+ 11
+
+ displayName
+
+
+
+ 12
+
+ optionalValue
+
+
+
+ 13
+
+ Second Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 14
+
+ intNameEntity
+ ignored
+
+
+ 15
+
+ icon
+
+
+
+ 16
+
+ iconColor
+
+
+
+ 17
+
+ displayName
+
+
+
+ 18
+
+ optionalValue
+
+
+
+ 19
+
+ Third Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 20
+
+ intNameEntity
+ ignored
+
+
+ 21
+
+ icon
+
+
+
+ 22
+
+ iconColor
+
+
+
+ 23
+
+ displayName
+
+
+
+ 24
+
+ optionalValue
+
+
+
+ 25
+
+ Fourth Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 26
+
+ intNameEntity
+ ignored
+
+
+ 27
+
+ icon
+
+
+
+ 28
+
+ iconColor
+
+
+
+ 29
+
+ displayName
+
+
+
+ 30
+
+ optionalValue
+
+
+
+ 31
+
+ Alternative Layout Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 32
+
+ intNameEntity
+ ignored
+
+
+ 33
+
+ icon
+
+
+
+ 34
+
+ iconColor
+
+
+
+ 35
+
+ displayName
+ ignored
+
+
+
+36
+
+ optionalValue
+
+ color~background~tTime~timeAMPM~tDate~tMainText~tForecast1~tForecast2~tForecast3~tForecast4~tForecast1Val~tForecast2Val~tForecast3Val~tForecast4Val~bar~tMainTextAlt2~tTimeAdd
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+ color
+
+
+
+ 1
+
+
+
+ background
+
+
+
+ 2
+
+
+
+ tTime
+
+
+
+ 3
+
+
+
+ timeAMPM
+
+
+
+ 4
+
+
+
+ tDate
+
+
+
+ 5
+
+
+
+ tMainText
+
+
+
+ 6
+
+
+
+ tForecast1
+
+
+
+ 7
+
+
+
+ tForecast2
+
+
+
+ 8
+
+
+
+ tForecast3
+
+
+
+ 9
+
+
+
+ tForecast4
+
+
+
+ 10
+
+
+
+ tForecast1Val
+
+
+
+ 11
+
+
+
+ tForecast2Val
+
+
+
+ 12
+
+
+
+ tForecast3Val
+
+
+
+ 13
+
+
+
+ tForecast4Val
+
+
+
+ 14
+
+
+
+ bar
+
+
+
+ 15
+
+
+
+ tMainTextAlt2
+
+
+
+
+16
+
+
+
+ tTimeAdd
+
+ notify~heading~textstatusUpdate~icon1~icon1Color~icon2~icon2~icon2color~icon1font~icon2fontcardEntities Page¶
+entityUpd~title~[navigation]~[entity_information]
+Example with 4 Entities:
+entityUpd~LightTest~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~light~light.bed_light~A~17299~Bed Light~0~light~light.ceiling_lights~B~52231~Ceiling Lights~1~switch~switch.ac~C~17299~AC~0~switch~switch.decorative_lights~D~65222~Decorative Lights~1
+~light~light.entityName~1~17299~Light1~0~shutter~cover.entityName~0~17299~Shutter2~iconUp|iconStop|iconDown~delete~~~~~~text~sensor.entityName~3~17299~Temperature~content~button~button.entityName~3~17299~bt-name~bt-text~switch~switch.entityName~4~17299~Switch1~0~number~input_number.entityName~4~17299~Number123~value|min|max~input_sel~input_select.entityName~3~17299~sel-name~sel-text
+
+
+
+
+
+
+
+ Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Entities
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 15
+ intNameEntity
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+
+
+ 20
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 21
+ intNameEntity
+
+
+ 22
+ icon
+
+
+
+ 23
+ iconColor
+
+
+
+ 24
+ displayName
+
+
+
+ 25
+ optionalValue
+
+
+ 26
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 27
+ intNameEntity
+
+
+ 28
+ icon
+
+
+
+ 29
+ iconColor
+
+
+
+ 30
+ displayName
+
+
+
+ 31
+ optionalValue
+
+
+ 32
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 33
+ intNameEntity
+
+
+ 34
+ icon
+
+
+
+ 35
+ iconColor
+
+
+
+ 36
+ displayName
+
+
+
+ 37
+ optionalValue
+
+
+ 38
+ Fifth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 39
+ intNameEntity
+
+
+ 40
+ icon
+
+
+
+ 41
+ iconColor
+
+
+
+ 42
+ displayName
+
+
+
+ 43
+ optionalValue
+
+
+ 44
+ Sixth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 45
+ intNameEntity
+
+
+ 46
+ icon
+
+
+
+ 47
+ iconColor
+
+
+
+ 48
+ displayName
+
+
+
+
+49
+ optionalValue
+ cardGrid Page¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Entities
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 15
+ intNameEntity
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+ ignored
+
+
+ 20
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 21
+ intNameEntity
+
+
+ 22
+ icon
+
+
+
+ 23
+ iconColor
+
+
+
+ 24
+ displayName
+
+
+
+ 25
+ optionalValue
+ ignored
+
+
+ 26
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 27
+ intNameEntity
+
+
+ 28
+ icon
+
+
+
+ 29
+ iconColor
+
+
+
+ 30
+ displayName
+
+
+
+ 31
+ optionalValue
+ ignored
+
+
+ 32
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 33
+ intNameEntity
+
+
+ 34
+ icon
+
+
+
+ 35
+ iconColor
+
+
+
+ 36
+ displayName
+
+
+
+ 37
+ optionalValue
+ ignored
+
+
+ 38
+ Fifth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 39
+ intNameEntity
+
+
+ 40
+ icon
+
+
+
+ 41
+ iconColor
+
+
+
+ 42
+ displayName
+
+
+
+ 43
+ optionalValue
+ ignored
+
+
+ 44
+ Sixth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 45
+ intNameEntity
+
+
+ 46
+ icon
+
+
+
+ 47
+ iconColor
+
+
+
+ 48
+ displayName
+
+
+
+
+49
+ optionalValue
+ ignored
+ cardMedia¶
+entityUpd~Kitchen~button~navigation.up~U~65535~~~delete~~~~~~media_player.kitchen~I'm a Hurricane~~Wellmess~~100~A~64704~B~media_pl~media_player.kitchen~C~17299~Kitchen~
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardMedia specific
+
+ cardMedia specific
+ intNameEntity
+
+
+
+ 15
+ 1st text row
+ title
+
+
+
+ 16
+ titleColor
+
+
+
+ 17
+ 2nd text row
+ author
+
+
+
+ 18
+ authorColor
+
+
+
+ 19
+ slider
+ volume
+ 0-100
+
+
+ 20
+ icon middle
+ playPauseIcon
+
+
+
+ 21
+ icon right side
+ onOffBtn
+ "disable" or color
+
+
+ 22
+ icon left side
+ iconShuffle
+ "disable" or icon
+
+
+ 23
+ Entities
+ upper left corner media icon
+ Entity Definition
+ type
+
+
+
+ 24
+ intNameEntity
+
+
+
+ 25
+ icon
+
+
+
+ 26
+ iconColor
+
+
+
+ 27
+ displayName
+ only used for popups
+
+
+ 28
+ optionalValue
+ ignored
+
+
+ 29
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 30
+ intNameEntity
+
+
+
+ 31
+ icon
+
+
+
+ 32
+ iconColor
+
+
+
+ 33
+ displayName
+ only used for popups
+
+
+ 34
+ optionalValue
+ ignored
+
+
+ 35
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 36
+ intNameEntity
+
+
+
+ 37
+ icon
+
+
+
+ 38
+ iconColor
+
+
+
+ 39
+ displayName
+ only used for popups
+
+
+ 40
+ optionalValue
+ ignored
+
+
+ 41
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 42
+ intNameEntity
+
+
+
+ 43
+ icon
+
+
+
+ 44
+ iconColor
+
+
+
+ 45
+ displayName
+ only used for popups
+
+
+ 46
+ optionalValue
+ ignored
+
+
+ 47
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 48
+ intNameEntity
+
+
+
+ 49
+ icon
+
+
+
+ 50
+ iconColor
+
+
+
+ 51
+ displayName
+ only used for popups
+
+
+ 52
+ optionalValue
+ ignored
+
+
+ 53
+ Fifth Entiy
+ Entity Definition
+ type
+
+
+
+ 54
+ intNameEntity
+
+
+
+ 55
+ icon
+
+
+
+ 56
+ iconColor
+
+
+
+ 57
+ displayName
+ only used for popups
+
+
+
+58
+ optionalValue
+ ignored
+ cardThermo¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+
+
+
+ 2
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+
+
+ intNameEntity
+
+
+
+ 15
+ 2nd text box
+ currentTemp
+
+
+
+ 16
+ target temperature
+ dstTemp
+ multiplied by 10
+
+
+ 17
+ Text 4th Box Left Side
+ status
+
+
+
+ 18
+ Min Temp
+ minTemp
+ multiplied by 10
+
+
+ 19
+ Max Temp
+ maxTemp
+ multiplied by 10
+
+
+ 20
+ Temperature Steps
+ tempStep
+ multiplied by 10
+
+
+ 21
+ bottom hvac_action 1
+ Hvac Action
+ icon
+
+
+
+ 22
+ iconColorActive
+
+
+
+ 23
+ buttonState
+
+
+
+ 24
+ intName
+
+
+
+ 25
+ bottom hvac_action 2
+ Hvac Action
+ icon
+
+
+
+ 26
+ iconColorActive
+
+
+
+ 27
+ buttonState
+
+
+
+ 28
+ intName
+
+
+
+ 29
+ bottom hvac_action 3
+ Hvac Action
+ icon
+
+
+
+ 30
+ iconColorActive
+
+
+
+ 31
+ buttonState
+
+
+
+ 32
+ intName
+
+
+
+ 33
+ bottom hvac_action 4
+ Hvac Action
+ icon
+
+
+
+ 34
+ iconColorActive
+
+
+
+ 35
+ buttonState
+
+
+
+ 36
+ intName
+
+
+
+ 37
+ bottom hvac_action 5
+ Hvac Action
+ icon
+
+
+
+ 38
+ iconColorActive
+
+
+
+ 39
+ buttonState
+
+
+
+ 40
+ intName
+
+
+
+ 41
+ bottom hvac_action 6
+ Hvac Action
+ icon
+
+
+
+ 42
+ iconColorActive
+
+
+
+ 43
+ buttonState
+
+
+
+ 44
+ intName
+
+
+
+ 45
+ bottom hvac_action 7
+ Hvac Action
+ icon
+
+
+
+ 46
+ iconColorActive
+
+
+
+ 47
+ buttonState
+
+
+
+ 48
+ intName
+
+
+
+ 49
+ bottom hvac_action 8
+ Hvac Action
+ icon
+
+
+
+ 50
+ iconColorActive
+
+
+
+ 51
+ buttonState
+
+
+
+ 52
+ intName
+
+
+
+ 53
+ Currently Label 1th Text Box
+ tCurTempLbl
+
+
+
+ 54
+ State Label 3th Text Box
+ tStateLbl
+
+
+
+ 55
+
+
+ tALbl
+ deprecated; ignored
+
+
+ 56
+ Temperature Unit (Celcius/Farhenheit)
+ tCF
+
+
+
+ 57
+ Second Destination Tempature (Heat/Cool)
+
+ second temp
+ ; multiplied by 10
+
+
+
+58
+ additonal detail button to open another page
+ btDetail
+ "1" to hide
+ cardAlarm¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardAlarm specific
+ card intNameEntity
+ intNameEntity
+
+
+
+ 15
+ 1st button right side
+ displayName
+
+
+
+ 16
+ intId
+
+
+
+ 17
+ 2nd button right side
+ displayName
+
+
+
+ 18
+ intId
+
+
+
+ 19
+ 3rd button right side
+ displayName
+
+
+
+ 20
+ intId
+
+
+
+ 21
+ 4th button right side
+ displayName
+
+
+
+ 22
+ intId
+
+
+
+ 23
+ icon next to code display
+ icon
+
+
+
+ 24
+ iconColor
+
+
+
+ 25
+ numpad
+ numpadStatus
+ "disable" or "enable"
+
+
+ 26
+ flashing of icon next to code
+ flashing status
+ "enable" or "disable"
+
+
+ 27
+ button bottom left corner
+ icon
+
+
+
+ 28
+ iconColor
+
+
+
+
+29
+ intNameEntity
+
+ cardQR¶
+entityUpd~Guest Wifi~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~WIFI:S:test_ssid;T:WPA;P:test_pw;;~text~iText.test_ssid~���~17299~Name~test_ssid~text~iText.test_pw~���~17299~Password~test_pw
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ intNameEntity
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardQR specific
+ qrcode text
+
+
+
+ 15
+ Entities
+ 1st Entity
+ Entity Definition
+ type
+
+
+
+ 16
+ intNameEntity
+
+
+
+ 17
+ icon
+
+
+
+ 18
+ iconColor
+
+
+
+ 19
+ displayName
+
+
+
+ 20
+ optionalValue
+
+
+
+ 21
+ 2nd Entity
+ Entity Definition
+ type
+
+
+
+ 22
+ intNameEntity
+
+
+
+ 23
+ icon
+
+
+
+ 24
+ iconColor
+
+
+
+ 25
+ displayName
+
+
+
+
+26
+ optionalValue
+
+ cardPower¶
+entityUpd~PowerTest~x~navUp~A~65535~~~delete~~~~~~text~sensor.power_consumption~B~17299~Power consumption~100W~1~text~sensor.power_consumption~C~17299~Power consumption~100W~1~text~sensor.today_energy~D~17299~Total energy 1~5836.0kWh~0~delete~~~~~~0~text~sensor.today_energy~E~17299~Total energy 1~5836.0kWh~-30~delete~~~~~~0~text~sensor.today_energy~F~65504~Total energy 1~5836.0kWh~90~text~sensor.today_energy~G~17299~Total energy 1~5836.0kWh~10
+
+
+
+
+
+
+
+ Parameter Number
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+
+
+
+ 2
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Home Icon / Value below Home Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 15
+ intNameEntity
+ ignored
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+
+
+
+ 20
+ speed
+ ignored
+
+
+ 21
+ Value above Home Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 22
+ intNameEntity
+ ignored
+
+
+ 23
+ icon
+ ignored
+
+
+ 24
+ iconColor
+ ignored
+
+
+ 25
+ displayName
+ ignored
+
+
+ 26
+ optionalValue
+
+
+
+ 27
+ speed
+ ignored
+
+
+ 28
+ 1st Item Upper Left
+ Entity Definition
+ type
+ ignored
+
+
+ 29
+ intNameEntity
+ ignored
+
+
+ 30
+ icon
+
+
+
+ 31
+ iconColor
+
+
+
+ 32
+ displayName
+
+
+
+ 33
+ optionalValue
+
+
+
+ 34
+ speed
+ numbers (between -120 and 120)
+
+
+ 35
+ 2nd Item Middle Left
+ Entity Definition
+ type
+ ignored
+
+
+ 36
+ intNameEntity
+ ignored
+
+
+ 37
+ icon
+
+
+
+ 38
+ iconColor
+
+
+
+ 39
+ displayName
+
+
+
+ 40
+ optionalValue
+
+
+
+ 41
+ speed
+ numbers (between -120 and 120)
+
+
+ 42
+ 3rd Item Bottom Left
+ Entity Definition
+ type
+ ignored
+
+
+ 43
+ intNameEntity
+ ignored
+
+
+ 44
+ icon
+
+
+
+ 45
+ iconColor
+
+
+
+ 46
+ displayName
+
+
+
+ 47
+ optionalValue
+
+
+
+ 48
+ speed
+ numbers (between -120 and 120)
+
+
+ 49
+ 4th Item Upper Right
+ Entity Definition
+ type
+ ignored
+
+
+ 50
+ intNameEntity
+ ignored
+
+
+ 51
+ icon
+
+
+
+ 52
+ iconColor
+
+
+
+ 53
+ displayName
+
+
+
+ 54
+ optionalValue
+
+
+
+ 55
+ speed
+ numbers (between -120 and 120)
+
+
+ 56
+ 5th Item Middle Right
+ Entity Definition
+ type
+ ignored
+
+
+ 57
+ intNameEntity
+ ignored
+
+
+ 58
+ icon
+
+
+
+ 59
+ iconColor
+
+
+
+ 60
+ displayName
+
+
+
+ 61
+ optionalValue
+
+
+
+ 62
+ speed
+ numbers (between -120 and 120)
+
+
+ 63
+ 6th Item Bottom Right
+ Entity Definition
+ type
+ ignored
+
+
+ 64
+ intNameEntity
+ ignored
+
+
+ 65
+ icon
+
+
+
+ 66
+ iconColor
+
+
+
+ 67
+ displayName
+
+
+
+ 68
+ optionalValue
+
+
+
+
+69
+ speed
+ numbers (between -120 and 120)
+ cardChart Page¶
+entityUpd~heading~navigation~color~yAxisLabel~yAxisTick:[yAxisTick]*[~value[:xAxisLabel]?]* entityUpd~Chart Demo~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~6666~Gas [kWh]~20:40:60:80:100~10~7^2:00~7~6^4:00~6~7^6:00~0~7^8:00~5~1^10:00~1~10^12:00~5~6^14:00~8popupLight Page¶
+entityUpdateDetail~entityName~*ignored*~*iconColor*~*buttonState*~*sliderBrightnessPos*~*sliderColorTempPos*~*colorMode*~*color_translation*~*color_temp_translation*~*brightness_translation*entityUpdateDetail~1~17299~1~100~78~enableentityUpdateDetail~1~17299~1~100~disablepopupShutter Page¶
+entityUpdateDetail~entityName~*sliderPos*~2ndrow~textPosition~icon1~iconUp~iconStop~iconDown~iconUpStatus~iconStopStatus~iconDownStatus~textTilt~iconTiltLeft~iconTiltStop~iconTiltRight~iconTiltLeftStatus~iconTiltStopStatus~iconTiltLeftStatus~tiltPosentityUpdateDetail~1~77popupNotify Page¶
+entityUpdateDetail~*internalName*~*tHeading*~*tHeadingColor*~*b1*~*tB1Color*~*b2*~*tB2Color*~*tText*~*tTextColor*~*sleepTimeout*~*font*~*alt_icon*~*altIconColor*exitPopuppopupThermo Page¶
+entityUpdateDetail~{entity_id}~{icon_id}~{icon_color}~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~popupInSel Page (input_select detail page)¶
+entityUpdateDetail2~*entity_id*~~*icon_color*~*input_sel*~*state*~*options*popupTimer¶
+entityUpdateDetail~{entity_id}~~{icon_color}~{entity_id}~{min_remaining}~{sec_remaining}~{editable}~{action1}~{action2}~{action3}~{label1}~{label2}~{label3}Messages from Nextion Display¶
+event,buttonPress2,pageName,bNextevent,buttonPress2,pageName,bPrevevent,buttonPress2,pageName,bExit,number_of_tapsevent,buttonPress2,pageName,sleepReachedstartup page¶
+event,startup,version,modelscreensaver page¶
+event,buttonPress2,screensaver,exit - Touch Event on Screensaverevent,screensaverOpen - Screensaver has openedcardEntities Page¶
+event,*eventName*,*entityName*,*actionName*,*optionalValue*event,buttonPress2,internalNameEntity,upevent,buttonPress2,internalNameEntity,downevent,buttonPress2,internalNameEntity,stopevent,buttonPress2,internalNameEntity,OnOff,1event,buttonPress2,internalNameEntity,buttonpopupLight Page¶
+event,pageOpenDetail,popupLight,internalNameEntityevent,buttonPress2,internalNameEntity,OnOff,1event,buttonPress2,internalNameEntity,brightnessSlider,50event,buttonPress2,internalNameEntity,colorTempSlider,50event,buttonPress2,internalNameEntity,colorWheel,x|y|whpopupShutter Page¶
+event,pageOpenDetail,popupShutter,internalNameEntityevent,buttonPress2,internalNameEntity,positionSlider,50popupNotify Page¶
+event,buttonPress2,*internalName*,notifyAction,yesevent,buttonPress2,*internalName*,notifyAction,nocardThermo Page¶
+event,buttonPress2,*entityName*,tempUpd,*temperature*event,buttonPress2,*entityName*,hvac_action,*hvac_action*cardMedia Page¶
+event,buttonPress2,internalNameEntity,media-backevent,buttonPress2,internalNameEntity,media-pauseevent,buttonPress2,internalNameEntity,media-nextevent,buttonPress2,internalNameEntity,volumeSlider,75cardAlarm Page¶
+event,buttonPress2,internalNameEntity,actionName,codeCustom Protocol¶
+55 BB [payload length] [payload length] [payload] [crc] [crc]
+Example for valid Message¶
+55 BB 04 00 31 33 33 37 5F 5B
+
+
+ Material Design Icons
+
+
+
+ Cheatsheet Usage
+
+
+
+
+ New Icons -
+
+
+ All Icons -
+
+
+ Deprecated Icons -
+ Overview¶
+
Features¶
+
+
+

Requirements¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Installation - ioBroker¶
+Sending Notifications to the Panel¶
+Seperate Page¶
+pageType popupNotifyentityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdTextentityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText~icon~iconColorfontIdText is the font used by the notification text
+Possible values are 0-5:
+Font 0 - Default - Size 24 (No Icons, Support for various special chars from different langs)
+Font 1 - Size 32 (Icons and limited chars)
+Font 2 - Size 32 (No Icons, Support for various special chars from different langs)
+Font 3 - Size 48 (Icons and limited chars)
+Font 4 - Size 80 (Icons and limited chars)
+Font 5 - Size 128 (ascii only)
+exitPopup{{'\r\n'}}nspanel_popup_notification:
+ alias: Popup Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{
+ title }}~65535~~~~~{{ message }}~65535~{{ timeout }}; Buzzer 2,2,2
+ mode: single
+ icon: mdi:message-badge
+nspanel_popup_notification:
+ alias: Popup Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{
+ title }}~65535~~~~~{{ message }}~65535~{{ timeout }}
+ mode: single
+ icon: mdi:message-badge
+Notification on screensaver¶
+notify~heading~textnspanel_screensaver_notification:
+ alias: Screensaver Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend notify~{{ heading }}~{{ message }}; Buzzer 2,2,2
+ mode: single
+ icon: mdi:message-badge
+nspanel_screensaver_notification:
+ alias: Screensaver Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend notify~{{ heading }}~{{ message }}
+ mode: single
+ icon: mdi:message-badge
+Buzzer¶
+BuzzerPWM 1
+Color Picker¶
+
+Change behaviour of hardware buttons¶
+Tasmota Rules¶
+Rule2 on Button1#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,buttonPress2,navPrev,button"} endon on Button2#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,buttonPress2,navNext,button"} endon
+
+Rule2 1
+Decouple buttons from controlling power outputs¶
+SetOption73 1
SetOption73 0Setup Home Assistant¶
+Installing AppDaemon¶
+
Instructions for users of HomeAssistant Core installed through docker containers.
+
+In case you have a homeassistant setup using docker cotainers and the Add-on Store is not available to you, you can follow this guide for setting up AppDaemon. https://appdaemon.readthedocs.io/en/latest/DOCKER_TUTORIAL.html
+Please also pay attention to the correct volume mount for the conf folder of appdaemon, that has to point to the appdaemon folder within your homeassistant config folder.
+
+Here is an example docker compose file for homeassistant and appdaemon:
+
+version: "3.5"
+services:
+ homeassistant:
+ image: ghcr.io/home-assistant/home-assistant:stable
+ container_name: homeassistant
+ network_mode: host
+ volumes:
+ - ./docker-data/homeassistant/:/config
+ - /etc/localtime:/etc/localtime:ro
+ environment:
+ - TZ=Europe/Berlin
+ privileged: true
+ restart: unless-stopped
+
+ appdaemon:
+ container_name: appdaemon
+ image: acockburn/appdaemon:4.2.3
+ environment:
+ - HA_URL=http://your-homeassistant-url:8123
+ - TOKEN="xxxxxx"
+ volumes:
+ - /etc/localtime:/etc/localtime:ro
+ - ./docker-data/homeassistant/appdaemon:/conf
+ depends_on:
+ - homeassistant
+ restart: unless-stopped
+Add babel package to AppDaemon Container (Optional)¶
+
Installing Studio Code Server¶
+apps.yaml config file in the Appdaemon folder.
+Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.Installing HomeAssistant Community Store¶
+Installing Lovelace AppDaemon Backend Application¶
+
+
+Configuration on the left menu bar in Home Assistant Web UIDevices & ServicesIntegrationsHACS and click on ConfigureEnable AppDaemon apps discovery & tracking
+ is checked, or check it and click Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HACS on the left menu bar in Home Assistant Web UIAutomations in the right panelExplore & download repositories in the bottom right cornerNSPanel, and click on NSPanel Lovelace UI Backend in the list that appearsDownload this repository with HACSDownload, and wait for HACS to
+ proceed with the downloadFlash Tasmota to Your NSPanel¶
+
+You can use the Tasmota Web Installer to do so.
+NSPanel Page of the Tasmota Template Repository
+ESPHome Component
+Configure Tasmota Template for NSPanel¶
+
+Upload Berry Driver to Tasmota¶
+
+Flash Firmware to Nextion Screen¶
+
+FlashNextion http://nspanel.pky.eu/lui-release.tft
+FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
+FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
+Alternatively, you can use your own web server or the one built into Home Assistant:
+
+Upload the nspanel.tft from the latest release to a web server (for example, the www folder of Home Assistant) and execute the following command in the Tasmota Console.
+(Development version: [TFT file from HMI folder](HMI/nspanel.tft))
+
+**The web server must be HTTP. HTTPS is not supported due to Berry language limitations in Tasmota.**
+
+FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
+Flash Tasmota to your NSPanel¶
+Configure Tasmota Template for NSPanel¶
+
{"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"}Upload Berry Driver to Tasmota¶
+Consoles > Console in Tasmota and execute the following command:Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1
+Flash Firmware to Nextion Screen¶
+FlashNextion http://nspanel.pky.eu/lui-release.tftFlashNextion http://nspanel.pky.eu/lui-us-p-release.tftFlashNextion http://nspanel.pky.eu/lui-us-l-release.tftAlternatively you can use your own webserver:
+
+Upload the nspanel.tft from the lastest release to a Webserver and execute the following command in Tasmota Console.
+
+**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota**
+
+`FlashNextion http://ip-address-of-your-webserver:8123/local/nspanel.tft`
+
","path":["Overview"],"tags":[]},{"location":"card-alarm/","level":1,"title":"Alarm Card","text":"
cards:\n - type: cardAlarm\n title: Alarm Test 1\n entity: alarm_control_panel.alarmo\ntype False string None Type of the card title True string None Title of the Page entity False string None contains the entity of the current card key True string None Used by navigate items alarmControl True complex None overwrites the action executed on pressing the left bottom icon, by default this button is used to show a list of open sensors on a failed attempt to arm. supportedModes True list None Supply list of arm modes if you want to limit the modes on the card. Example ['arm_away', 'arm_night']","path":["Configuration - apps.yaml (Home Assistant)","Cards","Alarm Card"],"tags":[]},{"location":"card-climate/","level":1,"title":"Climate/Thermo Card","text":" cards:\n - type: cardThermo\n title: HeatPump\n entity: climate.heatpump\n - type: cardThermo\n title: HvaC\n entity: climate.hvac\n - type: cardThermo\n title: ecobee\n entity: climate.ecobee\ntype False string None Type of the card entity False string None contains the entitiy of this card title True string None Title of the Page temperatureUnit True string celsius set this to fahrenheit to change the temperatureUnit on the page key True string None Used by navigate items in combination with the type (cardEntities_key) supportedModes True list None Supply list of heat actions if you want to limit the actions on the card. Example ['heat', 'off']","path":["Configuration - apps.yaml (Home Assistant)","Cards","Climate/Thermo Card"],"tags":[]},{"location":"card-entities/","level":1,"title":"Entities Page","text":" cards:\n - type: cardEntities\n title: Test Entities Card\n entities:\n - entity: light.bed_light\n - entity: switch.decorative_lights\n - entity: cover.hall_window\n - entity: sensor.outside_temperature\ntype False string None Type of the card entities False complex None contains a list of entities of this card title True string None Title of the Page key True string None Used by navigate items in combination with the type (cardEntities_key)
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Entities Page"],"tags":[]},{"location":"card-grid/","level":1,"title":"Grid Page","text":" cards:\n - type: cardGrid\n title: Test Grid Card\n entities:\n - entity: light.bed_light\n - entity: switch.decorative_lights\n - entity: sensor.outside_temperature\n name: Outside Temp\n - entity: sensor.carbon_monoxide\n - entity: light.entrance_color_white_lights\n name: Entrance\n - entity: light.office_rgbw_lights\n name: Office RGBW\n icon: mdi:office-building\ntype False string None Type of the card entities False complex None contains a list of entities of this card title True string None Title of the Page key True string None Used by navigate items in combination with the type (cardEntities_key)
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Grid Page"],"tags":[]},{"location":"card-media/","level":1,"title":"Media Card","text":" cards:\n - type: cardMedia\n entity: media_player.spotify\ntype False string None Type of the card title True string None Title of the Page entity False string None contains the entity of the current card entities False complex None contains a list of entities shown in the bottom row, supports all entities supported by cardGrid key True string None Used by navigate items Example with configured Entities
Example with action on upper left media icon - type: cardMedia\n title: Kitchen\n entity: media_player.kitchen\n entities:\n - entity: light.bed_light\n - entity: light.ceiling_lights\n - entity: light.entrance_color_white_lights\n - entity: light.kitchen_lights\n - entity: light.living_room_rgbww_lights\n
Example with moved spaker selection The icon for speaker selection is automatically appended to the end of the list and can be moved with entities in the list. With 6 entities it is possible to remove it entirely. - type: cardMedia\n title: Kitchen\n entity: input_select.test123\n status: media_player.kitchen\n
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Media Card"],"tags":[]},{"location":"card-power/","level":1,"title":"Power Card (v3.9 and higher)","text":" - type: cardMedia\n title: Kitchen\n entity: media_player.kitchen\n entities:\n - entity: delete\n - entity: delete\n cards:\n - type: cardPower\n title: Power Test\n entities:\n - entity: sensor.power_consumption\n icon: mdi:home\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:car\n speed: -20\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:battery\n speed: 20\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:solar-panel\n color: [255, 255, 0]\n speed: 30\n - entity: sensor.today_energy\n speed: -40\n icon: mdi:help\ntype False string None Type of the card entities False complex None contains entities of the card title True string None Title of the Page cooldown True float None Rate Limit for Entity Updates to the card in Seconds (cooldown: 0.5) key True string None Used by navigate items
-100 and 100.
It provides the number as a negative integer, making the dot move from the middle of the card toward the entity. If you want the dot to move toward from the middle of the card, just skip inverting it at the end of the template like this: speed: >-\n {% set entity_power = states('sensor.appliance_water_heater_power') |float | round(3)%}\n {% set total_power = states('sensor.ams_power_active') | float | round(3) %}\n {% set entity_usage = (entity_power / total_power * 100) | float %}\n {{ (entity_usage | round()) * -1 }}\n {{ (entity_usage | round()) }}\n cards:\n - type: cardQR\n title: Guest Wifi\n qrCode: \"WIFI:S:test_ssid;T:WPA;P:test_pw;;\"\n entities:\n - entity: iText.test_ssid\n name: Name\n icon: mdi:wifi\n - entity: iText.test_pw\n name: Password\n icon: mdi:key\ntype False string None Type of the card entities False complex None contains entities of the card, only valid on cardEntities and cardGrid and cardQR title True string None Title of the Page key True string None Used by navigate items qrCode False string None Value of the qrCode
\"WIFI:S:{{states('input_text.test_ssid')}};T:WPA;P:{{states('input_text.test_pw')}};;\" cards:\n - type: cardUnlock\n pin: 1234\n title: Admin Page\n destination: navigate.adminpage\n hiddenCards:\n - type: cardGrid\n title: Admin Page\n key: adminpage\n entities:\n - entity: light.schreibtischlampe\ntype False string None Type of the card title True string None Title of the Page destination False string None contains the navigation entity this card should navigate to on unlock pin False string 3830 pin to unlock key True string None Used by navigate items","path":["Configuration - apps.yaml (Home Assistant)","Cards","Unlock Card (v4.0 and higher)"],"tags":[]},{"location":"config-migration-standalone/","level":1,"title":"Migration to Standalone Rewrite Config","text":"apps.yaml config with the standalone rewrite panels.yaml config.
","path":["Migration to Standalone Rewrite Config"],"tags":[]},{"location":"config-migration-standalone/#high-level-differences","level":2,"title":"High-level differences","text":"
apps.yaml with module / class / configappdaemon.yaml)
","path":["Migration to Standalone Rewrite Config"],"tags":[]},{"location":"config-migration-standalone/#minimal-beforeafter-example","level":2,"title":"Minimal before/after example","text":"/config/panels.yamlnspanelsapps.yaml):nspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\npanels.yaml):
","path":["Migration to Standalone Rewrite Config"],"tags":[]},{"location":"config-migration-standalone/#important-key-changes","level":2,"title":"Important key changes","text":"Legacy key/concept Rewrite key/concept Notes home_assistant_address: \"http://supervisor\"\nhome_assistant_token: \"YOUR_TOKEN\"\n\nnspanels:\n panel-1:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\n locale: en_US\n timeZone: \"Europe/Berlin\"\n timeFormat: \"%H:%M\"\n dateFormat: \"full\"\n screensaver:\n entities:\n - entity: weather.home\n cards:\n - type: cardEntities\n title: Main\n entities:\n - entity: light.kitchen\nmodule, class, config wrapper removed Rewrite uses nspanels.<panel_name> directly. timezone timeZone Casing changed. dateFormatBabel dateFormat Use dateFormat in rewrite. temperatureUnit (legacy card-level usage) temp_unit (panel-level) Rewrite reads temp_unit from panel settings. brightness schedule lists not supported Rewrite supports integer or entity id for brightness values. updateMode / OTA URL override keys not supported Legacy update behavior is not part of rewrite config.
","path":["Migration to Standalone Rewrite Config"],"tags":[]},{"location":"config-overview/","level":1,"title":"Configuration","text":"apps.yaml inside of your Appdaemon config folder and add card and entities you want to display on the screen.---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\n---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\n sleepTimeout: 20\n sleepBrightness:\n - time: \"7:00:00\"\n value: 10\n - time: \"23:00:00\"\n value: 0\n locale: \"de_DE\"\n screensaver:\n entity: weather.k3ll3r\n cards:\n - type: cardEntities\n entities:\n - entity: switch.example_item\n - entity: light.example_item\n title: Example 1\n - type: cardGrid\n entities:\n - entity: switch.example_item\n - entity: light.example_item\n title: Example 2\npanelRecvTopic False string tele/tasmota_your_mqtt_topic/RESULT The mqtt topic used to receive messages. panelSendTopic False string cmnd/tasmota_your_mqtt_topic/CustomSend The mqtt topic used to send messages. updateMode True string auto-notify Update Mode for flashing of the nextion display firmware, by default it is showing a message asking for the update after updating the backend app in HACS; Possible values: \"auto\", \"auto-notify\", \"manual\" model True string eu Model; Possible values: \"eu\", \"us-l\" and \"us-p\" sleepTimeout True integer 20 Timeout for the screen to enter screensaver, to disable screensaver use 0 sleepBrightness True integer/complex 20 Brightness for the screen on the screensaver, see example below for complex/scheduled config. screenBrightness True integer/complex 100 Brightness for the screen during usage, config format is the same as sleepBrightness. sleepTracking True string None Forces screensaver brightness to 0 in case entity state is not_home or off, can be a group, person or device_tracker entity. sleepTrackingZones True list [\"not_home\", \"off\"] Allows you to set your own states for sleepTracking sleepOverride True complex None Allows overriding of the sleepBrightness if entity state is on, true or home. Overrides sleepBrightness but sleepTracking takes precedence. locale True string en_US Used by babel to determinante Date format on screensaver, also used for localization. dateFormatBabel True string full formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields timeFormat True string %H:%M Time Format on screensaver. Substring after ? is displayed in a seperate smaller textbox. Useful for 12h time format with AM/PM \"%I:%M ?%p\"dateAdditionalTemplate True string \"\" Addional Text dispayed after Date, can contain a Homeassistant Template Example \" - {{ states('sun.sun') }}\" timeAdditionalTemplate True string \"\" Addional Text dispayed below Time, can contain a Homeassistant Template dateFormat True string %A, %d. %B %Y date format used if babel is not installed timezone True string \"\" Timezone for the time on the panel: Europe/Berlin - See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of TZ Identifiers (supported from upcoming version v4.4) defaultBackgroundColor True string ha-dark backgroud color of all cards, valid values: black, ha-dark cards False complex configuration for cards that are displayed on panel; see docs for cards screensaver True complex configuration for screensaver; see docs for screensaver hiddenCards True complex configuration for cards that can be accessed though navigate items; see docs for cards","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#details-on-sleepbrightnessscreenbrightness-and-other-configs-related-to-screen-brightness","level":2,"title":"Details on sleepBrightness/screenBrightness and other configs related to screen brightness","text":" sleepBrightness:\n - time: \"7:00:00\"\n value: 10\n - time: \"23:00:00\"\n value: 0\n sleepBrightness:\n - time: \"sunrise\"\n value: 10\n - time: \"sunset + 1:00:00\"\n value: 0\n sleepBrightness: input_number.brightness_nspanel\n sleepBrightness: 50\nsleepTracking overrides this setting and sets the brightness to 0 if the state of the configured Home Assistant entity is off or not_home. You may also use a Home Assistant group to track multiple entities.sleepOverride overrides sleepBrightness but does not take precedence over sleepTracking. This is useful if, for example, you want your NSPanel to be brighter than usual if your light is on or if you want to override a panel dimming if you are in the room.
","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#supported-keys-for-locale-config","level":2,"title":"Supported keys for locale config","text":"Language Code Language sleepBrightness:\n - time: \"sunrise\"\n value: 20\n - time: \"sunset\"\n value: 0\n sleepOverride:\n entity: light.bedroomlight\n brightness: 20\naf_ZA Afrikaans ar_SY Arabic bg_BG Bulgarian ca_ES Catalan cs_CZ Czech da_DK Danish de_DE German el_GR Greek en_US English es_ES Spanish et_EE Estonian fa_IR Persian fi_FI Finnish fr_FR French he_IL Hebrew hr_xx Croatian hu_HU Hungarian hy_AM Armenian id_ID Indonesian is_IS Icelandic it_IT Italian lb_xx Luxembourgish lt_LT Lithuanian lv_LV Latvian nb_NO Norwegian nl_NL Dutch nn_NO Norwegian pl_PL Polish pt_PT Portuguese ro_RO Romanian ru_RU Russian sk_SK Slovak sl_SI Slovenian sv_SE Swedish th_TH Thai tr_TR Turkish uk_UA Ukrainian vi_VN Vietnamese zh_CN Simplified Chinese zh_TW Traditional Chinese","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#customize-ota-urls","level":2,"title":"Customize OTA URLs","text":"
","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-screensaver/","level":1,"title":"Config screensaver","text":"","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"config-screensaver/#possible-configuration-values-for-screensaver-config","level":4,"title":"Possible configuration values for screensaver config","text":"key optional type default description config:\n displayURL-US-L: \"http://example.com/us-l.tft\"\n displayURL-US-P: \"http://example.com/us-l.tft\"\n displayURL-EU: \"http://example.com/us-l.tft\"\n berryURL: \"http://exampe.com/autoexec.be\"\nentity True string weather.example weather entity from homeassistant entities True string None contains a list of entities of this card (will be used instead of entity) statusIcon1 True complex None status icon left to the date string, config similar to weatherOverride statusIcon2 True complex None status icon right to the date string, config similar to weatherOverride doubleTapToUnlock True boolean False requires to tap screensaver two times theme True complex configuration for theme defaultCard True string None default page after exiting screensaver; only works with top level cards defined in cards; needs to be a navigation item, see subpages (navigate.type_key) This config option will also be evaluated as a HomeAssistant Template. key True string None Used by navigate items type True string screensaver screensaver or screensaver2 screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n - entity: weather.demo_weather_north\n type: 1\n - entity: weather.demo_weather_north\n type: 2\n - entity: sensor.energy_usage\n screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n - entity: weather.demo_weather_north\n type: 1\n - entity: sensor.energy_usage\n - entity: delete\n - entity: sensor.indoor_temp\n icon: mdi:home-thermometer-outline\ntype: screensaver2 to switch the layout.
","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"config-screensaver/#possible-configuration-values-for-screensaver-theme-config-only-normal-screensaver-layout-not-screensaver2","level":4,"title":"Possible configuration values for screensaver theme config (only normal screensaver layout not screensaver2)","text":"key option type default description screensaver:\n type: screensaver2\n entities:\n - entity: weather.demo_weather_north\nbackground True list Black [R, G, B] time True list White [R, G, B] timeAMPM True list White [R, G, B] date True list White [R, G, B] tMainText True list White [R, G, B] tForecast1 True list White [R, G, B] tForecast2 True list White [R, G, B] tForecast3 True list White [R, G, B] tForecast4 True list White [R, G, B] tForecast1Val True list White [R, G, B] tForecast2Val True list White [R, G, B] tForecast3Val True list White [R, G, B] tForecast4Val True list White [R, G, B] bar True list White [R, G, B] tMainTextAlt2 True list White [R, G, B] tTimeAdd True list White [R, G, B] [255, 0, 0] for red or [0, 0, 255] for blue. These are translated internally to RGB565 (note that this has lower color depth so the colours may not appear the same). Also note that the screen has a low contrast ratio, so colors look sigificantly different at full display brightness and lowest brightness.
Config Example for configured statusIcons screensaver:\n theme:\n date: [255, 0, 0]\n screensaver:\n entity: weather.k3ll3r\n statusIcon1:\n entity: switch.example_item\n statusIcon2:\n entity: binary_sensor.example_item\naltFont: True to the statusIcon configuration. Icon/Color Overrides are also possible like on any other Entity.
Config Example for all white icons on screensaver screensaver:\n entity: weather.k3ll3r\n statusIcon1:\n entity: switch.example_item\n altFont: True\n statusIcon2:\n entity: binary_sensor.example_item\n altFont: True\n
Config Example for a custom date format on forecast screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 1\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 2\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 3\n color: [255,255,255]\n
See Babel Documentation (https://babel.pocoo.org/en/latest/dates.html#date-fields) or the Python Documenation (https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) in case you do not have babel installed.","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"configure_mqtt/","level":1,"title":"Configure MQTT on Tasmota","text":" screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n name: \"%a %-d/%-m\"\n - entity: weather.demo_weather_north\n type: 1\n name: \"%a %-d/%-m\"\n - entity: weather.demo_weather_north\n name: \"%a %-d/%-m\"\n type: 2\n - entity: weather.demo_weather_north\n name: \"%a %-d/%-m\"\n type: 3\nappdaemon.yaml Restart your AppDaemon Container (not HomeAssistant) after adding the MQTT Configuration./addon_configs/a0d7b954_appdaemon/appdeamon.yaml
","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"configure_mqtt/#configure-nspanel-on-appdaemon","level":1,"title":"Configure NsPanel on AppDaemon","text":"---\nsecrets: /homeassistant/secrets.yaml\nappdaemon:\n latitude: 52.0\n longitude: 4.0\n elevation: 2\n time_zone: Europe/Berlin\n app_dir: /homeassistant/appdaemon/apps/ # !!! This is really important for AppDaemon HA Addon >= 15\n plugins:\n HASS:\n type: hass\n MQTT:\n type: mqtt\n namespace: mqtt\n client_id: \"appdaemon\"\n client_host: core-mosquitto.local.hass.io # This should work if you are using supervised HomeAssistant; if not use the IP Address instead.\n #client_host: 192.168.75.30\n client_port: 1883\n client_user: \"mqttuser\"\n client_password: \"mqttpassword\"\n client_topics: NONE\nhttp:\n url: http://127.0.0.1:5050\nadmin:\napi:\nhadashboard:\nconfig/appdaemon/apps/apps.yamlapps.yaml to this location if it isn't there.---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\ntasmota_your_mqtt_topic to the topic used in Tasmota MQTT Configuration.
","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"entities/","level":1,"title":"Entities","text":"---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/first-nspanel-topic/RESULT\"\n panelSendTopic: \"cmnd/first-nspanel-topic/CustomSend\"\nnspanel-2:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/second-nspanel-topic/RESULT\"\n panelSendTopic: \"cmnd/second-nspanel-topic/CustomSend\"\nentity False string None name of ha entity name True string None Used to override names (supports home assistant templates) value True string None Used to override the value (supports home assistant templates) icon True string None Used to override icons color True array None Overwrite color of entity color: [255, 0, 0] state True string None Only displayed if Entity state is equal to this value state_not True string None Only displayed if Entity state is unequal to this value status True string None Only valid for navigate and service items, adds a entity to track state for the icon assumed_state True string None Only for cover items, up, down and stop buttons are always shown action_name True string None Only valid for script; Button label font True string None Used to change the font for cardGrid Icons; valid values are (small, medium-icon and medium). Currently only supported for homeassistant entities and not for internal ones. effectList True string None Only valid for light; for example [Android, Aurora (fav list for effects)","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#override-icons-or-names","level":2,"title":"Override Icons or Names","text":" entities:\n - entity: light.test_item\n name: NameOverride\n icon: mdi:lightbulb\n icon:\n \"on\": mdi:lightbulb\n \"off\": mdi:lightbulb\n
Dynamic color overwrites using homeassistant templates: color:\n \"on\": [255,0,0]\n \"off\": [0,0,255]\n
color: '{{iif(states(\"binary_sensor.test\")==\"on\", \"[0,255,0]\", \"[255,165,0]\")}}'\n It is also possible to use text instead of icons with text:X
icon:\n \"on\": mdi:lightbulb\n \"off\": \"text:\"\n Note: State Overrides are working with all state values, not only with \"on\" and \"off\".
To insert dynamic values from a homeassistant template, like a temperature you can also use ha: which will be rendered as homeassistant template. There probably not much cases where this is needed, but here is an exmaple to show the current temperature on the status icon of the screensaver:
statusIcon2:\n entity: climate.wohnzimmer_boden\n icon: 'ha:{{ state_attr(\"climate.wohnzimmer_boden\",\"current_temperature\")}}'\n If you want to display icons from a template you can put them between <I></I>
icon: 'ha:{{ iif(is_state('light.kitchen', 'on'), '<I>mdi:flashlight</I>', '<I>mdi:flashlight-off</I>') }}'\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#hide-item-based-on-state","level":2,"title":"Hide item based on state","text":"This sensor will only be shown on the card if it's state is equal to off
- entity: binary_sensor.sensor_bad_contact\n state: \"off\"\n This sensor will only be shown on the card if it's state is not equal to on
- entity: binary_sensor.sensor_kueche_contact\n state_not: \"on\"\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#hide-item-based-on-ha-template","level":2,"title":"Hide item based on HA Template","text":"The template must evaluate to true for the entity to hide.
- entity: binary_sensor.sensor_kueche_contact\n state_template: '{{ state_attr(\"sun.sun\",\"azimuth\") < 200 }}'\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#calling-service-directly-as-button","level":2,"title":"Calling service directly as button","text":"The following example shows how to call services directly, this enables you to call services on entities not (yet) supported by the backend and also to pass data to services.
- entity: service.light.turn_on\n data:\n entity_id: light.schreibtischlampe\n color_name: \"green\"\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"faq/","level":1,"title":"FAQ - Frequently Asked Questions","text":"","path":["Getting started (Home Assistant)","FAQ - Frequently Asked Questions"],"tags":[]},{"location":"faq/#waiting-for-content-this-is-taking-longer-than-usual-on-the-screen","level":2,"title":"Waiting for content - This is taking longer than usual on the screen","text":"You have most likely an error in your MQTT configuration somewhere. To find the error follow theese steps:
Check the location of your apps.yaml With the AppDaemon Addon >= 15 the config dir has been moved. It's required to configure the location back to the old one, this is done by the app_dir line in your appdaemon.yaml. This also requires you to move your apps.yaml to this location. Please make sure your apps.yaml is at /config/appdaemon/apps/apps.yaml and move it otherwise.
Check your appdaemon log. (Settings > Add-ons > AppDaemon > Log) You should see something like this: INFO MQTT: MQTT Plugin initialization complete If you are seeing Messages like this: CRITICAL MQTT: Could not complete MQTT Plugin initialization, for Connection was refused due to Not Authorised Your appdaemon mqtt config is wrong, check your appdaemon.yaml. The log of your mqtt broker might give you additional information.
Check MQTT Configuration of Tasmota. Your Tasmota device needs to connect sucessfully to your MQTT Broker, if you are in the waiting for content screen, the panel will send periodic messages to it's mqtt topic. Note that there is a minimum password length of 5 chars for the MQTT Connection in Tasmota.
Make sure that you are using the same topic in apps.yaml and in your tasmota configuration. The examples in the docs (MQTT Config) are an valid example (tasmota<>apps.yaml). Please don't modify the Full Topic in your Tasmota Config, unless you know the implications, changing the Full Topic will result in diffent Send and Receive Channels, that have to be correct in your apps.yaml.
If you are still in the waiting for content screen please share the following items, with the Waiting for Content Issue type on the Github Issues Page
HACS will show you that there is an update avalible and ask you to update. It is important to restart the AppDaemon Container afterwards.
","path":["Getting started (Home Assistant)","FAQ - Frequently Asked Questions"],"tags":[]},{"location":"faq/#update-display-firmware","level":3,"title":"Update Display Firmware","text":"You should get an notification on the screen, asking you to update the firmware. In case you want to update manually you can use the following commands.
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
You should get an notification on the screen, asking you to update the driver, if an update is needed.
You can update the berry driver directly from the Tasmota Console with the following command.
UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be
Click redownload in the menu of the app in HACS.
Select main version.
!!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!!
!!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!!
Click download.
Restart AppDaemon
Flash current Development Firmware in Tasmota Console. DO NOT USE THIS VERSION/URLS IF YOUR ARE NOT ON THE DEVELOPMENT VERSION
EU VERSION: FlashNextion http://nspanel.pky.eu/lui.tft
Development happens in the EU version, so it is possible that the US Version isn't up to date with the current development version of the EU firmware, the lastet US versions are still downloadable with the following links:
US LANDSCAPE: FlashNextion http://nspanel.pky.eu/lui-us-l.tft
US PORTRAIT: FlashNextion http://nspanel.pky.eu/lui-us-p.tft
The HMI Project of this project is only used to display stuff, navigation ist mostly up to the backend. This allows to be way more flexible.
Messages to the Panel can be send through the Command CustomSend, which is implemented in the berry driver. You can issue this command through MQTT by sending messages to the cmnd/XXX/CustomSend Topic. Messages from the Panel are send to the tele/XXX/RESULT Topic, encoded in json {\"CustomRecv\":\"message_from_screen\"}
On startup the panel will send {\"CustomRecv\":\"event,startup,39,eu\"} every few seconds.
event, #Every message from the screen will start with `event`\nstartup, #Startup Event\n39, #Current HMI Project Version\neu #Current HMI Project Model\n You can answer this message in many different ways, but in general the goal is to navigate way from the startup page. In the following example we will navigate to the screensaver page.
Send the following messages to the CustomSend Topic. (You can also send them on tasmota console for testing)
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#some-preperation-before-we-are-acually-navigating-away","level":3,"title":"Some preperation before we are acually navigating away:","text":"Send this every minute: time~18:17
Send this at least once at midnight: date~Donnerstag, 25. August 2022
Send theese message once after receiving the startup event (parameters will be explained later):
timeout~20
dimmode~10~100~6371
pageType~screensaver
After sending this command you should already see the time and date. To also show weather data you have to send them with weatherUpdate, but we will skip this for now.
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#exit-screensaver","level":3,"title":"Exit Screensaver","text":"Touching the panel on the screensaver will result in this MQTT Message on the result topic:
event,buttonPress2,screensaver,bExit,1
You can answer this by sending theese commands to the CustomSend Topic.
pageType~cardEntities
entityUpd~test~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~light~light.schreibtischlampe~X~17299~Schreibtischlampe~0~text~sensor.server_energy_power~Y~17299~Server ENERGY Power~155 W~shutter~cover.rolladenfenster_cover_1~Z~17299~Fenster Eingang~A|B|C|disable|enable|enable~switch~switch.bad~D~63142~Bad~1
set brightness of screensaver and active-brightness:
dimmode~0~100 - (screen off)
dimmode~100~100 - (screen on with full brightness)
set current time:
time~22:26
set current date:
date~Di 24. Februar
set screensaver timeout (set time in sec~ max 65):
timeout~15 - timeout after 15 seconds
timeout~0 - disable screensaver
change the page type:
pageType~pageStartup
pageType~cardEntities
pageType~cardThermo
pageType~cardMedia
pageType~popupLight~Schreibtischlampe~light.schreibtischlampe
pageType~popupNotify
pageType~screensaver
color~background~tTime~timeAMPM~tDate~tMainText~tForecast1~tForecast2~tForecast3~tForecast4~tForecast1Val~tForecast2Val~tForecast3Val~tForecast4Val~bar~tMainTextAlt2~tTimeAdd
notify~heading~text
statusUpdate~icon1~icon1Color~icon2~icon2~icon2color~icon1font~icon2font
Structure (Category): entityUpd~title~[navigation]~[entity_information] Example with 4 Entities:
entityUpd~LightTest~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~light~light.bed_light~A~17299~Bed Light~0~light~light.ceiling_lights~B~52231~Ceiling Lights~1~switch~switch.ac~C~17299~AC~0~switch~switch.decorative_lights~D~65222~Decorative Lights~1\n Possible entities on cardEntities/cardGrid:
~light~light.entityName~1~17299~Light1~0
~shutter~cover.entityName~0~17299~Shutter2~iconUp|iconStop|iconDown
~delete~~~~~
~text~sensor.entityName~3~17299~Temperature~content
~button~button.entityName~3~17299~bt-name~bt-text
~switch~switch.entityName~4~17299~Switch1~0
~number~input_number.entityName~4~17299~Number123~value|min|max
~input_sel~input_select.entityName~3~17299~sel-name~sel-text
cardGrid is using the exact same messageformat like cardEntities does. The only difference is, it ignores the information supplied in optionalValue, because it isn't needed for cardGrid.
Parameter Number Category Location Type Field Addional Information 0 instruction instruction entityUpd 1 title title title title 2 Navigation Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 Entities First Entity Entity Definition type 15 intNameEntity 16 icon 17 iconColor 18 displayName 19 optionalValue ignored 20 Second Entity Entity Definition type 21 intNameEntity 22 icon 23 iconColor 24 displayName 25 optionalValue ignored 26 Thrid Entity Entity Definition type 27 intNameEntity 28 icon 29 iconColor 30 displayName 31 optionalValue ignored 32 Forth Entiry Entity Definition type 33 intNameEntity 34 icon 35 iconColor 36 displayName 37 optionalValue ignored 38 Fifth Entiy (US Portrait Version) Entity Definition type 39 intNameEntity 40 icon 41 iconColor 42 displayName 43 optionalValue ignored 44 Sixth Entiy (US Portrait Version) Entity Definition type 45 intNameEntity 46 icon 47 iconColor 48 displayName 49 optionalValue ignored","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardmedia","level":3,"title":"cardMedia","text":"Example without icons in bottom row: entityUpd~Kitchen~button~navigation.up~U~65535~~~delete~~~~~~media_player.kitchen~I'm a Hurricane~~Wellmess~~100~A~64704~B~media_pl~media_player.kitchen~C~17299~Kitchen~
Serial Protocol of cardThermo is about to change; table will be completed later
Parameter Number Location Type Field Addional Information 0 instruction entityUpd 1 title title title 2 Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 intNameEntity 15 2nd text box currentTemp 16 target temperature dstTemp multiplied by 10 17 Text 4th Box Left Side status 18 Min Temp minTemp multiplied by 10 19 Max Temp maxTemp multiplied by 10 20 Temperature Steps tempStep multiplied by 10 21 bottom hvac_action 1 Hvac Action icon 22 iconColorActive 23 buttonState 24 intName 25 bottom hvac_action 2 Hvac Action icon 26 iconColorActive 27 buttonState 28 intName 29 bottom hvac_action 3 Hvac Action icon 30 iconColorActive 31 buttonState 32 intName 33 bottom hvac_action 4 Hvac Action icon 34 iconColorActive 35 buttonState 36 intName 37 bottom hvac_action 5 Hvac Action icon 38 iconColorActive 39 buttonState 40 intName 41 bottom hvac_action 6 Hvac Action icon 42 iconColorActive 43 buttonState 44 intName 45 bottom hvac_action 7 Hvac Action icon 46 iconColorActive 47 buttonState 48 intName 49 bottom hvac_action 8 Hvac Action icon 50 iconColorActive 51 buttonState 52 intName 53 Currently Label 1th Text Box tCurTempLbl 54 State Label 3th Text Box tStateLbl 55 tALbl deprecated; ignored 56 Temperature Unit (Celcius/Farhenheit) tCF 57 Second Destination Tempature (Heat/Cool) second temp ; multiplied by 10 58 additonal detail button to open another page btDetail \"1\" to hide","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardalarm","level":3,"title":"cardAlarm","text":"Parameter Number Category Location Type Field Addional Information 0 instruction instruction entityUpd 1 title title title title 2 Navigation Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 cardAlarm specific card intNameEntity intNameEntity 15 1st button right side displayName 16 intId 17 2nd button right side displayName 18 intId 19 3rd button right side displayName 20 intId 21 4th button right side displayName 22 intId 23 icon next to code display icon 24 iconColor 25 numpad numpadStatus \"disable\" or \"enable\" 26 flashing of icon next to code flashing status \"enable\" or \"disable\" 27 button bottom left corner icon 28 iconColor 29 intNameEntity","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardqr","level":3,"title":"cardQR","text":"Example: entityUpd~Guest Wifi~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~WIFI:S:test_ssid;T:WPA;P:test_pw;;~text~iText.test_ssid~���~17299~Name~test_ssid~text~iText.test_pw~���~17299~Password~test_pw
entityUpd~PowerTest~x~navUp~A~65535~~~delete~~~~~~text~sensor.power_consumption~B~17299~Power consumption~100W~1~text~sensor.power_consumption~C~17299~Power consumption~100W~1~text~sensor.today_energy~D~17299~Total energy 1~5836.0kWh~0~delete~~~~~~0~text~sensor.today_energy~E~17299~Total energy 1~5836.0kWh~-30~delete~~~~~~0~text~sensor.today_energy~F~65504~Total energy 1~5836.0kWh~90~text~sensor.today_energy~G~17299~Total energy 1~5836.0kWh~10
entityUpd~heading~navigation~color~yAxisLabel~yAxisTick:[yAxisTick]*[~value[:xAxisLabel]?]*
entityUpd~Chart Demo~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~6666~Gas [kWh]~20:40:60:80:100~10~7^2:00~7~6^4:00~6~7^6:00~0~7^8:00~5~1^10:00~1~10^12:00~5~6^14:00~8
entityUpdateDetail~entityName~*ignored*~*iconColor*~*buttonState*~*sliderBrightnessPos*~*sliderColorTempPos*~*colorMode*~*color_translation*~*color_temp_translation*~*brightness_translation*
entityUpdateDetail~1~17299~1~100~78~enable
entityUpdateDetail~1~17299~1~100~disable
entityUpdateDetail~entityName~*sliderPos*~2ndrow~textPosition~icon1~iconUp~iconStop~iconDown~iconUpStatus~iconStopStatus~iconDownStatus~textTilt~iconTiltLeft~iconTiltStop~iconTiltRight~iconTiltLeftStatus~iconTiltStopStatus~iconTiltLeftStatus~tiltPos
entityUpdateDetail~1~77
entityUpdateDetail~*internalName*~*tHeading*~*tHeadingColor*~*b1*~*tB1Color*~*b2*~*tB2Color*~*tText*~*tTextColor*~*sleepTimeout*~*font*~*alt_icon*~*altIconColor*
exitPopup
entityUpdateDetail~{entity_id}~{icon_id}~{icon_color}~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~
entityUpdateDetail2~*entity_id*~~*icon_color*~*input_sel*~*state*~*options*
options are ? seperated
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#popuptimer","level":3,"title":"popupTimer","text":"editable is 0 or 1
action fields are in the answer on the button press
in case action is empty the button will be hidden
entityUpdateDetail~{entity_id}~~{icon_color}~{entity_id}~{min_remaining}~{sec_remaining}~{editable}~{action1}~{action2}~{action3}~{label1}~{label2}~{label3}
event,buttonPress2,pageName,bNext
event,buttonPress2,pageName,bPrev
event,buttonPress2,pageName,bExit,number_of_taps
event,buttonPress2,pageName,sleepReached
event,startup,version,model
event,buttonPress2,screensaver,exit - Touch Event on Screensaver
event,screensaverOpen - Screensaver has opened
event,*eventName*,*entityName*,*actionName*,*optionalValue*
event,buttonPress2,internalNameEntity,up
event,buttonPress2,internalNameEntity,down
event,buttonPress2,internalNameEntity,stop
event,buttonPress2,internalNameEntity,OnOff,1
event,buttonPress2,internalNameEntity,button
event,pageOpenDetail,popupLight,internalNameEntity
event,buttonPress2,internalNameEntity,OnOff,1
event,buttonPress2,internalNameEntity,brightnessSlider,50
event,buttonPress2,internalNameEntity,colorTempSlider,50
event,buttonPress2,internalNameEntity,colorWheel,x|y|wh
event,pageOpenDetail,popupShutter,internalNameEntity
event,buttonPress2,internalNameEntity,positionSlider,50
event,buttonPress2,*internalName*,notifyAction,yes
event,buttonPress2,*internalName*,notifyAction,no
event,buttonPress2,*entityName*,tempUpd,*temperature*
event,buttonPress2,*entityName*,hvac_action,*hvac_action*
event,buttonPress2,internalNameEntity,media-back
event,buttonPress2,internalNameEntity,media-pause
event,buttonPress2,internalNameEntity,media-next
event,buttonPress2,internalNameEntity,volumeSlider,75
event,buttonPress2,internalNameEntity,actionName,code
55 BB [payload length] [payload length] [payload] [crc] [crc]\n Payload length contains the number of bytes of the payload.
CRC is \"CRC-16 (MODBUS) Big Endian\" calculated over the whole message
This protocol does not try to implement broken JSON Commands with a specified type (lol). Instead the commands are plain text commands with parameters.
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#example-for-valid-message","level":2,"title":"Example for valid Message","text":"This message has to be generated for the Message \"1337\" (1337 is not a valid command~ this is just an example)
55 BB 04 00 31 33 33 37 5F 5B\n","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"iobroker-install/","level":1,"title":"Installation - ioBroker","text":"The Backend for ioBroker is maintained by britzelpuf and armilar
See the wiki for documentation around setting lovelace-ui up with ioBroker
Wiki
Also see the Readme in the ioBroker Folder. iobroker ReadMe
","path":["Getting started (ioBroker)","Installation - ioBroker"],"tags":[]},{"location":"notifications/","level":1,"title":"Sending Notifications to the Panel","text":"There are two notification types, that can be triggered by sending a command over mqtt to the panel here are examples for homeassistant scripts:
","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#seperate-page","level":2,"title":"Seperate Page","text":"This is the notification used by the backend for updates, opening it requires to the following commands to the CustomSend Topic:
pageType popupNotify
entityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText
Alternative Layout with Icon:
entityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText~icon~iconColor
fontIdText is the font used by the notification text Possible values are 0-5:
Font 0 - Default - Size 24 (No Icons, Support for various special chars from different langs)\nFont 1 - Size 32 (Icons and limited chars)\nFont 2 - Size 32 (No Icons, Support for various special chars from different langs)\nFont 3 - Size 48 (Icons and limited chars)\nFont 4 - Size 80 (Icons and limited chars)\nFont 5 - Size 128 (ascii only)\n You need to use the acual char for the icon instead of the icon name which is used in the configuration. You can get the char of the icon from the cheatsheet.
https://docs.nspanel.pky.eu/icon-cheatsheet.html
It is possible to exit from the page by sending exitPopup
If you want to add newlines to your message add this string for the newline {{'\\r\\n'}}
Send Message to the Panel combined with a buzzer sound:
nspanel_popup_notification:\n alias: Popup Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{\n title }}~65535~~~~~{{ message }}~65535~{{ timeout }}; Buzzer 2,2,2\n mode: single\n icon: mdi:message-badge\n Send Message to the Panel:
nspanel_popup_notification:\n alias: Popup Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{\n title }}~65535~~~~~{{ message }}~65535~{{ timeout }}\n mode: single\n icon: mdi:message-badge\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#notification-on-screensaver","level":2,"title":"Notification on screensaver","text":"The screensaver can display Notifications by sending this command to the CustomSend topic: notify~heading~text
Send Message to the Screensaver combined with a buzzer sound:
nspanel_screensaver_notification:\n alias: Screensaver Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend notify~{{ heading }}~{{ message }}; Buzzer 2,2,2\n mode: single\n icon: mdi:message-badge\n Send Message to the Screensaver:
nspanel_screensaver_notification:\n alias: Screensaver Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend notify~{{ heading }}~{{ message }}\n mode: single\n icon: mdi:message-badge\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#buzzer","level":2,"title":"Buzzer","text":"See Tasmota Buzzer for commands.
It might be necessary to enable the buzzer with:
BuzzerPWM 1\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#color-picker","level":2,"title":"Color Picker","text":"Decimal RGB565: 0
","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"phys-btn/","level":1,"title":"Change behaviour of hardware buttons","text":"","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"phys-btn/#tasmota-rules","level":2,"title":"Tasmota Rules","text":"You can configure the buttons to mimic an UI element on the screen by configuring tasmota rules.
The following rule will change the behaviour of the two buttons to do page navigation.
Rule2 on Button1#state do Publish tele/%topic%/RESULT {\"CustomRecv\":\"event,buttonPress2,navPrev,button\"} endon on Button2#state do Publish tele/%topic%/RESULT {\"CustomRecv\":\"event,buttonPress2,navNext,button\"} endon\n\nRule2 1\n","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"phys-btn/#decouple-buttons-from-controlling-power-outputs","level":2,"title":"Decouple buttons from controlling power outputs","text":"If you do not want your NSPanel physical buttons to trigger the relays and prefer to have them as software configurable buttons, open the Tasmota console of your NSPanel and enter the following:
SetOption73 1
Your relays will now appear as switches in HomeAssistant and you can control your buttons by using automations:
You may reverse this change by entering the following in the Tasmota console of your NSPanel:
SetOption73 0
Please note: Doing this will mean that if HomeAssistant is not working for any reason your buttons will not function correctly.
","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"prepare_ha/","level":1,"title":"Setup Home Assistant","text":"","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-appdaemon","level":2,"title":"Installing AppDaemon","text":"The backend application for HomeAssistant is written in a python for AppDaemon. This means it requires a working and running installation of AppDaemon.
The easiest way to install it is through Home Assistant's Supervisor Add-on Store, it will be automaticly connected to your Home Assistant Instance.
Instructions for users of HomeAssistant Core installed through docker containers. In case you have a homeassistant setup using docker cotainers and the Add-on Store is not available to you, you can follow this guide for setting up AppDaemon. https://appdaemon.readthedocs.io/en/latest/DOCKER_TUTORIAL.html Please also pay attention to the correct volume mount for the conf folder of appdaemon, that has to point to the appdaemon folder within your homeassistant config folder. Here is an example docker compose file for homeassistant and appdaemon:version: \"3.5\"\nservices:\n homeassistant:\n image: ghcr.io/home-assistant/home-assistant:stable\n container_name: homeassistant\n network_mode: host\n volumes:\n - ./docker-data/homeassistant/:/config\n - /etc/localtime:/etc/localtime:ro\n environment:\n - TZ=Europe/Berlin\n privileged: true\n restart: unless-stopped\n\n appdaemon:\n container_name: appdaemon\n image: acockburn/appdaemon:4.2.3\n environment:\n - HA_URL=http://your-homeassistant-url:8123\n - TOKEN=\"xxxxxx\"\n volumes:\n - /etc/localtime:/etc/localtime:ro\n - ./docker-data/homeassistant/appdaemon:/conf\n depends_on:\n - homeassistant\n restart: unless-stopped\n","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#add-babel-package-to-appdaemon-container-optional","level":3,"title":"Add babel package to AppDaemon Container (Optional)","text":"For localisation (date in your local language) you need to add the python package babel to your AppDaemon Installation.
","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-studio-code-server","level":2,"title":"Installing Studio Code Server","text":"You will need a way to edit the apps.yaml config file in the Appdaemon folder. Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.
HACS is the Home Assistant Community Store and allows for community integrations and automations to be updated easily from the Home Assistant web user interface. You will be notified of updates, and they can be installed by a click on a button.
","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-lovelace-appdaemon-backend-application","level":2,"title":"Installing Lovelace AppDaemon Backend Application","text":"To install Lovelace UI Backend App with HACS, you will need to make sure that you enabled AppDaemon automations in HACS, as these are not enabled by default:
Configuration on the left menu bar in Home Assistant Web UIDevices & ServicesIntegrationsHACS and click on ConfigureEnable AppDaemon apps discovery & tracking is checked, or check it and click SubmitNow, to install NSPanel Lovelace UI Backend with HACS, follow these steps:
HACS on the left menu bar in Home Assistant Web UIAutomations in the right panelExplore & download repositories in the bottom right cornerNSPanel, and click on NSPanel Lovelace UI Backend in the list that appearsDownload this repository with HACSDownload, and wait for HACS to proceed with the downloadYou need to connect to your NSPanel via serial and flash Tasmota using tasmota32-nspanel.bin. You can use the Tasmota Web Installer to do so.
Check out Blakadder's Template Repo for more information on flashing. Do not use the autoexec.be from that page. NSPanel Page of the Tasmota Template Repository
If you prefer ESPHome over Tasmota, you can use this third-party ESPHome component, which replaces Tasmota and the Berry driver used in this project. ESPHome Component
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#configure-tasmota-template-for-nspanel","level":2,"title":"Configure Tasmota Template for NSPanel","text":"Configure the NSPanel template for Tasmota. (Go to Configuration > Configure Other, paste the template there, and make sure to tick the Activate checkbox.)
You can use the following template or copy the one from the Tasmota Template Repo Site:
{\"NAME\":\"NSPanel\",\"GPIO\":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],\"FLAG\":0,\"BASE\":1,\"CMND\":\"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1\"}
After a reboot of Tasmota, your screen will light up with the stock display firmware.
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#upload-berry-driver-to-tasmota","level":2,"title":"Upload Berry Driver to Tasmota","text":"Go to Consoles > Console in Tasmota and execute the following command:
Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0; Restart 1
This downloads the autoexec.be file from the repository and restarts Tasmota.
Note: This command also disables Matter to free up memory, as it's unlikely to be used by most Home Assistant users. (Matter can cause memory issues during flashing of the Nextion screen, but you can re-enable it later if needed.)
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#flash-firmware-to-nextion-screen","level":2,"title":"Flash Firmware to Nextion Screen","text":"Due to the limitations of Berry, it's not possible to download the TFT file directly from GitHub. A small server is available to download the file via HTTP.
Use one of the following commands in the Tasmota console (not the Berry console) to flash the latest release from this repository:
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
After sending the command, the screen should show a progress bar. The flashing process takes around 5 minutes.
Note for US users: You'll need to add the model config option to your apps.yaml later. More details can be found on the config overview page.
Alternatively, you can use your own web server or the one built into Home Assistant: Upload the nspanel.tft from the latest release to a web server (for example, the www folder of Home Assistant) and execute the following command in the Tasmota Console. (Development version: [TFT file from HMI folder](HMI/nspanel.tft)) **The web server must be HTTP. HTTPS is not supported due to Berry language limitations in Tasmota.** FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/","level":1,"title":"Flash Tasmota to your NSPanel","text":"You need to connect to your nspanel via serial and flash tasmota tasmota32-nspanel.bin to your NSPanel. You can use the Tasmota Web Installer to do so. Tasmota Web Installer
Checkout Blakadders Template Repo for more information on flashing, do not use the autoexec.be from this page. NSPanel Page of the Tasmota Template Repository
If you prefer EspHome over Tasmota, you can use this thrid party esphome component, which is replacing tasmota and the berry driver of this project. ESPHome component
","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#configure-tasmota-template-for-nspanel","level":2,"title":"Configure Tasmota Template for NSPanel","text":"Configure the NSPanel template for Tasmota. (Go to Configuration and Configure Other and paste the template there, make sure to tick the activate checkbox)
You can use the following template or copy the one on the Tasmota Template Repo Site.
{\"NAME\":\"NSPanel\",\"GPIO\":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],\"FLAG\":0,\"BASE\":1,\"CMND\":\"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1\"}
After a reboot of tasmota your screen will light up with the stock display firmware.
","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#upload-berry-driver-to-tasmota","level":2,"title":"Upload Berry Driver to Tasmota","text":"Go to Consoles > Console in Tasmota and execute the following command:
Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1\n","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#flash-firmware-to-nextion-screen","level":2,"title":"Flash Firmware to Nextion Screen","text":"Due the limitations of Berry, it's not possible to download the tft file directly from github, so I'm also renting a small server where you can download the file via HTTP.
Use the one following commands to flash the latest release from this repository, just execute the following Command in Tasmota:
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
You can configure entities with with the prefix navigate, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the previous page.
- entity: navigate.testKey\n will allow you to navigate to a cardGrid page with the configured key testKey
hiddenCards:\n - type: cardGrid\n title: Exmaple Grid\n entities:\n - entity: light.test_item\n key: testKey\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]},{"location":"subpages/#override-status-of-navigation-items","level":1,"title":"Override Status of Navigation Items","text":"You can override the status of navigation items, to make them look like different entities.
- entity: navigate.testKey\n status: climate.test\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]},{"location":"subpages/#override-navigation-items-itself","level":1,"title":"Override Navigation Items itself","text":" cards:\n - type: cardGrid\n title: Wohnzimmer\n navItem1:\n entity: light.bad_lights\n navItem2:\n entity: light.bad_lights\n entities:\n This can be used to add an home button to your subpages:
cards:\n - type: cardGrid\n title: Home\n key: home\n entities:\n - entity: light.bad\n\n hiddenCards:\n - type: cardGrid\n title: Wohnzimmer\n navItem2:\n entity: navigate.home\n icon: mdi:home\n entities:\n - entity: light.kitchen\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]}]}
\ No newline at end of file
diff --git a/sitemap.xml b/sitemap.xml
new file mode 100644
index 00000000..59676548
--- /dev/null
+++ b/sitemap.xml
@@ -0,0 +1,66 @@
+
+i&&s.push(r(n,i,d));let{value:h}=c[u];s.push(t(n,{start:d,end:i=m,value:h}))}return i{let o=n.data;switch(o.type){case 1:na.value=!0;break;case 3:typeof o.data.pagination.prev<"u"?it.value=He(H({},it.value),{pagination:o.data.pagination,items:[...it.value.items,...o.data.items]}):(it.value=o.data,ao(0));break}},qt(()=>{lr.value&&r.postMessage({type:0,data:lr.value})}),qt(()=>{na.value&&r.postMessage({type:2,data:Se.value})})}var oa={container:"p",hidden:"m"};function Mu(e){return z("div",{class:zt(oa.container,{[oa.hidden]:e.hidden}),onClick:()=>Dt()})}var ia={container:"r",disabled:"c"};function so(e){return z("button",{class:zt(ia.container,{[ia.disabled]:!e.onClick}),onClick:e.onClick,children:e.children})}var aa=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),ku=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,r,n)=>n?n.toUpperCase():r.toLowerCase()),sa=e=>{let t=ku(e);return t.charAt(0).toUpperCase()+t.slice(1)},Au=(...e)=>e.filter((t,r,n)=>!!t&&t.trim()!==""&&n.indexOf(t)===r).join(" ").trim(),Cu={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},Hu=c=>{var l=c,{color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:n,children:o,iconNode:i,class:a=""}=l,s=gr(l,["color","size","strokeWidth","absoluteStrokeWidth","children","iconNode","class"]);return Wt("svg",H(He(H({},Cu),{width:String(t),height:t,stroke:e,"stroke-width":n?Number(r)*24/Number(t):r,class:["lucide",a].join(" ")}),s),[...i.map(([u,p])=>Wt(u,p)),...Cr(o)])},bo=(e,t)=>{let r=a=>{var s=a,{class:n="",children:o}=s,i=gr(s,["class","children"]);return Wt(Hu,He(H({},i),{iconNode:t,class:Au(`lucide-${aa(sa(e))}`,`lucide-${aa(e)}`,n)}),o)};return r.displayName=sa(e),r},$u=bo("corner-down-left",[["path",{d:"M20 4v7a4 4 0 0 1-4 4H4",key:"6o5b7l"}],["path",{d:"m9 10-5 5 5 5",key:"1kshq7"}]]),Pu=bo("list-filter",[["path",{d:"M2 5h20",key:"1fs1ex"}],["path",{d:"M6 12h12",key:"8npq4p"}],["path",{d:"M9 19h6",key:"456am0"}]]),Iu=bo("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]),Yx=ml(dl(),1);function Ru({threshold:e=0,root:t=null,rootMargin:r="0%",freezeOnceVisible:n=!1,initialIsIntersecting:o=!1,onChange:i}={}){var a;let[s,c]=ro(null),[l,u]=ro(()=>({isIntersecting:o,entry:void 0})),p=Vt();p.current=i;let d=((a=l.entry)==null?void 0:a.isIntersecting)&&n;St(()=>{if(!s||!("IntersectionObserver"in window)||d)return;let v,S=new IntersectionObserver(x=>{let w=Array.isArray(S.thresholds)?S.thresholds:[S.thresholds];x.forEach(_=>{let de=_.isIntersecting&&w.some(be=>_.intersectionRatio>=be);u({isIntersecting:de,entry:_}),p.current&&p.current(de,_),de&&n&&v&&(v(),v=void 0)})},{threshold:e,root:t,rootMargin:r});return S.observe(s),()=>{S.disconnect()}},[s,JSON.stringify(e),t,r,d,n]);let m=Vt(null);St(()=>{var v;!s&&(v=l.entry)!=null&&v.target&&!n&&!d&&m.current!==l.entry.target&&(m.current=l.entry.target,u({isIntersecting:o,entry:void 0}))},[s,l.entry,n,d,o]);let h=[c,!!l.isIntersecting,l.entry];return h.ref=h[0],h.isIntersecting=h[1],h.entry=h[2],h}var lt={container:"n",hidden:"l",content:"u",pop:"d",badge:"y",sidebar:"i",controls:"w",results:"k",loadmore:"z"};function ju(e){let{isIntersecting:t,ref:r}=Ru({threshold:0});St(()=>{t&&au()},[t]);let n=Vt(null);St(()=>{n.current&&typeof Se.value.page>"u"&&n.current.scrollTo({top:0,behavior:"smooth"})},[Se.value]);let o=za();return z("div",{class:zt(lt.container,{[lt.hidden]:e.hidden}),children:[z("div",{class:lt.content,children:[z("div",{class:lt.controls,children:[z(so,{onClick:Dt,children:z(Iu,{})}),z(Uu,{focus:!e.hidden}),z(so,{onClick:Wa,children:[z(Pu,{}),o.length>0&&z("span",{class:lt.badge,children:o.length})]})]}),z("div",{class:lt.results,ref:n,children:[z(Nu,{keyboard:!e.hidden}),z("div",{class:lt.loadmore,ref:r})]})]}),z("div",{class:zt(lt.sidebar,{[lt.hidden]:fu()}),children:z(Fu,{})})]})}var Et={container:"X",list:"j",heading:"F",title:"I",item:"o",active:"g",value:"R",count:"q"};function Fu(e){let t=pu();return t.sort((r,n)=>n.node.count-r.node.count),z("div",{class:Et.container,children:[z("h3",{class:Et.heading,children:"Filters"}),z("h4",{class:Et.title,children:"Tags"}),z("ol",{class:Et.list,children:t.map(r=>z("li",{class:zt(Et.item,{[Et.active]:su(r.node.value)}),onClick:()=>cu(r.node.value),children:[z("span",{class:Et.value,children:r.node.value}),z("span",{class:Et.count,children:r.node.count})]}))})]})}var ca={container:"f"};function Uu(e){let t=Vt(null);return St(()=>{var r,n;e.focus?(r=t.current)==null||r.focus():(n=t.current)==null||n.blur()},[e.focus]),z("div",{class:ca.container,children:z("input",{ref:t,type:"text",class:ca.content,value:hn(vo()),onInput:r=>Va(_u(r.currentTarget.value)),autocapitalize:"off",autocomplete:"off",autocorrect:"off",placeholder:"Search",spellcheck:!1,role:"combobox"})})}var ut={container:"b",heading:"A",item:"a",active:"h",wrapper:"B",actions:"s",title:"x",path:"t"};function Nu(e){var a;let t=iu(),r=lu(),n=dn(),o=Vt([]);St(()=>{let s=o.current[n];s&&s.scrollIntoView({block:"center",behavior:"smooth"})},[n]),Aa(e.keyboard,s=>{let c=dn();s.key==="ArrowDown"?(s.preventDefault(),ao(Math.min(c+1,r.length-1))):s.key==="ArrowUp"&&(s.preventDefault(),ao(Math.max(c-1,0)))},[e.keyboard]);let i=(a=uu())!=null?a:0;return z(ft,{children:[r.length>0&&z("h3",{class:ut.heading,children:[z("span",{class:ut.bubble,children:new Intl.NumberFormat("en-US").format(i)})," ","results"]}),z("ol",{class:ut.container,children:r.map((s,c)=>{var d;let l=Ka(t[s.id].title,s.matches.find(({field:m})=>m==="title")),u=Lu((d=t[s.id].path)!=null?d:[],s.matches.find(({field:m})=>m==="path")),p=t[s.id].location;if(mu()){let m=encodeURIComponent(vo()),[h,v]=p.split("#",2);p=`${h}?h=${m.replace(/%20/g,"+")}`,typeof v<"u"&&(p+=`#${v}`)}return z("li",{children:z("a",{ref:m=>{o.current[c]=m},href:p,onClick:()=>Dt(),class:zt(ut.item,{[ut.active]:c===dn()}),children:[z("div",{class:ut.wrapper,children:[z("h2",{class:ut.title,children:l}),z("menu",{class:ut.path,children:u.map(m=>z("li",{children:m}))})]}),z("nav",{class:ut.actions,children:z(so,{children:z($u,{})})})]})})})})]})}var Du={container:"e"};function Wu(e){return Aa(!0,t=>{var r,n,o;if((t.metaKey||t.ctrlKey)&&t.key==="k")t.preventDefault(),Dt();else if((t.metaKey||t.ctrlKey)&&t.key==="j")document.body.classList.toggle("dark");else if(t.key==="Enter"&&!sr()){t.preventDefault(),Dt();let i=dn(),a=(n=(r=it.value)==null?void 0:r.items[i])==null?void 0:n.id;(o=lr.value)!=null&&o.items[a].location&&(window.location.href=lr.value.items[a].location)}else t.key==="Escape"&&!sr()&&(t.preventDefault(),Dt())},[]),z("div",{class:Du.container,children:[z(Mu,{hidden:sr()}),z(ju,{hidden:sr()})]})}function Ya(e,t){ou(e),xl(z(Wu,{}),t)}function go(){Dt()}function Vu(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function zu(){return R(b(window,"compositionstart").pipe(f(()=>!0)),b(window,"compositionend").pipe(f(()=>!1))).pipe(J(!1))}function Ga(){let e=b(window,"keydown").pipe(f(t=>({mode:sr()?"global":"search",type:t.key,meta:t.ctrlKey||t.metaKey,claim(){t.preventDefault(),t.stopPropagation()}})),L(({mode:t,type:r})=>{if(t==="global"){let n=yt();if(typeof n!="undefined")return!Vu(n,r)}return!0}),xe());return zu().pipe(g(t=>t?y:e))}function Ye(){return new URL(location.href)}function mt(e,t=!1){if(X("navigation.instant")&&!t){let r=A("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function Ja(){return new I}function Xa(){return location.hash.slice(1)}function Za(e){let t=A("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function _o(e){return R(b(window,"hashchange"),e).pipe(f(Xa),J(Xa()),L(t=>t.length>0),se(1))}function Qa(e){return _o(e).pipe(f(t=>Le(`[id="${t}"]`)),L(t=>typeof t!="undefined"))}function Ir(e){let t=matchMedia(e);return an(r=>t.addListener(()=>r(t.matches))).pipe(J(t.matches))}function es(){let e=matchMedia("print");return R(b(window,"beforeprint").pipe(f(()=>!0)),b(window,"afterprint").pipe(f(()=>!1))).pipe(J(e.matches))}function yo(e,t){return e.pipe(g(r=>r?t():y))}function xo(e,t){return new U(r=>{let n=new XMLHttpRequest;return n.open("GET",`${e}`),n.responseType="blob",n.addEventListener("load",()=>{n.status>=200&&n.status<300?(r.next(n.response),r.complete()):r.error(new Error(n.statusText))}),n.addEventListener("error",()=>{r.error(new Error("Network error"))}),n.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(n.addEventListener("progress",o=>{var i;if(o.lengthComputable)t.progress$.next(o.loaded/o.total*100);else{let a=(i=n.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(o.loaded/+a*100)}}),t.progress$.next(5)),n.send(),()=>n.abort()})}function et(e,t){return xo(e,t).pipe(g(r=>r.text()),f(r=>JSON.parse(r)),se(1))}function xn(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/html")),se(1))}function ts(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/xml")),se(1))}var wo={drawer:G("[data-md-toggle=drawer]"),search:G("[data-md-toggle=search]")};function Eo(e,t){wo[e].checked!==t&&wo[e].click()}function wn(e){let t=wo[e];return b(t,"change").pipe(f(()=>t.checked),J(t.checked))}function rs(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function ns(){return R(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(f(rs),J(rs()))}function os(){return{width:innerWidth,height:innerHeight}}function is(){return b(window,"resize",{passive:!0}).pipe(f(os),J(os()))}function as(){return re([ns(),is()]).pipe(f(([e,t])=>({offset:e,size:t})),se(1))}function En(e,{viewport$:t,header$:r}){let n=t.pipe(fe("size")),o=re([n,r]).pipe(f(()=>xt(e)));return re([r,t,o]).pipe(f(([{height:i},{offset:a,size:s},{x:c,y:l}])=>({offset:{x:a.x-c,y:a.y-l+i},size:s})))}var qu=G("#__config"),mr=JSON.parse(qu.textContent);mr.base=`${new URL(mr.base,Ye())}`;function Ue(){return mr}function X(e){return mr.features.includes(e)}function Bt(e,t){return typeof t!="undefined"?mr.translations[e].replace("#",t.toString()):mr.translations[e]}function dt(e,t=document){return G(`[data-md-component=${e}]`,t)}function Ee(e,t=document){return P(`[data-md-component=${e}]`,t)}function Ku(e){let t=G(".md-typeset > :first-child",e);return b(t,"click",{once:!0}).pipe(f(()=>G(".md-typeset",e)),f(r=>({hash:__md_hash(r.innerHTML)})))}function ss(e){if(!X("announce.dismiss")||!e.childElementCount)return y;if(!e.hidden){let t=G(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return j(()=>{let t=new I;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Ku(e).pipe($(r=>t.next(r)),V(()=>t.complete()),f(r=>H({ref:e},r)))})}function Bu(e,{target$:t}){return t.pipe(f(r=>({hidden:r!==e})))}function cs(e,t){let r=new I;return r.subscribe(({hidden:n})=>{e.hidden=n}),Bu(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))}function To(e,t){return t==="inline"?A("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"})):A("div",{class:"md-tooltip",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"}))}function Tn(...e){return A("div",{class:"md-tooltip2",role:"dialog"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function ls(...e){return A("div",{class:"md-tooltip2",role:"tooltip"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function us(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("a",{href:r,class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}else return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("span",{class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}function ps(e){return A("button",{class:"md-code__button",title:Bt("clipboard.copy"),"data-clipboard-target":`#${e} > code`,"data-md-type":"copy"})}function fs(){return A("button",{class:"md-code__button",title:"Toggle line selection","data-md-type":"select"})}function ms(){return A("nav",{class:"md-code__nav"})}var Ju=_r(So());function hs(e){return A("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>A("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?Li(r):r)))}function Oo(e){let t=`tabbed-control tabbed-control--${e}`;return A("div",{class:t,hidden:!0},A("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function vs(e){return A("div",{class:"md-typeset__scrollwrap"},A("div",{class:"md-typeset__table"},e))}function Xu(e){var n;let t=Ue(),r=new URL(`../${e.version}/`,t.base);return A("li",{class:"md-version__item"},A("a",{href:`${r}`,class:"md-version__link"},e.title,((n=t.version)==null?void 0:n.alias)&&e.aliases.length>0&&A("span",{class:"md-version__alias"},e.aliases[0])))}function bs(e,t){var n;let r=Ue();return e=e.filter(o=>{var i;return!((i=o.properties)!=null&&i.hidden)}),A("div",{class:"md-version"},A("button",{class:"md-version__current","aria-label":Bt("select.version")},t.title,((n=r.version)==null?void 0:n.alias)&&t.aliases.length>0&&A("span",{class:"md-version__alias"},t.aliases[0])),A("ul",{class:"md-version__list"},e.map(Xu)))}var Zu=0;function Qu(e,t=250){let r=re([ir(e),Ft(e,t)]).pipe(f(([o,i])=>o||i),ie()),n=j(()=>Ai(e)).pipe(oe(Ut),Lr(1),Ze(r),f(()=>Ci(e)));return r.pipe(Sr(o=>o),g(()=>re([r,n])),f(([o,i])=>({active:o,offset:i})),xe())}function Rr(e,t,r=250){let{content$:n,viewport$:o}=t,i=`__tooltip2_${Zu++}`;return j(()=>{let a=new I,s=new jn(!1);a.pipe(he(),ye(!1)).subscribe(s);let c=s.pipe(Tr(u=>Ve(+!u*250,Nn)),ie(),g(u=>u?n:y),$(u=>u.id=i),xe());re([a.pipe(f(({active:u})=>u)),c.pipe(g(u=>Ft(u,250)),J(!1))]).pipe(f(u=>u.some(p=>p))).subscribe(s);let l=s.pipe(L(u=>u),pe(c,o),f(([u,p,{size:d}])=>{let m=e.getBoundingClientRect(),h=m.width/2;if(p.role==="tooltip")return{x:h,y:8+m.height};if(m.y>=d.height/2){let{height:v}=Ae(p);return{x:h,y:-16-v}}else return{x:h,y:16+m.height}}));return re([c,a,l]).subscribe(([u,{offset:p},d])=>{u.style.setProperty("--md-tooltip-host-x",`${p.x}px`),u.style.setProperty("--md-tooltip-host-y",`${p.y}px`),u.style.setProperty("--md-tooltip-x",`${d.x}px`),u.style.setProperty("--md-tooltip-y",`${d.y}px`),u.classList.toggle("md-tooltip2--top",d.y<0),u.classList.toggle("md-tooltip2--bottom",d.y>=0)}),s.pipe(L(u=>u),pe(c,(u,p)=>p),L(u=>u.role==="tooltip")).subscribe(u=>{let p=Ae(G(":scope > *",u));u.style.setProperty("--md-tooltip-width",`${p.width}px`),u.style.setProperty("--md-tooltip-tail","0px")}),s.pipe(ie(),Ie(je),pe(c)).subscribe(([u,p])=>{p.classList.toggle("md-tooltip2--active",u)}),re([s.pipe(L(u=>u)),c]).subscribe(([u,p])=>{p.role==="dialog"?(e.setAttribute("aria-controls",i),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",i)}),s.pipe(L(u=>!u)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Qu(e,r).pipe($(u=>a.next(u)),V(()=>a.complete()),f(u=>H({ref:e},u)))})}function Ge(e,{viewport$:t},r=document.body){return Rr(e,{content$:new U(n=>{let o=e.title,i=ls(o);return n.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",o)}}),viewport$:t},0)}function ep(e,t){let r=j(()=>re([Hi(e),Ut(t)])).pipe(f(([{x:n,y:o},i])=>{let{width:a,height:s}=Ae(e);return{x:n-i.x+a/2,y:o-i.y+s/2}}));return ir(e).pipe(g(n=>r.pipe(f(o=>({active:n,offset:o})),Me(+!n||1/0))))}function gs(e,t,{target$:r}){let[n,o]=Array.from(e.children);return j(()=>{let i=new I,a=i.pipe(he(),ye(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),wt(e).pipe(Q(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),R(i.pipe(L(({active:s})=>s)),i.pipe(Be(250),L(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(n):n.remove()},complete(){e.prepend(n)}}),i.pipe(Xe(16,je)).subscribe(({active:s})=>{n.classList.toggle("md-tooltip--active",s)}),i.pipe(Lr(125,je),L(()=>!!e.offsetParent),f(()=>e.offsetParent.getBoundingClientRect()),f(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),b(o,"click").pipe(Q(a),L(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),b(o,"mousedown").pipe(Q(a),pe(i)).subscribe(([s,{active:c}])=>{var l;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(c){s.preventDefault();let u=e.parentElement.closest(".md-annotation");u instanceof HTMLElement?u.focus():(l=yt())==null||l.blur()}}),r.pipe(Q(a),L(s=>s===n),It(125)).subscribe(()=>e.focus()),ep(e,t).pipe($(s=>i.next(s)),V(()=>i.complete()),f(s=>H({ref:e},s)))})}function tp(e){let t=Ue();if(e.tagName!=="CODE")return[e];let r=[".c",".c1",".cm"];if(t.annotate){let n=e.closest("[class|=language]");if(n)for(let o of Array.from(n.classList)){if(!o.startsWith("language-"))continue;let[,i]=o.split("-");i in t.annotate&&r.push(...t.annotate[i])}}return P(r.join(", "),e)}function rp(e){let t=[];for(let r of tp(e)){let n=[],o=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=o.nextNode();i;i=o.nextNode())n.push(i);for(let i of n){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,c]=a;if(typeof c=="undefined"){let l=i.splitText(a.index);i=l.splitText(s.length),t.push(l)}else{i.textContent=s,t.push(i);break}}}}return t}function _s(e,t){t.append(...Array.from(e.childNodes))}function Sn(e,t,{target$:r,print$:n}){let o=t.closest("[id]"),i=o==null?void 0:o.id,a=new Map;for(let s of rp(t)){let[,c]=s.textContent.match(/\((\d+)\)/);Le(`:scope > li:nth-child(${c})`,e)&&(a.set(c,us(c,i)),s.replaceWith(a.get(c)))}return a.size===0?y:j(()=>{let s=new I,c=s.pipe(he(),ye(!0)),l=[];for(let[u,p]of a)l.push([G(".md-typeset",p),G(`:scope > li:nth-child(${u})`,e)]);return n.pipe(Q(c)).subscribe(u=>{e.hidden=!u,e.classList.toggle("md-annotation-list",u);for(let[p,d]of l)u?_s(p,d):_s(d,p)}),R(...[...a].map(([,u])=>gs(u,t,{target$:r}))).pipe(V(()=>s.complete()),xe())})}function ys(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return ys(t)}}function xs(e,t){return j(()=>{let r=ys(e);return typeof r!="undefined"?Sn(r,e,t):y})}var Es=_r(Mo());var np=0,ws=R(b(window,"keydown").pipe(f(()=>!0)),R(b(window,"keyup"),b(window,"contextmenu")).pipe(f(()=>!1))).pipe(J(!1),se(1));function Ts(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Ts(t)}}function op(e){return Re(e).pipe(f(({width:t})=>({scrollable:Mr(e).width>t})),fe("scrollable"))}function Ss(e,t){let{matches:r}=matchMedia("(hover)"),n=j(()=>{let o=new I,i=o.pipe(Bn(1));o.subscribe(({scrollable:m})=>{m&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[],s=e.closest("pre"),c=s.closest("[id]"),l=c?c.id:np++;s.id=`__code_${l}`;let u=[],p=e.closest(".highlight");if(p instanceof HTMLElement){let m=Ts(p);if(typeof m!="undefined"&&(p.classList.contains("annotate")||X("content.code.annotate"))){let h=Sn(m,e,t);u.push(Re(p).pipe(Q(i),f(({width:v,height:S})=>v&&S),ie(),g(v=>v?h:y)))}}let d=P(":scope > span[id]",e);if(d.length&&(e.classList.add("md-code__content"),e.closest(".select")||X("content.code.select")&&!e.closest(".no-select"))){let m=+d[0].id.split("-").pop(),h=fs();a.push(h),X("content.tooltips")&&u.push(Ge(h,{viewport$}));let v=b(h,"click").pipe(Or(M=>!M,!1),$(()=>h.blur()),xe());v.subscribe(M=>{h.classList.toggle("md-code__button--active",M)});let S=me(d).pipe(oe(M=>Ft(M).pipe(f(O=>[M,O]))));v.pipe(g(M=>M?S:y)).subscribe(([M,O])=>{let N=Le(".hll.select",M);if(N&&!O)N.replaceWith(...Array.from(N.childNodes));else if(!N&&O){let ee=document.createElement("span");ee.className="hll select",ee.append(...Array.from(M.childNodes).slice(1)),M.append(ee)}});let x=me(d).pipe(oe(M=>b(M,"mousedown").pipe($(O=>O.preventDefault()),f(()=>M)))),w=v.pipe(g(M=>M?x:y),pe(ws),f(([M,O])=>{var ee;let N=d.indexOf(M)+m;if(O===!1)return[N,N];{let le=P(".hll",e).map(ce=>d.indexOf(ce.parentElement)+m);return(ee=window.getSelection())==null||ee.removeAllRanges(),[Math.min(N,...le),Math.max(N,...le)]}})),_=_o(y).pipe(L(M=>M.startsWith(`__codelineno-${l}-`)));_.subscribe(M=>{let[,,O]=M.split("-"),N=O.split(":").map(le=>+le-m+1);N.length===1&&N.push(N[0]);for(let le of P(".hll:not(.select)",e))le.replaceWith(...Array.from(le.childNodes));let ee=d.slice(N[0]-1,N[1]);for(let le of ee){let ce=document.createElement("span");ce.className="hll",ce.append(...Array.from(le.childNodes).slice(1)),le.append(ce)}}),_.pipe(Me(1),Ie(ge)).subscribe(M=>{if(M.includes(":")){let O=document.getElementById(M.split(":")[0]);O&&setTimeout(()=>{let N=O,ee=-64;for(;N!==document.body;)ee+=N.offsetTop,N=N.offsetParent;window.scrollTo({top:ee})},1)}});let be=me(P('a[href^="#__codelineno"]',p)).pipe(oe(M=>b(M,"click").pipe($(O=>O.preventDefault()),f(()=>M)))).pipe(Q(i),pe(ws),f(([M,O])=>{let ee=+G(`[id="${M.hash.slice(1)}"]`).parentElement.id.split("-").pop();if(O===!1)return[ee,ee];{let le=P(".hll",e).map(ce=>+ce.parentElement.id.split("-").pop());return[Math.min(ee,...le),Math.max(ee,...le)]}}));R(w,be).subscribe(M=>{let O=`#__codelineno-${l}-`;M[0]===M[1]?O+=M[0]:O+=`${M[0]}:${M[1]}`,history.replaceState({},"",O),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+O,oldURL:window.location.href}))})}if(Es.default.isSupported()&&(e.closest(".copy")||X("content.code.copy")&&!e.closest(".no-copy"))){let m=ps(s.id);a.push(m),X("content.tooltips")&&u.push(Ge(m,{viewport$}))}if(a.length){let m=ms();m.append(...a),s.insertBefore(m,e)}return op(e).pipe($(m=>o.next(m)),V(()=>o.complete()),f(m=>H({ref:e},m)),Rt(R(...u).pipe(Q(i))))});return X("content.lazy")?wt(e).pipe(L(o=>o),Me(1),g(()=>n)):n}function ip(e,{target$:t,print$:r}){let n=!0;return R(t.pipe(f(o=>o.closest("details:not([open])")),L(o=>e===o),f(()=>({action:"open",reveal:!0}))),r.pipe(L(o=>o||!n),$(()=>n=e.open),f(o=>({action:o?"open":"close"}))))}function Os(e,t){return j(()=>{let r=new I;return r.subscribe(({action:n,reveal:o})=>{e.toggleAttribute("open",n==="open"),o&&e.scrollIntoView()}),ip(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))})}var Ls=0,Ms=new Map;function ap(e){let t=document.createElement("h3");t.innerHTML=e.innerHTML;let r=[t],n=e.nextElementSibling;for(;n&&!(n instanceof HTMLHeadingElement);)r.push(n.cloneNode(!0)),n=n.nextElementSibling;return r}function sp(e,t){for(let r of P("[href], [src]",e))for(let n of["href","src"]){let o=r.getAttribute(n);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){r[n]=new URL(r.getAttribute(n),t).toString();break}}for(let r of P("[name^=__], [for]",e))for(let n of["id","for","name"]){let o=r.getAttribute(n);o&&r.setAttribute(n,`${o}$preview_${Ls}`)}return Ls++,Y(e)}function cp(e){let t=Ms.get(e.toString());return t?Y(t):xn(e).pipe(g(r=>sp(r,e)),f(r=>(Ms.set(e.toString(),r),r)))}function ks(e,t){let{sitemap$:r}=t;if(!(e instanceof HTMLAnchorElement))return y;if(!(X("navigation.instant.preview")||e.hasAttribute("data-preview")))return y;e.removeAttribute("title");let n=re([ir(e),Ft(e).pipe(ke(1))]).pipe(f(([i,a])=>i||a),ie(),L(i=>i));return $t([r,n]).pipe(g(([i])=>{let a=new URL(e.href);return a.search=a.hash="",i.has(`${a}`)?Y(a):y}),g(i=>cp(i)),g(i=>{let a=e.hash?`article [id="${e.hash.slice(1)}"]`:"article h1",s=Le(a,i);return typeof s=="undefined"?y:Y(ap(s))})).pipe(g(i=>{let a=new U(s=>{let c=Tn(...i);return s.next(c),document.body.append(c),()=>c.remove()});return Rr(e,H({content$:a},t))}))}var As=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color)}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs marker.marker.composition.class path,defs marker.marker.dependency.class path,defs marker.marker.extension.class path{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs marker.marker.aggregation.class path{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}[id^=entity] path,[id^=entity] rect{fill:var(--md-default-bg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs .marker.oneOrMore.er *,defs .marker.onlyOne.er *,defs .marker.zeroOrMore.er *,defs .marker.zeroOrOne.er *{stroke:var(--md-mermaid-edge-color)!important}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var ko,up=0;function pp(){return typeof mermaid=="undefined"||mermaid instanceof Element?ar("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):Y(void 0)}function Cs(e){return e.classList.remove("mermaid"),ko||(ko=pp().pipe($(()=>mermaid.initialize({startOnLoad:!1,themeCSS:As,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),f(()=>{}),se(1))),ko.subscribe(()=>Uo(null,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${up++}`,r=A("div",{class:"mermaid"}),n=e.textContent,{svg:o,fn:i}=yield mermaid.render(t,n),a=r.attachShadow({mode:"closed"});a.innerHTML=o,e.replaceWith(r),i==null||i(a)})),ko.pipe(f(()=>({ref:e})))}var Hs=A("table");function $s(e){return e.replaceWith(Hs),Hs.replaceWith(vs(e)),Y({ref:e})}function fp(e){let t=e.find(r=>r.checked)||e[0];return R(...e.map(r=>b(r,"change").pipe(f(()=>G(`label[for="${r.id}"]`))))).pipe(J(G(`label[for="${t.id}"]`)),f(r=>({active:r})))}function Ps(e,{viewport$:t,target$:r}){let n=G(".tabbed-labels",e),o=P(":scope > input",e),i=Oo("prev");e.append(i);let a=Oo("next");return e.append(a),j(()=>{let s=new I,c=s.pipe(he(),ye(!0));re([s,Re(e),wt(e)]).pipe(Q(c),Xe(1,je)).subscribe({next([{active:l},u]){let p=xt(l),{width:d}=Ae(l);e.style.setProperty("--md-indicator-x",`${p.x}px`),e.style.setProperty("--md-indicator-width",`${d}px`);let m=ln(n);(p.x List of supported config keys of this card: List of supported config keys of this card: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: The first two entities are shown in the middle of the card, all other entities are used around it. Any entity overrides (e.g. icon, color) in the first entity apply to the middle of the card. List of supported config keys of this card: List of supported entitiy types for this page: N.B. Negative values will likely be truncated and not display gracefully. For this reason, when measuring energy you should use the same inputs as you use on the Home Assistant Energy Dashboard (i.e. separate grid import and grid export) and similarly when measuring power. Some details about speed: Speed expects an integer input between It is possible to calculate the speed through a Home Assistant template, this allows to calculate the speed in relation to other data in Home Assistant. This template will calculate a speed setting based on the amount of power drawn on a device as a fraction of the total power usage.
+ List of supported config keys of this card: List of supported entitiy types for this page: The qrCode value is evaluated as a homeassistant Template, so it is possible to get values from HomeAssistant within the qrCode. Can be used to navigate to create pin locked navigation to a hidden card. List of supported config keys of this card: This page compares the legacy AppDaemon For the full rewrite docs, including full key descriptions, see: Old AppDaemon version: Standalone rewrite: Old ( New ( If you are migrating now, use the standalone migration page for the complete mapping: To confiure your NSPanel to your needs, you need to edit the If you've sucessfully set up mqtt, you should already have a configuration looking like this: You can continue from this point adding configuration for the weather forcecast on the screensaver, configuring a schedule for the brightness of the screensaver and your first cards. This is the full list of configuration options supported for the config key: It is possible to schedule a brightness change for the screen at specific times. It is also possible to use a static value or an input_number/sensor with the range between 0 and 100 as value for sleepBrightness/screenBrightness: The config option The config option The following example configuration is turning off the screen after sunset, but in case the bedroom light is on the NSPanel brightness will be 20 instead of 0. In case you need to change the OTA URLs to do automatic updates without internet access for tasmota, you can modify the OTA URLs: Example for the a screensaver config with custom entities/overrides: Using a 6th entity will automatically activate the alternative layout. You can use override the options described on the entities documentation page to override colors, names or values of the entities. With Version 4.0.0 there is another alternative layout for the screensaver: Configuration is similar, you just need to add Specify colours as red green and blue values from 0-255 e.g. Example for the theme config: It is possible to increase the size of the font used for the icons by adding Configure your MQTT Server in Tasmota.
+See Tasmota MQTT Documentation for more details. Please leave the Full Topic as it is in default configuration (and on the screenshot). Change the topic to something unique for your panel, you will need this topic later in the configuration of your panel in appdaemon / apps.yaml The configuration has been moved out of the config folder from homeassistant. This is how you can access it with the VSCode Addon. For the app to work you need a working MQTT Configuration in AppDaemon. Please add the configuration of your mqtt server, user and password to your existing You will find this file in the following location: Please add the following minimal configuration to your apps.yaml, which is located in Note: You need to move your Please adjust If your configuration is correct you should get the following screens on your panel: Entities are mainly used on cardEntities and cardGrid. It is possible to overwrite and configure varrious things on Entities. To overwrite Icons or Names of entities you can configure an icon and/or name in your configuration, please see the following example.
+Only the icons listed in the Icon Cheatsheet are useable. It is also possible to configure different icon overwrites per state: It is also possible to configure different color overwrites per state: It is also possible to use text instead of icons with Note: State Overrides are working with all state values, not only with "on" and "off". To insert dynamic values from a homeassistant template, like a temperature you can also use If you want to display icons from a template you can put them between This sensor will only be shown on the card if it's state is equal to This sensor will only be shown on the card if it's state is not equal to The template must evaluate to The following example shows how to call services directly, this enables you to call services on entities not (yet) supported by the backend and also to pass data to services. You have most likely an error in your MQTT configuration somewhere. To find the error follow theese steps: Check the location of your apps.yaml
+With the AppDaemon Addon >= 15 the config dir has been moved.
+It's required to configure the location back to the old one, this is done by the Check your appdaemon log. (Settings > Add-ons > AppDaemon > Log)
+You should see something like this:
+ Check MQTT Configuration of Tasmota.
+Your Tasmota device needs to connect sucessfully to your MQTT Broker, if you are in the waiting for content screen, the panel will send periodic messages to it's mqtt topic. Note that there is a minimum password length of 5 chars for the MQTT Connection in Tasmota. Make sure that you are using the same topic in apps.yaml and in your tasmota configuration.
+The examples in the docs (MQTT Config) are an valid example (tasmota<>apps.yaml). If you are still in the waiting for content screen please share the following items, with the Waiting for Content Issue type on the Github Issues Page HACS will show you that there is an update avalible and ask you to update. It is important to restart the AppDaemon Container afterwards. You should get an notification on the screen, asking you to update the firmware. In case you want to update manually you can use the following commands. EU Version: US Version Portrait: US Version Landscape: You should get an notification on the screen, asking you to update the driver, if an update is needed. You can update the berry driver directly from the Tasmota Console with the following command. Click redownload in the menu of the app in HACS. Select main version. !!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!! !!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!! Click download. Restart AppDaemon Flash current Development Firmware in Tasmota Console. DO NOT USE THIS VERSION/URLS IF YOUR ARE NOT ON THE DEVELOPMENT VERSION EU VERSION: Development happens in the EU version, so it is possible that the US Version isn't up to date with the current development version of the EU firmware, the lastet US versions are still downloadable with the following links: US LANDSCAPE: US PORTRAIT: The HMI Project of this project is only used to display stuff, navigation ist mostly up to the backend. This allows to be way more flexible. Messages to the Panel can be send through the Command On startup the panel will send You can answer this message in many different ways, but in general the goal is to navigate way from the startup page. In the following example we will navigate to the screensaver page. Send the following messages to the CustomSend Topic. (You can also send them on tasmota console for testing) Send this every minute: Send this at least once at midnight: Send theese message once after receiving the startup event (parameters will be explained later): After sending this command you should already see the time and date.
+To also show weather data you have to send them with weatherUpdate, but we will skip this for now. Touching the panel on the screensaver will result in this MQTT Message on the result topic: You can answer this by sending theese commands to the CustomSend Topic. set brightness of screensaver and active-brightness: set current time: set current date: set screensaver timeout (set time in sec~ max 65): change the page type: Structure (Category): Possible entities on cardEntities/cardGrid: cardGrid is using the exact same messageformat like cardEntities does. The only difference is, it ignores the information supplied in optionalValue, because it isn't needed for cardGrid. Example without icons in bottom row: Serial Protocol of cardThermo is about to change; table will be completed later Example: options are ? seperated editable is 0 or 1 action fields are in the answer on the button press in case action is empty the button will be hidden Payload length contains the number of bytes of the payload. CRC is "CRC-16 (MODBUS) Big Endian" calculated over the whole message This protocol does not try to implement broken JSON Commands with a specified type (lol).
+Instead the commands are plain text commands with parameters. This message has to be generated for the Message "1337" (1337 is not a valid command~ this is just an example) Thanks to aderusha for this great nextion font: Generate-HASP-Fonts
+ Deprecated icons will be removed in a future major release.
+ If you like this project consider buying me a pizza 🍕 NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in the Design of HomeAssistant's Lovelace UI Design. EU Model and US Model supported (in portrait and landscape orientation) Content of the screen is controlled by a AppDaemon Python Script installed on your HomeAssistant Instance. Or an TypeScript on your ioBroker Instance in case you are an ioBroker User. NsPanel needs to be flashed with Tasmota (or with the 3rd Party ESPHome Component from @sairon) Localization (currently 40 languages) Everything is dynamically configurable by a yaml config, no need to code or touch Nextion Editor It works with Tasmota and MQTT.
+To control the panel and update it with content from HomeAssistant there is an AppDaemon App. See the following picture to get an idea of the look of this firmware for NSPanel. Some (not all) screenshots from the US Portrait Version: The Backend for ioBroker is maintained by britzelpuf and armilar See the wiki for documentation around setting lovelace-ui up with ioBroker Also see the Readme in the ioBroker Folder.
+iobroker ReadMe There are two notification types, that can be triggered by sending a command over mqtt to the panel here are examples for homeassistant scripts: This is the notification used by the backend for updates, opening it requires to the following commands to the CustomSend Topic: Alternative Layout with Icon: You need to use the acual char for the icon instead of the icon name which is used in the configuration. You can get the char of the icon from the cheatsheet. https://docs.nspanel.pky.eu/icon-cheatsheet.html It is possible to exit from the page by sending If you want to add newlines to your message add this string for the newline Send Message to the Panel combined with a buzzer sound: Send Message to the Panel: The screensaver can display Notifications by sending this command to the CustomSend topic: Send Message to the Screensaver combined with a buzzer sound: Send Message to the Screensaver: See Tasmota Buzzer for commands. It might be necessary to enable the buzzer with:
+ Decimal RGB565: 0 You can configure the buttons to mimic an UI element on the screen by configuring tasmota rules. The following rule will change the behaviour of the two buttons to do page navigation. If you do not want your NSPanel physical buttons to trigger the relays and prefer to have them as software configurable buttons, open the Tasmota console of your NSPanel and enter the following: Your relays will now appear as switches in HomeAssistant and you can control your buttons by using automations: You may reverse this change by entering the following in the Tasmota console of your NSPanel: Please note: Doing this will mean that if HomeAssistant is not working for any reason your buttons will not function correctly. The backend application for HomeAssistant is written in a python for AppDaemon.
+This means it requires a working and running installation of AppDaemon. The easiest way to install it is through Home Assistant's Supervisor Add-on Store, it will be automaticly connected to your Home Assistant Instance. For localisation (date in your local language) you need to add the python package babel to your AppDaemon Installation. You will need a way to edit the HACS is the Home Assistant Community Store and allows for community integrations and
+automations to be updated easily from the Home Assistant web user interface.
+You will be notified of updates, and they can be installed by a click on a button. To install Lovelace UI Backend App with HACS, you will need to make sure that you enabled
+AppDaemon automations in HACS, as these are not enabled by default: Now, to install NSPanel Lovelace UI Backend with HACS, follow these steps: You need to connect to your NSPanel via serial and flash Tasmota using tasmota32-nspanel.bin. Check out Blakadder's Template Repo for more information on flashing. Do not use the autoexec.be from that page. If you prefer ESPHome over Tasmota, you can use this third-party ESPHome component, which replaces Tasmota and the Berry driver used in this project. Configure the NSPanel template for Tasmota. (Go to Configuration > Configure Other, paste the template there, and make sure to tick the Activate checkbox.) You can use the following template or copy the one from the Tasmota Template Repo Site: {"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"} After a reboot of Tasmota, your screen will light up with the stock display firmware. Go to Consoles > Console in Tasmota and execute the following command: Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0; Restart 1 This downloads the autoexec.be file from the repository and restarts Tasmota. Note: This command also disables Matter to free up memory, as it's unlikely to be used by most Home Assistant users. (Matter can cause memory issues during flashing of the Nextion screen, but you can re-enable it later if needed.) Due to the limitations of Berry, it's not possible to download the TFT file directly from GitHub. A small server is available to download the file via HTTP. Use one of the following commands in the Tasmota console (not the Berry console) to flash the latest release from this repository: EU Version: US Version Portrait: US Version Landscape: After sending the command, the screen should show a progress bar. The flashing process takes around 5 minutes. Note for US users: You'll need to add the model config option to your apps.yaml later. More details can be found on the config overview page. You need to connect to your nspanel via serial and flash tasmota tasmota32-nspanel.bin to your NSPanel.
+You can use the Tasmota Web Installer to do so. Tasmota Web Installer Checkout Blakadders Template Repo for more information on flashing, do not use the autoexec.be from this page.
+NSPanel Page of the Tasmota Template Repository If you prefer EspHome over Tasmota, you can use this thrid party esphome component, which is replacing tasmota and the berry driver of this project.
+ESPHome component Configure the NSPanel template for Tasmota. (Go to Configuration and Configure Other and paste the template there, make sure to tick the activate checkbox) You can use the following template or copy the one on the Tasmota Template Repo Site. After a reboot of tasmota your screen will light up with the stock display firmware. Go to Due the limitations of Berry, it's not possible to download the tft file directly from github, so I'm also renting a small server where you can download the file via HTTP. Use the one following commands to flash the latest release from this repository, just execute the following Command in Tasmota: EU Version: US Version Portrait: US Version Landscape: If you like this project consider buying me a pizza 🍕 NsPanel Lovelace UI is a Firmware for the nextion screen inside of NSPanel in the Design of HomeAssistant's Lovelace UI Design. EU Model and US Model supported (in portrait and landscape orientation) Content of the screen is controlled by a AppDaemon Python Script installed on your HomeAssistant Instance. Or an TypeScript on your ioBroker Instance in case you are an ioBroker User. NsPanel needs to be flashed with Tasmota (or with the 3rd Party ESPHome Component from @sairon) Localization (currently 40 languages) Everything is dynamically configurable by a yaml config, no need to code or touch Nextion Editor It works with Tasmota and MQTT. To control the panel and update it with content from HomeAssistant there is an AppDaemon App. See the following picture to get an idea of the look of this firmware for NSPanel. Some (not all) screenshots from the US Portrait Version: List of supported config keys of this card: List of supported config keys of this card: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: List of supported entitiy types for this page: List of supported config keys of this card: The first two entities are shown in the middle of the card, all other entities are used around it. Any entity overrides (e.g. icon, color) in the first entity apply to the middle of the card. List of supported config keys of this card: List of supported entitiy types for this page: N.B. Negative values will likely be truncated and not display gracefully. For this reason, when measuring energy you should use the same inputs as you use on the Home Assistant Energy Dashboard (i.e. separate grid import and grid export) and similarly when measuring power. Some details about speed: Speed expects an integer input between It is possible to calculate the speed through a Home Assistant template, this allows to calculate the speed in relation to other data in Home Assistant. This template will calculate a speed setting based on the amount of power drawn on a device as a fraction of the total power usage. =t.count.fields)return{documents:r,terms:l};let o=t.shards[n];return e.forEach(a=>{let{occurrences:s}=o.terms[a];for(let u=0;uAlarm Card¶
+
cards:
+ - type: cardAlarm
+ title: Alarm Test 1
+ entity: alarm_control_panel.alarmo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+entityFalse
+string
+
+Nonecontains the entity of the current card
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+alarmControlTrue
+complex
+
+Noneoverwrites the action executed on pressing the left bottom icon, by default this button is used to show a list of open sensors on a failed attempt to arm.
+
+
+
+
+supportedModesTrue
+list
+
+NoneSupply list of arm modes if you want to limit the modes on the card. Example
+['arm_away', 'arm_night']Climate/Thermo Card¶
+
cards:
+ - type: cardThermo
+ title: HeatPump
+ entity: climate.heatpump
+ - type: cardThermo
+ title: HvaC
+ entity: climate.hvac
+ - type: cardThermo
+ title: ecobee
+ entity: climate.ecobee
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entityFalse
+string
+
+Nonecontains the entitiy of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+temperatureUnitTrue
+string
+
+celsiusset this to fahrenheit to change the temperatureUnit on the page
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+supportedModesTrue
+list
+
+NoneSupply list of heat actions if you want to limit the actions on the card. Example
+['heat', 'off']Entities Page¶
+
cards:
+ - type: cardEntities
+ title: Test Entities Card
+ entities:
+ - entity: light.bed_light
+ - entity: switch.decorative_lights
+ - entity: cover.hall_window
+ - entity: sensor.outside_temperature
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Grid Page¶
+
cards:
+ - type: cardGrid
+ title: Test Grid Card
+ entities:
+ - entity: light.bed_light
+ - entity: switch.decorative_lights
+ - entity: sensor.outside_temperature
+ name: Outside Temp
+ - entity: sensor.carbon_monoxide
+ - entity: light.entrance_color_white_lights
+ name: Entrance
+ - entity: light.office_rgbw_lights
+ name: Office RGBW
+ icon: mdi:office-building
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities of this card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items in combination with the type (cardEntities_key)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Media Card¶
+
cards:
+ - type: cardMedia
+ entity: media_player.spotify
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+entityFalse
+string
+
+Nonecontains the entity of the current card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains a list of entities shown in the bottom row, supports all entities supported by cardGrid
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+Example with configured Entities
+
+ - type: cardMedia
+ title: Kitchen
+ entity: media_player.kitchen
+ entities:
+ - entity: light.bed_light
+ - entity: light.ceiling_lights
+ - entity: light.entrance_color_white_lights
+ - entity: light.kitchen_lights
+ - entity: light.living_room_rgbww_lights
+Example with action on upper left media icon
+
+ - type: cardMedia
+ title: Kitchen
+ entity: input_select.test123
+ status: media_player.kitchen
+Example with moved spaker selection
+
+The icon for speaker selection is automatically appended to the end of the list and can be moved with entities in the list.
+With 6 entities it is possible to remove it entirely.
+ - type: cardMedia
+ title: Kitchen
+ entity: media_player.kitchen
+ entities:
+ - entity: delete
+ - entity: delete
+Power Card (v3.9 and higher)¶
+
cards:
+ - type: cardPower
+ title: Power Test
+ entities:
+ - entity: sensor.power_consumption
+ icon: mdi:home
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:car
+ speed: -20
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:battery
+ speed: 20
+ - entity: delete
+ - entity: sensor.today_energy
+ icon: mdi:solar-panel
+ color: [255, 255, 0]
+ speed: 30
+ - entity: sensor.today_energy
+ speed: -40
+ icon: mdi:help
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains entities of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+cooldownTrue
+float
+
+NoneRate Limit for Entity Updates to the card in Seconds (
+cooldown: 0.5)
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+-100 and 100. speed: >-
+ {% set entity_power = states('sensor.appliance_water_heater_power') |float | round(3)%}
+ {% set total_power = states('sensor.ams_power_active') | float | round(3) %}
+ {% set entity_usage = (entity_power / total_power * 100) | float %}
+ {{ (entity_usage | round()) * -1 }}
+ {{ (entity_usage | round()) }}
+WiFi / QR Card¶
+
cards:
+ - type: cardQR
+ title: Guest Wifi
+ qrCode: "WIFI:S:test_ssid;T:WPA;P:test_pw;;"
+ entities:
+ - entity: iText.test_ssid
+ name: Name
+ icon: mdi:wifi
+ - entity: iText.test_pw
+ name: Password
+ icon: mdi:key
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+entitiesFalse
+complex
+
+Nonecontains entities of the card, only valid on cardEntities and cardGrid and cardQR
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+
+qrCodeFalse
+string
+
+NoneValue of the qrCode
+
+
+"WIFI:S:{{states('input_text.test_ssid')}};T:WPA;P:{{states('input_text.test_pw')}};;"Unlock Card (v4.0 and higher)¶
+
cards:
+ - type: cardUnlock
+ pin: 1234
+ title: Admin Page
+ destination: navigate.adminpage
+ hiddenCards:
+ - type: cardGrid
+ title: Admin Page
+ key: adminpage
+ entities:
+ - entity: light.schreibtischlampe
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+typeFalse
+string
+
+NoneType of the card
+
+
+
+titleTrue
+string
+
+NoneTitle of the Page
+
+
+
+destinationFalse
+string
+
+Nonecontains the navigation entity this card should navigate to on unlock
+
+
+
+pinFalse
+string
+3830
+pin to unlock
+
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+Migration to Standalone Rewrite Config¶
+apps.yaml config with the standalone rewrite panels.yaml config.High-level differences¶
+
+
+apps.yaml with module / class / configappdaemon.yaml)
+
+/config/panels.yamlnspanelsMinimal before/after example¶
+apps.yaml):nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+panels.yaml):home_assistant_address: "http://supervisor"
+home_assistant_token: "YOUR_TOKEN"
+
+nspanels:
+ panel-1:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+ locale: en_US
+ timeZone: "Europe/Berlin"
+ timeFormat: "%H:%M"
+ dateFormat: "full"
+ screensaver:
+ entities:
+ - entity: weather.home
+ cards:
+ - type: cardEntities
+ title: Main
+ entities:
+ - entity: light.kitchen
+Important key changes¶
+
+
+
+
+
+
+
+Legacy key/concept
+Rewrite key/concept
+Notes
+
+
+
+module, class, config wrapperremoved
+Rewrite uses
+nspanels.<panel_name> directly.
+
+
+timezone
+timeZoneCasing changed.
+
+
+
+dateFormatBabel
+dateFormatUse
+dateFormat in rewrite.
+
+
+temperatureUnit (legacy card-level usage)
+temp_unit (panel-level)Rewrite reads
+temp_unit from panel settings.
+
+brightness schedule lists
+not supported
+Rewrite supports integer or entity id for brightness values.
+
+
+
+
+updateMode / OTA URL override keysnot supported
+Legacy update behavior is not part of rewrite config.
+Configuration¶
+apps.yaml inside of your Appdaemon config folder and add card and entities you want to display on the screen.---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+ sleepTimeout: 20
+ sleepBrightness:
+ - time: "7:00:00"
+ value: 10
+ - time: "23:00:00"
+ value: 0
+ locale: "de_DE"
+ screensaver:
+ entity: weather.k3ll3r
+ cards:
+ - type: cardEntities
+ entities:
+ - entity: switch.example_item
+ - entity: light.example_item
+ title: Example 1
+ - type: cardGrid
+ entities:
+ - entity: switch.example_item
+ - entity: light.example_item
+ title: Example 2
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+panelRecvTopicFalse
+string
+
+tele/tasmota_your_mqtt_topic/RESULTThe mqtt topic used to receive messages.
+
+
+
+panelSendTopicFalse
+string
+
+cmnd/tasmota_your_mqtt_topic/CustomSendThe mqtt topic used to send messages.
+
+
+
+updateModeTrue
+string
+
+auto-notifyUpdate Mode for flashing of the nextion display firmware, by default it is showing a message asking for the update after updating the backend app in HACS; Possible values: "auto", "auto-notify", "manual"
+
+
+
+modelTrue
+string
+
+euModel; Possible values: "eu", "us-l" and "us-p"
+
+
+
+sleepTimeoutTrue
+integer
+
+20Timeout for the screen to enter screensaver, to disable screensaver use 0
+
+
+
+sleepBrightnessTrue
+integer/complex
+
+20Brightness for the screen on the screensaver, see example below for complex/scheduled config.
+
+
+
+screenBrightnessTrue
+integer/complex
+
+100Brightness for the screen during usage, config format is the same as sleepBrightness.
+
+
+
+sleepTrackingTrue
+string
+None
+Forces screensaver brightness to 0 in case entity state is not_home or off, can be a group, person or device_tracker entity.
+
+
+
+sleepTrackingZonesTrue
+list
+
+["not_home", "off"]Allows you to set your own states for sleepTracking
+
+
+
+sleepOverrideTrue
+complex
+None
+Allows overriding of the sleepBrightness if entity state is on, true or home. Overrides sleepBrightness but sleepTracking takes precedence.
+
+
+
+localeTrue
+string
+
+en_USUsed by babel to determinante Date format on screensaver, also used for localization.
+
+
+
+dateFormatBabelTrue
+string
+
+fullformatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields
+
+
+
+timeFormatTrue
+string
+
+%H:%MTime Format on screensaver. Substring after
+? is displayed in a seperate smaller textbox. Useful for 12h time format with AM/PM "%I:%M ?%p"
+
+
+dateAdditionalTemplateTrue
+string
+
+""Addional Text dispayed after Date, can contain a Homeassistant Template Example
+" - {{ states('sun.sun') }}"
+
+
+timeAdditionalTemplateTrue
+string
+
+""Addional Text dispayed below Time, can contain a Homeassistant Template
+
+
+
+dateFormatTrue
+string
+
+%A, %d. %B %Ydate format used if babel is not installed
+
+
+
+timezoneTrue
+string
+""
+Timezone for the time on the panel:
+Europe/Berlin - See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of TZ Identifiers (supported from upcoming version v4.4)
+
+
+defaultBackgroundColorTrue
+string
+ha-dark
+backgroud color of all cards, valid values:
+black, ha-dark
+
+
+cardsFalse
+complex
+
+ configuration for cards that are displayed on panel; see docs for cards
+
+
+
+screensaverTrue
+complex
+
+ configuration for screensaver; see docs for screensaver
+
+
+
+
+hiddenCardsTrue
+complex
+
+ configuration for cards that can be accessed though navigate items; see docs for cards
+Details on sleepBrightness/screenBrightness and other configs related to screen brightness¶
+ sleepBrightness:
+ - time: "7:00:00"
+ value: 10
+ - time: "23:00:00"
+ value: 0
+ sleepBrightness:
+ - time: "sunrise"
+ value: 10
+ - time: "sunset + 1:00:00"
+ value: 0
+ sleepBrightness: input_number.brightness_nspanel
+ sleepBrightness: 50
+sleepTracking overrides this setting and sets the brightness to 0 if the state of the configured Home Assistant entity is off or not_home. You may also use a Home Assistant group to track multiple entities.sleepOverride overrides sleepBrightness but does not take precedence over sleepTracking. This is useful if, for example, you want your NSPanel to be brighter than usual if your light is on or if you want to override a panel dimming if you are in the room. sleepBrightness:
+ - time: "sunrise"
+ value: 20
+ - time: "sunset"
+ value: 0
+ sleepOverride:
+ entity: light.bedroomlight
+ brightness: 20
+Supported keys for locale config¶
+
+
+
+
+
+
+
+Language Code
+Language
+
+
+
+af_ZAAfrikaans
+
+
+
+ar_SYArabic
+
+
+
+bg_BGBulgarian
+
+
+
+ca_ESCatalan
+
+
+
+cs_CZCzech
+
+
+
+da_DKDanish
+
+
+
+de_DEGerman
+
+
+
+el_GRGreek
+
+
+
+en_USEnglish
+
+
+
+es_ESSpanish
+
+
+
+et_EEEstonian
+
+
+
+fa_IRPersian
+
+
+
+fi_FIFinnish
+
+
+
+fr_FRFrench
+
+
+
+he_ILHebrew
+
+
+
+hr_xxCroatian
+
+
+
+hu_HUHungarian
+
+
+
+hy_AMArmenian
+
+
+
+id_IDIndonesian
+
+
+
+is_ISIcelandic
+
+
+
+it_ITItalian
+
+
+
+lb_xxLuxembourgish
+
+
+
+lt_LTLithuanian
+
+
+
+lv_LVLatvian
+
+
+
+nb_NONorwegian
+
+
+
+nl_NLDutch
+
+
+
+nn_NONorwegian
+
+
+
+pl_PLPolish
+
+
+
+pt_PTPortuguese
+
+
+
+ro_RORomanian
+
+
+
+ru_RURussian
+
+
+
+sk_SKSlovak
+
+
+
+sl_SISlovenian
+
+
+
+sv_SESwedish
+
+
+
+th_THThai
+
+
+
+tr_TRTurkish
+
+
+
+uk_UAUkrainian
+
+
+
+vi_VNVietnamese
+
+
+
+zh_CNSimplified Chinese
+
+
+
+
+zh_TWTraditional Chinese
+Customize OTA URLs¶
+ config:
+ displayURL-US-L: "http://example.com/us-l.tft"
+ displayURL-US-P: "http://example.com/us-l.tft"
+ displayURL-EU: "http://example.com/us-l.tft"
+ berryURL: "http://exampe.com/autoexec.be"
+Config screensaver
+
+Possible configuration values for screensaver config¶
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+entityTrue
+string
+
+weather.exampleweather entity from homeassistant
+
+
+
+entitiesTrue
+string
+
+Nonecontains a list of entities of this card (will be used instead of entity)
+
+
+
+statusIcon1True
+complex
+
+Nonestatus icon left to the date string, config similar to weatherOverride
+
+
+
+statusIcon2True
+complex
+
+Nonestatus icon right to the date string, config similar to weatherOverride
+
+
+
+doubleTapToUnlockTrue
+boolean
+
+Falserequires to tap screensaver two times
+
+
+
+themeTrue
+complex
+
+ configuration for theme
+
+
+
+defaultCardTrue
+string
+
+Nonedefault page after exiting screensaver; only works with top level cards defined in cards; needs to be a navigation item, see subpages (navigate.type_key) This config option will also be evaluated as a HomeAssistant Template.
+
+
+
+keyTrue
+string
+
+NoneUsed by navigate items
+
+
+
+
+typeTrue
+string
+
+screensaver
+screensaver or screensaver2 screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ - entity: weather.demo_weather_north
+ type: 1
+ - entity: weather.demo_weather_north
+ type: 2
+ - entity: sensor.energy_usage
+
screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ - entity: weather.demo_weather_north
+ type: 1
+ - entity: sensor.energy_usage
+ - entity: delete
+ - entity: sensor.indoor_temp
+ icon: mdi:home-thermometer-outline
+type: screensaver2 to switch the layout.
screensaver:
+ type: screensaver2
+ entities:
+ - entity: weather.demo_weather_north
+Possible configuration values for screensaver theme config (only normal screensaver layout not screensaver2)¶
+
+
+
+
+
+
+
+key
+option
+type
+default
+description
+
+
+
+backgroundTrue
+list
+Black
+
+[R, G, B]
+
+
+timeTrue
+list
+White
+
+[R, G, B]
+
+
+timeAMPMTrue
+list
+White
+
+[R, G, B]
+
+
+dateTrue
+list
+White
+
+[R, G, B]
+
+
+tMainTextTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast1True
+list
+White
+
+[R, G, B]
+
+
+tForecast2True
+list
+White
+
+[R, G, B]
+
+
+tForecast3True
+list
+White
+
+[R, G, B]
+
+
+tForecast4True
+list
+White
+
+[R, G, B]
+
+
+tForecast1ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast2ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast3ValTrue
+list
+White
+
+[R, G, B]
+
+
+tForecast4ValTrue
+list
+White
+
+[R, G, B]
+
+
+barTrue
+list
+White
+
+[R, G, B]
+
+
+tMainTextAlt2True
+list
+White
+
+[R, G, B]
+
+
+
+tTimeAddTrue
+list
+White
+
+[R, G, B][255, 0, 0] for red or [0, 0, 255] for blue. These are translated internally to RGB565 (note that this has lower color depth so the colours may not appear the same). Also note that the screen has a low contrast ratio, so colors look sigificantly different at full display brightness and lowest brightness. screensaver:
+ theme:
+ date: [255, 0, 0]
+Config Example for configured statusIcons
+
+ screensaver:
+ entity: weather.k3ll3r
+ statusIcon1:
+ entity: switch.example_item
+ statusIcon2:
+ entity: binary_sensor.example_item
+altFont: True to the statusIcon configuration. Icon/Color Overrides are also possible like on any other Entity.Config Example for configured statusIcons with increased size of the icons
+
+ screensaver:
+ entity: weather.k3ll3r
+ statusIcon1:
+ entity: switch.example_item
+ altFont: True
+ statusIcon2:
+ entity: binary_sensor.example_item
+ altFont: True
+Config Example for all white icons on screensaver
+
+ screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 1
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 2
+ color: [255,255,255]
+ - entity: weather.demo_weather_north
+ type: 3
+ color: [255,255,255]
+Config Example for a custom date format on forecast
+
+ screensaver:
+ entities:
+ - entity: weather.demo_weather_north
+ - entity: weather.demo_weather_north
+ type: 0
+ name: "%a %-d/%-m"
+ - entity: weather.demo_weather_north
+ type: 1
+ name: "%a %-d/%-m"
+ - entity: weather.demo_weather_north
+ name: "%a %-d/%-m"
+ type: 2
+ - entity: weather.demo_weather_north
+ name: "%a %-d/%-m"
+ type: 3
+Configure MQTT on Tasmota¶
+
Note for Appdeamon Addon Version >= 15¶
+Configure MQTT Connection on AppDaemon¶
+appdaemon.yaml Restart your AppDaemon Container (not HomeAssistant) after adding the MQTT Configuration./addon_configs/a0d7b954_appdaemon/appdeamon.yaml---
+secrets: /homeassistant/secrets.yaml
+appdaemon:
+ latitude: 52.0
+ longitude: 4.0
+ elevation: 2
+ time_zone: Europe/Berlin
+ app_dir: /homeassistant/appdaemon/apps/ # !!! This is really important for AppDaemon HA Addon >= 15
+ plugins:
+ HASS:
+ type: hass
+ MQTT:
+ type: mqtt
+ namespace: mqtt
+ client_id: "appdaemon"
+ client_host: core-mosquitto.local.hass.io # This should work if you are using supervised HomeAssistant; if not use the IP Address instead.
+ #client_host: 192.168.75.30
+ client_port: 1883
+ client_user: "mqttuser"
+ client_password: "mqttpassword"
+ client_topics: NONE
+http:
+ url: http://127.0.0.1:5050
+admin:
+api:
+hadashboard:
+Configure NsPanel on AppDaemon¶
+config/appdaemon/apps/apps.yamlapps.yaml to this location if it isn't there.---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_your_mqtt_topic/RESULT"
+ panelSendTopic: "cmnd/tasmota_your_mqtt_topic/CustomSend"
+ model: eu
+tasmota_your_mqtt_topic to the topic used in Tasmota MQTT Configuration.
Note: You can add multiple panels to this configuration:
+
+---
+nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/first-nspanel-topic/RESULT"
+ panelSendTopic: "cmnd/first-nspanel-topic/CustomSend"
+nspanel-2:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/second-nspanel-topic/RESULT"
+ panelSendTopic: "cmnd/second-nspanel-topic/CustomSend"
+Entities¶
+Possible configuration values for entities key:¶
+
+
+
+
+
+
+
+key
+optional
+type
+default
+description
+
+
+
+entityFalse
+string
+
+Nonename of ha entity
+
+
+
+nameTrue
+string
+
+NoneUsed to override names (supports home assistant templates)
+
+
+
+valueTrue
+string
+
+NoneUsed to override the value (supports home assistant templates)
+
+
+
+iconTrue
+string
+
+NoneUsed to override icons
+
+
+
+colorTrue
+array
+
+NoneOverwrite color of entity
+color: [255, 0, 0]
+
+
+stateTrue
+string
+
+NoneOnly displayed if Entity state is equal to this value
+
+
+
+state_notTrue
+string
+
+NoneOnly displayed if Entity state is unequal to this value
+
+
+
+statusTrue
+string
+
+NoneOnly valid for navigate and service items, adds a entity to track state for the icon
+
+
+
+assumed_stateTrue
+string
+
+NoneOnly for cover items, up, down and stop buttons are always shown
+
+
+
+action_nameTrue
+string
+
+NoneOnly valid for script; Button label
+
+
+
+fontTrue
+string
+
+NoneUsed to change the font for cardGrid Icons; valid values are (
+small, medium-icon and medium). Currently only supported for homeassistant entities and not for internal ones.
+
+
+
+effectListTrue
+string
+
+NoneOnly valid for light; for example
+[Android, Aurora (fav list for effects)Override Icons or Names¶
+ entities:
+ - entity: light.test_item
+ name: NameOverride
+ icon: mdi:lightbulb
+ icon:
+ "on": mdi:lightbulb
+ "off": mdi:lightbulb
+ color:
+ "on": [255,0,0]
+ "off": [0,0,255]
+ color: '{{iif(states("binary_sensor.test")=="on", "[0,255,0]", "[255,165,0]")}}'
+text:X icon:
+ "on": mdi:lightbulb
+ "off": "text:"
+ha: which will be rendered as homeassistant template.
+There probably not much cases where this is needed, but here is an exmaple to show the current temperature on the status icon of the screensaver: statusIcon2:
+ entity: climate.wohnzimmer_boden
+ icon: 'ha:{{ state_attr("climate.wohnzimmer_boden","current_temperature")}}'
+<I></I> icon: 'ha:{{ iif(is_state('light.kitchen', 'on'), '<I>mdi:flashlight</I>', '<I>mdi:flashlight-off</I>') }}'
+Hide item based on state¶
+off - entity: binary_sensor.sensor_bad_contact
+ state: "off"
+on - entity: binary_sensor.sensor_kueche_contact
+ state_not: "on"
+Hide item based on HA Template¶
+true for the entity to hide. - entity: binary_sensor.sensor_kueche_contact
+ state_template: '{{ state_attr("sun.sun","azimuth") < 200 }}'
+Calling service directly as button¶
+ - entity: service.light.turn_on
+ data:
+ entity_id: light.schreibtischlampe
+ color_name: "green"
+FAQ - Frequently Asked Questions¶
+Waiting for content - This is taking longer than usual on the screen¶
+
+
+app_dir line in your appdaemon.yaml.
+This also requires you to move your apps.yaml to this location. Please make sure your apps.yaml is at /config/appdaemon/apps/apps.yaml and move it otherwise.INFO MQTT: MQTT Plugin initialization complete
+If you are seeing Messages like this:
+CRITICAL MQTT: Could not complete MQTT Plugin initialization, for Connection was refused due to Not Authorised
+Your appdaemon mqtt config is wrong, check your appdaemon.yaml.
+The log of your mqtt broker might give you additional information.
+Please don't modify the Full Topic in your Tasmota Config, unless you know the implications, changing the Full Topic will result in diffent Send and Receive Channels, that have to be correct in your apps.yaml.
+
+How to update¶
+Update AppDaemon Script¶
+Update Display Firmware¶
+FlashNextion http://nspanel.pky.eu/lui-release.tftFlashNextion http://nspanel.pky.eu/lui-us-p-release.tftFlashNextion http://nspanel.pky.eu/lui-us-l-release.tftUpdate Tasmota Berry Driver¶
+UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.beHow to upgrade from a release to the current development version¶
+
+
+
+
+FlashNextion http://nspanel.pky.eu/lui.tftFlashNextion http://nspanel.pky.eu/lui-us-l.tftFlashNextion http://nspanel.pky.eu/lui-us-p.tftNSPanel Lovelace UI¶
+CustomSend, which is implemented in the berry driver.
+You can issue this command through MQTT by sending messages to the cmnd/XXX/CustomSend Topic.
+Messages from the Panel are send to the tele/XXX/RESULT Topic, encoded in json {"CustomRecv":"message_from_screen"}Table of contents¶
+
+
+Startup¶
+{"CustomRecv":"event,startup,39,eu"} every few seconds.event, #Every message from the screen will start with `event`
+startup, #Startup Event
+39, #Current HMI Project Version
+eu #Current HMI Project Model
+Some preperation before we are acually navigating away:¶
+time~18:17date~Donnerstag, 25. August 2022timeout~20dimmode~10~100~6371Navigate from the startup page to the screensaver, by sending this command to the CustomSend Topic.¶
+pageType~screensaverExit Screensaver¶
+event,buttonPress2,screensaver,bExit,1pageType~cardEntitiesentityUpd~test~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~light~light.schreibtischlampe~X~17299~Schreibtischlampe~0~text~sensor.server_energy_power~Y~17299~Server ENERGY Power~155 W~shutter~cover.rolladenfenster_cover_1~Z~17299~Fenster Eingang~A|B|C|disable|enable|enable~switch~switch.bad~D~63142~Bad~1Messages to Nextion Display¶
+General Commands, implemented on all pages¶
+dimmode~0~100 - (screen off)dimmode~100~100 - (screen on with full brightness)time~22:26date~Di 24. Februartimeout~15 - timeout after 15 secondstimeout~0 - disable screensaverpageType~pageStartuppageType~cardEntitiespageType~cardThermopageType~cardMediapageType~popupLight~Schreibtischlampe~light.schreibtischlampepageType~popupNotifypageType~screensaverscreensaver page¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ weatherupdate
+
+
+
+ 1
+
+ Main Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 2
+
+ intNameEntity
+ ignored
+
+
+ 3
+
+ icon
+
+
+
+ 4
+
+ iconColor
+
+
+
+ 5
+
+ displayName
+ ignored
+
+
+ 6
+
+ optionalValue
+
+
+
+ 7
+
+ First Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 8
+
+ intNameEntity
+ ignored
+
+
+ 9
+
+ icon
+
+
+
+ 10
+
+ iconColor
+
+
+
+ 11
+
+ displayName
+
+
+
+ 12
+
+ optionalValue
+
+
+
+ 13
+
+ Second Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 14
+
+ intNameEntity
+ ignored
+
+
+ 15
+
+ icon
+
+
+
+ 16
+
+ iconColor
+
+
+
+ 17
+
+ displayName
+
+
+
+ 18
+
+ optionalValue
+
+
+
+ 19
+
+ Third Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 20
+
+ intNameEntity
+ ignored
+
+
+ 21
+
+ icon
+
+
+
+ 22
+
+ iconColor
+
+
+
+ 23
+
+ displayName
+
+
+
+ 24
+
+ optionalValue
+
+
+
+ 25
+
+ Fourth Forecast Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 26
+
+ intNameEntity
+ ignored
+
+
+ 27
+
+ icon
+
+
+
+ 28
+
+ iconColor
+
+
+
+ 29
+
+ displayName
+
+
+
+ 30
+
+ optionalValue
+
+
+
+ 31
+
+ Alternative Layout Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 32
+
+ intNameEntity
+ ignored
+
+
+ 33
+
+ icon
+
+
+
+ 34
+
+ iconColor
+
+
+
+ 35
+
+ displayName
+ ignored
+
+
+
+36
+
+ optionalValue
+
+ color~background~tTime~timeAMPM~tDate~tMainText~tForecast1~tForecast2~tForecast3~tForecast4~tForecast1Val~tForecast2Val~tForecast3Val~tForecast4Val~bar~tMainTextAlt2~tTimeAdd
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+ color
+
+
+
+ 1
+
+
+
+ background
+
+
+
+ 2
+
+
+
+ tTime
+
+
+
+ 3
+
+
+
+ timeAMPM
+
+
+
+ 4
+
+
+
+ tDate
+
+
+
+ 5
+
+
+
+ tMainText
+
+
+
+ 6
+
+
+
+ tForecast1
+
+
+
+ 7
+
+
+
+ tForecast2
+
+
+
+ 8
+
+
+
+ tForecast3
+
+
+
+ 9
+
+
+
+ tForecast4
+
+
+
+ 10
+
+
+
+ tForecast1Val
+
+
+
+ 11
+
+
+
+ tForecast2Val
+
+
+
+ 12
+
+
+
+ tForecast3Val
+
+
+
+ 13
+
+
+
+ tForecast4Val
+
+
+
+ 14
+
+
+
+ bar
+
+
+
+ 15
+
+
+
+ tMainTextAlt2
+
+
+
+
+16
+
+
+
+ tTimeAdd
+
+ notify~heading~textstatusUpdate~icon1~icon1Color~icon2~icon2~icon2color~icon1font~icon2fontcardEntities Page¶
+entityUpd~title~[navigation]~[entity_information]
+Example with 4 Entities:
+entityUpd~LightTest~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~light~light.bed_light~A~17299~Bed Light~0~light~light.ceiling_lights~B~52231~Ceiling Lights~1~switch~switch.ac~C~17299~AC~0~switch~switch.decorative_lights~D~65222~Decorative Lights~1
+~light~light.entityName~1~17299~Light1~0~shutter~cover.entityName~0~17299~Shutter2~iconUp|iconStop|iconDown~delete~~~~~~text~sensor.entityName~3~17299~Temperature~content~button~button.entityName~3~17299~bt-name~bt-text~switch~switch.entityName~4~17299~Switch1~0~number~input_number.entityName~4~17299~Number123~value|min|max~input_sel~input_select.entityName~3~17299~sel-name~sel-text
+
+
+
+
+
+
+
+ Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Entities
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 15
+ intNameEntity
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+
+
+ 20
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 21
+ intNameEntity
+
+
+ 22
+ icon
+
+
+
+ 23
+ iconColor
+
+
+
+ 24
+ displayName
+
+
+
+ 25
+ optionalValue
+
+
+ 26
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 27
+ intNameEntity
+
+
+ 28
+ icon
+
+
+
+ 29
+ iconColor
+
+
+
+ 30
+ displayName
+
+
+
+ 31
+ optionalValue
+
+
+ 32
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 33
+ intNameEntity
+
+
+ 34
+ icon
+
+
+
+ 35
+ iconColor
+
+
+
+ 36
+ displayName
+
+
+
+ 37
+ optionalValue
+
+
+ 38
+ Fifth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 39
+ intNameEntity
+
+
+ 40
+ icon
+
+
+
+ 41
+ iconColor
+
+
+
+ 42
+ displayName
+
+
+
+ 43
+ optionalValue
+
+
+ 44
+ Sixth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 45
+ intNameEntity
+
+
+ 46
+ icon
+
+
+
+ 47
+ iconColor
+
+
+
+ 48
+ displayName
+
+
+
+
+49
+ optionalValue
+ cardGrid Page¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Entities
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 15
+ intNameEntity
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+ ignored
+
+
+ 20
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 21
+ intNameEntity
+
+
+ 22
+ icon
+
+
+
+ 23
+ iconColor
+
+
+
+ 24
+ displayName
+
+
+
+ 25
+ optionalValue
+ ignored
+
+
+ 26
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 27
+ intNameEntity
+
+
+ 28
+ icon
+
+
+
+ 29
+ iconColor
+
+
+
+ 30
+ displayName
+
+
+
+ 31
+ optionalValue
+ ignored
+
+
+ 32
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 33
+ intNameEntity
+
+
+ 34
+ icon
+
+
+
+ 35
+ iconColor
+
+
+
+ 36
+ displayName
+
+
+
+ 37
+ optionalValue
+ ignored
+
+
+ 38
+ Fifth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 39
+ intNameEntity
+
+
+ 40
+ icon
+
+
+
+ 41
+ iconColor
+
+
+
+ 42
+ displayName
+
+
+
+ 43
+ optionalValue
+ ignored
+
+
+ 44
+ Sixth Entiy (US Portrait Version)
+ Entity Definition
+ type
+
+
+
+ 45
+ intNameEntity
+
+
+ 46
+ icon
+
+
+
+ 47
+ iconColor
+
+
+
+ 48
+ displayName
+
+
+
+
+49
+ optionalValue
+ ignored
+ cardMedia¶
+entityUpd~Kitchen~button~navigation.up~U~65535~~~delete~~~~~~media_player.kitchen~I'm a Hurricane~~Wellmess~~100~A~64704~B~media_pl~media_player.kitchen~C~17299~Kitchen~
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardMedia specific
+
+ cardMedia specific
+ intNameEntity
+
+
+
+ 15
+ 1st text row
+ title
+
+
+
+ 16
+ titleColor
+
+
+
+ 17
+ 2nd text row
+ author
+
+
+
+ 18
+ authorColor
+
+
+
+ 19
+ slider
+ volume
+ 0-100
+
+
+ 20
+ icon middle
+ playPauseIcon
+
+
+
+ 21
+ icon right side
+ onOffBtn
+ "disable" or color
+
+
+ 22
+ icon left side
+ iconShuffle
+ "disable" or icon
+
+
+ 23
+ Entities
+ upper left corner media icon
+ Entity Definition
+ type
+
+
+
+ 24
+ intNameEntity
+
+
+
+ 25
+ icon
+
+
+
+ 26
+ iconColor
+
+
+
+ 27
+ displayName
+ only used for popups
+
+
+ 28
+ optionalValue
+ ignored
+
+
+ 29
+ First Entity
+ Entity Definition
+ type
+
+
+
+ 30
+ intNameEntity
+
+
+
+ 31
+ icon
+
+
+
+ 32
+ iconColor
+
+
+
+ 33
+ displayName
+ only used for popups
+
+
+ 34
+ optionalValue
+ ignored
+
+
+ 35
+ Second Entity
+ Entity Definition
+ type
+
+
+
+ 36
+ intNameEntity
+
+
+
+ 37
+ icon
+
+
+
+ 38
+ iconColor
+
+
+
+ 39
+ displayName
+ only used for popups
+
+
+ 40
+ optionalValue
+ ignored
+
+
+ 41
+ Thrid Entity
+ Entity Definition
+ type
+
+
+
+ 42
+ intNameEntity
+
+
+
+ 43
+ icon
+
+
+
+ 44
+ iconColor
+
+
+
+ 45
+ displayName
+ only used for popups
+
+
+ 46
+ optionalValue
+ ignored
+
+
+ 47
+ Forth Entiry
+ Entity Definition
+ type
+
+
+
+ 48
+ intNameEntity
+
+
+
+ 49
+ icon
+
+
+
+ 50
+ iconColor
+
+
+
+ 51
+ displayName
+ only used for popups
+
+
+ 52
+ optionalValue
+ ignored
+
+
+ 53
+ Fifth Entiy
+ Entity Definition
+ type
+
+
+
+ 54
+ intNameEntity
+
+
+
+ 55
+ icon
+
+
+
+ 56
+ iconColor
+
+
+
+ 57
+ displayName
+ only used for popups
+
+
+
+58
+ optionalValue
+ ignored
+ cardThermo¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+
+
+
+ 2
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+
+
+ intNameEntity
+
+
+
+ 15
+ 2nd text box
+ currentTemp
+
+
+
+ 16
+ target temperature
+ dstTemp
+ multiplied by 10
+
+
+ 17
+ Text 4th Box Left Side
+ status
+
+
+
+ 18
+ Min Temp
+ minTemp
+ multiplied by 10
+
+
+ 19
+ Max Temp
+ maxTemp
+ multiplied by 10
+
+
+ 20
+ Temperature Steps
+ tempStep
+ multiplied by 10
+
+
+ 21
+ bottom hvac_action 1
+ Hvac Action
+ icon
+
+
+
+ 22
+ iconColorActive
+
+
+
+ 23
+ buttonState
+
+
+
+ 24
+ intName
+
+
+
+ 25
+ bottom hvac_action 2
+ Hvac Action
+ icon
+
+
+
+ 26
+ iconColorActive
+
+
+
+ 27
+ buttonState
+
+
+
+ 28
+ intName
+
+
+
+ 29
+ bottom hvac_action 3
+ Hvac Action
+ icon
+
+
+
+ 30
+ iconColorActive
+
+
+
+ 31
+ buttonState
+
+
+
+ 32
+ intName
+
+
+
+ 33
+ bottom hvac_action 4
+ Hvac Action
+ icon
+
+
+
+ 34
+ iconColorActive
+
+
+
+ 35
+ buttonState
+
+
+
+ 36
+ intName
+
+
+
+ 37
+ bottom hvac_action 5
+ Hvac Action
+ icon
+
+
+
+ 38
+ iconColorActive
+
+
+
+ 39
+ buttonState
+
+
+
+ 40
+ intName
+
+
+
+ 41
+ bottom hvac_action 6
+ Hvac Action
+ icon
+
+
+
+ 42
+ iconColorActive
+
+
+
+ 43
+ buttonState
+
+
+
+ 44
+ intName
+
+
+
+ 45
+ bottom hvac_action 7
+ Hvac Action
+ icon
+
+
+
+ 46
+ iconColorActive
+
+
+
+ 47
+ buttonState
+
+
+
+ 48
+ intName
+
+
+
+ 49
+ bottom hvac_action 8
+ Hvac Action
+ icon
+
+
+
+ 50
+ iconColorActive
+
+
+
+ 51
+ buttonState
+
+
+
+ 52
+ intName
+
+
+
+ 53
+ Currently Label 1th Text Box
+ tCurTempLbl
+
+
+
+ 54
+ State Label 3th Text Box
+ tStateLbl
+
+
+
+ 55
+
+
+ tALbl
+ deprecated; ignored
+
+
+ 56
+ Temperature Unit (Celcius/Farhenheit)
+ tCF
+
+
+
+ 57
+ Second Destination Tempature (Heat/Cool)
+
+ second temp
+ ; multiplied by 10
+
+
+
+58
+ additonal detail button to open another page
+ btDetail
+ "1" to hide
+ cardAlarm¶
+
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ title
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardAlarm specific
+ card intNameEntity
+ intNameEntity
+
+
+
+ 15
+ 1st button right side
+ displayName
+
+
+
+ 16
+ intId
+
+
+
+ 17
+ 2nd button right side
+ displayName
+
+
+
+ 18
+ intId
+
+
+
+ 19
+ 3rd button right side
+ displayName
+
+
+
+ 20
+ intId
+
+
+
+ 21
+ 4th button right side
+ displayName
+
+
+
+ 22
+ intId
+
+
+
+ 23
+ icon next to code display
+ icon
+
+
+
+ 24
+ iconColor
+
+
+
+ 25
+ numpad
+ numpadStatus
+ "disable" or "enable"
+
+
+ 26
+ flashing of icon next to code
+ flashing status
+ "enable" or "disable"
+
+
+ 27
+ button bottom left corner
+ icon
+
+
+
+ 28
+ iconColor
+
+
+
+
+29
+ intNameEntity
+
+ cardQR¶
+entityUpd~Guest Wifi~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~WIFI:S:test_ssid;T:WPA;P:test_pw;;~text~iText.test_ssid~���~17299~Name~test_ssid~text~iText.test_pw~���~17299~Password~test_pw
+
+
+
+
+
+
+
+ Parameter Number
+ Category
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+ instruction
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+ intNameEntity
+
+
+
+ 2
+ Navigation
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ cardQR specific
+ qrcode text
+
+
+
+ 15
+ Entities
+ 1st Entity
+ Entity Definition
+ type
+
+
+
+ 16
+ intNameEntity
+
+
+
+ 17
+ icon
+
+
+
+ 18
+ iconColor
+
+
+
+ 19
+ displayName
+
+
+
+ 20
+ optionalValue
+
+
+
+ 21
+ 2nd Entity
+ Entity Definition
+ type
+
+
+
+ 22
+ intNameEntity
+
+
+
+ 23
+ icon
+
+
+
+ 24
+ iconColor
+
+
+
+ 25
+ displayName
+
+
+
+
+26
+ optionalValue
+
+ cardPower¶
+entityUpd~PowerTest~x~navUp~A~65535~~~delete~~~~~~text~sensor.power_consumption~B~17299~Power consumption~100W~1~text~sensor.power_consumption~C~17299~Power consumption~100W~1~text~sensor.today_energy~D~17299~Total energy 1~5836.0kWh~0~delete~~~~~~0~text~sensor.today_energy~E~17299~Total energy 1~5836.0kWh~-30~delete~~~~~~0~text~sensor.today_energy~F~65504~Total energy 1~5836.0kWh~90~text~sensor.today_energy~G~17299~Total energy 1~5836.0kWh~10
+
+
+
+
+
+
+
+ Parameter Number
+ Location
+ Type
+ Field
+ Addional Information
+
+
+ 0
+
+ instruction
+ entityUpd
+
+
+
+ 1
+ title
+ title
+ title
+
+
+
+ 2
+ Upper Left Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 3
+ intNameEntity
+
+
+
+ 4
+ icon
+
+
+
+ 5
+ iconColor
+
+
+
+ 6
+ displayName
+ ignored
+
+
+ 7
+ optionalValue
+ ignored
+
+
+ 8
+ Upper Right Icon
+ Entity Definition
+ type
+ (ignored)¹
+
+
+ 9
+ intNameEntity
+
+
+
+ 10
+ icon
+
+
+
+ 11
+ iconColor
+
+
+
+ 12
+ displayName
+ ignored
+
+
+ 13
+ optionalValue
+ ignored
+
+
+ 14
+ Home Icon / Value below Home Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 15
+ intNameEntity
+ ignored
+
+
+ 16
+ icon
+
+
+
+ 17
+ iconColor
+
+
+
+ 18
+ displayName
+
+
+
+ 19
+ optionalValue
+
+
+
+ 20
+ speed
+ ignored
+
+
+ 21
+ Value above Home Icon
+ Entity Definition
+ type
+ ignored
+
+
+ 22
+ intNameEntity
+ ignored
+
+
+ 23
+ icon
+ ignored
+
+
+ 24
+ iconColor
+ ignored
+
+
+ 25
+ displayName
+ ignored
+
+
+ 26
+ optionalValue
+
+
+
+ 27
+ speed
+ ignored
+
+
+ 28
+ 1st Item Upper Left
+ Entity Definition
+ type
+ ignored
+
+
+ 29
+ intNameEntity
+ ignored
+
+
+ 30
+ icon
+
+
+
+ 31
+ iconColor
+
+
+
+ 32
+ displayName
+
+
+
+ 33
+ optionalValue
+
+
+
+ 34
+ speed
+ numbers (between -120 and 120)
+
+
+ 35
+ 2nd Item Middle Left
+ Entity Definition
+ type
+ ignored
+
+
+ 36
+ intNameEntity
+ ignored
+
+
+ 37
+ icon
+
+
+
+ 38
+ iconColor
+
+
+
+ 39
+ displayName
+
+
+
+ 40
+ optionalValue
+
+
+
+ 41
+ speed
+ numbers (between -120 and 120)
+
+
+ 42
+ 3rd Item Bottom Left
+ Entity Definition
+ type
+ ignored
+
+
+ 43
+ intNameEntity
+ ignored
+
+
+ 44
+ icon
+
+
+
+ 45
+ iconColor
+
+
+
+ 46
+ displayName
+
+
+
+ 47
+ optionalValue
+
+
+
+ 48
+ speed
+ numbers (between -120 and 120)
+
+
+ 49
+ 4th Item Upper Right
+ Entity Definition
+ type
+ ignored
+
+
+ 50
+ intNameEntity
+ ignored
+
+
+ 51
+ icon
+
+
+
+ 52
+ iconColor
+
+
+
+ 53
+ displayName
+
+
+
+ 54
+ optionalValue
+
+
+
+ 55
+ speed
+ numbers (between -120 and 120)
+
+
+ 56
+ 5th Item Middle Right
+ Entity Definition
+ type
+ ignored
+
+
+ 57
+ intNameEntity
+ ignored
+
+
+ 58
+ icon
+
+
+
+ 59
+ iconColor
+
+
+
+ 60
+ displayName
+
+
+
+ 61
+ optionalValue
+
+
+
+ 62
+ speed
+ numbers (between -120 and 120)
+
+
+ 63
+ 6th Item Bottom Right
+ Entity Definition
+ type
+ ignored
+
+
+ 64
+ intNameEntity
+ ignored
+
+
+ 65
+ icon
+
+
+
+ 66
+ iconColor
+
+
+
+ 67
+ displayName
+
+
+
+ 68
+ optionalValue
+
+
+
+
+69
+ speed
+ numbers (between -120 and 120)
+ cardChart Page¶
+entityUpd~heading~navigation~color~yAxisLabel~yAxisTick:[yAxisTick]*[~value[:xAxisLabel]?]* entityUpd~Chart Demo~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~6666~Gas [kWh]~20:40:60:80:100~10~7^2:00~7~6^4:00~6~7^6:00~0~7^8:00~5~1^10:00~1~10^12:00~5~6^14:00~8popupLight Page¶
+entityUpdateDetail~entityName~*ignored*~*iconColor*~*buttonState*~*sliderBrightnessPos*~*sliderColorTempPos*~*colorMode*~*color_translation*~*color_temp_translation*~*brightness_translation*entityUpdateDetail~1~17299~1~100~78~enableentityUpdateDetail~1~17299~1~100~disablepopupShutter Page¶
+entityUpdateDetail~entityName~*sliderPos*~2ndrow~textPosition~icon1~iconUp~iconStop~iconDown~iconUpStatus~iconStopStatus~iconDownStatus~textTilt~iconTiltLeft~iconTiltStop~iconTiltRight~iconTiltLeftStatus~iconTiltStopStatus~iconTiltLeftStatus~tiltPosentityUpdateDetail~1~77popupNotify Page¶
+entityUpdateDetail~*internalName*~*tHeading*~*tHeadingColor*~*b1*~*tB1Color*~*b2*~*tB2Color*~*tText*~*tTextColor*~*sleepTimeout*~*font*~*alt_icon*~*altIconColor*exitPopuppopupThermo Page¶
+entityUpdateDetail~{entity_id}~{icon_id}~{icon_color}~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~popupInSel Page (input_select detail page)¶
+entityUpdateDetail2~*entity_id*~~*icon_color*~*input_sel*~*state*~*options*popupTimer¶
+entityUpdateDetail~{entity_id}~~{icon_color}~{entity_id}~{min_remaining}~{sec_remaining}~{editable}~{action1}~{action2}~{action3}~{label1}~{label2}~{label3}Messages from Nextion Display¶
+event,buttonPress2,pageName,bNextevent,buttonPress2,pageName,bPrevevent,buttonPress2,pageName,bExit,number_of_tapsevent,buttonPress2,pageName,sleepReachedstartup page¶
+event,startup,version,modelscreensaver page¶
+event,buttonPress2,screensaver,exit - Touch Event on Screensaverevent,screensaverOpen - Screensaver has openedcardEntities Page¶
+event,*eventName*,*entityName*,*actionName*,*optionalValue*event,buttonPress2,internalNameEntity,upevent,buttonPress2,internalNameEntity,downevent,buttonPress2,internalNameEntity,stopevent,buttonPress2,internalNameEntity,OnOff,1event,buttonPress2,internalNameEntity,buttonpopupLight Page¶
+event,pageOpenDetail,popupLight,internalNameEntityevent,buttonPress2,internalNameEntity,OnOff,1event,buttonPress2,internalNameEntity,brightnessSlider,50event,buttonPress2,internalNameEntity,colorTempSlider,50event,buttonPress2,internalNameEntity,colorWheel,x|y|whpopupShutter Page¶
+event,pageOpenDetail,popupShutter,internalNameEntityevent,buttonPress2,internalNameEntity,positionSlider,50popupNotify Page¶
+event,buttonPress2,*internalName*,notifyAction,yesevent,buttonPress2,*internalName*,notifyAction,nocardThermo Page¶
+event,buttonPress2,*entityName*,tempUpd,*temperature*event,buttonPress2,*entityName*,hvac_action,*hvac_action*cardMedia Page¶
+event,buttonPress2,internalNameEntity,media-backevent,buttonPress2,internalNameEntity,media-pauseevent,buttonPress2,internalNameEntity,media-nextevent,buttonPress2,internalNameEntity,volumeSlider,75cardAlarm Page¶
+event,buttonPress2,internalNameEntity,actionName,codeCustom Protocol¶
+55 BB [payload length] [payload length] [payload] [crc] [crc]
+Example for valid Message¶
+55 BB 04 00 31 33 33 37 5F 5B
+
+
+ Material Design Icons
+
+
+
+ Cheatsheet Usage
+
+
+
+
+ New Icons -
+
+
+ All Icons -
+
+
+ Deprecated Icons -
+ Overview¶
+
Features¶
+
+
+

Requirements¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Installation - ioBroker¶
+Sending Notifications to the Panel¶
+Seperate Page¶
+pageType popupNotifyentityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdTextentityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText~icon~iconColorfontIdText is the font used by the notification text
+Possible values are 0-5:
+Font 0 - Default - Size 24 (No Icons, Support for various special chars from different langs)
+Font 1 - Size 32 (Icons and limited chars)
+Font 2 - Size 32 (No Icons, Support for various special chars from different langs)
+Font 3 - Size 48 (Icons and limited chars)
+Font 4 - Size 80 (Icons and limited chars)
+Font 5 - Size 128 (ascii only)
+exitPopup{{'\r\n'}}nspanel_popup_notification:
+ alias: Popup Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{
+ title }}~65535~~~~~{{ message }}~65535~{{ timeout }}; Buzzer 2,2,2
+ mode: single
+ icon: mdi:message-badge
+nspanel_popup_notification:
+ alias: Popup Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{
+ title }}~65535~~~~~{{ message }}~65535~{{ timeout }}
+ mode: single
+ icon: mdi:message-badge
+Notification on screensaver¶
+notify~heading~textnspanel_screensaver_notification:
+ alias: Screensaver Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend notify~{{ heading }}~{{ message }}; Buzzer 2,2,2
+ mode: single
+ icon: mdi:message-badge
+nspanel_screensaver_notification:
+ alias: Screensaver Notification
+ sequence:
+ - service: mqtt.publish
+ data:
+ topic: cmnd/tasmota_NsPanelTerrasse/Backlog
+ payload: CustomSend notify~{{ heading }}~{{ message }}
+ mode: single
+ icon: mdi:message-badge
+Buzzer¶
+BuzzerPWM 1
+Color Picker¶
+
+Change behaviour of hardware buttons¶
+Tasmota Rules¶
+Rule2 on Button1#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,buttonPress2,navPrev,button"} endon on Button2#state do Publish tele/%topic%/RESULT {"CustomRecv":"event,buttonPress2,navNext,button"} endon
+
+Rule2 1
+Decouple buttons from controlling power outputs¶
+SetOption73 1
SetOption73 0Setup Home Assistant¶
+Installing AppDaemon¶
+
Instructions for users of HomeAssistant Core installed through docker containers.
+
+In case you have a homeassistant setup using docker cotainers and the Add-on Store is not available to you, you can follow this guide for setting up AppDaemon. https://appdaemon.readthedocs.io/en/latest/DOCKER_TUTORIAL.html
+Please also pay attention to the correct volume mount for the conf folder of appdaemon, that has to point to the appdaemon folder within your homeassistant config folder.
+
+Here is an example docker compose file for homeassistant and appdaemon:
+
+version: "3.5"
+services:
+ homeassistant:
+ image: ghcr.io/home-assistant/home-assistant:stable
+ container_name: homeassistant
+ network_mode: host
+ volumes:
+ - ./docker-data/homeassistant/:/config
+ - /etc/localtime:/etc/localtime:ro
+ environment:
+ - TZ=Europe/Berlin
+ privileged: true
+ restart: unless-stopped
+
+ appdaemon:
+ container_name: appdaemon
+ image: acockburn/appdaemon:4.2.3
+ environment:
+ - HA_URL=http://your-homeassistant-url:8123
+ - TOKEN="xxxxxx"
+ volumes:
+ - /etc/localtime:/etc/localtime:ro
+ - ./docker-data/homeassistant/appdaemon:/conf
+ depends_on:
+ - homeassistant
+ restart: unless-stopped
+Add babel package to AppDaemon Container (Optional)¶
+
Installing Studio Code Server¶
+apps.yaml config file in the Appdaemon folder.
+Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.Installing HomeAssistant Community Store¶
+Installing Lovelace AppDaemon Backend Application¶
+
+
+Configuration on the left menu bar in Home Assistant Web UIDevices & ServicesIntegrationsHACS and click on ConfigureEnable AppDaemon apps discovery & tracking
+ is checked, or check it and click Submit
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HACS on the left menu bar in Home Assistant Web UIAutomations in the right panelExplore & download repositories in the bottom right cornerNSPanel, and click on NSPanel Lovelace UI Backend in the list that appearsDownload this repository with HACSDownload, and wait for HACS to
+ proceed with the downloadFlash Tasmota to Your NSPanel¶
+
+You can use the Tasmota Web Installer to do so.
+NSPanel Page of the Tasmota Template Repository
+ESPHome Component
+Configure Tasmota Template for NSPanel¶
+
+Upload Berry Driver to Tasmota¶
+
+Flash Firmware to Nextion Screen¶
+
+FlashNextion http://nspanel.pky.eu/lui-release.tft
+FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
+FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
+Alternatively, you can use your own web server or the one built into Home Assistant:
+
+Upload the nspanel.tft from the latest release to a web server (for example, the www folder of Home Assistant) and execute the following command in the Tasmota Console.
+(Development version: [TFT file from HMI folder](HMI/nspanel.tft))
+
+**The web server must be HTTP. HTTPS is not supported due to Berry language limitations in Tasmota.**
+
+FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft
+Flash Tasmota to your NSPanel¶
+Configure Tasmota Template for NSPanel¶
+
{"NAME":"NSPanel","GPIO":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],"FLAG":0,"BASE":1,"CMND":"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1"}Upload Berry Driver to Tasmota¶
+Consoles > Console in Tasmota and execute the following command:Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1
+Flash Firmware to Nextion Screen¶
+FlashNextion http://nspanel.pky.eu/lui-release.tftFlashNextion http://nspanel.pky.eu/lui-us-p-release.tftFlashNextion http://nspanel.pky.eu/lui-us-l-release.tftAlternatively you can use your own webserver:
+
+Upload the nspanel.tft from the lastest release to a Webserver and execute the following command in Tasmota Console.
+
+**Webserver must be HTTP, HTTPS is not supported, due to limitations of berry lang on tasmota**
+
+`FlashNextion http://ip-address-of-your-webserver:8123/local/nspanel.tft`
+
","path":["Overview"],"tags":[]},{"location":"card-alarm/","level":1,"title":"Alarm Card","text":"
cards:\n - type: cardAlarm\n title: Alarm Test 1\n entity: alarm_control_panel.alarmo\ntype False string None Type of the card title True string None Title of the Page entity False string None contains the entity of the current card key True string None Used by navigate items alarmControl True complex None overwrites the action executed on pressing the left bottom icon, by default this button is used to show a list of open sensors on a failed attempt to arm. supportedModes True list None Supply list of arm modes if you want to limit the modes on the card. Example ['arm_away', 'arm_night']","path":["Configuration - apps.yaml (Home Assistant)","Cards","Alarm Card"],"tags":[]},{"location":"card-climate/","level":1,"title":"Climate/Thermo Card","text":" cards:\n - type: cardThermo\n title: HeatPump\n entity: climate.heatpump\n - type: cardThermo\n title: HvaC\n entity: climate.hvac\n - type: cardThermo\n title: ecobee\n entity: climate.ecobee\ntype False string None Type of the card entity False string None contains the entitiy of this card title True string None Title of the Page temperatureUnit True string celsius set this to fahrenheit to change the temperatureUnit on the page key True string None Used by navigate items in combination with the type (cardEntities_key) supportedModes True list None Supply list of heat actions if you want to limit the actions on the card. Example ['heat', 'off']","path":["Configuration - apps.yaml (Home Assistant)","Cards","Climate/Thermo Card"],"tags":[]},{"location":"card-entities/","level":1,"title":"Entities Page","text":" cards:\n - type: cardEntities\n title: Test Entities Card\n entities:\n - entity: light.bed_light\n - entity: switch.decorative_lights\n - entity: cover.hall_window\n - entity: sensor.outside_temperature\ntype False string None Type of the card entities False complex None contains a list of entities of this card title True string None Title of the Page key True string None Used by navigate items in combination with the type (cardEntities_key)
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Entities Page"],"tags":[]},{"location":"card-grid/","level":1,"title":"Grid Page","text":" cards:\n - type: cardGrid\n title: Test Grid Card\n entities:\n - entity: light.bed_light\n - entity: switch.decorative_lights\n - entity: sensor.outside_temperature\n name: Outside Temp\n - entity: sensor.carbon_monoxide\n - entity: light.entrance_color_white_lights\n name: Entrance\n - entity: light.office_rgbw_lights\n name: Office RGBW\n icon: mdi:office-building\ntype False string None Type of the card entities False complex None contains a list of entities of this card title True string None Title of the Page key True string None Used by navigate items in combination with the type (cardEntities_key)
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Grid Page"],"tags":[]},{"location":"card-media/","level":1,"title":"Media Card","text":" cards:\n - type: cardMedia\n entity: media_player.spotify\ntype False string None Type of the card title True string None Title of the Page entity False string None contains the entity of the current card entities False complex None contains a list of entities shown in the bottom row, supports all entities supported by cardGrid key True string None Used by navigate items Example with configured Entities
Example with action on upper left media icon - type: cardMedia\n title: Kitchen\n entity: media_player.kitchen\n entities:\n - entity: light.bed_light\n - entity: light.ceiling_lights\n - entity: light.entrance_color_white_lights\n - entity: light.kitchen_lights\n - entity: light.living_room_rgbww_lights\n
Example with moved spaker selection The icon for speaker selection is automatically appended to the end of the list and can be moved with entities in the list. With 6 entities it is possible to remove it entirely. - type: cardMedia\n title: Kitchen\n entity: input_select.test123\n status: media_player.kitchen\n
","path":["Configuration - apps.yaml (Home Assistant)","Cards","Media Card"],"tags":[]},{"location":"card-power/","level":1,"title":"Power Card (v3.9 and higher)","text":" - type: cardMedia\n title: Kitchen\n entity: media_player.kitchen\n entities:\n - entity: delete\n - entity: delete\n cards:\n - type: cardPower\n title: Power Test\n entities:\n - entity: sensor.power_consumption\n icon: mdi:home\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:car\n speed: -20\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:battery\n speed: 20\n - entity: delete\n - entity: sensor.today_energy\n icon: mdi:solar-panel\n color: [255, 255, 0]\n speed: 30\n - entity: sensor.today_energy\n speed: -40\n icon: mdi:help\ntype False string None Type of the card entities False complex None contains entities of the card title True string None Title of the Page cooldown True float None Rate Limit for Entity Updates to the card in Seconds (cooldown: 0.5) key True string None Used by navigate items
-100 and 100.
It provides the number as a negative integer, making the dot move from the middle of the card toward the entity. If you want the dot to move toward from the middle of the card, just skip inverting it at the end of the template like this: speed: >-\n {% set entity_power = states('sensor.appliance_water_heater_power') |float | round(3)%}\n {% set total_power = states('sensor.ams_power_active') | float | round(3) %}\n {% set entity_usage = (entity_power / total_power * 100) | float %}\n {{ (entity_usage | round()) * -1 }}\n {{ (entity_usage | round()) }}\n
cards:\n - type: cardQR\n title: Guest Wifi\n qrCode: \"WIFI:S:test_ssid;T:WPA;P:test_pw;;\"\n entities:\n - entity: iText.test_ssid\n name: Name\n icon: mdi:wifi\n - entity: iText.test_pw\n name: Password\n icon: mdi:key\n List of supported config keys of this card:
key optional type default descriptiontype False string None Type of the card entities False complex None contains entities of the card, only valid on cardEntities and cardGrid and cardQR title True string None Title of the Page key True string None Used by navigate items qrCode False string None Value of the qrCode List of supported entitiy types for this page:
The qrCode value is evaluated as a homeassistant Template, so it is possible to get values from HomeAssistant within the qrCode.
\"WIFI:S:{{states('input_text.test_ssid')}};T:WPA;P:{{states('input_text.test_pw')}};;\"
Can be used to navigate to create pin locked navigation to a hidden card.
cards:\n - type: cardUnlock\n pin: 1234\n title: Admin Page\n destination: navigate.adminpage\n hiddenCards:\n - type: cardGrid\n title: Admin Page\n key: adminpage\n entities:\n - entity: light.schreibtischlampe\n List of supported config keys of this card:
key optional type default descriptiontype False string None Type of the card title True string None Title of the Page destination False string None contains the navigation entity this card should navigate to on unlock pin False string 3830 pin to unlock key True string None Used by navigate items","path":["Configuration - apps.yaml (Home Assistant)","Cards","Unlock Card (v4.0 and higher)"],"tags":[]},{"location":"config-migration-standalone/","level":1,"title":"Migration to Standalone Rewrite Config","text":"This page compares the legacy AppDaemon apps.yaml config with the standalone rewrite panels.yaml config.
For the full rewrite docs, including full key descriptions, see:
Old AppDaemon version:
apps.yaml with module / class / configappdaemon.yaml)Standalone rewrite:
/config/panels.yamlnspanelsOld (apps.yaml):
nspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\n New (panels.yaml):
home_assistant_address: \"http://supervisor\"\nhome_assistant_token: \"YOUR_TOKEN\"\n\nnspanels:\n panel-1:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\n locale: en_US\n timeZone: \"Europe/Berlin\"\n timeFormat: \"%H:%M\"\n dateFormat: \"full\"\n screensaver:\n entities:\n - entity: weather.home\n cards:\n - type: cardEntities\n title: Main\n entities:\n - entity: light.kitchen\n","path":["Migration to Standalone Rewrite Config"],"tags":[]},{"location":"config-migration-standalone/#important-key-changes","level":2,"title":"Important key changes","text":"Legacy key/concept Rewrite key/concept Notes module, class, config wrapper removed Rewrite uses nspanels.<panel_name> directly. timezone timeZone Casing changed. dateFormatBabel dateFormat Use dateFormat in rewrite. temperatureUnit (legacy card-level usage) temp_unit (panel-level) Rewrite reads temp_unit from panel settings. brightness schedule lists not supported Rewrite supports integer or entity id for brightness values. updateMode / OTA URL override keys not supported Legacy update behavior is not part of rewrite config. If you are migrating now, use the standalone migration page for the complete mapping:
To confiure your NSPanel to your needs, you need to edit the apps.yaml inside of your Appdaemon config folder and add card and entities you want to display on the screen.
If you've sucessfully set up mqtt, you should already have a configuration looking like this:
---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\n You can continue from this point adding configuration for the weather forcecast on the screensaver, configuring a schedule for the brightness of the screensaver and your first cards.
---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\n sleepTimeout: 20\n sleepBrightness:\n - time: \"7:00:00\"\n value: 10\n - time: \"23:00:00\"\n value: 0\n locale: \"de_DE\"\n screensaver:\n entity: weather.k3ll3r\n cards:\n - type: cardEntities\n entities:\n - entity: switch.example_item\n - entity: light.example_item\n title: Example 1\n - type: cardGrid\n entities:\n - entity: switch.example_item\n - entity: light.example_item\n title: Example 2\n This is the full list of configuration options supported for the config key:
key optional type default descriptionpanelRecvTopic False string tele/tasmota_your_mqtt_topic/RESULT The mqtt topic used to receive messages. panelSendTopic False string cmnd/tasmota_your_mqtt_topic/CustomSend The mqtt topic used to send messages. updateMode True string auto-notify Update Mode for flashing of the nextion display firmware, by default it is showing a message asking for the update after updating the backend app in HACS; Possible values: \"auto\", \"auto-notify\", \"manual\" model True string eu Model; Possible values: \"eu\", \"us-l\" and \"us-p\" sleepTimeout True integer 20 Timeout for the screen to enter screensaver, to disable screensaver use 0 sleepBrightness True integer/complex 20 Brightness for the screen on the screensaver, see example below for complex/scheduled config. screenBrightness True integer/complex 100 Brightness for the screen during usage, config format is the same as sleepBrightness. sleepTracking True string None Forces screensaver brightness to 0 in case entity state is not_home or off, can be a group, person or device_tracker entity. sleepTrackingZones True list [\"not_home\", \"off\"] Allows you to set your own states for sleepTracking sleepOverride True complex None Allows overriding of the sleepBrightness if entity state is on, true or home. Overrides sleepBrightness but sleepTracking takes precedence. locale True string en_US Used by babel to determinante Date format on screensaver, also used for localization. dateFormatBabel True string full formatting options on https://babel.pocoo.org/en/latest/dates.html?highlight=name%20of%20day#date-fields timeFormat True string %H:%M Time Format on screensaver. Substring after ? is displayed in a seperate smaller textbox. Useful for 12h time format with AM/PM \"%I:%M ?%p\" dateAdditionalTemplate True string \"\" Addional Text dispayed after Date, can contain a Homeassistant Template Example \" - {{ states('sun.sun') }}\" timeAdditionalTemplate True string \"\" Addional Text dispayed below Time, can contain a Homeassistant Template dateFormat True string %A, %d. %B %Y date format used if babel is not installed timezone True string \"\" Timezone for the time on the panel: Europe/Berlin - See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of TZ Identifiers (supported from upcoming version v4.4) defaultBackgroundColor True string ha-dark backgroud color of all cards, valid values: black, ha-dark cards False complex configuration for cards that are displayed on panel; see docs for cards screensaver True complex configuration for screensaver; see docs for screensaver hiddenCards True complex configuration for cards that can be accessed though navigate items; see docs for cards","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#details-on-sleepbrightnessscreenbrightness-and-other-configs-related-to-screen-brightness","level":2,"title":"Details on sleepBrightness/screenBrightness and other configs related to screen brightness","text":"It is possible to schedule a brightness change for the screen at specific times.
sleepBrightness:\n - time: \"7:00:00\"\n value: 10\n - time: \"23:00:00\"\n value: 0\n sleepBrightness:\n - time: \"sunrise\"\n value: 10\n - time: \"sunset + 1:00:00\"\n value: 0\n It is also possible to use a static value or an input_number/sensor with the range between 0 and 100 as value for sleepBrightness/screenBrightness:
sleepBrightness: input_number.brightness_nspanel\n sleepBrightness: 50\n The config option sleepTracking overrides this setting and sets the brightness to 0 if the state of the configured Home Assistant entity is off or not_home. You may also use a Home Assistant group to track multiple entities.
The config option sleepOverride overrides sleepBrightness but does not take precedence over sleepTracking. This is useful if, for example, you want your NSPanel to be brighter than usual if your light is on or if you want to override a panel dimming if you are in the room.
The following example configuration is turning off the screen after sunset, but in case the bedroom light is on the NSPanel brightness will be 20 instead of 0.
sleepBrightness:\n - time: \"sunrise\"\n value: 20\n - time: \"sunset\"\n value: 0\n sleepOverride:\n entity: light.bedroomlight\n brightness: 20\n","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#supported-keys-for-locale-config","level":2,"title":"Supported keys for locale config","text":"Language Code Language af_ZA Afrikaans ar_SY Arabic bg_BG Bulgarian ca_ES Catalan cs_CZ Czech da_DK Danish de_DE German el_GR Greek en_US English es_ES Spanish et_EE Estonian fa_IR Persian fi_FI Finnish fr_FR French he_IL Hebrew hr_xx Croatian hu_HU Hungarian hy_AM Armenian id_ID Indonesian is_IS Icelandic it_IT Italian lb_xx Luxembourgish lt_LT Lithuanian lv_LV Latvian nb_NO Norwegian nl_NL Dutch nn_NO Norwegian pl_PL Polish pt_PT Portuguese ro_RO Romanian ru_RU Russian sk_SK Slovak sl_SI Slovenian sv_SE Swedish th_TH Thai tr_TR Turkish uk_UA Ukrainian vi_VN Vietnamese zh_CN Simplified Chinese zh_TW Traditional Chinese","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-overview/#customize-ota-urls","level":2,"title":"Customize OTA URLs","text":"In case you need to change the OTA URLs to do automatic updates without internet access for tasmota, you can modify the OTA URLs:
config:\n displayURL-US-L: \"http://example.com/us-l.tft\"\n displayURL-US-P: \"http://example.com/us-l.tft\"\n displayURL-EU: \"http://example.com/us-l.tft\"\n berryURL: \"http://exampe.com/autoexec.be\"\n","path":["Configuration - apps.yaml (Home Assistant)","Configuration"],"tags":[]},{"location":"config-screensaver/","level":1,"title":"Config screensaver","text":"","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"config-screensaver/#possible-configuration-values-for-screensaver-config","level":4,"title":"Possible configuration values for screensaver config","text":"key optional type default description entity True string weather.example weather entity from homeassistant entities True string None contains a list of entities of this card (will be used instead of entity) statusIcon1 True complex None status icon left to the date string, config similar to weatherOverride statusIcon2 True complex None status icon right to the date string, config similar to weatherOverride doubleTapToUnlock True boolean False requires to tap screensaver two times theme True complex configuration for theme defaultCard True string None default page after exiting screensaver; only works with top level cards defined in cards; needs to be a navigation item, see subpages (navigate.type_key) This config option will also be evaluated as a HomeAssistant Template. key True string None Used by navigate items type True string screensaver screensaver or screensaver2 Example for the a screensaver config with custom entities/overrides:
screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n - entity: weather.demo_weather_north\n type: 1\n - entity: weather.demo_weather_north\n type: 2\n - entity: sensor.energy_usage\n Using a 6th entity will automatically activate the alternative layout.
screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n - entity: weather.demo_weather_north\n type: 1\n - entity: sensor.energy_usage\n - entity: delete\n - entity: sensor.indoor_temp\n icon: mdi:home-thermometer-outline\n You can use override the options described on the entities documentation page to override colors, names or values of the entities.
With Version 4.0.0 there is another alternative layout for the screensaver:
Configuration is similar, you just need to add type: screensaver2 to switch the layout.
screensaver:\n type: screensaver2\n entities:\n - entity: weather.demo_weather_north\n","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"config-screensaver/#possible-configuration-values-for-screensaver-theme-config-only-normal-screensaver-layout-not-screensaver2","level":4,"title":"Possible configuration values for screensaver theme config (only normal screensaver layout not screensaver2)","text":"key option type default description background True list Black [R, G, B] time True list White [R, G, B] timeAMPM True list White [R, G, B] date True list White [R, G, B] tMainText True list White [R, G, B] tForecast1 True list White [R, G, B] tForecast2 True list White [R, G, B] tForecast3 True list White [R, G, B] tForecast4 True list White [R, G, B] tForecast1Val True list White [R, G, B] tForecast2Val True list White [R, G, B] tForecast3Val True list White [R, G, B] tForecast4Val True list White [R, G, B] bar True list White [R, G, B] tMainTextAlt2 True list White [R, G, B] tTimeAdd True list White [R, G, B] Specify colours as red green and blue values from 0-255 e.g. [255, 0, 0] for red or [0, 0, 255] for blue. These are translated internally to RGB565 (note that this has lower color depth so the colours may not appear the same). Also note that the screen has a low contrast ratio, so colors look sigificantly different at full display brightness and lowest brightness.
Example for the theme config:
screensaver:\n theme:\n date: [255, 0, 0]\n Config Example for configured statusIcons screensaver:\n entity: weather.k3ll3r\n statusIcon1:\n entity: switch.example_item\n statusIcon2:\n entity: binary_sensor.example_item\n It is possible to increase the size of the font used for the icons by adding altFont: True to the statusIcon configuration. Icon/Color Overrides are also possible like on any other Entity.
screensaver:\n entity: weather.k3ll3r\n statusIcon1:\n entity: switch.example_item\n altFont: True\n statusIcon2:\n entity: binary_sensor.example_item\n altFont: True\n Config Example for all white icons on screensaver screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 1\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 2\n color: [255,255,255]\n - entity: weather.demo_weather_north\n type: 3\n color: [255,255,255]\n Config Example for a custom date format on forecast screensaver:\n entities:\n - entity: weather.demo_weather_north\n - entity: weather.demo_weather_north\n type: 0\n name: \"%a %-d/%-m\"\n - entity: weather.demo_weather_north\n type: 1\n name: \"%a %-d/%-m\"\n - entity: weather.demo_weather_north\n name: \"%a %-d/%-m\"\n type: 2\n - entity: weather.demo_weather_north\n name: \"%a %-d/%-m\"\n type: 3\n See Babel Documentation (https://babel.pocoo.org/en/latest/dates.html#date-fields) or the Python Documenation (https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes) in case you do not have babel installed.","path":["Configuration - apps.yaml (Home Assistant)","Config screensaver"],"tags":[]},{"location":"configure_mqtt/","level":1,"title":"Configure MQTT on Tasmota","text":"Configure your MQTT Server in Tasmota. See Tasmota MQTT Documentation for more details.
Please leave the Full Topic as it is in default configuration (and on the screenshot).
Change the topic to something unique for your panel, you will need this topic later in the configuration of your panel in appdaemon / apps.yaml
","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"configure_mqtt/#note-for-appdeamon-addon-version-15","level":1,"title":"Note for Appdeamon Addon Version >= 15","text":"The configuration has been moved out of the config folder from homeassistant. This is how you can access it with the VSCode Addon.
","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"configure_mqtt/#configure-mqtt-connection-on-appdaemon","level":1,"title":"Configure MQTT Connection on AppDaemon","text":"For the app to work you need a working MQTT Configuration in AppDaemon. Please add the configuration of your mqtt server, user and password to your existing appdaemon.yaml Restart your AppDaemon Container (not HomeAssistant) after adding the MQTT Configuration.
You will find this file in the following location: /addon_configs/a0d7b954_appdaemon/appdeamon.yaml
---\nsecrets: /homeassistant/secrets.yaml\nappdaemon:\n latitude: 52.0\n longitude: 4.0\n elevation: 2\n time_zone: Europe/Berlin\n app_dir: /homeassistant/appdaemon/apps/ # !!! This is really important for AppDaemon HA Addon >= 15\n plugins:\n HASS:\n type: hass\n MQTT:\n type: mqtt\n namespace: mqtt\n client_id: \"appdaemon\"\n client_host: core-mosquitto.local.hass.io # This should work if you are using supervised HomeAssistant; if not use the IP Address instead.\n #client_host: 192.168.75.30\n client_port: 1883\n client_user: \"mqttuser\"\n client_password: \"mqttpassword\"\n client_topics: NONE\nhttp:\n url: http://127.0.0.1:5050\nadmin:\napi:\nhadashboard:\n","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"configure_mqtt/#configure-nspanel-on-appdaemon","level":1,"title":"Configure NsPanel on AppDaemon","text":"Please add the following minimal configuration to your apps.yaml, which is located in config/appdaemon/apps/apps.yaml
Note: You need to move your apps.yaml to this location if it isn't there.
---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_your_mqtt_topic/RESULT\"\n panelSendTopic: \"cmnd/tasmota_your_mqtt_topic/CustomSend\"\n model: eu\n Please adjust tasmota_your_mqtt_topic to the topic used in Tasmota MQTT Configuration.
If your configuration is correct you should get the following screens on your panel:
Note: You can add multiple panels to this configuration:---\nnspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/first-nspanel-topic/RESULT\"\n panelSendTopic: \"cmnd/first-nspanel-topic/CustomSend\"\nnspanel-2:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/second-nspanel-topic/RESULT\"\n panelSendTopic: \"cmnd/second-nspanel-topic/CustomSend\"\n","path":["Getting started (Home Assistant)","First steps","Configure MQTT on Tasmota"],"tags":[]},{"location":"entities/","level":1,"title":"Entities","text":"Entities are mainly used on cardEntities and cardGrid.
It is possible to overwrite and configure varrious things on Entities.
","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#possible-configuration-values-for-entities-key","level":2,"title":"Possible configuration values for entities key:","text":"key optional type default descriptionentity False string None name of ha entity name True string None Used to override names (supports home assistant templates) value True string None Used to override the value (supports home assistant templates) icon True string None Used to override icons color True array None Overwrite color of entity color: [255, 0, 0] state True string None Only displayed if Entity state is equal to this value state_not True string None Only displayed if Entity state is unequal to this value status True string None Only valid for navigate and service items, adds a entity to track state for the icon assumed_state True string None Only for cover items, up, down and stop buttons are always shown action_name True string None Only valid for script; Button label font True string None Used to change the font for cardGrid Icons; valid values are (small, medium-icon and medium). Currently only supported for homeassistant entities and not for internal ones. effectList True string None Only valid for light; for example [Android, Aurora (fav list for effects)","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#override-icons-or-names","level":2,"title":"Override Icons or Names","text":"To overwrite Icons or Names of entities you can configure an icon and/or name in your configuration, please see the following example. Only the icons listed in the Icon Cheatsheet are useable.
entities:\n - entity: light.test_item\n name: NameOverride\n icon: mdi:lightbulb\n It is also possible to configure different icon overwrites per state:
icon:\n \"on\": mdi:lightbulb\n \"off\": mdi:lightbulb\n It is also possible to configure different color overwrites per state:
color:\n \"on\": [255,0,0]\n \"off\": [0,0,255]\n Dynamic color overwrites using homeassistant templates: color: '{{iif(states(\"binary_sensor.test\")==\"on\", \"[0,255,0]\", \"[255,165,0]\")}}'\n It is also possible to use text instead of icons with text:X
icon:\n \"on\": mdi:lightbulb\n \"off\": \"text:\"\n Note: State Overrides are working with all state values, not only with \"on\" and \"off\".
To insert dynamic values from a homeassistant template, like a temperature you can also use ha: which will be rendered as homeassistant template. There probably not much cases where this is needed, but here is an exmaple to show the current temperature on the status icon of the screensaver:
statusIcon2:\n entity: climate.wohnzimmer_boden\n icon: 'ha:{{ state_attr(\"climate.wohnzimmer_boden\",\"current_temperature\")}}'\n If you want to display icons from a template you can put them between <I></I>
icon: 'ha:{{ iif(is_state('light.kitchen', 'on'), '<I>mdi:flashlight</I>', '<I>mdi:flashlight-off</I>') }}'\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#hide-item-based-on-state","level":2,"title":"Hide item based on state","text":"This sensor will only be shown on the card if it's state is equal to off
- entity: binary_sensor.sensor_bad_contact\n state: \"off\"\n This sensor will only be shown on the card if it's state is not equal to on
- entity: binary_sensor.sensor_kueche_contact\n state_not: \"on\"\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#hide-item-based-on-ha-template","level":2,"title":"Hide item based on HA Template","text":"The template must evaluate to true for the entity to hide.
- entity: binary_sensor.sensor_kueche_contact\n state_template: '{{ state_attr(\"sun.sun\",\"azimuth\") < 200 }}'\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"entities/#calling-service-directly-as-button","level":2,"title":"Calling service directly as button","text":"The following example shows how to call services directly, this enables you to call services on entities not (yet) supported by the backend and also to pass data to services.
- entity: service.light.turn_on\n data:\n entity_id: light.schreibtischlampe\n color_name: \"green\"\n","path":["Configuration - apps.yaml (Home Assistant)","Entities"],"tags":[]},{"location":"faq/","level":1,"title":"FAQ - Frequently Asked Questions","text":"","path":["Getting started (Home Assistant)","FAQ - Frequently Asked Questions"],"tags":[]},{"location":"faq/#waiting-for-content-this-is-taking-longer-than-usual-on-the-screen","level":2,"title":"Waiting for content - This is taking longer than usual on the screen","text":"You have most likely an error in your MQTT configuration somewhere. To find the error follow theese steps:
Check the location of your apps.yaml With the AppDaemon Addon >= 15 the config dir has been moved. It's required to configure the location back to the old one, this is done by the app_dir line in your appdaemon.yaml. This also requires you to move your apps.yaml to this location. Please make sure your apps.yaml is at /config/appdaemon/apps/apps.yaml and move it otherwise.
Check your appdaemon log. (Settings > Add-ons > AppDaemon > Log) You should see something like this: INFO MQTT: MQTT Plugin initialization complete If you are seeing Messages like this: CRITICAL MQTT: Could not complete MQTT Plugin initialization, for Connection was refused due to Not Authorised Your appdaemon mqtt config is wrong, check your appdaemon.yaml. The log of your mqtt broker might give you additional information.
Check MQTT Configuration of Tasmota. Your Tasmota device needs to connect sucessfully to your MQTT Broker, if you are in the waiting for content screen, the panel will send periodic messages to it's mqtt topic. Note that there is a minimum password length of 5 chars for the MQTT Connection in Tasmota.
Make sure that you are using the same topic in apps.yaml and in your tasmota configuration. The examples in the docs (MQTT Config) are an valid example (tasmota<>apps.yaml). Please don't modify the Full Topic in your Tasmota Config, unless you know the implications, changing the Full Topic will result in diffent Send and Receive Channels, that have to be correct in your apps.yaml.
If you are still in the waiting for content screen please share the following items, with the Waiting for Content Issue type on the Github Issues Page
HACS will show you that there is an update avalible and ask you to update. It is important to restart the AppDaemon Container afterwards.
","path":["Getting started (Home Assistant)","FAQ - Frequently Asked Questions"],"tags":[]},{"location":"faq/#update-display-firmware","level":3,"title":"Update Display Firmware","text":"You should get an notification on the screen, asking you to update the firmware. In case you want to update manually you can use the following commands.
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
You should get an notification on the screen, asking you to update the driver, if an update is needed.
You can update the berry driver directly from the Tasmota Console with the following command.
UpdateDriverVersion https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be
Click redownload in the menu of the app in HACS.
Select main version.
!!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!!
!!! Wait for it to load, dropdown needs to be selectable again, otherwise it will download the latest release !!!
Click download.
Restart AppDaemon
Flash current Development Firmware in Tasmota Console. DO NOT USE THIS VERSION/URLS IF YOUR ARE NOT ON THE DEVELOPMENT VERSION
EU VERSION: FlashNextion http://nspanel.pky.eu/lui.tft
Development happens in the EU version, so it is possible that the US Version isn't up to date with the current development version of the EU firmware, the lastet US versions are still downloadable with the following links:
US LANDSCAPE: FlashNextion http://nspanel.pky.eu/lui-us-l.tft
US PORTRAIT: FlashNextion http://nspanel.pky.eu/lui-us-p.tft
The HMI Project of this project is only used to display stuff, navigation ist mostly up to the backend. This allows to be way more flexible.
Messages to the Panel can be send through the Command CustomSend, which is implemented in the berry driver. You can issue this command through MQTT by sending messages to the cmnd/XXX/CustomSend Topic. Messages from the Panel are send to the tele/XXX/RESULT Topic, encoded in json {\"CustomRecv\":\"message_from_screen\"}
On startup the panel will send {\"CustomRecv\":\"event,startup,39,eu\"} every few seconds.
event, #Every message from the screen will start with `event`\nstartup, #Startup Event\n39, #Current HMI Project Version\neu #Current HMI Project Model\n You can answer this message in many different ways, but in general the goal is to navigate way from the startup page. In the following example we will navigate to the screensaver page.
Send the following messages to the CustomSend Topic. (You can also send them on tasmota console for testing)
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#some-preperation-before-we-are-acually-navigating-away","level":3,"title":"Some preperation before we are acually navigating away:","text":"Send this every minute: time~18:17
Send this at least once at midnight: date~Donnerstag, 25. August 2022
Send theese message once after receiving the startup event (parameters will be explained later):
timeout~20
dimmode~10~100~6371
pageType~screensaver
After sending this command you should already see the time and date. To also show weather data you have to send them with weatherUpdate, but we will skip this for now.
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#exit-screensaver","level":3,"title":"Exit Screensaver","text":"Touching the panel on the screensaver will result in this MQTT Message on the result topic:
event,buttonPress2,screensaver,bExit,1
You can answer this by sending theese commands to the CustomSend Topic.
pageType~cardEntities
entityUpd~test~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~light~light.schreibtischlampe~X~17299~Schreibtischlampe~0~text~sensor.server_energy_power~Y~17299~Server ENERGY Power~155 W~shutter~cover.rolladenfenster_cover_1~Z~17299~Fenster Eingang~A|B|C|disable|enable|enable~switch~switch.bad~D~63142~Bad~1
set brightness of screensaver and active-brightness:
dimmode~0~100 - (screen off)
dimmode~100~100 - (screen on with full brightness)
set current time:
time~22:26
set current date:
date~Di 24. Februar
set screensaver timeout (set time in sec~ max 65):
timeout~15 - timeout after 15 seconds
timeout~0 - disable screensaver
change the page type:
pageType~pageStartup
pageType~cardEntities
pageType~cardThermo
pageType~cardMedia
pageType~popupLight~Schreibtischlampe~light.schreibtischlampe
pageType~popupNotify
pageType~screensaver
color~background~tTime~timeAMPM~tDate~tMainText~tForecast1~tForecast2~tForecast3~tForecast4~tForecast1Val~tForecast2Val~tForecast3Val~tForecast4Val~bar~tMainTextAlt2~tTimeAdd
notify~heading~text
statusUpdate~icon1~icon1Color~icon2~icon2~icon2color~icon1font~icon2font
Structure (Category): entityUpd~title~[navigation]~[entity_information] Example with 4 Entities:
entityUpd~LightTest~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~light~light.bed_light~A~17299~Bed Light~0~light~light.ceiling_lights~B~52231~Ceiling Lights~1~switch~switch.ac~C~17299~AC~0~switch~switch.decorative_lights~D~65222~Decorative Lights~1\n Possible entities on cardEntities/cardGrid:
~light~light.entityName~1~17299~Light1~0
~shutter~cover.entityName~0~17299~Shutter2~iconUp|iconStop|iconDown
~delete~~~~~
~text~sensor.entityName~3~17299~Temperature~content
~button~button.entityName~3~17299~bt-name~bt-text
~switch~switch.entityName~4~17299~Switch1~0
~number~input_number.entityName~4~17299~Number123~value|min|max
~input_sel~input_select.entityName~3~17299~sel-name~sel-text
cardGrid is using the exact same messageformat like cardEntities does. The only difference is, it ignores the information supplied in optionalValue, because it isn't needed for cardGrid.
Parameter Number Category Location Type Field Addional Information 0 instruction instruction entityUpd 1 title title title title 2 Navigation Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 Entities First Entity Entity Definition type 15 intNameEntity 16 icon 17 iconColor 18 displayName 19 optionalValue ignored 20 Second Entity Entity Definition type 21 intNameEntity 22 icon 23 iconColor 24 displayName 25 optionalValue ignored 26 Thrid Entity Entity Definition type 27 intNameEntity 28 icon 29 iconColor 30 displayName 31 optionalValue ignored 32 Forth Entiry Entity Definition type 33 intNameEntity 34 icon 35 iconColor 36 displayName 37 optionalValue ignored 38 Fifth Entiy (US Portrait Version) Entity Definition type 39 intNameEntity 40 icon 41 iconColor 42 displayName 43 optionalValue ignored 44 Sixth Entiy (US Portrait Version) Entity Definition type 45 intNameEntity 46 icon 47 iconColor 48 displayName 49 optionalValue ignored","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardmedia","level":3,"title":"cardMedia","text":"Example without icons in bottom row: entityUpd~Kitchen~button~navigation.up~U~65535~~~delete~~~~~~media_player.kitchen~I'm a Hurricane~~Wellmess~~100~A~64704~B~media_pl~media_player.kitchen~C~17299~Kitchen~
Serial Protocol of cardThermo is about to change; table will be completed later
Parameter Number Location Type Field Addional Information 0 instruction entityUpd 1 title title title 2 Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 intNameEntity 15 2nd text box currentTemp 16 target temperature dstTemp multiplied by 10 17 Text 4th Box Left Side status 18 Min Temp minTemp multiplied by 10 19 Max Temp maxTemp multiplied by 10 20 Temperature Steps tempStep multiplied by 10 21 bottom hvac_action 1 Hvac Action icon 22 iconColorActive 23 buttonState 24 intName 25 bottom hvac_action 2 Hvac Action icon 26 iconColorActive 27 buttonState 28 intName 29 bottom hvac_action 3 Hvac Action icon 30 iconColorActive 31 buttonState 32 intName 33 bottom hvac_action 4 Hvac Action icon 34 iconColorActive 35 buttonState 36 intName 37 bottom hvac_action 5 Hvac Action icon 38 iconColorActive 39 buttonState 40 intName 41 bottom hvac_action 6 Hvac Action icon 42 iconColorActive 43 buttonState 44 intName 45 bottom hvac_action 7 Hvac Action icon 46 iconColorActive 47 buttonState 48 intName 49 bottom hvac_action 8 Hvac Action icon 50 iconColorActive 51 buttonState 52 intName 53 Currently Label 1th Text Box tCurTempLbl 54 State Label 3th Text Box tStateLbl 55 tALbl deprecated; ignored 56 Temperature Unit (Celcius/Farhenheit) tCF 57 Second Destination Tempature (Heat/Cool) second temp ; multiplied by 10 58 additonal detail button to open another page btDetail \"1\" to hide","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardalarm","level":3,"title":"cardAlarm","text":"Parameter Number Category Location Type Field Addional Information 0 instruction instruction entityUpd 1 title title title title 2 Navigation Upper Left Icon Entity Definition type (ignored)¹ 3 intNameEntity 4 icon 5 iconColor 6 displayName ignored 7 optionalValue ignored 8 Upper Right Icon Entity Definition type (ignored)¹ 9 intNameEntity 10 icon 11 iconColor 12 displayName ignored 13 optionalValue ignored 14 cardAlarm specific card intNameEntity intNameEntity 15 1st button right side displayName 16 intId 17 2nd button right side displayName 18 intId 19 3rd button right side displayName 20 intId 21 4th button right side displayName 22 intId 23 icon next to code display icon 24 iconColor 25 numpad numpadStatus \"disable\" or \"enable\" 26 flashing of icon next to code flashing status \"enable\" or \"disable\" 27 button bottom left corner icon 28 iconColor 29 intNameEntity","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#cardqr","level":3,"title":"cardQR","text":"Example: entityUpd~Guest Wifi~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~WIFI:S:test_ssid;T:WPA;P:test_pw;;~text~iText.test_ssid~���~17299~Name~test_ssid~text~iText.test_pw~���~17299~Password~test_pw
entityUpd~PowerTest~x~navUp~A~65535~~~delete~~~~~~text~sensor.power_consumption~B~17299~Power consumption~100W~1~text~sensor.power_consumption~C~17299~Power consumption~100W~1~text~sensor.today_energy~D~17299~Total energy 1~5836.0kWh~0~delete~~~~~~0~text~sensor.today_energy~E~17299~Total energy 1~5836.0kWh~-30~delete~~~~~~0~text~sensor.today_energy~F~65504~Total energy 1~5836.0kWh~90~text~sensor.today_energy~G~17299~Total energy 1~5836.0kWh~10
entityUpd~heading~navigation~color~yAxisLabel~yAxisTick:[yAxisTick]*[~value[:xAxisLabel]?]*
entityUpd~Chart Demo~~button~navigate.prev~<~65535~~~button~navigate.next~>~65535~~~~6666~Gas [kWh]~20:40:60:80:100~10~7^2:00~7~6^4:00~6~7^6:00~0~7^8:00~5~1^10:00~1~10^12:00~5~6^14:00~8
entityUpdateDetail~entityName~*ignored*~*iconColor*~*buttonState*~*sliderBrightnessPos*~*sliderColorTempPos*~*colorMode*~*color_translation*~*color_temp_translation*~*brightness_translation*
entityUpdateDetail~1~17299~1~100~78~enable
entityUpdateDetail~1~17299~1~100~disable
entityUpdateDetail~entityName~*sliderPos*~2ndrow~textPosition~icon1~iconUp~iconStop~iconDown~iconUpStatus~iconStopStatus~iconDownStatus~textTilt~iconTiltLeft~iconTiltStop~iconTiltRight~iconTiltLeftStatus~iconTiltStopStatus~iconTiltLeftStatus~tiltPos
entityUpdateDetail~1~77
entityUpdateDetail~*internalName*~*tHeading*~*tHeadingColor*~*b1*~*tB1Color*~*b2*~*tB2Color*~*tText*~*tTextColor*~*sleepTimeout*~*font*~*alt_icon*~*altIconColor*
exitPopup
entityUpdateDetail~{entity_id}~{icon_id}~{icon_color}~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~{heading}~{mode}~mode1~mode1?mode2?mode3~
entityUpdateDetail2~*entity_id*~~*icon_color*~*input_sel*~*state*~*options*
options are ? seperated
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#popuptimer","level":3,"title":"popupTimer","text":"editable is 0 or 1
action fields are in the answer on the button press
in case action is empty the button will be hidden
entityUpdateDetail~{entity_id}~~{icon_color}~{entity_id}~{min_remaining}~{sec_remaining}~{editable}~{action1}~{action2}~{action3}~{label1}~{label2}~{label3}
event,buttonPress2,pageName,bNext
event,buttonPress2,pageName,bPrev
event,buttonPress2,pageName,bExit,number_of_taps
event,buttonPress2,pageName,sleepReached
event,startup,version,model
event,buttonPress2,screensaver,exit - Touch Event on Screensaver
event,screensaverOpen - Screensaver has opened
event,*eventName*,*entityName*,*actionName*,*optionalValue*
event,buttonPress2,internalNameEntity,up
event,buttonPress2,internalNameEntity,down
event,buttonPress2,internalNameEntity,stop
event,buttonPress2,internalNameEntity,OnOff,1
event,buttonPress2,internalNameEntity,button
event,pageOpenDetail,popupLight,internalNameEntity
event,buttonPress2,internalNameEntity,OnOff,1
event,buttonPress2,internalNameEntity,brightnessSlider,50
event,buttonPress2,internalNameEntity,colorTempSlider,50
event,buttonPress2,internalNameEntity,colorWheel,x|y|wh
event,pageOpenDetail,popupShutter,internalNameEntity
event,buttonPress2,internalNameEntity,positionSlider,50
event,buttonPress2,*internalName*,notifyAction,yes
event,buttonPress2,*internalName*,notifyAction,no
event,buttonPress2,*entityName*,tempUpd,*temperature*
event,buttonPress2,*entityName*,hvac_action,*hvac_action*
event,buttonPress2,internalNameEntity,media-back
event,buttonPress2,internalNameEntity,media-pause
event,buttonPress2,internalNameEntity,media-next
event,buttonPress2,internalNameEntity,volumeSlider,75
event,buttonPress2,internalNameEntity,actionName,code
55 BB [payload length] [payload length] [payload] [crc] [crc]\n Payload length contains the number of bytes of the payload.
CRC is \"CRC-16 (MODBUS) Big Endian\" calculated over the whole message
This protocol does not try to implement broken JSON Commands with a specified type (lol). Instead the commands are plain text commands with parameters.
","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"hmi-serial-protocol/#example-for-valid-message","level":2,"title":"Example for valid Message","text":"This message has to be generated for the Message \"1337\" (1337 is not a valid command~ this is just an example)
55 BB 04 00 31 33 33 37 5F 5B\n","path":["NSPanel Lovelace UI"],"tags":[]},{"location":"iobroker-install/","level":1,"title":"Installation - ioBroker","text":"The Backend for ioBroker is maintained by britzelpuf and armilar
See the wiki for documentation around setting lovelace-ui up with ioBroker
Wiki
Also see the Readme in the ioBroker Folder. iobroker ReadMe
","path":["Getting started (ioBroker)","Installation - ioBroker"],"tags":[]},{"location":"notifications/","level":1,"title":"Sending Notifications to the Panel","text":"There are two notification types, that can be triggered by sending a command over mqtt to the panel here are examples for homeassistant scripts:
","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#seperate-page","level":2,"title":"Seperate Page","text":"This is the notification used by the backend for updates, opening it requires to the following commands to the CustomSend Topic:
pageType popupNotify
entityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText
Alternative Layout with Icon:
entityUpdateDetail~internalName~heading~headingColor~button1text~button1color~button2text~tB2Color~notificationText~textColor~sleepTimeout~fontIdText~icon~iconColor
fontIdText is the font used by the notification text Possible values are 0-5:
Font 0 - Default - Size 24 (No Icons, Support for various special chars from different langs)\nFont 1 - Size 32 (Icons and limited chars)\nFont 2 - Size 32 (No Icons, Support for various special chars from different langs)\nFont 3 - Size 48 (Icons and limited chars)\nFont 4 - Size 80 (Icons and limited chars)\nFont 5 - Size 128 (ascii only)\n You need to use the acual char for the icon instead of the icon name which is used in the configuration. You can get the char of the icon from the cheatsheet.
https://docs.nspanel.pky.eu/icon-cheatsheet.html
It is possible to exit from the page by sending exitPopup
If you want to add newlines to your message add this string for the newline {{'\\r\\n'}}
Send Message to the Panel combined with a buzzer sound:
nspanel_popup_notification:\n alias: Popup Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{\n title }}~65535~~~~~{{ message }}~65535~{{ timeout }}; Buzzer 2,2,2\n mode: single\n icon: mdi:message-badge\n Send Message to the Panel:
nspanel_popup_notification:\n alias: Popup Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend pageType~popupNotify; CustomSend entityUpdateDetail~id~{{\n title }}~65535~~~~~{{ message }}~65535~{{ timeout }}\n mode: single\n icon: mdi:message-badge\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#notification-on-screensaver","level":2,"title":"Notification on screensaver","text":"The screensaver can display Notifications by sending this command to the CustomSend topic: notify~heading~text
Send Message to the Screensaver combined with a buzzer sound:
nspanel_screensaver_notification:\n alias: Screensaver Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend notify~{{ heading }}~{{ message }}; Buzzer 2,2,2\n mode: single\n icon: mdi:message-badge\n Send Message to the Screensaver:
nspanel_screensaver_notification:\n alias: Screensaver Notification\n sequence:\n - service: mqtt.publish\n data:\n topic: cmnd/tasmota_NsPanelTerrasse/Backlog\n payload: CustomSend notify~{{ heading }}~{{ message }}\n mode: single\n icon: mdi:message-badge\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#buzzer","level":2,"title":"Buzzer","text":"See Tasmota Buzzer for commands.
It might be necessary to enable the buzzer with:
BuzzerPWM 1\n","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"notifications/#color-picker","level":2,"title":"Color Picker","text":"Decimal RGB565: 0
","path":["Configuration - apps.yaml (Home Assistant)","Sending Notifications to the Panel"],"tags":[]},{"location":"phys-btn/","level":1,"title":"Change behaviour of hardware buttons","text":"","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"phys-btn/#tasmota-rules","level":2,"title":"Tasmota Rules","text":"You can configure the buttons to mimic an UI element on the screen by configuring tasmota rules.
The following rule will change the behaviour of the two buttons to do page navigation.
Rule2 on Button1#state do Publish tele/%topic%/RESULT {\"CustomRecv\":\"event,buttonPress2,navPrev,button\"} endon on Button2#state do Publish tele/%topic%/RESULT {\"CustomRecv\":\"event,buttonPress2,navNext,button\"} endon\n\nRule2 1\n","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"phys-btn/#decouple-buttons-from-controlling-power-outputs","level":2,"title":"Decouple buttons from controlling power outputs","text":"If you do not want your NSPanel physical buttons to trigger the relays and prefer to have them as software configurable buttons, open the Tasmota console of your NSPanel and enter the following:
SetOption73 1
Your relays will now appear as switches in HomeAssistant and you can control your buttons by using automations:
You may reverse this change by entering the following in the Tasmota console of your NSPanel:
SetOption73 0
Please note: Doing this will mean that if HomeAssistant is not working for any reason your buttons will not function correctly.
","path":["Configuration - apps.yaml (Home Assistant)","Change behaviour of hardware buttons"],"tags":[]},{"location":"prepare_ha/","level":1,"title":"Setup Home Assistant","text":"","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-appdaemon","level":2,"title":"Installing AppDaemon","text":"The backend application for HomeAssistant is written in a python for AppDaemon. This means it requires a working and running installation of AppDaemon.
The easiest way to install it is through Home Assistant's Supervisor Add-on Store, it will be automaticly connected to your Home Assistant Instance.
Instructions for users of HomeAssistant Core installed through docker containers. In case you have a homeassistant setup using docker cotainers and the Add-on Store is not available to you, you can follow this guide for setting up AppDaemon. https://appdaemon.readthedocs.io/en/latest/DOCKER_TUTORIAL.html Please also pay attention to the correct volume mount for the conf folder of appdaemon, that has to point to the appdaemon folder within your homeassistant config folder. Here is an example docker compose file for homeassistant and appdaemon:version: \"3.5\"\nservices:\n homeassistant:\n image: ghcr.io/home-assistant/home-assistant:stable\n container_name: homeassistant\n network_mode: host\n volumes:\n - ./docker-data/homeassistant/:/config\n - /etc/localtime:/etc/localtime:ro\n environment:\n - TZ=Europe/Berlin\n privileged: true\n restart: unless-stopped\n\n appdaemon:\n container_name: appdaemon\n image: acockburn/appdaemon:4.2.3\n environment:\n - HA_URL=http://your-homeassistant-url:8123\n - TOKEN=\"xxxxxx\"\n volumes:\n - /etc/localtime:/etc/localtime:ro\n - ./docker-data/homeassistant/appdaemon:/conf\n depends_on:\n - homeassistant\n restart: unless-stopped\n","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#add-babel-package-to-appdaemon-container-optional","level":3,"title":"Add babel package to AppDaemon Container (Optional)","text":"For localisation (date in your local language) you need to add the python package babel to your AppDaemon Installation.
","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-studio-code-server","level":2,"title":"Installing Studio Code Server","text":"You will need a way to edit the apps.yaml config file in the Appdaemon folder. Install Studio Code Server from Home Assistant's Supervisor Add-on Store to easily edit configuration Files on your HomeAssistant Instance.
HACS is the Home Assistant Community Store and allows for community integrations and automations to be updated easily from the Home Assistant web user interface. You will be notified of updates, and they can be installed by a click on a button.
","path":["Getting started (Home Assistant)","First steps","Setup Home Assistant"],"tags":[]},{"location":"prepare_ha/#installing-lovelace-appdaemon-backend-application","level":2,"title":"Installing Lovelace AppDaemon Backend Application","text":"To install Lovelace UI Backend App with HACS, you will need to make sure that you enabled AppDaemon automations in HACS, as these are not enabled by default:
Configuration on the left menu bar in Home Assistant Web UIDevices & ServicesIntegrationsHACS and click on ConfigureEnable AppDaemon apps discovery & tracking is checked, or check it and click SubmitNow, to install NSPanel Lovelace UI Backend with HACS, follow these steps:
HACS on the left menu bar in Home Assistant Web UIAutomations in the right panelExplore & download repositories in the bottom right cornerNSPanel, and click on NSPanel Lovelace UI Backend in the list that appearsDownload this repository with HACSDownload, and wait for HACS to proceed with the downloadYou need to connect to your NSPanel via serial and flash Tasmota using tasmota32-nspanel.bin. You can use the Tasmota Web Installer to do so.
Check out Blakadder's Template Repo for more information on flashing. Do not use the autoexec.be from that page. NSPanel Page of the Tasmota Template Repository
If you prefer ESPHome over Tasmota, you can use this third-party ESPHome component, which replaces Tasmota and the Berry driver used in this project. ESPHome Component
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#configure-tasmota-template-for-nspanel","level":2,"title":"Configure Tasmota Template for NSPanel","text":"Configure the NSPanel template for Tasmota. (Go to Configuration > Configure Other, paste the template there, and make sure to tick the Activate checkbox.)
You can use the following template or copy the one from the Tasmota Template Repo Site:
{\"NAME\":\"NSPanel\",\"GPIO\":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],\"FLAG\":0,\"BASE\":1,\"CMND\":\"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1\"}
After a reboot of Tasmota, your screen will light up with the stock display firmware.
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#upload-berry-driver-to-tasmota","level":2,"title":"Upload Berry Driver to Tasmota","text":"Go to Consoles > Console in Tasmota and execute the following command:
Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; SetOption151 0; Restart 1
This downloads the autoexec.be file from the repository and restarts Tasmota.
Note: This command also disables Matter to free up memory, as it's unlikely to be used by most Home Assistant users. (Matter can cause memory issues during flashing of the Nextion screen, but you can re-enable it later if needed.)
","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel/#flash-firmware-to-nextion-screen","level":2,"title":"Flash Firmware to Nextion Screen","text":"Due to the limitations of Berry, it's not possible to download the TFT file directly from GitHub. A small server is available to download the file via HTTP.
Use one of the following commands in the Tasmota console (not the Berry console) to flash the latest release from this repository:
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
After sending the command, the screen should show a progress bar. The flashing process takes around 5 minutes.
Note for US users: You'll need to add the model config option to your apps.yaml later. More details can be found on the config overview page.
Alternatively, you can use your own web server or the one built into Home Assistant: Upload the nspanel.tft from the latest release to a web server (for example, the www folder of Home Assistant) and execute the following command in the Tasmota Console. (Development version: [TFT file from HMI folder](HMI/nspanel.tft)) **The web server must be HTTP. HTTPS is not supported due to Berry language limitations in Tasmota.** FlashNextion http://ip-address-of-your-homeassistant:8123/local/nspanel.tft","path":["Getting started (Home Assistant)","First steps","Flash Tasmota to Your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/","level":1,"title":"Flash Tasmota to your NSPanel","text":"You need to connect to your nspanel via serial and flash tasmota tasmota32-nspanel.bin to your NSPanel. You can use the Tasmota Web Installer to do so. Tasmota Web Installer
Checkout Blakadders Template Repo for more information on flashing, do not use the autoexec.be from this page. NSPanel Page of the Tasmota Template Repository
If you prefer EspHome over Tasmota, you can use this thrid party esphome component, which is replacing tasmota and the berry driver of this project. ESPHome component
","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#configure-tasmota-template-for-nspanel","level":2,"title":"Configure Tasmota Template for NSPanel","text":"Configure the NSPanel template for Tasmota. (Go to Configuration and Configure Other and paste the template there, make sure to tick the activate checkbox)
You can use the following template or copy the one on the Tasmota Template Repo Site.
{\"NAME\":\"NSPanel\",\"GPIO\":[0,0,0,0,3872,0,0,0,0,0,32,0,0,0,0,225,0,480,224,1,0,0,0,33,0,0,0,0,0,0,0,0,0,0,4736,0],\"FLAG\":0,\"BASE\":1,\"CMND\":\"ADCParam 2,11200,10000,3950 | Sleep 0 | BuzzerPWM 1\"}
After a reboot of tasmota your screen will light up with the stock display firmware.
","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#upload-berry-driver-to-tasmota","level":2,"title":"Upload Berry Driver to Tasmota","text":"Go to Consoles > Console in Tasmota and execute the following command:
Backlog UrlFetch https://raw.githubusercontent.com/joBr99/nspanel-lovelace-ui/main/tasmota/autoexec.be; Restart 1\n","path":["Getting started (ioBroker)","Flash Tasmota to your NSPanel"],"tags":[]},{"location":"prepare_nspanel_ioBroker/#flash-firmware-to-nextion-screen","level":2,"title":"Flash Firmware to Nextion Screen","text":"Due the limitations of Berry, it's not possible to download the tft file directly from github, so I'm also renting a small server where you can download the file via HTTP.
Use the one following commands to flash the latest release from this repository, just execute the following Command in Tasmota:
EU Version: FlashNextion http://nspanel.pky.eu/lui-release.tft
US Version Portrait: FlashNextion http://nspanel.pky.eu/lui-us-p-release.tft
US Version Landscape: FlashNextion http://nspanel.pky.eu/lui-us-l-release.tft
You can configure entities with with the prefix navigate, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the previous page.
- entity: navigate.testKey\n will allow you to navigate to a cardGrid page with the configured key testKey
hiddenCards:\n - type: cardGrid\n title: Exmaple Grid\n entities:\n - entity: light.test_item\n key: testKey\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]},{"location":"subpages/#override-status-of-navigation-items","level":1,"title":"Override Status of Navigation Items","text":"You can override the status of navigation items, to make them look like different entities.
- entity: navigate.testKey\n status: climate.test\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]},{"location":"subpages/#override-navigation-items-itself","level":1,"title":"Override Navigation Items itself","text":" cards:\n - type: cardGrid\n title: Wohnzimmer\n navItem1:\n entity: light.bad_lights\n navItem2:\n entity: light.bad_lights\n entities:\n This can be used to add an home button to your subpages:
cards:\n - type: cardGrid\n title: Home\n key: home\n entities:\n - entity: light.bad\n\n hiddenCards:\n - type: cardGrid\n title: Wohnzimmer\n navItem2:\n entity: navigate.home\n icon: mdi:home\n entities:\n - entity: light.kitchen\n","path":["Configuration - apps.yaml (Home Assistant)","Subpages"],"tags":[]}]}
\ No newline at end of file
diff --git a/stable/sitemap.xml b/stable/sitemap.xml
new file mode 100644
index 00000000..59676548
--- /dev/null
+++ b/stable/sitemap.xml
@@ -0,0 +1,66 @@
+
+You can configure entities with with the prefix navigate, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the previous page.
- entity: navigate.testKey
+will allow you to navigate to a cardGrid page with the configured key testKey
+ hiddenCards:
+ - type: cardGrid
+ title: Exmaple Grid
+ entities:
+ - entity: light.test_item
+ key: testKey
+You can override the status of navigation items, to make them look like different entities.
+ - entity: navigate.testKey
+ status: climate.test
+
cards:
+ - type: cardGrid
+ title: Wohnzimmer
+ navItem1:
+ entity: light.bad_lights
+ navItem2:
+ entity: light.bad_lights
+ entities:
+This can be used to add an home button to your subpages:
+ cards:
+ - type: cardGrid
+ title: Home
+ key: home
+ entities:
+ - entity: light.bad
+
+ hiddenCards:
+ - type: cardGrid
+ title: Wohnzimmer
+ navItem2:
+ entity: navigate.home
+ icon: mdi:home
+ entities:
+ - entity: light.kitchen
+i&&s.push(r(n,i,d));let{value:h}=c[u];s.push(t(n,{start:d,end:i=m,value:h}))}return i{let o=n.data;switch(o.type){case 1:na.value=!0;break;case 3:typeof o.data.pagination.prev<"u"?it.value=He(H({},it.value),{pagination:o.data.pagination,items:[...it.value.items,...o.data.items]}):(it.value=o.data,ao(0));break}},qt(()=>{lr.value&&r.postMessage({type:0,data:lr.value})}),qt(()=>{na.value&&r.postMessage({type:2,data:Se.value})})}var oa={container:"p",hidden:"m"};function Mu(e){return z("div",{class:zt(oa.container,{[oa.hidden]:e.hidden}),onClick:()=>Dt()})}var ia={container:"r",disabled:"c"};function so(e){return z("button",{class:zt(ia.container,{[ia.disabled]:!e.onClick}),onClick:e.onClick,children:e.children})}var aa=e=>e.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),ku=e=>e.replace(/^([A-Z])|[\s-_]+(\w)/g,(t,r,n)=>n?n.toUpperCase():r.toLowerCase()),sa=e=>{let t=ku(e);return t.charAt(0).toUpperCase()+t.slice(1)},Au=(...e)=>e.filter((t,r,n)=>!!t&&t.trim()!==""&&n.indexOf(t)===r).join(" ").trim(),Cu={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round"},Hu=c=>{var l=c,{color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:n,children:o,iconNode:i,class:a=""}=l,s=gr(l,["color","size","strokeWidth","absoluteStrokeWidth","children","iconNode","class"]);return Wt("svg",H(He(H({},Cu),{width:String(t),height:t,stroke:e,"stroke-width":n?Number(r)*24/Number(t):r,class:["lucide",a].join(" ")}),s),[...i.map(([u,p])=>Wt(u,p)),...Cr(o)])},bo=(e,t)=>{let r=a=>{var s=a,{class:n="",children:o}=s,i=gr(s,["class","children"]);return Wt(Hu,He(H({},i),{iconNode:t,class:Au(`lucide-${aa(sa(e))}`,`lucide-${aa(e)}`,n)}),o)};return r.displayName=sa(e),r},$u=bo("corner-down-left",[["path",{d:"M20 4v7a4 4 0 0 1-4 4H4",key:"6o5b7l"}],["path",{d:"m9 10-5 5 5 5",key:"1kshq7"}]]),Pu=bo("list-filter",[["path",{d:"M2 5h20",key:"1fs1ex"}],["path",{d:"M6 12h12",key:"8npq4p"}],["path",{d:"M9 19h6",key:"456am0"}]]),Iu=bo("search",[["path",{d:"m21 21-4.34-4.34",key:"14j7rj"}],["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}]]),Yx=ml(dl(),1);function Ru({threshold:e=0,root:t=null,rootMargin:r="0%",freezeOnceVisible:n=!1,initialIsIntersecting:o=!1,onChange:i}={}){var a;let[s,c]=ro(null),[l,u]=ro(()=>({isIntersecting:o,entry:void 0})),p=Vt();p.current=i;let d=((a=l.entry)==null?void 0:a.isIntersecting)&&n;St(()=>{if(!s||!("IntersectionObserver"in window)||d)return;let v,S=new IntersectionObserver(x=>{let w=Array.isArray(S.thresholds)?S.thresholds:[S.thresholds];x.forEach(_=>{let de=_.isIntersecting&&w.some(be=>_.intersectionRatio>=be);u({isIntersecting:de,entry:_}),p.current&&p.current(de,_),de&&n&&v&&(v(),v=void 0)})},{threshold:e,root:t,rootMargin:r});return S.observe(s),()=>{S.disconnect()}},[s,JSON.stringify(e),t,r,d,n]);let m=Vt(null);St(()=>{var v;!s&&(v=l.entry)!=null&&v.target&&!n&&!d&&m.current!==l.entry.target&&(m.current=l.entry.target,u({isIntersecting:o,entry:void 0}))},[s,l.entry,n,d,o]);let h=[c,!!l.isIntersecting,l.entry];return h.ref=h[0],h.isIntersecting=h[1],h.entry=h[2],h}var lt={container:"n",hidden:"l",content:"u",pop:"d",badge:"y",sidebar:"i",controls:"w",results:"k",loadmore:"z"};function ju(e){let{isIntersecting:t,ref:r}=Ru({threshold:0});St(()=>{t&&au()},[t]);let n=Vt(null);St(()=>{n.current&&typeof Se.value.page>"u"&&n.current.scrollTo({top:0,behavior:"smooth"})},[Se.value]);let o=za();return z("div",{class:zt(lt.container,{[lt.hidden]:e.hidden}),children:[z("div",{class:lt.content,children:[z("div",{class:lt.controls,children:[z(so,{onClick:Dt,children:z(Iu,{})}),z(Uu,{focus:!e.hidden}),z(so,{onClick:Wa,children:[z(Pu,{}),o.length>0&&z("span",{class:lt.badge,children:o.length})]})]}),z("div",{class:lt.results,ref:n,children:[z(Nu,{keyboard:!e.hidden}),z("div",{class:lt.loadmore,ref:r})]})]}),z("div",{class:zt(lt.sidebar,{[lt.hidden]:fu()}),children:z(Fu,{})})]})}var Et={container:"X",list:"j",heading:"F",title:"I",item:"o",active:"g",value:"R",count:"q"};function Fu(e){let t=pu();return t.sort((r,n)=>n.node.count-r.node.count),z("div",{class:Et.container,children:[z("h3",{class:Et.heading,children:"Filters"}),z("h4",{class:Et.title,children:"Tags"}),z("ol",{class:Et.list,children:t.map(r=>z("li",{class:zt(Et.item,{[Et.active]:su(r.node.value)}),onClick:()=>cu(r.node.value),children:[z("span",{class:Et.value,children:r.node.value}),z("span",{class:Et.count,children:r.node.count})]}))})]})}var ca={container:"f"};function Uu(e){let t=Vt(null);return St(()=>{var r,n;e.focus?(r=t.current)==null||r.focus():(n=t.current)==null||n.blur()},[e.focus]),z("div",{class:ca.container,children:z("input",{ref:t,type:"text",class:ca.content,value:hn(vo()),onInput:r=>Va(_u(r.currentTarget.value)),autocapitalize:"off",autocomplete:"off",autocorrect:"off",placeholder:"Search",spellcheck:!1,role:"combobox"})})}var ut={container:"b",heading:"A",item:"a",active:"h",wrapper:"B",actions:"s",title:"x",path:"t"};function Nu(e){var a;let t=iu(),r=lu(),n=dn(),o=Vt([]);St(()=>{let s=o.current[n];s&&s.scrollIntoView({block:"center",behavior:"smooth"})},[n]),Aa(e.keyboard,s=>{let c=dn();s.key==="ArrowDown"?(s.preventDefault(),ao(Math.min(c+1,r.length-1))):s.key==="ArrowUp"&&(s.preventDefault(),ao(Math.max(c-1,0)))},[e.keyboard]);let i=(a=uu())!=null?a:0;return z(ft,{children:[r.length>0&&z("h3",{class:ut.heading,children:[z("span",{class:ut.bubble,children:new Intl.NumberFormat("en-US").format(i)})," ","results"]}),z("ol",{class:ut.container,children:r.map((s,c)=>{var d;let l=Ka(t[s.id].title,s.matches.find(({field:m})=>m==="title")),u=Lu((d=t[s.id].path)!=null?d:[],s.matches.find(({field:m})=>m==="path")),p=t[s.id].location;if(mu()){let m=encodeURIComponent(vo()),[h,v]=p.split("#",2);p=`${h}?h=${m.replace(/%20/g,"+")}`,typeof v<"u"&&(p+=`#${v}`)}return z("li",{children:z("a",{ref:m=>{o.current[c]=m},href:p,onClick:()=>Dt(),class:zt(ut.item,{[ut.active]:c===dn()}),children:[z("div",{class:ut.wrapper,children:[z("h2",{class:ut.title,children:l}),z("menu",{class:ut.path,children:u.map(m=>z("li",{children:m}))})]}),z("nav",{class:ut.actions,children:z(so,{children:z($u,{})})})]})})})})]})}var Du={container:"e"};function Wu(e){return Aa(!0,t=>{var r,n,o;if((t.metaKey||t.ctrlKey)&&t.key==="k")t.preventDefault(),Dt();else if((t.metaKey||t.ctrlKey)&&t.key==="j")document.body.classList.toggle("dark");else if(t.key==="Enter"&&!sr()){t.preventDefault(),Dt();let i=dn(),a=(n=(r=it.value)==null?void 0:r.items[i])==null?void 0:n.id;(o=lr.value)!=null&&o.items[a].location&&(window.location.href=lr.value.items[a].location)}else t.key==="Escape"&&!sr()&&(t.preventDefault(),Dt())},[]),z("div",{class:Du.container,children:[z(Mu,{hidden:sr()}),z(ju,{hidden:sr()})]})}function Ya(e,t){ou(e),xl(z(Wu,{}),t)}function go(){Dt()}function Vu(e,t){switch(e.constructor){case HTMLInputElement:return e.type==="radio"?/^Arrow/.test(t):!0;case HTMLSelectElement:case HTMLTextAreaElement:return!0;default:return e.isContentEditable}}function zu(){return R(b(window,"compositionstart").pipe(f(()=>!0)),b(window,"compositionend").pipe(f(()=>!1))).pipe(J(!1))}function Ga(){let e=b(window,"keydown").pipe(f(t=>({mode:sr()?"global":"search",type:t.key,meta:t.ctrlKey||t.metaKey,claim(){t.preventDefault(),t.stopPropagation()}})),L(({mode:t,type:r})=>{if(t==="global"){let n=yt();if(typeof n!="undefined")return!Vu(n,r)}return!0}),xe());return zu().pipe(g(t=>t?y:e))}function Ye(){return new URL(location.href)}function mt(e,t=!1){if(X("navigation.instant")&&!t){let r=A("a",{href:e.href});document.body.appendChild(r),r.click(),r.remove()}else location.href=e.href}function Ja(){return new I}function Xa(){return location.hash.slice(1)}function Za(e){let t=A("a",{href:e});t.addEventListener("click",r=>r.stopPropagation()),t.click()}function _o(e){return R(b(window,"hashchange"),e).pipe(f(Xa),J(Xa()),L(t=>t.length>0),se(1))}function Qa(e){return _o(e).pipe(f(t=>Le(`[id="${t}"]`)),L(t=>typeof t!="undefined"))}function Ir(e){let t=matchMedia(e);return an(r=>t.addListener(()=>r(t.matches))).pipe(J(t.matches))}function es(){let e=matchMedia("print");return R(b(window,"beforeprint").pipe(f(()=>!0)),b(window,"afterprint").pipe(f(()=>!1))).pipe(J(e.matches))}function yo(e,t){return e.pipe(g(r=>r?t():y))}function xo(e,t){return new U(r=>{let n=new XMLHttpRequest;return n.open("GET",`${e}`),n.responseType="blob",n.addEventListener("load",()=>{n.status>=200&&n.status<300?(r.next(n.response),r.complete()):r.error(new Error(n.statusText))}),n.addEventListener("error",()=>{r.error(new Error("Network error"))}),n.addEventListener("abort",()=>{r.complete()}),typeof(t==null?void 0:t.progress$)!="undefined"&&(n.addEventListener("progress",o=>{var i;if(o.lengthComputable)t.progress$.next(o.loaded/o.total*100);else{let a=(i=n.getResponseHeader("Content-Length"))!=null?i:0;t.progress$.next(o.loaded/+a*100)}}),t.progress$.next(5)),n.send(),()=>n.abort()})}function et(e,t){return xo(e,t).pipe(g(r=>r.text()),f(r=>JSON.parse(r)),se(1))}function xn(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/html")),se(1))}function ts(e,t){let r=new DOMParser;return xo(e,t).pipe(g(n=>n.text()),f(n=>r.parseFromString(n,"text/xml")),se(1))}var wo={drawer:G("[data-md-toggle=drawer]"),search:G("[data-md-toggle=search]")};function Eo(e,t){wo[e].checked!==t&&wo[e].click()}function wn(e){let t=wo[e];return b(t,"change").pipe(f(()=>t.checked),J(t.checked))}function rs(){return{x:Math.max(0,scrollX),y:Math.max(0,scrollY)}}function ns(){return R(b(window,"scroll",{passive:!0}),b(window,"resize",{passive:!0})).pipe(f(rs),J(rs()))}function os(){return{width:innerWidth,height:innerHeight}}function is(){return b(window,"resize",{passive:!0}).pipe(f(os),J(os()))}function as(){return re([ns(),is()]).pipe(f(([e,t])=>({offset:e,size:t})),se(1))}function En(e,{viewport$:t,header$:r}){let n=t.pipe(fe("size")),o=re([n,r]).pipe(f(()=>xt(e)));return re([r,t,o]).pipe(f(([{height:i},{offset:a,size:s},{x:c,y:l}])=>({offset:{x:a.x-c,y:a.y-l+i},size:s})))}var qu=G("#__config"),mr=JSON.parse(qu.textContent);mr.base=`${new URL(mr.base,Ye())}`;function Ue(){return mr}function X(e){return mr.features.includes(e)}function Bt(e,t){return typeof t!="undefined"?mr.translations[e].replace("#",t.toString()):mr.translations[e]}function dt(e,t=document){return G(`[data-md-component=${e}]`,t)}function Ee(e,t=document){return P(`[data-md-component=${e}]`,t)}function Ku(e){let t=G(".md-typeset > :first-child",e);return b(t,"click",{once:!0}).pipe(f(()=>G(".md-typeset",e)),f(r=>({hash:__md_hash(r.innerHTML)})))}function ss(e){if(!X("announce.dismiss")||!e.childElementCount)return y;if(!e.hidden){let t=G(".md-typeset",e);__md_hash(t.innerHTML)===__md_get("__announce")&&(e.hidden=!0)}return j(()=>{let t=new I;return t.subscribe(({hash:r})=>{e.hidden=!0,__md_set("__announce",r)}),Ku(e).pipe($(r=>t.next(r)),V(()=>t.complete()),f(r=>H({ref:e},r)))})}function Bu(e,{target$:t}){return t.pipe(f(r=>({hidden:r!==e})))}function cs(e,t){let r=new I;return r.subscribe(({hidden:n})=>{e.hidden=n}),Bu(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))}function To(e,t){return t==="inline"?A("div",{class:"md-tooltip md-tooltip--inline",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"})):A("div",{class:"md-tooltip",id:e,role:"tooltip"},A("div",{class:"md-tooltip__inner md-typeset"}))}function Tn(...e){return A("div",{class:"md-tooltip2",role:"dialog"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function ls(...e){return A("div",{class:"md-tooltip2",role:"tooltip"},A("div",{class:"md-tooltip2__inner md-typeset"},e))}function us(e,t){if(t=t?`${t}_annotation_${e}`:void 0,t){let r=t?`#${t}`:void 0;return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("a",{href:r,class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}else return A("aside",{class:"md-annotation",tabIndex:0},To(t),A("span",{class:"md-annotation__index",tabIndex:-1},A("span",{"data-md-annotation-id":e})))}function ps(e){return A("button",{class:"md-code__button",title:Bt("clipboard.copy"),"data-clipboard-target":`#${e} > code`,"data-md-type":"copy"})}function fs(){return A("button",{class:"md-code__button",title:"Toggle line selection","data-md-type":"select"})}function ms(){return A("nav",{class:"md-code__nav"})}var Ju=_r(So());function hs(e){return A("ul",{class:"md-source__facts"},Object.entries(e).map(([t,r])=>A("li",{class:`md-source__fact md-source__fact--${t}`},typeof r=="number"?Li(r):r)))}function Oo(e){let t=`tabbed-control tabbed-control--${e}`;return A("div",{class:t,hidden:!0},A("button",{class:"tabbed-button",tabIndex:-1,"aria-hidden":"true"}))}function vs(e){return A("div",{class:"md-typeset__scrollwrap"},A("div",{class:"md-typeset__table"},e))}function Xu(e){var n;let t=Ue(),r=new URL(`../${e.version}/`,t.base);return A("li",{class:"md-version__item"},A("a",{href:`${r}`,class:"md-version__link"},e.title,((n=t.version)==null?void 0:n.alias)&&e.aliases.length>0&&A("span",{class:"md-version__alias"},e.aliases[0])))}function bs(e,t){var n;let r=Ue();return e=e.filter(o=>{var i;return!((i=o.properties)!=null&&i.hidden)}),A("div",{class:"md-version"},A("button",{class:"md-version__current","aria-label":Bt("select.version")},t.title,((n=r.version)==null?void 0:n.alias)&&t.aliases.length>0&&A("span",{class:"md-version__alias"},t.aliases[0])),A("ul",{class:"md-version__list"},e.map(Xu)))}var Zu=0;function Qu(e,t=250){let r=re([ir(e),Ft(e,t)]).pipe(f(([o,i])=>o||i),ie()),n=j(()=>Ai(e)).pipe(oe(Ut),Lr(1),Ze(r),f(()=>Ci(e)));return r.pipe(Sr(o=>o),g(()=>re([r,n])),f(([o,i])=>({active:o,offset:i})),xe())}function Rr(e,t,r=250){let{content$:n,viewport$:o}=t,i=`__tooltip2_${Zu++}`;return j(()=>{let a=new I,s=new jn(!1);a.pipe(he(),ye(!1)).subscribe(s);let c=s.pipe(Tr(u=>Ve(+!u*250,Nn)),ie(),g(u=>u?n:y),$(u=>u.id=i),xe());re([a.pipe(f(({active:u})=>u)),c.pipe(g(u=>Ft(u,250)),J(!1))]).pipe(f(u=>u.some(p=>p))).subscribe(s);let l=s.pipe(L(u=>u),pe(c,o),f(([u,p,{size:d}])=>{let m=e.getBoundingClientRect(),h=m.width/2;if(p.role==="tooltip")return{x:h,y:8+m.height};if(m.y>=d.height/2){let{height:v}=Ae(p);return{x:h,y:-16-v}}else return{x:h,y:16+m.height}}));return re([c,a,l]).subscribe(([u,{offset:p},d])=>{u.style.setProperty("--md-tooltip-host-x",`${p.x}px`),u.style.setProperty("--md-tooltip-host-y",`${p.y}px`),u.style.setProperty("--md-tooltip-x",`${d.x}px`),u.style.setProperty("--md-tooltip-y",`${d.y}px`),u.classList.toggle("md-tooltip2--top",d.y<0),u.classList.toggle("md-tooltip2--bottom",d.y>=0)}),s.pipe(L(u=>u),pe(c,(u,p)=>p),L(u=>u.role==="tooltip")).subscribe(u=>{let p=Ae(G(":scope > *",u));u.style.setProperty("--md-tooltip-width",`${p.width}px`),u.style.setProperty("--md-tooltip-tail","0px")}),s.pipe(ie(),Ie(je),pe(c)).subscribe(([u,p])=>{p.classList.toggle("md-tooltip2--active",u)}),re([s.pipe(L(u=>u)),c]).subscribe(([u,p])=>{p.role==="dialog"?(e.setAttribute("aria-controls",i),e.setAttribute("aria-haspopup","dialog")):e.setAttribute("aria-describedby",i)}),s.pipe(L(u=>!u)).subscribe(()=>{e.removeAttribute("aria-controls"),e.removeAttribute("aria-describedby"),e.removeAttribute("aria-haspopup")}),Qu(e,r).pipe($(u=>a.next(u)),V(()=>a.complete()),f(u=>H({ref:e},u)))})}function Ge(e,{viewport$:t},r=document.body){return Rr(e,{content$:new U(n=>{let o=e.title,i=ls(o);return n.next(i),e.removeAttribute("title"),r.append(i),()=>{i.remove(),e.setAttribute("title",o)}}),viewport$:t},0)}function ep(e,t){let r=j(()=>re([Hi(e),Ut(t)])).pipe(f(([{x:n,y:o},i])=>{let{width:a,height:s}=Ae(e);return{x:n-i.x+a/2,y:o-i.y+s/2}}));return ir(e).pipe(g(n=>r.pipe(f(o=>({active:n,offset:o})),Me(+!n||1/0))))}function gs(e,t,{target$:r}){let[n,o]=Array.from(e.children);return j(()=>{let i=new I,a=i.pipe(he(),ye(!0));return i.subscribe({next({offset:s}){e.style.setProperty("--md-tooltip-x",`${s.x}px`),e.style.setProperty("--md-tooltip-y",`${s.y}px`)},complete(){e.style.removeProperty("--md-tooltip-x"),e.style.removeProperty("--md-tooltip-y")}}),wt(e).pipe(Q(a)).subscribe(s=>{e.toggleAttribute("data-md-visible",s)}),R(i.pipe(L(({active:s})=>s)),i.pipe(Be(250),L(({active:s})=>!s))).subscribe({next({active:s}){s?e.prepend(n):n.remove()},complete(){e.prepend(n)}}),i.pipe(Xe(16,je)).subscribe(({active:s})=>{n.classList.toggle("md-tooltip--active",s)}),i.pipe(Lr(125,je),L(()=>!!e.offsetParent),f(()=>e.offsetParent.getBoundingClientRect()),f(({x:s})=>s)).subscribe({next(s){s?e.style.setProperty("--md-tooltip-0",`${-s}px`):e.style.removeProperty("--md-tooltip-0")},complete(){e.style.removeProperty("--md-tooltip-0")}}),b(o,"click").pipe(Q(a),L(s=>!(s.metaKey||s.ctrlKey))).subscribe(s=>{s.stopPropagation(),s.preventDefault()}),b(o,"mousedown").pipe(Q(a),pe(i)).subscribe(([s,{active:c}])=>{var l;if(s.button!==0||s.metaKey||s.ctrlKey)s.preventDefault();else if(c){s.preventDefault();let u=e.parentElement.closest(".md-annotation");u instanceof HTMLElement?u.focus():(l=yt())==null||l.blur()}}),r.pipe(Q(a),L(s=>s===n),It(125)).subscribe(()=>e.focus()),ep(e,t).pipe($(s=>i.next(s)),V(()=>i.complete()),f(s=>H({ref:e},s)))})}function tp(e){let t=Ue();if(e.tagName!=="CODE")return[e];let r=[".c",".c1",".cm"];if(t.annotate){let n=e.closest("[class|=language]");if(n)for(let o of Array.from(n.classList)){if(!o.startsWith("language-"))continue;let[,i]=o.split("-");i in t.annotate&&r.push(...t.annotate[i])}}return P(r.join(", "),e)}function rp(e){let t=[];for(let r of tp(e)){let n=[],o=document.createNodeIterator(r,NodeFilter.SHOW_TEXT);for(let i=o.nextNode();i;i=o.nextNode())n.push(i);for(let i of n){let a;for(;a=/(\(\d+\))(!)?/.exec(i.textContent);){let[,s,c]=a;if(typeof c=="undefined"){let l=i.splitText(a.index);i=l.splitText(s.length),t.push(l)}else{i.textContent=s,t.push(i);break}}}}return t}function _s(e,t){t.append(...Array.from(e.childNodes))}function Sn(e,t,{target$:r,print$:n}){let o=t.closest("[id]"),i=o==null?void 0:o.id,a=new Map;for(let s of rp(t)){let[,c]=s.textContent.match(/\((\d+)\)/);Le(`:scope > li:nth-child(${c})`,e)&&(a.set(c,us(c,i)),s.replaceWith(a.get(c)))}return a.size===0?y:j(()=>{let s=new I,c=s.pipe(he(),ye(!0)),l=[];for(let[u,p]of a)l.push([G(".md-typeset",p),G(`:scope > li:nth-child(${u})`,e)]);return n.pipe(Q(c)).subscribe(u=>{e.hidden=!u,e.classList.toggle("md-annotation-list",u);for(let[p,d]of l)u?_s(p,d):_s(d,p)}),R(...[...a].map(([,u])=>gs(u,t,{target$:r}))).pipe(V(()=>s.complete()),xe())})}function ys(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return ys(t)}}function xs(e,t){return j(()=>{let r=ys(e);return typeof r!="undefined"?Sn(r,e,t):y})}var Es=_r(Mo());var np=0,ws=R(b(window,"keydown").pipe(f(()=>!0)),R(b(window,"keyup"),b(window,"contextmenu")).pipe(f(()=>!1))).pipe(J(!1),se(1));function Ts(e){if(e.nextElementSibling){let t=e.nextElementSibling;if(t.tagName==="OL")return t;if(t.tagName==="P"&&!t.children.length)return Ts(t)}}function op(e){return Re(e).pipe(f(({width:t})=>({scrollable:Mr(e).width>t})),fe("scrollable"))}function Ss(e,t){let{matches:r}=matchMedia("(hover)"),n=j(()=>{let o=new I,i=o.pipe(Bn(1));o.subscribe(({scrollable:m})=>{m&&r?e.setAttribute("tabindex","0"):e.removeAttribute("tabindex")});let a=[],s=e.closest("pre"),c=s.closest("[id]"),l=c?c.id:np++;s.id=`__code_${l}`;let u=[],p=e.closest(".highlight");if(p instanceof HTMLElement){let m=Ts(p);if(typeof m!="undefined"&&(p.classList.contains("annotate")||X("content.code.annotate"))){let h=Sn(m,e,t);u.push(Re(p).pipe(Q(i),f(({width:v,height:S})=>v&&S),ie(),g(v=>v?h:y)))}}let d=P(":scope > span[id]",e);if(d.length&&(e.classList.add("md-code__content"),e.closest(".select")||X("content.code.select")&&!e.closest(".no-select"))){let m=+d[0].id.split("-").pop(),h=fs();a.push(h),X("content.tooltips")&&u.push(Ge(h,{viewport$}));let v=b(h,"click").pipe(Or(M=>!M,!1),$(()=>h.blur()),xe());v.subscribe(M=>{h.classList.toggle("md-code__button--active",M)});let S=me(d).pipe(oe(M=>Ft(M).pipe(f(O=>[M,O]))));v.pipe(g(M=>M?S:y)).subscribe(([M,O])=>{let N=Le(".hll.select",M);if(N&&!O)N.replaceWith(...Array.from(N.childNodes));else if(!N&&O){let ee=document.createElement("span");ee.className="hll select",ee.append(...Array.from(M.childNodes).slice(1)),M.append(ee)}});let x=me(d).pipe(oe(M=>b(M,"mousedown").pipe($(O=>O.preventDefault()),f(()=>M)))),w=v.pipe(g(M=>M?x:y),pe(ws),f(([M,O])=>{var ee;let N=d.indexOf(M)+m;if(O===!1)return[N,N];{let le=P(".hll",e).map(ce=>d.indexOf(ce.parentElement)+m);return(ee=window.getSelection())==null||ee.removeAllRanges(),[Math.min(N,...le),Math.max(N,...le)]}})),_=_o(y).pipe(L(M=>M.startsWith(`__codelineno-${l}-`)));_.subscribe(M=>{let[,,O]=M.split("-"),N=O.split(":").map(le=>+le-m+1);N.length===1&&N.push(N[0]);for(let le of P(".hll:not(.select)",e))le.replaceWith(...Array.from(le.childNodes));let ee=d.slice(N[0]-1,N[1]);for(let le of ee){let ce=document.createElement("span");ce.className="hll",ce.append(...Array.from(le.childNodes).slice(1)),le.append(ce)}}),_.pipe(Me(1),Ie(ge)).subscribe(M=>{if(M.includes(":")){let O=document.getElementById(M.split(":")[0]);O&&setTimeout(()=>{let N=O,ee=-64;for(;N!==document.body;)ee+=N.offsetTop,N=N.offsetParent;window.scrollTo({top:ee})},1)}});let be=me(P('a[href^="#__codelineno"]',p)).pipe(oe(M=>b(M,"click").pipe($(O=>O.preventDefault()),f(()=>M)))).pipe(Q(i),pe(ws),f(([M,O])=>{let ee=+G(`[id="${M.hash.slice(1)}"]`).parentElement.id.split("-").pop();if(O===!1)return[ee,ee];{let le=P(".hll",e).map(ce=>+ce.parentElement.id.split("-").pop());return[Math.min(ee,...le),Math.max(ee,...le)]}}));R(w,be).subscribe(M=>{let O=`#__codelineno-${l}-`;M[0]===M[1]?O+=M[0]:O+=`${M[0]}:${M[1]}`,history.replaceState({},"",O),window.dispatchEvent(new HashChangeEvent("hashchange",{newURL:window.location.origin+window.location.pathname+O,oldURL:window.location.href}))})}if(Es.default.isSupported()&&(e.closest(".copy")||X("content.code.copy")&&!e.closest(".no-copy"))){let m=ps(s.id);a.push(m),X("content.tooltips")&&u.push(Ge(m,{viewport$}))}if(a.length){let m=ms();m.append(...a),s.insertBefore(m,e)}return op(e).pipe($(m=>o.next(m)),V(()=>o.complete()),f(m=>H({ref:e},m)),Rt(R(...u).pipe(Q(i))))});return X("content.lazy")?wt(e).pipe(L(o=>o),Me(1),g(()=>n)):n}function ip(e,{target$:t,print$:r}){let n=!0;return R(t.pipe(f(o=>o.closest("details:not([open])")),L(o=>e===o),f(()=>({action:"open",reveal:!0}))),r.pipe(L(o=>o||!n),$(()=>n=e.open),f(o=>({action:o?"open":"close"}))))}function Os(e,t){return j(()=>{let r=new I;return r.subscribe(({action:n,reveal:o})=>{e.toggleAttribute("open",n==="open"),o&&e.scrollIntoView()}),ip(e,t).pipe($(n=>r.next(n)),V(()=>r.complete()),f(n=>H({ref:e},n)))})}var Ls=0,Ms=new Map;function ap(e){let t=document.createElement("h3");t.innerHTML=e.innerHTML;let r=[t],n=e.nextElementSibling;for(;n&&!(n instanceof HTMLHeadingElement);)r.push(n.cloneNode(!0)),n=n.nextElementSibling;return r}function sp(e,t){for(let r of P("[href], [src]",e))for(let n of["href","src"]){let o=r.getAttribute(n);if(o&&!/^(?:[a-z]+:)?\/\//i.test(o)){r[n]=new URL(r.getAttribute(n),t).toString();break}}for(let r of P("[name^=__], [for]",e))for(let n of["id","for","name"]){let o=r.getAttribute(n);o&&r.setAttribute(n,`${o}$preview_${Ls}`)}return Ls++,Y(e)}function cp(e){let t=Ms.get(e.toString());return t?Y(t):xn(e).pipe(g(r=>sp(r,e)),f(r=>(Ms.set(e.toString(),r),r)))}function ks(e,t){let{sitemap$:r}=t;if(!(e instanceof HTMLAnchorElement))return y;if(!(X("navigation.instant.preview")||e.hasAttribute("data-preview")))return y;e.removeAttribute("title");let n=re([ir(e),Ft(e).pipe(ke(1))]).pipe(f(([i,a])=>i||a),ie(),L(i=>i));return $t([r,n]).pipe(g(([i])=>{let a=new URL(e.href);return a.search=a.hash="",i.has(`${a}`)?Y(a):y}),g(i=>cp(i)),g(i=>{let a=e.hash?`article [id="${e.hash.slice(1)}"]`:"article h1",s=Le(a,i);return typeof s=="undefined"?y:Y(ap(s))})).pipe(g(i=>{let a=new U(s=>{let c=Tn(...i);return s.next(c),document.body.append(c),()=>c.remove()});return Rr(e,H({content$:a},t))}))}var As=".node circle,.node ellipse,.node path,.node polygon,.node rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}marker{fill:var(--md-mermaid-edge-color)!important}.edgeLabel .label rect{fill:#0000}.flowchartTitleText{fill:var(--md-mermaid-label-fg-color)}.label{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.label foreignObject{line-height:normal;overflow:visible}.label div .edgeLabel{color:var(--md-mermaid-label-fg-color)}.edgeLabel,.edgeLabel p,.label div .edgeLabel{background-color:var(--md-mermaid-label-bg-color)}.edgeLabel,.edgeLabel p{fill:var(--md-mermaid-label-bg-color);color:var(--md-mermaid-edge-color)}.edgePath .path,.flowchart-link{stroke:var(--md-mermaid-edge-color)}.edgePath .arrowheadPath{fill:var(--md-mermaid-edge-color);stroke:none}.cluster rect{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}.cluster span{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}g #flowchart-circleEnd,g #flowchart-circleStart,g #flowchart-crossEnd,g #flowchart-crossStart,g #flowchart-pointEnd,g #flowchart-pointStart{stroke:none}.classDiagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.classGroup line,g.classGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.classGroup text{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.classLabel .box{fill:var(--md-mermaid-label-bg-color);background-color:var(--md-mermaid-label-bg-color);opacity:1}.classLabel .label{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.node .divider{stroke:var(--md-mermaid-node-fg-color)}.relation{stroke:var(--md-mermaid-edge-color)}.cardinality{fill:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}.cardinality text{fill:inherit!important}defs marker.marker.composition.class path,defs marker.marker.dependency.class path,defs marker.marker.extension.class path{fill:var(--md-mermaid-edge-color)!important;stroke:var(--md-mermaid-edge-color)!important}defs marker.marker.aggregation.class path{fill:var(--md-mermaid-label-bg-color)!important;stroke:var(--md-mermaid-edge-color)!important}.statediagramTitleText{fill:var(--md-mermaid-label-fg-color)}g.stateGroup rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}g.stateGroup .state-title{fill:var(--md-mermaid-label-fg-color)!important;font-family:var(--md-mermaid-font-family)}g.stateGroup .composit{fill:var(--md-mermaid-label-bg-color)}.nodeLabel,.nodeLabel p{color:var(--md-mermaid-label-fg-color);font-family:var(--md-mermaid-font-family)}a .nodeLabel{text-decoration:underline}.node circle.state-end,.node circle.state-start,.start-state{fill:var(--md-mermaid-edge-color);stroke:none}.end-state-inner,.end-state-outer{fill:var(--md-mermaid-edge-color)}.end-state-inner,.node circle.state-end{stroke:var(--md-mermaid-label-bg-color)}.transition{stroke:var(--md-mermaid-edge-color)}[id^=state-fork] rect,[id^=state-join] rect{fill:var(--md-mermaid-edge-color)!important;stroke:none!important}.statediagram-cluster.statediagram-cluster .inner{fill:var(--md-default-bg-color)}.statediagram-cluster rect{fill:var(--md-mermaid-node-bg-color);stroke:var(--md-mermaid-node-fg-color)}.statediagram-state rect.divider{fill:var(--md-default-fg-color--lightest);stroke:var(--md-default-fg-color--lighter)}defs #statediagram-barbEnd{stroke:var(--md-mermaid-edge-color)}[id^=entity] path,[id^=entity] rect{fill:var(--md-default-bg-color)}.relationshipLine{stroke:var(--md-mermaid-edge-color)}defs .marker.oneOrMore.er *,defs .marker.onlyOne.er *,defs .marker.zeroOrMore.er *,defs .marker.zeroOrOne.er *{stroke:var(--md-mermaid-edge-color)!important}text:not([class]):last-child{fill:var(--md-mermaid-label-fg-color)}.actor{fill:var(--md-mermaid-sequence-actor-bg-color);stroke:var(--md-mermaid-sequence-actor-border-color)}text.actor>tspan{fill:var(--md-mermaid-sequence-actor-fg-color);font-family:var(--md-mermaid-font-family)}line{stroke:var(--md-mermaid-sequence-actor-line-color)}.actor-man circle,.actor-man line{fill:var(--md-mermaid-sequence-actorman-bg-color);stroke:var(--md-mermaid-sequence-actorman-line-color)}.messageLine0,.messageLine1{stroke:var(--md-mermaid-sequence-message-line-color)}.note{fill:var(--md-mermaid-sequence-note-bg-color);stroke:var(--md-mermaid-sequence-note-border-color)}.loopText,.loopText>tspan,.messageText,.noteText>tspan{stroke:none;font-family:var(--md-mermaid-font-family)!important}.messageText{fill:var(--md-mermaid-sequence-message-fg-color)}.loopText,.loopText>tspan{fill:var(--md-mermaid-sequence-loop-fg-color)}.noteText>tspan{fill:var(--md-mermaid-sequence-note-fg-color)}#arrowhead path{fill:var(--md-mermaid-sequence-message-line-color);stroke:none}.loopLine{fill:var(--md-mermaid-sequence-loop-bg-color);stroke:var(--md-mermaid-sequence-loop-border-color)}.labelBox{fill:var(--md-mermaid-sequence-label-bg-color);stroke:none}.labelText,.labelText>span{fill:var(--md-mermaid-sequence-label-fg-color);font-family:var(--md-mermaid-font-family)}.sequenceNumber{fill:var(--md-mermaid-sequence-number-fg-color)}rect.rect{fill:var(--md-mermaid-sequence-box-bg-color);stroke:none}rect.rect+text.text{fill:var(--md-mermaid-sequence-box-fg-color)}defs #sequencenumber{fill:var(--md-mermaid-sequence-number-bg-color)!important}";var ko,up=0;function pp(){return typeof mermaid=="undefined"||mermaid instanceof Element?ar("https://unpkg.com/mermaid@11/dist/mermaid.min.js"):Y(void 0)}function Cs(e){return e.classList.remove("mermaid"),ko||(ko=pp().pipe($(()=>mermaid.initialize({startOnLoad:!1,themeCSS:As,sequence:{actorFontSize:"16px",messageFontSize:"16px",noteFontSize:"16px"}})),f(()=>{}),se(1))),ko.subscribe(()=>Uo(null,null,function*(){e.classList.add("mermaid");let t=`__mermaid_${up++}`,r=A("div",{class:"mermaid"}),n=e.textContent,{svg:o,fn:i}=yield mermaid.render(t,n),a=r.attachShadow({mode:"closed"});a.innerHTML=o,e.replaceWith(r),i==null||i(a)})),ko.pipe(f(()=>({ref:e})))}var Hs=A("table");function $s(e){return e.replaceWith(Hs),Hs.replaceWith(vs(e)),Y({ref:e})}function fp(e){let t=e.find(r=>r.checked)||e[0];return R(...e.map(r=>b(r,"change").pipe(f(()=>G(`label[for="${r.id}"]`))))).pipe(J(G(`label[for="${t.id}"]`)),f(r=>({active:r})))}function Ps(e,{viewport$:t,target$:r}){let n=G(".tabbed-labels",e),o=P(":scope > input",e),i=Oo("prev");e.append(i);let a=Oo("next");return e.append(a),j(()=>{let s=new I,c=s.pipe(he(),ye(!0));re([s,Re(e),wt(e)]).pipe(Q(c),Xe(1,je)).subscribe({next([{active:l},u]){let p=xt(l),{width:d}=Ae(l);e.style.setProperty("--md-indicator-x",`${p.x}px`),e.style.setProperty("--md-indicator-width",`${d}px`);let m=ln(n);(p.x Keys: Notes: Notes: Keys: Keys: Keys: Typical target in The runtime reads one YAML file (default: Example: The rewrite supports two panel input/output modes. Enabled when: Behavior: Example receive payload: Enabled when key Behavior: Service payload shape: Entities are used in cards and screensaver lists. The rewrite supports Home Assistant template rendering for selected fields when prefixed with Example: In add-on mode, the container startup script: Relevant files: Start with one panel: If you run this container/process outside Supervisor: This documentation covers the standalone rewrite located in It is a Python backend that: This docs set is intentionally separate from the AppDaemon docs in This page explains how to migrate panel configuration from the legacy AppDaemon Old (AppDaemon): New (rewrite): Old AppDaemon ( New rewrite ( In AppDaemon setups, MQTT and Home Assistant connectivity was mostly configured via AppDaemon plugin settings. In the rewrite, connectivity is resolved directly by the runtime: Some legacy entity config fields are not implemented in the rewrite parser/renderer: Supported and commonly used fields in rewrite: Screensaver entities use the same entity format as other cards. For This documentation covers the standalone rewrite located in It is a Python backend that: This docs set is intentionally separate from the AppDaemon docs in Keys: Notes: Notes: Keys: Keys: Keys: Typical target in The runtime reads one YAML file (default: Example: The rewrite supports two panel input/output modes. Enabled when: Behavior: Example receive payload: Enabled when key Behavior: Service payload shape: Entities are used in cards and screensaver lists. The rewrite supports Home Assistant template rendering for selected fields when prefixed with Example: In add-on mode, the container startup script: Relevant files: Start with one panel: If you run this container/process outside Supervisor: This page explains how to migrate panel configuration from the legacy AppDaemon Old (AppDaemon): New (rewrite): Old AppDaemon ( New rewrite ( In AppDaemon setups, MQTT and Home Assistant connectivity was mostly configured via AppDaemon plugin settings. In the rewrite, connectivity is resolved directly by the runtime: Some legacy entity config fields are not implemented in the rewrite parser/renderer: Supported and commonly used fields in rewrite: Screensaver entities use the same entity format as other cards. For Symptoms: Checks: Symptoms: Checks: Symptoms: Checks: Checks: Checks: Symptoms: Checks: Symptoms: Checks: Symptoms: Checks: Checks: Checks: You can configure entities with with the prefix will allow you to navigate to a cardGrid page with the configured key testKey You can override the status of navigation items, to make them look like different entities. This can be used to add an home button to your subpages:=t.count.fields)return{documents:r,terms:l};let o=t.shards[n];return e.forEach(a=>{let{occurrences:s}=o.terms[a];for(let u=0;uCards¶
+Supported card types¶
+
+
+cardEntitiescardGridcardQRcardPowercardMediacardThermocardAlarmcardUnlockCommon card keys¶
+
+
+
+
+
+
+
+key
+required
+type
+description
+
+
+
+typeyes
+string
+Card type.
+
+
+
+titleno
+string
+Card title.
+
+
+
+
+keyno
+string
+Navigation key used by
+navigate.<key>.
+cardEntities and cardGrid¶- type: cardEntities
+ title: Main
+ key: main
+ entities:
+ - entity: light.kitchen
+ - entity: navigate.settings
+ icon: mdi:cog
+
+
+entities is required.cardGrid auto-switches to cardGrid2 if more than 6 entities are present.
+cardQR¶- type: cardQR
+ title: Guest WiFi
+ qrCode: "WIFI:S:myssid;T:WPA;P:mypassword;;"
+ entities:
+ - entity: iText.myssid
+ name: SSID
+ icon: mdi:wifi
+
+
+qrCode optional (default value exists, but set it explicitly)entity / entities
+cardPower¶- type: cardPower
+ title: Energy
+ entities:
+ - entity: sensor.house_power
+ - entity: delete
+ - entity: sensor.solar_power
+
+
+entities is required.speed key is accepted in config but currently not applied by the renderer.
+cardMedia¶- type: cardMedia
+ title: Living Room
+ entity: media_player.living_room
+ entities:
+ - entity: light.ambient
+ - entity: switch.tv_bias_light
+
+
+entity or first generated entity).entities are rendered as action buttons on the bottom row.
+cardThermo¶- type: cardThermo
+ title: Heating
+ entity: climate.downstairs
+ supported_modes: ["heat", "off"]
+
+
+entity requiredsupported_modes optional (filters shown HVAC mode buttons)
+cardAlarm¶- type: cardAlarm
+ title: House Alarm
+ entity: alarm_control_panel.house
+ supported_modes: ["arm_home", "arm_away", "arm_night"]
+
+
+entity requiredsupported_modes optional
+cardUnlock¶- type: cardUnlock
+ title: Admin
+ pin: 1234
+ destination: navigate.admin
+
+
+pin requireddestination requiredhiddenCards:hiddenCards:
+ - type: cardGrid
+ key: admin
+ title: Admin
+ entities:
+ - entity: switch.maintenance_mode
+Configuration¶
+./panels.yaml, add-on mode: /config/panels.yaml).Top-level keys¶
+
+
+
+
+
+
+
+key
+required
+type
+default
+description
+
+
+
+nspanelsyes
+object
+none
+Map of panel definitions.
+
+
+
+home_assistant_addressrecommended
+string
+none
+Home Assistant base URL. In add-on mode it is auto-filled as
+http://supervisor if missing.
+
+
+home_assistant_tokenrecommended
+string
+none
+Long-lived token or Supervisor token.
+
+
+
+mqtt_serverrequired in MQTT mode
+string
+from env
+MQTT host.
+
+
+
+mqtt_portrequired in MQTT mode
+int
+from env
+MQTT port.
+
+
+
+mqtt_usernamerequired in MQTT mode
+string
+from env
+MQTT username.
+
+
+
+mqtt_passwordrequired in MQTT mode
+string
+from env
+MQTT password.
+
+
+
+use_ha_apioptional
+any
+absent
+If present, MQTT input mode is disabled and HA event mode is used.
+
+
+
+timeZoneoptional
+string
+
+Europe/BerlinGlobal fallback for panel
+timeZone.
+
+
+
+hiddenCardsoptional
+list
+
+[]Global fallback for panel
+hiddenCards.Panel keys (
+nspanels.<name>)¶
+
+
+
+
+
+
+key
+required
+type
+default
+description
+
+
+
+panelRecvTopicyes
+string
+none
+Receive channel for panel events.
+
+
+
+panelSendTopicyes
+string
+none
+Send channel for panel commands.
+
+
+
+localeyes
+string
+none
+Locale used for translations and date formatting.
+
+
+
+timeZonerecommended
+string
+from top-level
+timeZoneTime zone for clock.
+
+
+
+timeFormatyes
+string
+none
+Python
+strftime format.
+
+
+dateFormatyes
+string
+none
+Babel date format (example:
+full, medium).
+
+
+modeloptional
+string
+
+euPanel model (
+eu, us-p, us-l).
+
+
+temp_unitoptional
+string
+
+celsiusThermostat card unit (
+celsius or fahrenheit).
+
+
+sleepTimeoutoptional
+int
+
+20Seconds before screensaver.
+
+
+
+sleepBrightnessoptional
+int or entity_id
+
+10Screensaver brightness.
+
+
+
+screenBrightnessoptional
+int or entity_id
+
+100Active-screen brightness.
+
+
+
+sleepTrackingoptional
+entity_id
+none
+Forces sleep brightness to 0 when entity state matches
+sleepTrackingZones.
+
+
+sleepTrackingZonesoptional
+list
+
+["not_home", "off"]States that trigger forced dimming.
+
+
+
+sleepOverrideoptional
+object
+none
+Override sleep brightness when entity is
+on/true/home.
+
+
+defaultBackgroundColoroptional
+string
+
+ha-dark
+ha-dark or black.
+
+
+featExperimentalSlidersoptional
+int
+
+0Forwarded in dimmode command.
+
+
+
+defaultCardoptional
+string
+none
+Default card when leaving screensaver (
+navigate.<key>).
+
+
+screensaveryes
+object
+none
+Screensaver definition.
+
+
+
+cardsyes
+list
+none
+Top-level cards.
+
+
+
+
+hiddenCardsoptional
+list
+
+[]Hidden cards addressable through
+navigate.<key>.Brightness behavior¶
+
+
+sleepBrightness: input_number.nspanel_sleep
+screenBrightness: input_number.nspanel_awake
+sleepTracking: person.john
+sleepTrackingZones: ["not_home", "off"]
+sleepOverride:
+ entity: light.bedroom
+ brightness: 30
+Connection Modes¶
+1) MQTT mode (default)¶
+
+
+mqtt_server is configureduse_ha_api is not present
+
+panelRecvTopicCustomRecvpanelSendTopic{"CustomRecv":"event,startup,54,eu"}
+2) Home Assistant API mode (
+use_ha_api)¶use_ha_api exists in config.
+
+esphome.nspanel.datadevice_id (must match configured panelRecvTopic)<panelSendTopic>_nspanelui_api_calldata: "...panel command..."
+command: 2
+Common to both modes¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Entities¶
+Entity keys¶
+
+
+
+
+
+
+
+key
+required
+type
+description
+
+
+
+entityyes
+string
+Home Assistant entity id, or internal entity (
+navigate.*, delete, iText.*).
+
+
+nameno
+string
+Display name override.
+
+
+
+iconno
+string or map
+Icon override (
+mdi:*), optionally per state.
+
+
+colorno
+
+[r,g,b] or mapColor override, optionally per state.
+
+
+
+valueno
+string
+Value override.
+
+
+
+fontno
+string
+Icon font variant (
+small, medium, medium-icon, large).
+
+
+statusno
+string
+Extra status entity for
+navigate.* items.
+
+
+effectListno
+list
+Custom light effect list for detail popup.
+
+
+
+attributeno
+string
+Weather attribute to display.
+
+
+
+dayno
+int
+Weather daily forecast index.
+
+
+
+hourno
+int
+Weather hourly forecast index.
+
+
+
+
+unitno
+string
+Value suffix.
+Supported Home Assistant domains¶
+
+
+switchinput_booleanautomationlockinput_textinput_selectselectlightfanbuttoninput_buttonscenescriptnumberinput_numbertimeralarm_control_panelvacuummedia_playersunpersonclimatecoversensorbinary_sensorweatherInternal entities¶
+
+
+navigate.<key>: Navigate to card with matching key.navigate.UP: Navigate back.delete: Placeholder/empty slot.iText.<text>: Static text entry.Template-based values¶
+ha::
+
+icon: "ha:{{ ... }}"color: "ha:{{ ... }}" (must evaluate to JSON RGB list)value: "ha:{{ ... }}"qrCode: "ha:{{ ... }}"- entity: light.kitchen
+ icon:
+ "on": mdi:lightbulb
+ "off": mdi:lightbulb-outline
+ color:
+ "on": [255, 210, 90]
+ "off": [80, 120, 170]
+Getting Started¶
+Home Assistant add-on mode¶
+
+
+CONFIG_FILE=/config/panels.yaml/config/panels.yaml from the bundled example if it does not exist
+
+nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/run.shnspanel-lovelace-ui/config.yamlMinimal
+panels.yaml¶home_assistant_address: "http://supervisor"
+home_assistant_token: "SUPERVISOR_TOKEN_OR_LONG_LIVED_TOKEN"
+
+nspanels:
+ kitchen:
+ panelRecvTopic: "tele/tasmota_kitchen/RESULT"
+ panelSendTopic: "cmnd/tasmota_kitchen/CustomSend"
+ locale: "en_US"
+ timeZone: "Europe/Berlin"
+ timeFormat: "%H:%M"
+ dateFormat: "full"
+ screensaver:
+ entities:
+ - entity: weather.home
+ cards:
+ - type: cardEntities
+ title: Main
+ entities:
+ - entity: light.kitchen
+ - entity: switch.coffee_machine
+Important notes¶
+
+
+cards and screensaver are required per panel.timeFormat, dateFormat, and locale should be set per panel.panelRecvTopic / panelSendTopic are required.Running standalone (outside HA add-on)¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ home_assistant_address and home_assistant_token in YAMLmqtt_server, mqtt_port, mqtt_username, mqtt_password) or environmentCONFIG_FILE if the config is not ./panels.yamlOverview¶
+nspanel-lovelace-ui/.
+
+docs/.Rewrite location¶
+
+
+nspanel-lovelace-ui/nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/panels.yaml.exampleWhat is supported¶
+
+
+cardEntitiescardGrid (auto-switches to cardGrid2 when needed)cardQRcardPowercardMediacardThermocardAlarmcardUnlockRuntime model¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ panels.yaml.Migration from AppDaemon Config¶
+apps.yaml format to the standalone rewrite panels.yaml format.File and structure changes¶
+
+
+apps.yamlappdaemon.yaml, plugin config, and app config)
+
+panels.yaml (usually /config/panels.yaml)Minimal before/after example¶
+apps.yaml):nspanel-1:
+ module: nspanel-lovelace-ui
+ class: NsPanelLovelaceUIManager
+ config:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+ locale: en_US
+ timeFormat: "%H:%M"
+panels.yaml):home_assistant_address: "http://supervisor"
+home_assistant_token: "YOUR_TOKEN"
+
+nspanels:
+ panel-1:
+ panelRecvTopic: "tele/tasmota_panel/RESULT"
+ panelSendTopic: "cmnd/tasmota_panel/CustomSend"
+ model: eu
+ locale: en_US
+ timeZone: "Europe/Berlin"
+ timeFormat: "%H:%M"
+ dateFormat: "full"
+ screensaver:
+ entities:
+ - entity: weather.home
+ cards:
+ - type: cardEntities
+ title: Main
+ entities:
+ - entity: light.kitchen
+Key mapping¶
+
+
+
+
+
+
+
+Legacy AppDaemon key or concept
+Standalone rewrite
+Notes
+
+
+
+module, class, config wrapperremoved
+Rewrite uses
+nspanels.<panel_name> directly.
+
+
+panelRecvTopic
+panelRecvTopicSame meaning.
+
+
+
+panelSendTopic
+panelSendTopicSame meaning.
+
+
+
+model
+modelSame meaning (
+eu, us-p, us-l).
+
+
+locale
+localeSame meaning.
+
+
+
+timeFormat
+timeFormatSame meaning.
+
+
+
+timezone (legacy docs casing)
+timeZoneUse exact camelCase
+timeZone.
+
+
+dateFormatBabel / dateFormat
+dateFormatRewrite expects
+dateFormat.
+
+
+cards
+cardsSame concept.
+
+
+
+hiddenCards
+hiddenCardsSame concept.
+
+
+
+screensaver
+screensaverSame concept; some legacy theme options are not available.
+
+
+
+defaultCard under screensaver usage
+defaultCard (panel level)Use as panel-level key in rewrite.
+
+
+
+temperatureUnit (card-level legacy usage)
+temp_unit (panel level)Rewrite reads panel-level
+temp_unit.
+
+
+sleepBrightness list schedulenot supported
+Rewrite supports integer or entity id, not list-based schedules.
+
+
+
+screenBrightness list schedulenot supported
+Rewrite supports integer or entity id, not list-based schedules.
+
+
+
+sleepTracking
+sleepTrackingSame concept.
+
+
+
+sleepTrackingZones
+sleepTrackingZonesSame concept.
+
+
+
+sleepOverride
+sleepOverrideSame concept.
+
+
+
+updateMode / OTA URL overrides (displayURL-*, berryURL)not supported
+Rewrite does not implement these legacy update keys.
+
+
+
+
+theme, dateAdditionalTemplate, timeAdditionalTemplatenot supported
+Not implemented in rewrite config.
+Connection config differences¶
+
+
+home_assistant_addresshome_assistant_tokenmqtt_server, mqtt_port, mqtt_username, mqtt_passworduse_ha_api to use Home Assistant event mode instead of MQTT receive modeEntity-level differences to watch¶
+
+
+state, state_not, state_templateservice.* action entries with custom dataaction_name
+
+entity, name, icon, color, value, fontattribute, day, hour, uniteffectListstatus for navigate.* entitiesMigration checklist¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ /config/panels.yaml from the rewrite example.nspanel-1, nspanel-2, ...) into nspanels.module/class/config wrappers.timezone to timeZone.dateFormat, timeFormat, screensaver, and cards.Screensaver¶
+screensaver is a required object in each panel config.Keys¶
+
+
+
+
+
+
+
+key
+required
+type
+default
+description
+
+
+
+typeno
+string
+
+screensaverLayout type (
+screensaver / screensaver2).
+
+
+entitiesyes*
+list
+none
+Screensaver entities.
+
+
+
+entityyes*
+string
+none
+Single-entity shortcut.
+
+
+
+statusIcon1no
+object
+none
+Left status icon near date.
+
+
+
+statusIcon2no
+object
+none
+Right status icon near date.
+
+
+
+doubleTapToUnlockno
+bool
+
+falseRequires double tap when leaving screensaver.
+
+
+
+
+sleepTimeoutno
+int
+panel
+sleepTimeoutPer-screensaver timeout override.
+* Provide at least one of entity or entities.Screensaver entities¶
+weather.<entity> you can also use:
+
+attribute (default temperature)day (daily forecast index)hour (hourly forecast index)unit (suffix, default °C for temperature-like attributes)Example¶
+screensaver:
+ type: screensaver
+ doubleTapToUnlock: true
+ sleepTimeout: 30
+ statusIcon1:
+ entity: binary_sensor.front_door
+ icon:
+ "on": mdi:door-open
+ "off": mdi:door-closed
+ font: medium-icon
+ statusIcon2:
+ entity: sensor.outdoor_temperature
+ icon: mdi:thermometer
+ entities:
+ - entity: weather.home
+ attribute: temperature
+ - entity: weather.home
+ day: 1
+ attribute: temperature
+ - entity: weather.home
+ day: 2
+ attribute: temperature
+ - entity: sensor.indoor_temperature
+ icon: mdi:home-thermometer
+nspanel-lovelace-ui/.
docs/.
","path":["Overview"],"tags":[]},{"location":"#what-is-supported","level":2,"title":"What is supported","text":"nspanel-lovelace-ui/nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/panels.yaml.example
","path":["Overview"],"tags":[]},{"location":"#runtime-model","level":2,"title":"Runtime model","text":"cardEntitiescardGrid (auto-switches to cardGrid2 when needed)cardQRcardPowercardMediacardThermocardAlarmcardUnlock
","path":["Overview"],"tags":[]},{"location":"cards/","level":1,"title":"Cards","text":"","path":["Cards"],"tags":[]},{"location":"cards/#supported-card-types","level":2,"title":"Supported card types","text":"panels.yaml.
","path":["Cards"],"tags":[]},{"location":"cards/#common-card-keys","level":2,"title":"Common card keys","text":"key required type description cardEntitiescardGridcardQRcardPowercardMediacardThermocardAlarmcardUnlocktype yes string Card type. title no string Card title. key no string Navigation key used by navigate.<key>.","path":["Cards"],"tags":[]},{"location":"cards/#cardentities-and-cardgrid","level":2,"title":"cardEntities and cardGrid","text":"- type: cardEntities\n title: Main\n key: main\n entities:\n - entity: light.kitchen\n - entity: navigate.settings\n icon: mdi:cog\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardqr","level":2,"title":"entities is required.cardGrid auto-switches to cardGrid2 if more than 6 entities are present.cardQR","text":"- type: cardQR\n title: Guest WiFi\n qrCode: \"WIFI:S:myssid;T:WPA;P:mypassword;;\"\n entities:\n - entity: iText.myssid\n name: SSID\n icon: mdi:wifi\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardpower","level":2,"title":"qrCode optional (default value exists, but set it explicitly)entity / entitiescardPower","text":"- type: cardPower\n title: Energy\n entities:\n - entity: sensor.house_power\n - entity: delete\n - entity: sensor.solar_power\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardmedia","level":2,"title":"entities is required.speed key is accepted in config but currently not applied by the renderer.cardMedia","text":"- type: cardMedia\n title: Living Room\n entity: media_player.living_room\n entities:\n - entity: light.ambient\n - entity: switch.tv_bias_light\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardthermo","level":2,"title":"entity or first generated entity).entities are rendered as action buttons on the bottom row.cardThermo","text":"- type: cardThermo\n title: Heating\n entity: climate.downstairs\n supported_modes: [\"heat\", \"off\"]\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardalarm","level":2,"title":"entity requiredsupported_modes optional (filters shown HVAC mode buttons)cardAlarm","text":"- type: cardAlarm\n title: House Alarm\n entity: alarm_control_panel.house\n supported_modes: [\"arm_home\", \"arm_away\", \"arm_night\"]\n
","path":["Cards"],"tags":[]},{"location":"cards/#cardunlock","level":2,"title":"entity requiredsupported_modes optionalcardUnlock","text":"- type: cardUnlock\n title: Admin\n pin: 1234\n destination: navigate.admin\n
pin requireddestination requiredhiddenCards:
","path":["Cards"],"tags":[]},{"location":"configuration/","level":1,"title":"Configuration","text":"hiddenCards:\n - type: cardGrid\n key: admin\n title: Admin\n entities:\n - entity: switch.maintenance_mode\n./panels.yaml, add-on mode: /config/panels.yaml).nspanels yes object none Map of panel definitions. home_assistant_address recommended string none Home Assistant base URL. In add-on mode it is auto-filled as http://supervisor if missing. home_assistant_token recommended string none Long-lived token or Supervisor token. mqtt_server required in MQTT mode string from env MQTT host. mqtt_port required in MQTT mode int from env MQTT port. mqtt_username required in MQTT mode string from env MQTT username. mqtt_password required in MQTT mode string from env MQTT password. use_ha_api optional any absent If present, MQTT input mode is disabled and HA event mode is used. timeZone optional string Europe/Berlin Global fallback for panel timeZone. hiddenCards optional list [] Global fallback for panel hiddenCards.","path":["Configuration"],"tags":[]},{"location":"configuration/#panel-keys-nspanelsname","level":2,"title":"Panel keys (nspanels.<name>)","text":"key required type default description panelRecvTopic yes string none Receive channel for panel events. panelSendTopic yes string none Send channel for panel commands. locale yes string none Locale used for translations and date formatting. timeZone recommended string from top-level timeZone Time zone for clock. timeFormat yes string none Python strftime format. dateFormat yes string none Babel date format (example: full, medium). model optional string eu Panel model (eu, us-p, us-l). temp_unit optional string celsius Thermostat card unit (celsius or fahrenheit). sleepTimeout optional int 20 Seconds before screensaver. sleepBrightness optional int or entity_id 10 Screensaver brightness. screenBrightness optional int or entity_id 100 Active-screen brightness. sleepTracking optional entity_id none Forces sleep brightness to 0 when entity state matches sleepTrackingZones. sleepTrackingZones optional list [\"not_home\", \"off\"] States that trigger forced dimming. sleepOverride optional object none Override sleep brightness when entity is on/true/home. defaultBackgroundColor optional string ha-dark ha-dark or black. featExperimentalSliders optional int 0 Forwarded in dimmode command. defaultCard optional string none Default card when leaving screensaver (navigate.<key>). screensaver yes object none Screensaver definition. cards yes list none Top-level cards. hiddenCards optional list [] Hidden cards addressable through navigate.<key>.","path":["Configuration"],"tags":[]},{"location":"configuration/#brightness-behavior","level":2,"title":"Brightness behavior","text":"
","path":["Configuration"],"tags":[]},{"location":"connection-modes/","level":1,"title":"Connection Modes","text":"sleepBrightness: input_number.nspanel_sleep\nscreenBrightness: input_number.nspanel_awake\nsleepTracking: person.john\nsleepTrackingZones: [\"not_home\", \"off\"]\nsleepOverride:\n entity: light.bedroom\n brightness: 30\n
mqtt_server is configureduse_ha_api is not present
panelRecvTopicCustomRecvpanelSendTopic
","path":["Connection Modes"],"tags":[]},{"location":"connection-modes/#2-home-assistant-api-mode-use_ha_api","level":2,"title":"2) Home Assistant API mode ({\"CustomRecv\":\"event,startup,54,eu\"}\nuse_ha_api)","text":"use_ha_api exists in config.
esphome.nspanel.datadevice_id (must match configured panelRecvTopic)<panelSendTopic>_nspanelui_api_call
","path":["Connection Modes"],"tags":[]},{"location":"connection-modes/#common-to-both-modes","level":2,"title":"Common to both modes","text":"data: \"...panel command...\"\ncommand: 2\n
","path":["Connection Modes"],"tags":[]},{"location":"entities/","level":1,"title":"Entities","text":"entity yes string Home Assistant entity id, or internal entity (navigate.*, delete, iText.*). name no string Display name override. icon no string or map Icon override (mdi:*), optionally per state. color no [r,g,b] or map Color override, optionally per state. value no string Value override. font no string Icon font variant (small, medium, medium-icon, large). status no string Extra status entity for navigate.* items. effectList no list Custom light effect list for detail popup. attribute no string Weather attribute to display. day no int Weather daily forecast index. hour no int Weather hourly forecast index. unit no string Value suffix.","path":["Entities"],"tags":[]},{"location":"entities/#supported-home-assistant-domains","level":2,"title":"Supported Home Assistant domains","text":"
","path":["Entities"],"tags":[]},{"location":"entities/#internal-entities","level":2,"title":"Internal entities","text":"switchinput_booleanautomationlockinput_textinput_selectselectlightfanbuttoninput_buttonscenescriptnumberinput_numbertimeralarm_control_panelvacuummedia_playersunpersonclimatecoversensorbinary_sensorweather
","path":["Entities"],"tags":[]},{"location":"entities/#template-based-values","level":2,"title":"Template-based values","text":"navigate.<key>: Navigate to card with matching key.navigate.UP: Navigate back.delete: Placeholder/empty slot.iText.<text>: Static text entry.ha::
icon: \"ha:{{ ... }}\"color: \"ha:{{ ... }}\" (must evaluate to JSON RGB list)value: \"ha:{{ ... }}\"qrCode: \"ha:{{ ... }}\"
","path":["Entities"],"tags":[]},{"location":"getting-started/","level":1,"title":"Getting Started","text":"","path":["Getting Started"],"tags":[]},{"location":"getting-started/#home-assistant-add-on-mode","level":2,"title":"Home Assistant add-on mode","text":"- entity: light.kitchen\n icon:\n \"on\": mdi:lightbulb\n \"off\": mdi:lightbulb-outline\n color:\n \"on\": [255, 210, 90]\n \"off\": [80, 120, 170]\n
CONFIG_FILE=/config/panels.yaml/config/panels.yaml from the bundled example if it does not exist
","path":["Getting Started"],"tags":[]},{"location":"getting-started/#minimal-panelsyaml","level":2,"title":"Minimal nspanel-lovelace-ui/rootfs/usr/bin/mqtt-manager/run.shnspanel-lovelace-ui/config.yamlpanels.yaml","text":"
","path":["Getting Started"],"tags":[]},{"location":"getting-started/#important-notes","level":2,"title":"Important notes","text":"home_assistant_address: \"http://supervisor\"\nhome_assistant_token: \"SUPERVISOR_TOKEN_OR_LONG_LIVED_TOKEN\"\n\nnspanels:\n kitchen:\n panelRecvTopic: \"tele/tasmota_kitchen/RESULT\"\n panelSendTopic: \"cmnd/tasmota_kitchen/CustomSend\"\n locale: \"en_US\"\n timeZone: \"Europe/Berlin\"\n timeFormat: \"%H:%M\"\n dateFormat: \"full\"\n screensaver:\n entities:\n - entity: weather.home\n cards:\n - type: cardEntities\n title: Main\n entities:\n - entity: light.kitchen\n - entity: switch.coffee_machine\n
","path":["Getting Started"],"tags":[]},{"location":"getting-started/#running-standalone-outside-ha-add-on","level":2,"title":"Running standalone (outside HA add-on)","text":"cards and screensaver are required per panel.timeFormat, dateFormat, and locale should be set per panel.panelRecvTopic / panelSendTopic are required.
","path":["Getting Started"],"tags":[]},{"location":"migration-appdaemon/","level":1,"title":"Migration from AppDaemon Config","text":"home_assistant_address and home_assistant_token in YAMLmqtt_server, mqtt_port, mqtt_username, mqtt_password) or environmentCONFIG_FILE if the config is not ./panels.yamlapps.yaml format to the standalone rewrite panels.yaml format.
apps.yamlappdaemon.yaml, plugin config, and app config)
","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"migration-appdaemon/#minimal-beforeafter-example","level":2,"title":"Minimal before/after example","text":"panels.yaml (usually /config/panels.yaml)apps.yaml):nspanel-1:\n module: nspanel-lovelace-ui\n class: NsPanelLovelaceUIManager\n config:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\n locale: en_US\n timeFormat: \"%H:%M\"\npanels.yaml):
","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"migration-appdaemon/#key-mapping","level":2,"title":"Key mapping","text":"Legacy AppDaemon key or concept Standalone rewrite Notes home_assistant_address: \"http://supervisor\"\nhome_assistant_token: \"YOUR_TOKEN\"\n\nnspanels:\n panel-1:\n panelRecvTopic: \"tele/tasmota_panel/RESULT\"\n panelSendTopic: \"cmnd/tasmota_panel/CustomSend\"\n model: eu\n locale: en_US\n timeZone: \"Europe/Berlin\"\n timeFormat: \"%H:%M\"\n dateFormat: \"full\"\n screensaver:\n entities:\n - entity: weather.home\n cards:\n - type: cardEntities\n title: Main\n entities:\n - entity: light.kitchen\nmodule, class, config wrapper removed Rewrite uses nspanels.<panel_name> directly. panelRecvTopic panelRecvTopic Same meaning. panelSendTopic panelSendTopic Same meaning. model model Same meaning (eu, us-p, us-l). locale locale Same meaning. timeFormat timeFormat Same meaning. timezone (legacy docs casing) timeZone Use exact camelCase timeZone. dateFormatBabel / dateFormat dateFormat Rewrite expects dateFormat. cards cards Same concept. hiddenCards hiddenCards Same concept. screensaver screensaver Same concept; some legacy theme options are not available. defaultCard under screensaver usage defaultCard (panel level) Use as panel-level key in rewrite. temperatureUnit (card-level legacy usage) temp_unit (panel level) Rewrite reads panel-level temp_unit. sleepBrightness list schedule not supported Rewrite supports integer or entity id, not list-based schedules. screenBrightness list schedule not supported Rewrite supports integer or entity id, not list-based schedules. sleepTracking sleepTracking Same concept. sleepTrackingZones sleepTrackingZones Same concept. sleepOverride sleepOverride Same concept. updateMode / OTA URL overrides (displayURL-*, berryURL) not supported Rewrite does not implement these legacy update keys. theme, dateAdditionalTemplate, timeAdditionalTemplate not supported Not implemented in rewrite config.","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"migration-appdaemon/#connection-config-differences","level":2,"title":"Connection config differences","text":"
","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"migration-appdaemon/#entity-level-differences-to-watch","level":2,"title":"Entity-level differences to watch","text":"home_assistant_addresshome_assistant_tokenmqtt_server, mqtt_port, mqtt_username, mqtt_passworduse_ha_api to use Home Assistant event mode instead of MQTT receive mode
state, state_not, state_templateservice.* action entries with custom dataaction_name
","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"migration-appdaemon/#migration-checklist","level":2,"title":"Migration checklist","text":"entity, name, icon, color, value, fontattribute, day, hour, uniteffectListstatus for navigate.* entities
","path":["Migration from AppDaemon Config"],"tags":[]},{"location":"screensaver/","level":1,"title":"Screensaver","text":"/config/panels.yaml from the rewrite example.nspanel-1, nspanel-2, ...) into nspanels.module/class/config wrappers.timezone to timeZone.dateFormat, timeFormat, screensaver, and cards.screensaver is a required object in each panel config.type no string screensaver Layout type (screensaver / screensaver2). entities yes* list none Screensaver entities. entity yes* string none Single-entity shortcut. statusIcon1 no object none Left status icon near date. statusIcon2 no object none Right status icon near date. doubleTapToUnlock no bool false Requires double tap when leaving screensaver. sleepTimeout no int panel sleepTimeout Per-screensaver timeout override. * Provide at least one of entity or entities.weather.<entity> you can also use:
","path":["Screensaver"],"tags":[]},{"location":"screensaver/#example","level":2,"title":"Example","text":"attribute (default temperature)day (daily forecast index)hour (hourly forecast index)unit (suffix, default °C for temperature-like attributes)
","path":["Screensaver"],"tags":[]},{"location":"troubleshooting/","level":1,"title":"Troubleshooting","text":"","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#config-does-not-load","level":2,"title":"Config does not load","text":"screensaver:\n type: screensaver\n doubleTapToUnlock: true\n sleepTimeout: 30\n statusIcon1:\n entity: binary_sensor.front_door\n icon:\n \"on\": mdi:door-open\n \"off\": mdi:door-closed\n font: medium-icon\n statusIcon2:\n entity: sensor.outdoor_temperature\n icon: mdi:thermometer\n entities:\n - entity: weather.home\n attribute: temperature\n - entity: weather.home\n day: 1\n attribute: temperature\n - entity: weather.home\n day: 2\n attribute: temperature\n - entity: sensor.indoor_temperature\n icon: mdi:home-thermometer\n
","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#mqtt-not-connected","level":2,"title":"MQTT not connected","text":"CONFIG_FILE path.panelRecvTopic, panelSendTopic, locale, timeFormat, dateFormat, screensaver, cards.
","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#home-assistant-websocket-not-connected","level":2,"title":"Home Assistant websocket not connected","text":"mqtt_server, mqtt_port, mqtt_username, mqtt_password.panelRecvTopic.CustomRecv JSON key.
","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#card-does-not-open-or-navigate","level":2,"title":"Card does not open or navigate","text":"home_assistant_address and home_assistant_token.
","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#brightness-behaves-unexpectedly","level":2,"title":"Brightness behaves unexpectedly","text":"navigate.<key>, confirm target card has matching key.cardUnlock, confirm destination and pin are set.type is one of the implemented types.
","path":["Troubleshooting"],"tags":[]},{"location":"troubleshooting/#useful-logs-to-look-for","level":2,"title":"Useful logs to look for","text":"sleepTracking, sleepTrackingZones, and sleepOverride.
","path":["Troubleshooting"],"tags":[]}]}
\ No newline at end of file
diff --git a/standalone/sitemap.xml b/standalone/sitemap.xml
new file mode 100644
index 00000000..1901afbf
--- /dev/null
+++ b/standalone/sitemap.xml
@@ -0,0 +1,30 @@
+
+Config file not foundError while parsing YAML fileConnected to MQTT ServerHome Assistant auth OKcard type ... not implementedNot implemented: <button action>Troubleshooting¶
+Config does not load¶
+
+
+
+
+CONFIG_FILE path.panelRecvTopic, panelSendTopic, locale, timeFormat, dateFormat, screensaver, cards.MQTT not connected¶
+
+
+
+
+mqtt_server, mqtt_port, mqtt_username, mqtt_password.panelRecvTopic.CustomRecv JSON key.Home Assistant websocket not connected¶
+
+
+
+
+home_assistant_address and home_assistant_token.Card does not open or navigate¶
+
+
+navigate.<key>, confirm target card has matching key.cardUnlock, confirm destination and pin are set.type is one of the implemented types.Brightness behaves unexpectedly¶
+
+
+sleepTracking, sleepTrackingZones, and sleepOverride.Useful logs to look for¶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Config file not foundError while parsing YAML fileConnected to MQTT ServerHome Assistant auth OKcard type ... not implementedNot implemented: <button action>Subpages¶
+navigate, that are navigating to cards, in case it's hidden card, the navigation items will change and the arrow is bringing you back to the previous page. - entity: navigate.testKey
+ hiddenCards:
+ - type: cardGrid
+ title: Exmaple Grid
+ entities:
+ - entity: light.test_item
+ key: testKey
+Override Status of Navigation Items¶
+ - entity: navigate.testKey
+ status: climate.test
+Override Navigation Items itself¶
+
cards:
+ - type: cardGrid
+ title: Wohnzimmer
+ navItem1:
+ entity: light.bad_lights
+ navItem2:
+ entity: light.bad_lights
+ entities:
+ cards:
+ - type: cardGrid
+ title: Home
+ key: home
+ entities:
+ - entity: light.bad
+
+ hiddenCards:
+ - type: cardGrid
+ title: Wohnzimmer
+ navItem2:
+ entity: navigate.home
+ icon: mdi:home
+ entities:
+ - entity: light.kitchen
+