140 lines
68 KiB
HTML
140 lines
68 KiB
HTML
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="Home Assistant MCP Server Documentation"><link rel=canonical href=https://jango-blockchained.github.io/advanced-homeassistant-mcp/development/best-practices.html><link rel=prev href=../testing.html><link rel=next href=interfaces.html><link rel=icon href=../assets/images/favicon.ico><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.6.2"><title>Best Practices - MCP Server for Home Assistant</title><link rel=stylesheet href=../assets/stylesheets/main.d7758b05.min.css><link rel=stylesheet href=../assets/stylesheets/palette.06af60db.min.css><script src=https://unpkg.com/iframe-worker/shim></script><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=stylesheet href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"><style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style><link rel=stylesheet href=../assets/_mkdocstrings.css><link rel=stylesheet href=../stylesheets/extra.css><script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script><script id=__analytics>function __md_analytics(){function e(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],e("js",new Date),e("config",""),document.addEventListener("DOMContentLoaded",(function(){document.forms.search&&document.forms.search.query.addEventListener("blur",(function(){this.value&&e("event","search",{search_term:this.value})}));document$.subscribe((function(){var t=document.forms.feedback;if(void 0!==t)for(var a of t.querySelectorAll("[type=submit]"))a.addEventListener("click",(function(a){a.preventDefault();var n=document.location.pathname,d=this.getAttribute("data-md-value");e("event","feedback",{page:n,data:d}),t.firstElementChild.disabled=!0;var r=t.querySelector(".md-feedback__note [data-md-value='"+d+"']");r&&(r.hidden=!1)})),t.hidden=!1})),location$.subscribe((function(t){e("config","",{page_path:t.pathname})}))}));var t=document.createElement("script");t.async=!0,t.src="https://www.googletagmanager.com/gtag/js?id=",document.getElementById("__analytics").insertAdjacentElement("afterEnd",t)}</script><script>if("undefined"!=typeof __md_analytics){var consent=__md_get("__consent");consent&&consent.analytics&&__md_analytics()}</script></head> <body dir=ltr data-md-color-scheme=slate data-md-color-primary=deep-purple data-md-color-accent=purple> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#development-best-practices class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <div data-md-color-scheme=default data-md-component=outdated hidden> </div> <header class="md-header md-header--shadow md-header--lifted" data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../index.html title="MCP Server for Home Assistant" class="md-header__button md-logo" aria-label="MCP Server for Home Assistant" data-md-component=logo> <img src=../assets/images/logo.png alt=logo> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> MCP Server for Home Assistant </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Best Practices </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=deep-purple data-md-color-accent=purple aria-label="Switch to light mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 7a5 5 0 0 1 5 5 5 5 0 0 1-5 5 5 5 0 0 1-5-5 5 5 0 0 1 5-5m0 2a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3m0-7 2.39 3.42C13.65 5.15 12.84 5 12 5s-1.65.15-2.39.42zM3.34 7l4.16-.35A7.2 7.2 0 0 0 5.94 8.5c-.44.74-.69 1.5-.83 2.29zm.02 10 1.76-3.77a7.131 7.131 0 0 0 2.38 4.14zM20.65 7l-1.77 3.79a7.02 7.02 0 0 0-2.38-4.15zm-.01 10-4.14.36c.59-.51 1.12-1.14 1.54-1.86.42-.73.69-1.5.83-2.29zM12 22l-2.41-3.44c.74.27 1.55.44 2.41.44.82 0 1.63-.17 2.37-.44z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=deep-purple data-md-color-accent=purple aria-label="Switch to dark mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="m17.75 4.09-2.53 1.94.91 3.06-2.63-1.81-2.63 1.81.91-3.06-2.53-1.94L12.44 4l1.06-3 1.06 3zm3.5 6.91-1.64 1.25.59 1.98-1.7-1.17-1.7 1.17.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95zm-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14.4-.4.82-.76 1.27-1.08.75-.53 1.93.36 1.85 1.19-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82-2.81 3.14-2.7 7.96.31 10.98 3.02 3.01 7.84 3.12 10.98.31"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> <div class=md-search data-md-component=search role=dialog> <label class=md-search__overlay for=__search></label> <div class=md-search__inner role=search> <form class=md-search__form name=search> <input type=text class=md-search__input name=query aria-label=Search placeholder=Search autocapitalize=off autocorrect=off autocomplete=off spellcheck=false data-md-component=search-query required> <label class="md-search__icon md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </label> <nav class=md-search__options aria-label=Search> <a href=javascript:void(0) class="md-search__icon md-icon" title=Share aria-label=Share data-clipboard data-clipboard-text data-md-component=search-share tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91s2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08"/></svg> </a> <button type=reset class="md-search__icon md-icon" title=Clear aria-label=Clear tabindex=-1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> </button> </nav> <div class=md-search__suggest data-md-component=search-suggest></div> </form> <div class=md-search__output> <div class=md-search__scrollwrap tabindex=0 data-md-scrollfix> <div class=md-search-result data-md-component=search-result> <div class=md-search-result__meta> Initializing search </div> <ol class=md-search-result__list role=presentation></ol> </div> </div> </div> </div> </div> <div class=md-header__source> <a href=https://github.com/jango-blockchained/advanced-homeassistant-mcp title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> GitHub </div> </a> </div> </nav> <nav class=md-tabs aria-label=Tabs data-md-component=tabs> <div class=md-grid> <ul class=md-tabs__list> <li class=md-tabs__item> <a href=../index.html class=md-tabs__link> Home </a> </li> <li class=md-tabs__item> <a href=../getting-started/index.html class=md-tabs__link> Getting Started </a> </li> <li class=md-tabs__item> <a href=../api/index.html class=md-tabs__link> API Reference </a> </li> <li class=md-tabs__item> <a href=../usage.html class=md-tabs__link> Usage </a> </li> <li class=md-tabs__item> <a href=../config/index.html class=md-tabs__link> Configuration </a> </li> <li class=md-tabs__item> <a href=../tools/index.html class=md-tabs__link> Tools </a> </li> <li class="md-tabs__item md-tabs__item--active"> <a href=index.html class=md-tabs__link> Development </a> </li> <li class=md-tabs__item> <a href=../examples/index.html class=md-tabs__link> Examples </a> </li> </ul> </div> </nav> </header> <div class=md-container data-md-component=container> <main class=md-main data-md-component=main> <div class="md-main__inner md-grid"> <div class="md-sidebar md-sidebar--primary" data-md-component=sidebar data-md-type=navigation> <div class=md-sidebar__scrollwrap> <div class=md-sidebar__inner> <nav class="md-nav md-nav--primary md-nav--lifted md-nav--integrated" aria-label=Navigation data-md-level=0> <label class=md-nav__title for=__drawer> <a href=../index.html title="MCP Server for Home Assistant" class="md-nav__button md-logo" aria-label="MCP Server for Home Assistant" data-md-component=logo> <img src=../assets/images/logo.png alt=logo> </a> MCP Server for Home Assistant </label> <div class=md-nav__source> <a href=https://github.com/jango-blockchained/advanced-homeassistant-mcp title="Go to repository" class=md-source data-md-component=source> <div class="md-source__icon md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </div> <div class=md-source__repository> GitHub </div> </a> </div> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=../index.html class=md-nav__link> <span class=md-ellipsis> Home </span> </a> </li> <li class="md-nav__item md-nav__item--pruned md-nav__item--nested"> <a href=../getting-started/index.html class=md-nav__link> <span class=md-ellipsis> Getting Started </span> <span class="md-nav__icon md-icon"></span> </a> </li> <li class="md-nav__item md-nav__item--pruned md-nav__item--nested"> <a href=../api/index.html class=md-nav__link> <span class=md-ellipsis> API Reference </span> <span class="md-nav__icon md-icon"></span> </a> </li> <li class=md-nav__item> <a href=../usage.html class=md-nav__link> <span class=md-ellipsis> Usage </span> </a> </li> <li class="md-nav__item md-nav__item--pruned md-nav__item--nested"> <a href=../config/index.html class=md-nav__link> <span class=md-ellipsis> Configuration </span> <span class="md-nav__icon md-icon"></span> </a> </li> <li class="md-nav__item md-nav__item--pruned md-nav__item--nested"> <a href=../tools/index.html class=md-nav__link> <span class=md-ellipsis> Tools </span> <span class="md-nav__icon md-icon"></span> </a> </li> <li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested"> <input class="md-nav__toggle md-toggle " type=checkbox id=__nav_7 checked> <div class="md-nav__link md-nav__container"> <a href=index.html class="md-nav__link "> <span class=md-ellipsis> Development </span> </a> <label class="md-nav__link " for=__nav_7 id=__nav_7_label tabindex> <span class="md-nav__icon md-icon"></span> </label> </div> <nav class=md-nav data-md-level=1 aria-labelledby=__nav_7_label aria-expanded=true> <label class=md-nav__title for=__nav_7> <span class="md-nav__icon md-icon"></span> Development </label> <ul class=md-nav__list data-md-scrollfix> <li class=md-nav__item> <a href=environment.html class=md-nav__link> <span class=md-ellipsis> Environment Setup </span> </a> </li> <li class=md-nav__item> <a href=../architecture.html class=md-nav__link> <span class=md-ellipsis> Architecture </span> </a> </li> <li class=md-nav__item> <a href=../contributing.html class=md-nav__link> <span class=md-ellipsis> Contributing </span> </a> </li> <li class=md-nav__item> <a href=../testing.html class=md-nav__link> <span class=md-ellipsis> Testing </span> </a> </li> <li class="md-nav__item md-nav__item--active"> <input class="md-nav__toggle md-toggle" type=checkbox id=__toc> <label class="md-nav__link md-nav__link--active" for=__toc> <span class=md-ellipsis> Best Practices </span> <span class="md-nav__icon md-icon"></span> </label> <a href=best-practices.html class="md-nav__link md-nav__link--active"> <span class=md-ellipsis> Best Practices </span> </a> <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> <label class=md-nav__title for=__toc> <span class="md-nav__icon md-icon"></span> Table of contents </label> <ul class=md-nav__list data-md-component=toc data-md-scrollfix> <li class=md-nav__item> <a href=#code-style class=md-nav__link> <span class=md-ellipsis> Code Style </span> </a> <nav class=md-nav aria-label="Code Style"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#typescript class=md-nav__link> <span class=md-ellipsis> TypeScript </span> </a> </li> <li class=md-nav__item> <a href=#naming-conventions class=md-nav__link> <span class=md-ellipsis> Naming Conventions </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#architecture class=md-nav__link> <span class=md-ellipsis> Architecture </span> </a> <nav class=md-nav aria-label=Architecture> <ul class=md-nav__list> <li class=md-nav__item> <a href=#solid-principles class=md-nav__link> <span class=md-ellipsis> SOLID Principles </span> </a> </li> <li class=md-nav__item> <a href=#example class=md-nav__link> <span class=md-ellipsis> Example </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#error-handling class=md-nav__link> <span class=md-ellipsis> Error Handling </span> </a> <nav class=md-nav aria-label="Error Handling"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#best-practices class=md-nav__link> <span class=md-ellipsis> Best Practices </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#testing class=md-nav__link> <span class=md-ellipsis> Testing </span> </a> <nav class=md-nav aria-label=Testing> <ul class=md-nav__list> <li class=md-nav__item> <a href=#guidelines class=md-nav__link> <span class=md-ellipsis> Guidelines </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#performance class=md-nav__link> <span class=md-ellipsis> Performance </span> </a> <nav class=md-nav aria-label=Performance> <ul class=md-nav__list> <li class=md-nav__item> <a href=#optimization class=md-nav__link> <span class=md-ellipsis> Optimization </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#security class=md-nav__link> <span class=md-ellipsis> Security </span> </a> <nav class=md-nav aria-label=Security> <ul class=md-nav__list> <li class=md-nav__item> <a href=#guidelines_1 class=md-nav__link> <span class=md-ellipsis> Guidelines </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#documentation class=md-nav__link> <span class=md-ellipsis> Documentation </span> </a> <nav class=md-nav aria-label=Documentation> <ul class=md-nav__list> <li class=md-nav__item> <a href=#standards class=md-nav__link> <span class=md-ellipsis> Standards </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#logging class=md-nav__link> <span class=md-ellipsis> Logging </span> </a> <nav class=md-nav aria-label=Logging> <ul class=md-nav__list> <li class=md-nav__item> <a href=#best-practices_1 class=md-nav__link> <span class=md-ellipsis> Best Practices </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#version-control class=md-nav__link> <span class=md-ellipsis> Version Control </span> </a> <nav class=md-nav aria-label="Version Control"> <ul class=md-nav__list> <li class=md-nav__item> <a href=#guidelines_2 class=md-nav__link> <span class=md-ellipsis> Guidelines </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=#see-also class=md-nav__link> <span class=md-ellipsis> See Also </span> </a> </li> </ul> </nav> </li> <li class=md-nav__item> <a href=interfaces.html class=md-nav__link> <span class=md-ellipsis> Interfaces </span> </a> </li> <li class=md-nav__item> <a href=tools.html class=md-nav__link> <span class=md-ellipsis> Tool Development </span> </a> </li> <li class=md-nav__item> <a href=test-migration-guide.html class=md-nav__link> <span class=md-ellipsis> Test Migration Guide </span> </a> </li> <li class=md-nav__item> <a href=../troubleshooting.html class=md-nav__link> <span class=md-ellipsis> Troubleshooting </span> </a> </li> <li class=md-nav__item> <a href=../deployment.html class=md-nav__link> <span class=md-ellipsis> Deployment </span> </a> </li> <li class=md-nav__item> <a href=../roadmap.html class=md-nav__link> <span class=md-ellipsis> Roadmap </span> </a> </li> </ul> </nav> </li> <li class="md-nav__item md-nav__item--pruned md-nav__item--nested"> <a href=../examples/index.html class=md-nav__link> <span class=md-ellipsis> Examples </span> <span class="md-nav__icon md-icon"></span> </a> </li> </ul> </nav> </div> </div> </div> <div class=md-content data-md-component=content> <article class="md-content__inner md-typeset"> <h1 id=development-best-practices>Development Best Practices</h1> <p>This guide outlines the best practices for developing tools and features for the Home Assistant MCP.</p> <h2 id=code-style>Code Style</h2> <h3 id=typescript>TypeScript</h3> <ol> <li>Use TypeScript for all new code</li> <li>Enable strict mode</li> <li>Use explicit types</li> <li>Avoid <code>any</code> type</li> <li>Use interfaces over types</li> <li>Document with JSDoc comments</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-0-1><a id=__codelineno-0-1 name=__codelineno-0-1 href=#__codelineno-0-1></a><span class=cm>/** </span>
|
|
</span><span id=__span-0-2><a id=__codelineno-0-2 name=__codelineno-0-2 href=#__codelineno-0-2></a><span class=cm> * Represents a device in the system.</span>
|
|
</span><span id=__span-0-3><a id=__codelineno-0-3 name=__codelineno-0-3 href=#__codelineno-0-3></a><span class=cm> * @interface</span>
|
|
</span><span id=__span-0-4><a id=__codelineno-0-4 name=__codelineno-0-4 href=#__codelineno-0-4></a><span class=cm> */</span>
|
|
</span><span id=__span-0-5><a id=__codelineno-0-5 name=__codelineno-0-5 href=#__codelineno-0-5></a><span class=kd>interface</span><span class=w> </span><span class=nx>Device</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-0-6><a id=__codelineno-0-6 name=__codelineno-0-6 href=#__codelineno-0-6></a><span class=w> </span><span class=cm>/** Unique device identifier */</span>
|
|
</span><span id=__span-0-7><a id=__codelineno-0-7 name=__codelineno-0-7 href=#__codelineno-0-7></a><span class=w> </span><span class=nx>id</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>;</span>
|
|
</span><span id=__span-0-8><a id=__codelineno-0-8 name=__codelineno-0-8 href=#__codelineno-0-8></a>
|
|
</span><span id=__span-0-9><a id=__codelineno-0-9 name=__codelineno-0-9 href=#__codelineno-0-9></a><span class=w> </span><span class=cm>/** Human-readable device name */</span>
|
|
</span><span id=__span-0-10><a id=__codelineno-0-10 name=__codelineno-0-10 href=#__codelineno-0-10></a><span class=w> </span><span class=nx>name</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>;</span>
|
|
</span><span id=__span-0-11><a id=__codelineno-0-11 name=__codelineno-0-11 href=#__codelineno-0-11></a>
|
|
</span><span id=__span-0-12><a id=__codelineno-0-12 name=__codelineno-0-12 href=#__codelineno-0-12></a><span class=w> </span><span class=cm>/** Device state */</span>
|
|
</span><span id=__span-0-13><a id=__codelineno-0-13 name=__codelineno-0-13 href=#__codelineno-0-13></a><span class=w> </span><span class=nx>state</span><span class=o>:</span><span class=w> </span><span class=kt>DeviceState</span><span class=p>;</span>
|
|
</span><span id=__span-0-14><a id=__codelineno-0-14 name=__codelineno-0-14 href=#__codelineno-0-14></a><span class=p>}</span>
|
|
</span></code></pre></div> <h3 id=naming-conventions>Naming Conventions</h3> <ol> <li>Use PascalCase for:</li> <li>Classes</li> <li>Interfaces</li> <li>Types</li> <li> <p>Enums</p> </li> <li> <p>Use camelCase for:</p> </li> <li>Variables</li> <li>Functions</li> <li>Methods</li> <li> <p>Properties</p> </li> <li> <p>Use UPPER_SNAKE_CASE for:</p> </li> <li>Constants</li> <li>Enum values</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-1-1><a id=__codelineno-1-1 name=__codelineno-1-1 href=#__codelineno-1-1></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceManager</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-1-2><a id=__codelineno-1-2 name=__codelineno-1-2 href=#__codelineno-1-2></a><span class=w> </span><span class=k>private</span><span class=w> </span><span class=k>readonly</span><span class=w> </span><span class=nx>DEFAULT_TIMEOUT</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>5000</span><span class=p>;</span>
|
|
</span><span id=__span-1-3><a id=__codelineno-1-3 name=__codelineno-1-3 href=#__codelineno-1-3></a>
|
|
</span><span id=__span-1-4><a id=__codelineno-1-4 name=__codelineno-1-4 href=#__codelineno-1-4></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>getDeviceState</span><span class=p>(</span><span class=nx>deviceId</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>)</span><span class=o>:</span><span class=w> </span><span class=nb>Promise</span><span class=o><</span><span class=nx>DeviceState</span><span class=o>></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-1-5><a id=__codelineno-1-5 name=__codelineno-1-5 href=#__codelineno-1-5></a><span class=w> </span><span class=c1>// Implementation</span>
|
|
</span><span id=__span-1-6><a id=__codelineno-1-6 name=__codelineno-1-6 href=#__codelineno-1-6></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-1-7><a id=__codelineno-1-7 name=__codelineno-1-7 href=#__codelineno-1-7></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=architecture>Architecture</h2> <h3 id=solid-principles>SOLID Principles</h3> <ol> <li>Single Responsibility</li> <li>Each class/module has one job</li> <li> <p>Split complex functionality</p> </li> <li> <p>Open/Closed</p> </li> <li>Open for extension</li> <li> <p>Closed for modification</p> </li> <li> <p>Liskov Substitution</p> </li> <li>Subtypes must be substitutable</li> <li> <p>Use interfaces properly</p> </li> <li> <p>Interface Segregation</p> </li> <li>Keep interfaces focused</li> <li> <p>Split large interfaces</p> </li> <li> <p>Dependency Inversion</p> </li> <li>Depend on abstractions</li> <li>Use dependency injection</li> </ol> <h3 id=example>Example</h3> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-2-1><a id=__codelineno-2-1 name=__codelineno-2-1 href=#__codelineno-2-1></a><span class=c1>// Bad</span>
|
|
</span><span id=__span-2-2><a id=__codelineno-2-2 name=__codelineno-2-2 href=#__codelineno-2-2></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceManager</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-2-3><a id=__codelineno-2-3 name=__codelineno-2-3 href=#__codelineno-2-3></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>getState</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-2-4><a id=__codelineno-2-4 name=__codelineno-2-4 href=#__codelineno-2-4></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>setState</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-2-5><a id=__codelineno-2-5 name=__codelineno-2-5 href=#__codelineno-2-5></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>sendNotification</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span><span class=w> </span><span class=c1>// Wrong responsibility</span>
|
|
</span><span id=__span-2-6><a id=__codelineno-2-6 name=__codelineno-2-6 href=#__codelineno-2-6></a><span class=p>}</span>
|
|
</span><span id=__span-2-7><a id=__codelineno-2-7 name=__codelineno-2-7 href=#__codelineno-2-7></a>
|
|
</span><span id=__span-2-8><a id=__codelineno-2-8 name=__codelineno-2-8 href=#__codelineno-2-8></a><span class=c1>// Good</span>
|
|
</span><span id=__span-2-9><a id=__codelineno-2-9 name=__codelineno-2-9 href=#__codelineno-2-9></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceManager</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-2-10><a id=__codelineno-2-10 name=__codelineno-2-10 href=#__codelineno-2-10></a><span class=w> </span><span class=kr>constructor</span><span class=p>(</span>
|
|
</span><span id=__span-2-11><a id=__codelineno-2-11 name=__codelineno-2-11 href=#__codelineno-2-11></a><span class=w> </span><span class=k>private</span><span class=w> </span><span class=nx>notifier</span><span class=o>:</span><span class=w> </span><span class=kt>NotificationService</span>
|
|
</span><span id=__span-2-12><a id=__codelineno-2-12 name=__codelineno-2-12 href=#__codelineno-2-12></a><span class=w> </span><span class=p>)</span><span class=w> </span><span class=p>{}</span>
|
|
</span><span id=__span-2-13><a id=__codelineno-2-13 name=__codelineno-2-13 href=#__codelineno-2-13></a>
|
|
</span><span id=__span-2-14><a id=__codelineno-2-14 name=__codelineno-2-14 href=#__codelineno-2-14></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>getState</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-2-15><a id=__codelineno-2-15 name=__codelineno-2-15 href=#__codelineno-2-15></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>setState</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-2-16><a id=__codelineno-2-16 name=__codelineno-2-16 href=#__codelineno-2-16></a><span class=p>}</span>
|
|
</span><span id=__span-2-17><a id=__codelineno-2-17 name=__codelineno-2-17 href=#__codelineno-2-17></a>
|
|
</span><span id=__span-2-18><a id=__codelineno-2-18 name=__codelineno-2-18 href=#__codelineno-2-18></a><span class=kd>class</span><span class=w> </span><span class=nx>NotificationService</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-2-19><a id=__codelineno-2-19 name=__codelineno-2-19 href=#__codelineno-2-19></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>send</span><span class=p>()</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-2-20><a id=__codelineno-2-20 name=__codelineno-2-20 href=#__codelineno-2-20></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=error-handling>Error Handling</h2> <h3 id=best-practices>Best Practices</h3> <ol> <li>Use custom error classes</li> <li>Include error codes</li> <li>Provide meaningful messages</li> <li>Include error context</li> <li>Handle async errors</li> <li>Log appropriately</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-3-1><a id=__codelineno-3-1 name=__codelineno-3-1 href=#__codelineno-3-1></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceError</span><span class=w> </span><span class=k>extends</span><span class=w> </span><span class=ne>Error</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-3-2><a id=__codelineno-3-2 name=__codelineno-3-2 href=#__codelineno-3-2></a><span class=w> </span><span class=kr>constructor</span><span class=p>(</span>
|
|
</span><span id=__span-3-3><a id=__codelineno-3-3 name=__codelineno-3-3 href=#__codelineno-3-3></a><span class=w> </span><span class=nx>message</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>,</span>
|
|
</span><span id=__span-3-4><a id=__codelineno-3-4 name=__codelineno-3-4 href=#__codelineno-3-4></a><span class=w> </span><span class=k>public</span><span class=w> </span><span class=nx>code</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>,</span>
|
|
</span><span id=__span-3-5><a id=__codelineno-3-5 name=__codelineno-3-5 href=#__codelineno-3-5></a><span class=w> </span><span class=k>public</span><span class=w> </span><span class=nx>context</span><span class=o>:</span><span class=w> </span><span class=kt>Record</span><span class=o><</span><span class=kt>string</span><span class=p>,</span><span class=w> </span><span class=nx>any</span><span class=o>></span>
|
|
</span><span id=__span-3-6><a id=__codelineno-3-6 name=__codelineno-3-6 href=#__codelineno-3-6></a><span class=w> </span><span class=p>)</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-3-7><a id=__codelineno-3-7 name=__codelineno-3-7 href=#__codelineno-3-7></a><span class=w> </span><span class=k>super</span><span class=p>(</span><span class=nx>message</span><span class=p>);</span>
|
|
</span><span id=__span-3-8><a id=__codelineno-3-8 name=__codelineno-3-8 href=#__codelineno-3-8></a><span class=w> </span><span class=k>this</span><span class=p>.</span><span class=nx>name</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=s1>'DeviceError'</span><span class=p>;</span>
|
|
</span><span id=__span-3-9><a id=__codelineno-3-9 name=__codelineno-3-9 href=#__codelineno-3-9></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-3-10><a id=__codelineno-3-10 name=__codelineno-3-10 href=#__codelineno-3-10></a><span class=p>}</span>
|
|
</span><span id=__span-3-11><a id=__codelineno-3-11 name=__codelineno-3-11 href=#__codelineno-3-11></a>
|
|
</span><span id=__span-3-12><a id=__codelineno-3-12 name=__codelineno-3-12 href=#__codelineno-3-12></a><span class=k>try</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-3-13><a id=__codelineno-3-13 name=__codelineno-3-13 href=#__codelineno-3-13></a><span class=w> </span><span class=k>await</span><span class=w> </span><span class=nx>device</span><span class=p>.</span><span class=nx>connect</span><span class=p>();</span>
|
|
</span><span id=__span-3-14><a id=__codelineno-3-14 name=__codelineno-3-14 href=#__codelineno-3-14></a><span class=p>}</span><span class=w> </span><span class=k>catch</span><span class=w> </span><span class=p>(</span><span class=nx>error</span><span class=p>)</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-3-15><a id=__codelineno-3-15 name=__codelineno-3-15 href=#__codelineno-3-15></a><span class=w> </span><span class=k>throw</span><span class=w> </span><span class=ow>new</span><span class=w> </span><span class=nx>DeviceError</span><span class=p>(</span>
|
|
</span><span id=__span-3-16><a id=__codelineno-3-16 name=__codelineno-3-16 href=#__codelineno-3-16></a><span class=w> </span><span class=s1>'Failed to connect to device'</span><span class=p>,</span>
|
|
</span><span id=__span-3-17><a id=__codelineno-3-17 name=__codelineno-3-17 href=#__codelineno-3-17></a><span class=w> </span><span class=s1>'DEVICE_CONNECTION_ERROR'</span><span class=p>,</span>
|
|
</span><span id=__span-3-18><a id=__codelineno-3-18 name=__codelineno-3-18 href=#__codelineno-3-18></a><span class=w> </span><span class=p>{</span><span class=w> </span><span class=nx>deviceId</span><span class=o>:</span><span class=w> </span><span class=kt>device.id</span><span class=p>,</span><span class=w> </span><span class=nx>attempt</span><span class=o>:</span><span class=w> </span><span class=kt>1</span><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-3-19><a id=__codelineno-3-19 name=__codelineno-3-19 href=#__codelineno-3-19></a><span class=w> </span><span class=p>);</span>
|
|
</span><span id=__span-3-20><a id=__codelineno-3-20 name=__codelineno-3-20 href=#__codelineno-3-20></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=testing>Testing</h2> <h3 id=guidelines>Guidelines</h3> <ol> <li>Write unit tests first</li> <li>Use meaningful descriptions</li> <li>Test edge cases</li> <li>Mock external dependencies</li> <li>Keep tests focused</li> <li>Use test fixtures</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-4-1><a id=__codelineno-4-1 name=__codelineno-4-1 href=#__codelineno-4-1></a><span class=nx>describe</span><span class=p>(</span><span class=s1>'DeviceManager'</span><span class=p>,</span><span class=w> </span><span class=p>()</span><span class=w> </span><span class=p>=></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-4-2><a id=__codelineno-4-2 name=__codelineno-4-2 href=#__codelineno-4-2></a><span class=w> </span><span class=kd>let</span><span class=w> </span><span class=nx>manager</span><span class=o>:</span><span class=w> </span><span class=kt>DeviceManager</span><span class=p>;</span>
|
|
</span><span id=__span-4-3><a id=__codelineno-4-3 name=__codelineno-4-3 href=#__codelineno-4-3></a><span class=w> </span><span class=kd>let</span><span class=w> </span><span class=nx>mockDevice</span><span class=o>:</span><span class=w> </span><span class=kt>jest.Mocked</span><span class=o><</span><span class=nx>Device</span><span class=o>></span><span class=p>;</span>
|
|
</span><span id=__span-4-4><a id=__codelineno-4-4 name=__codelineno-4-4 href=#__codelineno-4-4></a>
|
|
</span><span id=__span-4-5><a id=__codelineno-4-5 name=__codelineno-4-5 href=#__codelineno-4-5></a><span class=w> </span><span class=nx>beforeEach</span><span class=p>(()</span><span class=w> </span><span class=p>=></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-4-6><a id=__codelineno-4-6 name=__codelineno-4-6 href=#__codelineno-4-6></a><span class=w> </span><span class=nx>mockDevice</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-4-7><a id=__codelineno-4-7 name=__codelineno-4-7 href=#__codelineno-4-7></a><span class=w> </span><span class=nx>id</span><span class=o>:</span><span class=w> </span><span class=s1>'test_device'</span><span class=p>,</span>
|
|
</span><span id=__span-4-8><a id=__codelineno-4-8 name=__codelineno-4-8 href=#__codelineno-4-8></a><span class=w> </span><span class=nx>getState</span><span class=o>:</span><span class=w> </span><span class=kt>jest.fn</span><span class=p>()</span>
|
|
</span><span id=__span-4-9><a id=__codelineno-4-9 name=__codelineno-4-9 href=#__codelineno-4-9></a><span class=w> </span><span class=p>};</span>
|
|
</span><span id=__span-4-10><a id=__codelineno-4-10 name=__codelineno-4-10 href=#__codelineno-4-10></a><span class=w> </span><span class=nx>manager</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=ow>new</span><span class=w> </span><span class=nx>DeviceManager</span><span class=p>(</span><span class=nx>mockDevice</span><span class=p>);</span>
|
|
</span><span id=__span-4-11><a id=__codelineno-4-11 name=__codelineno-4-11 href=#__codelineno-4-11></a><span class=w> </span><span class=p>});</span>
|
|
</span><span id=__span-4-12><a id=__codelineno-4-12 name=__codelineno-4-12 href=#__codelineno-4-12></a>
|
|
</span><span id=__span-4-13><a id=__codelineno-4-13 name=__codelineno-4-13 href=#__codelineno-4-13></a><span class=w> </span><span class=nx>it</span><span class=p>(</span><span class=s1>'should get device state'</span><span class=p>,</span><span class=w> </span><span class=k>async</span><span class=w> </span><span class=p>()</span><span class=w> </span><span class=p>=></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-4-14><a id=__codelineno-4-14 name=__codelineno-4-14 href=#__codelineno-4-14></a><span class=w> </span><span class=nx>mockDevice</span><span class=p>.</span><span class=nx>getState</span><span class=p>.</span><span class=nx>mockResolvedValue</span><span class=p>(</span><span class=s1>'on'</span><span class=p>);</span>
|
|
</span><span id=__span-4-15><a id=__codelineno-4-15 name=__codelineno-4-15 href=#__codelineno-4-15></a><span class=w> </span><span class=kd>const</span><span class=w> </span><span class=nx>state</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>await</span><span class=w> </span><span class=nx>manager</span><span class=p>.</span><span class=nx>getDeviceState</span><span class=p>();</span>
|
|
</span><span id=__span-4-16><a id=__codelineno-4-16 name=__codelineno-4-16 href=#__codelineno-4-16></a><span class=w> </span><span class=nx>expect</span><span class=p>(</span><span class=nx>state</span><span class=p>).</span><span class=nx>toBe</span><span class=p>(</span><span class=s1>'on'</span><span class=p>);</span>
|
|
</span><span id=__span-4-17><a id=__codelineno-4-17 name=__codelineno-4-17 href=#__codelineno-4-17></a><span class=w> </span><span class=p>});</span>
|
|
</span><span id=__span-4-18><a id=__codelineno-4-18 name=__codelineno-4-18 href=#__codelineno-4-18></a><span class=p>});</span>
|
|
</span></code></pre></div> <h2 id=performance>Performance</h2> <h3 id=optimization>Optimization</h3> <ol> <li>Use caching</li> <li>Implement pagination</li> <li>Optimize database queries</li> <li>Use connection pooling</li> <li>Implement rate limiting</li> <li>Batch operations</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-5-1><a id=__codelineno-5-1 name=__codelineno-5-1 href=#__codelineno-5-1></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceCache</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-5-2><a id=__codelineno-5-2 name=__codelineno-5-2 href=#__codelineno-5-2></a><span class=w> </span><span class=k>private</span><span class=w> </span><span class=nx>cache</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=ow>new</span><span class=w> </span><span class=nb>Map</span><span class=o><</span><span class=kt>string</span><span class=p>,</span><span class=w> </span><span class=nx>CacheEntry</span><span class=o>></span><span class=p>();</span>
|
|
</span><span id=__span-5-3><a id=__codelineno-5-3 name=__codelineno-5-3 href=#__codelineno-5-3></a><span class=w> </span><span class=k>private</span><span class=w> </span><span class=k>readonly</span><span class=w> </span><span class=nx>TTL</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=mf>60000</span><span class=p>;</span><span class=w> </span><span class=c1>// 1 minute</span>
|
|
</span><span id=__span-5-4><a id=__codelineno-5-4 name=__codelineno-5-4 href=#__codelineno-5-4></a>
|
|
</span><span id=__span-5-5><a id=__codelineno-5-5 name=__codelineno-5-5 href=#__codelineno-5-5></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>getDevice</span><span class=p>(</span><span class=nx>id</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>)</span><span class=o>:</span><span class=w> </span><span class=nb>Promise</span><span class=o><</span><span class=nx>Device</span><span class=o>></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-5-6><a id=__codelineno-5-6 name=__codelineno-5-6 href=#__codelineno-5-6></a><span class=w> </span><span class=kd>const</span><span class=w> </span><span class=nx>cached</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>this</span><span class=p>.</span><span class=nx>cache</span><span class=p>.</span><span class=nx>get</span><span class=p>(</span><span class=nx>id</span><span class=p>);</span>
|
|
</span><span id=__span-5-7><a id=__codelineno-5-7 name=__codelineno-5-7 href=#__codelineno-5-7></a><span class=w> </span><span class=k>if</span><span class=w> </span><span class=p>(</span><span class=nx>cached</span><span class=w> </span><span class=o>&&</span><span class=w> </span><span class=nb>Date</span><span class=p>.</span><span class=nx>now</span><span class=p>()</span><span class=w> </span><span class=o>-</span><span class=w> </span><span class=nx>cached</span><span class=p>.</span><span class=nx>timestamp</span><span class=w> </span><span class=o><</span><span class=w> </span><span class=k>this</span><span class=p>.</span><span class=nx>TTL</span><span class=p>)</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-5-8><a id=__codelineno-5-8 name=__codelineno-5-8 href=#__codelineno-5-8></a><span class=w> </span><span class=k>return</span><span class=w> </span><span class=nx>cached</span><span class=p>.</span><span class=nx>device</span><span class=p>;</span>
|
|
</span><span id=__span-5-9><a id=__codelineno-5-9 name=__codelineno-5-9 href=#__codelineno-5-9></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-5-10><a id=__codelineno-5-10 name=__codelineno-5-10 href=#__codelineno-5-10></a>
|
|
</span><span id=__span-5-11><a id=__codelineno-5-11 name=__codelineno-5-11 href=#__codelineno-5-11></a><span class=w> </span><span class=kd>const</span><span class=w> </span><span class=nx>device</span><span class=w> </span><span class=o>=</span><span class=w> </span><span class=k>await</span><span class=w> </span><span class=k>this</span><span class=p>.</span><span class=nx>fetchDevice</span><span class=p>(</span><span class=nx>id</span><span class=p>);</span>
|
|
</span><span id=__span-5-12><a id=__codelineno-5-12 name=__codelineno-5-12 href=#__codelineno-5-12></a><span class=w> </span><span class=k>this</span><span class=p>.</span><span class=nx>cache</span><span class=p>.</span><span class=nx>set</span><span class=p>(</span><span class=nx>id</span><span class=p>,</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-5-13><a id=__codelineno-5-13 name=__codelineno-5-13 href=#__codelineno-5-13></a><span class=w> </span><span class=nx>device</span><span class=p>,</span>
|
|
</span><span id=__span-5-14><a id=__codelineno-5-14 name=__codelineno-5-14 href=#__codelineno-5-14></a><span class=w> </span><span class=nx>timestamp</span><span class=o>:</span><span class=w> </span><span class=kt>Date.now</span><span class=p>()</span>
|
|
</span><span id=__span-5-15><a id=__codelineno-5-15 name=__codelineno-5-15 href=#__codelineno-5-15></a><span class=w> </span><span class=p>});</span>
|
|
</span><span id=__span-5-16><a id=__codelineno-5-16 name=__codelineno-5-16 href=#__codelineno-5-16></a>
|
|
</span><span id=__span-5-17><a id=__codelineno-5-17 name=__codelineno-5-17 href=#__codelineno-5-17></a><span class=w> </span><span class=k>return</span><span class=w> </span><span class=nx>device</span><span class=p>;</span>
|
|
</span><span id=__span-5-18><a id=__codelineno-5-18 name=__codelineno-5-18 href=#__codelineno-5-18></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-5-19><a id=__codelineno-5-19 name=__codelineno-5-19 href=#__codelineno-5-19></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=security>Security</h2> <h3 id=guidelines_1>Guidelines</h3> <ol> <li>Validate all input</li> <li>Use parameterized queries</li> <li>Implement rate limiting</li> <li>Use proper authentication</li> <li>Follow OWASP guidelines</li> <li>Sanitize output</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-6-1><a id=__codelineno-6-1 name=__codelineno-6-1 href=#__codelineno-6-1></a><span class=kd>class</span><span class=w> </span><span class=nx>InputValidator</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-6-2><a id=__codelineno-6-2 name=__codelineno-6-2 href=#__codelineno-6-2></a><span class=w> </span><span class=k>static</span><span class=w> </span><span class=nx>validateDeviceId</span><span class=p>(</span><span class=nx>id</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>)</span><span class=o>:</span><span class=w> </span><span class=kt>boolean</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-6-3><a id=__codelineno-6-3 name=__codelineno-6-3 href=#__codelineno-6-3></a><span class=w> </span><span class=k>return</span><span class=w> </span><span class=sr>/^[a-zA-Z0-9_-]{1,64}$/</span><span class=p>.</span><span class=nx>test</span><span class=p>(</span><span class=nx>id</span><span class=p>);</span>
|
|
</span><span id=__span-6-4><a id=__codelineno-6-4 name=__codelineno-6-4 href=#__codelineno-6-4></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-6-5><a id=__codelineno-6-5 name=__codelineno-6-5 href=#__codelineno-6-5></a>
|
|
</span><span id=__span-6-6><a id=__codelineno-6-6 name=__codelineno-6-6 href=#__codelineno-6-6></a><span class=w> </span><span class=k>static</span><span class=w> </span><span class=nx>sanitizeOutput</span><span class=p>(</span><span class=nx>data</span><span class=o>:</span><span class=w> </span><span class=kt>any</span><span class=p>)</span><span class=o>:</span><span class=w> </span><span class=nx>any</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-6-7><a id=__codelineno-6-7 name=__codelineno-6-7 href=#__codelineno-6-7></a><span class=w> </span><span class=c1>// Implement output sanitization</span>
|
|
</span><span id=__span-6-8><a id=__codelineno-6-8 name=__codelineno-6-8 href=#__codelineno-6-8></a><span class=w> </span><span class=k>return</span><span class=w> </span><span class=nx>data</span><span class=p>;</span>
|
|
</span><span id=__span-6-9><a id=__codelineno-6-9 name=__codelineno-6-9 href=#__codelineno-6-9></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-6-10><a id=__codelineno-6-10 name=__codelineno-6-10 href=#__codelineno-6-10></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=documentation>Documentation</h2> <h3 id=standards>Standards</h3> <ol> <li>Use JSDoc comments</li> <li>Document interfaces</li> <li>Include examples</li> <li>Document errors</li> <li>Keep docs updated</li> <li>Use markdown</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-7-1><a id=__codelineno-7-1 name=__codelineno-7-1 href=#__codelineno-7-1></a><span class=cm>/**</span>
|
|
</span><span id=__span-7-2><a id=__codelineno-7-2 name=__codelineno-7-2 href=#__codelineno-7-2></a><span class=cm> * Manages device operations.</span>
|
|
</span><span id=__span-7-3><a id=__codelineno-7-3 name=__codelineno-7-3 href=#__codelineno-7-3></a><span class=cm> * @class</span>
|
|
</span><span id=__span-7-4><a id=__codelineno-7-4 name=__codelineno-7-4 href=#__codelineno-7-4></a><span class=cm> */</span>
|
|
</span><span id=__span-7-5><a id=__codelineno-7-5 name=__codelineno-7-5 href=#__codelineno-7-5></a><span class=kd>class</span><span class=w> </span><span class=nx>DeviceManager</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-7-6><a id=__codelineno-7-6 name=__codelineno-7-6 href=#__codelineno-7-6></a><span class=w> </span><span class=cm>/**</span>
|
|
</span><span id=__span-7-7><a id=__codelineno-7-7 name=__codelineno-7-7 href=#__codelineno-7-7></a><span class=cm> * Gets the current state of a device.</span>
|
|
</span><span id=__span-7-8><a id=__codelineno-7-8 name=__codelineno-7-8 href=#__codelineno-7-8></a><span class=cm> * @param {string} deviceId - The device identifier.</span>
|
|
</span><span id=__span-7-9><a id=__codelineno-7-9 name=__codelineno-7-9 href=#__codelineno-7-9></a><span class=cm> * @returns {Promise<DeviceState>} The current device state.</span>
|
|
</span><span id=__span-7-10><a id=__codelineno-7-10 name=__codelineno-7-10 href=#__codelineno-7-10></a><span class=cm> * @throws {DeviceError} If device is not found or unavailable.</span>
|
|
</span><span id=__span-7-11><a id=__codelineno-7-11 name=__codelineno-7-11 href=#__codelineno-7-11></a><span class=cm> * @example</span>
|
|
</span><span id=__span-7-12><a id=__codelineno-7-12 name=__codelineno-7-12 href=#__codelineno-7-12></a><span class=cm> * const state = await deviceManager.getDeviceState('living_room_light');</span>
|
|
</span><span id=__span-7-13><a id=__codelineno-7-13 name=__codelineno-7-13 href=#__codelineno-7-13></a><span class=cm> */</span>
|
|
</span><span id=__span-7-14><a id=__codelineno-7-14 name=__codelineno-7-14 href=#__codelineno-7-14></a><span class=w> </span><span class=k>async</span><span class=w> </span><span class=nx>getDeviceState</span><span class=p>(</span><span class=nx>deviceId</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>)</span><span class=o>:</span><span class=w> </span><span class=nb>Promise</span><span class=o><</span><span class=nx>DeviceState</span><span class=o>></span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-7-15><a id=__codelineno-7-15 name=__codelineno-7-15 href=#__codelineno-7-15></a><span class=w> </span><span class=c1>// Implementation</span>
|
|
</span><span id=__span-7-16><a id=__codelineno-7-16 name=__codelineno-7-16 href=#__codelineno-7-16></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-7-17><a id=__codelineno-7-17 name=__codelineno-7-17 href=#__codelineno-7-17></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=logging>Logging</h2> <h3 id=best-practices_1>Best Practices</h3> <ol> <li>Use appropriate levels</li> <li>Include context</li> <li>Structure log data</li> <li>Handle sensitive data</li> <li>Implement rotation</li> <li>Use correlation IDs</li> </ol> <div class="language-typescript highlight"><pre><span></span><code><span id=__span-8-1><a id=__codelineno-8-1 name=__codelineno-8-1 href=#__codelineno-8-1></a><span class=kd>class</span><span class=w> </span><span class=nx>Logger</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-8-2><a id=__codelineno-8-2 name=__codelineno-8-2 href=#__codelineno-8-2></a><span class=w> </span><span class=nx>info</span><span class=p>(</span><span class=nx>message</span><span class=o>:</span><span class=w> </span><span class=kt>string</span><span class=p>,</span><span class=w> </span><span class=nx>context</span><span class=o>:</span><span class=w> </span><span class=kt>Record</span><span class=o><</span><span class=kt>string</span><span class=p>,</span><span class=w> </span><span class=nx>any</span><span class=o>></span><span class=p>)</span><span class=w> </span><span class=p>{</span>
|
|
</span><span id=__span-8-3><a id=__codelineno-8-3 name=__codelineno-8-3 href=#__codelineno-8-3></a><span class=w> </span><span class=nx>console</span><span class=p>.</span><span class=nx>log</span><span class=p>(</span><span class=nb>JSON</span><span class=p>.</span><span class=nx>stringify</span><span class=p>({</span>
|
|
</span><span id=__span-8-4><a id=__codelineno-8-4 name=__codelineno-8-4 href=#__codelineno-8-4></a><span class=w> </span><span class=nx>level</span><span class=o>:</span><span class=w> </span><span class=s1>'info'</span><span class=p>,</span>
|
|
</span><span id=__span-8-5><a id=__codelineno-8-5 name=__codelineno-8-5 href=#__codelineno-8-5></a><span class=w> </span><span class=nx>message</span><span class=p>,</span>
|
|
</span><span id=__span-8-6><a id=__codelineno-8-6 name=__codelineno-8-6 href=#__codelineno-8-6></a><span class=w> </span><span class=nx>context</span><span class=p>,</span>
|
|
</span><span id=__span-8-7><a id=__codelineno-8-7 name=__codelineno-8-7 href=#__codelineno-8-7></a><span class=w> </span><span class=nx>timestamp</span><span class=o>:</span><span class=w> </span><span class=kt>new</span><span class=w> </span><span class=nb>Date</span><span class=p>().</span><span class=nx>toISOString</span><span class=p>(),</span>
|
|
</span><span id=__span-8-8><a id=__codelineno-8-8 name=__codelineno-8-8 href=#__codelineno-8-8></a><span class=w> </span><span class=nx>correlationId</span><span class=o>:</span><span class=w> </span><span class=kt>context.correlationId</span>
|
|
</span><span id=__span-8-9><a id=__codelineno-8-9 name=__codelineno-8-9 href=#__codelineno-8-9></a><span class=w> </span><span class=p>}));</span>
|
|
</span><span id=__span-8-10><a id=__codelineno-8-10 name=__codelineno-8-10 href=#__codelineno-8-10></a><span class=w> </span><span class=p>}</span>
|
|
</span><span id=__span-8-11><a id=__codelineno-8-11 name=__codelineno-8-11 href=#__codelineno-8-11></a><span class=p>}</span>
|
|
</span></code></pre></div> <h2 id=version-control>Version Control</h2> <h3 id=guidelines_2>Guidelines</h3> <ol> <li>Use meaningful commits</li> <li>Follow branching strategy</li> <li>Write good PR descriptions</li> <li>Review code thoroughly</li> <li>Keep changes focused</li> <li>Use conventional commits</li> </ol> <div class="language-bash highlight"><pre><span></span><code><span id=__span-9-1><a id=__codelineno-9-1 name=__codelineno-9-1 href=#__codelineno-9-1></a><span class=c1># Good commit messages</span>
|
|
</span><span id=__span-9-2><a id=__codelineno-9-2 name=__codelineno-9-2 href=#__codelineno-9-2></a>git<span class=w> </span>commit<span class=w> </span>-m<span class=w> </span><span class=s2>"feat(device): add support for zigbee devices"</span>
|
|
</span><span id=__span-9-3><a id=__codelineno-9-3 name=__codelineno-9-3 href=#__codelineno-9-3></a>git<span class=w> </span>commit<span class=w> </span>-m<span class=w> </span><span class=s2>"fix(api): handle timeout errors properly"</span>
|
|
</span></code></pre></div> <h2 id=see-also>See Also</h2> <ul> <li><a href=tools.html>Tool Development Guide</a></li> <li><a href=interfaces.html>Interface Documentation</a></li> <li><a href=../testing.html>Testing Guide</a> </li> </ul> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">February 5, 2025</span> </span> <span class=md-source-file__fact> <span class=md-icon title=Created> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M14.47 15.08 11 13V7h1.5v5.25l3.08 1.83c-.41.28-.79.62-1.11 1m-1.39 4.84c-.36.05-.71.08-1.08.08-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8c0 .37-.03.72-.08 1.08.69.1 1.33.32 1.92.64.1-.56.16-1.13.16-1.72 0-5.5-4.5-10-10-10S2 6.5 2 12s4.47 10 10 10c.59 0 1.16-.06 1.72-.16-.32-.59-.54-1.23-.64-1.92M18 15v3h-3v2h3v3h2v-3h3v-2h-3v-3z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date">February 5, 2025</span> </span> </aside> <form class=md-feedback name=feedback hidden> <fieldset> <legend class=md-feedback__title> Was this page helpful? </legend> <div class=md-feedback__inner> <div class=md-feedback__list> <button class="md-feedback__icon md-icon" type=submit title="This page was helpful" data-md-value=1> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 12a8 8 0 0 0-8-8 8 8 0 0 0-8 8 8 8 0 0 0 8 8 8 8 0 0 0 8-8m2 0a10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2a10 10 0 0 1 10 10M10 9.5c0 .8-.7 1.5-1.5 1.5S7 10.3 7 9.5 7.7 8 8.5 8s1.5.7 1.5 1.5m7 0c0 .8-.7 1.5-1.5 1.5S14 10.3 14 9.5 14.7 8 15.5 8s1.5.7 1.5 1.5m-5 7.73c-1.75 0-3.29-.73-4.19-1.81L9.23 14c.45.72 1.52 1.23 2.77 1.23s2.32-.51 2.77-1.23l1.42 1.42c-.9 1.08-2.44 1.81-4.19 1.81"/></svg> </button> <button class="md-feedback__icon md-icon" type=submit title="This page could be improved" data-md-value=0> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 12a8 8 0 0 0-8-8 8 8 0 0 0-8 8 8 8 0 0 0 8 8 8 8 0 0 0 8-8m2 0a10 10 0 0 1-10 10A10 10 0 0 1 2 12 10 10 0 0 1 12 2a10 10 0 0 1 10 10m-6.5-4c.8 0 1.5.7 1.5 1.5s-.7 1.5-1.5 1.5-1.5-.7-1.5-1.5.7-1.5 1.5-1.5M10 9.5c0 .8-.7 1.5-1.5 1.5S7 10.3 7 9.5 7.7 8 8.5 8s1.5.7 1.5 1.5m2 4.5c1.75 0 3.29.72 4.19 1.81l-1.42 1.42C14.32 16.5 13.25 16 12 16s-2.32.5-2.77 1.23l-1.42-1.42C8.71 14.72 10.25 14 12 14"/></svg> </button> </div> <div class=md-feedback__note> <div data-md-value=1 hidden> Thanks for your feedback! </div> <div data-md-value=0 hidden> Thanks for your feedback! Please consider creating an issue to help us improve. </div> </div> </div> </fieldset> </form> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> </main> <footer class=md-footer> <nav class="md-footer__inner md-grid" aria-label=Footer> <a href=../testing.html class="md-footer__link md-footer__link--prev" aria-label="Previous: Testing"> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11z"/></svg> </div> <div class=md-footer__title> <span class=md-footer__direction> Previous </span> <div class=md-ellipsis> Testing </div> </div> </a> <a href=interfaces.html class="md-footer__link md-footer__link--next" aria-label="Next: Interfaces"> <div class=md-footer__title> <span class=md-footer__direction> Next </span> <div class=md-ellipsis> Interfaces </div> </div> <div class="md-footer__button md-icon"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11z"/></svg> </div> </a> </nav> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright © 2025 jango-blockchained </div> Made with <a href=https://squidfunk.github.io/mkdocs-material/ target=_blank rel=noopener> Material for MkDocs </a> </div> <div class=md-social> <a href=https://github.com/jango-blockchained/homeassistant-mcp target=_blank rel=noopener title=github.com class=md-social__link> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 496 512"><!-- Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8M97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1m-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7m32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1m-11.4-14.7c-1.6 1-1.6 3.6 0 5.9s4.3 3.3 5.6 2.3c1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2"/></svg> </a> <a href=https://hub.docker.com/r/jangoblockchained/homeassistant-mcp target=_blank rel=noopener title=hub.docker.com class=md-social__link> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 640 512"><!-- Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2024 Fonticons, Inc.--><path d="M349.9 236.3h-66.1v-59.4h66.1zm0-204.3h-66.1v60.7h66.1zm78.2 144.8H362v59.4h66.1zm-156.3-72.1h-66.1v60.1h66.1zm78.1 0h-66.1v60.1h66.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1zm78.1 0h-66.1v59.4h66.1zm-78.1-72.1h-66.1v60.1h66.1z"/></svg> </a> </div> </div> </div> </footer> </div> <div class=md-dialog data-md-component=dialog> <div class="md-dialog__inner md-typeset"></div> </div> <div class=md-consent data-md-component=consent id=__consent hidden> <div class=md-consent__overlay></div> <aside class=md-consent__inner> <form class="md-consent__form md-grid md-typeset" name=consent> <h4>Cookie consent</h4> <p>We use cookies to recognize your repeated visits and preferences, as well as to measure the effectiveness of our documentation and whether users find what they're searching for. With your consent, you're helping us to make our documentation better.</p> <input class=md-toggle type=checkbox id=__settings> <div class=md-consent__settings> <ul class=task-list> <li class=task-list-item> <label class=task-list-control> <input type=checkbox name=analytics checked> <span class=task-list-indicator></span> Google Analytics </label> </li> <li class=task-list-item> <label class=task-list-control> <input type=checkbox name=github checked> <span class=task-list-indicator></span> GitHub </label> </li> </ul> </div> <div class=md-consent__controls> <button class="md-button md-button--primary">Accept</button> <button type=reset class="md-button md-button--primary">Reject</button> <label class=md-button for=__settings>Manage settings</label> </div> </form> </aside> </div> <script>var consent=__md_get("__consent");if(consent)for(var input of document.forms.consent.elements)input.name&&(input.checked=consent[input.name]||!1);else"file:"!==location.protocol&&setTimeout((function(){document.querySelector("[data-md-component=consent]").hidden=!1}),250);var form=document.forms.consent;for(var action of["submit","reset"])form.addEventListener(action,(function(e){if(e.preventDefault(),"reset"===e.type)for(var n of document.forms.consent.elements)n.name&&(n.checked=!1);__md_set("__consent",Object.fromEntries(Array.from(new FormData(form).keys()).map((function(e){return[e,!0]})))),location.hash="",location.reload()}))</script> <script id=__config type=application/json>{"base": "..", "features": ["navigation.tabs", "navigation.tabs.sticky", "navigation.indexes", "navigation.sections", "navigation.expand", "navigation.path", "navigation.footer", "navigation.prune", "navigation.tracking", "navigation.instant", "header.autohide", "toc.integrate", "toc.follow", "announce.dismiss", "search.suggest", "search.highlight", "search.share", "content.code.annotate", "content.code.copy", "content.code.select", "content.tabs.link", "content.tooltips"], "search": "../assets/javascripts/workers/search.f8cc74c7.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}, "version": {"default": "latest", "provider": "mike"}}</script> <script src=../assets/javascripts/bundle.f13b1293.min.js></script> <script src=../javascripts/mathjax.js></script> <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script> <script src=https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js></script> <script src=../javascripts/extra.js></script> </body> </html> |