fix: refine a high-residual calibration on the map's own floor

User-Visible: no
Issue: #162
This commit is contained in:
Codex
2026-09-03 19:55:52 +03:00
parent 4b8cf6e04d
commit 49f69f60db
30 changed files with 424 additions and 317 deletions
@@ -1,125 +1,125 @@
{
"schema": 1,
"fingerprint": "6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4",
"fingerprint": "55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c",
"entry": "houseplan-card.js",
"initialViewFiles": [
"houseplan-assets/houseplan-card-D6f_gZ66.js",
"houseplan-assets/houseplan-card-DmogMO2s.js",
"houseplan-card.js"
],
"initialViewGzipBytes": 292967,
"initialViewGzipBytes": 292978,
"lazyFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/fr-DoCVletV.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/fr-DQDe-eOF.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
],
"lazyGzipBytes": 219793,
"lazyGzipBytes": 220396,
"lazyEditorFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js"
],
"lazyEditorGzipBytes": 163779,
"lazyEditorGzipBytes": 164368,
"lazyOnboardingFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
],
"lazyOnboardingGzipBytes": 14230,
"lazyOnboardingGzipBytes": 14232,
"lazyLocaleFiles": [
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/fr-DoCVletV.js"
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/fr-DQDe-eOF.js"
],
"lazyLocaleGzipBytes": 49061,
"lazyLocaleGzipBytes": 49076,
"files": [
{
"path": "houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"sha256": "b80d106e7eebe023bbffbb3d3a67ddec01c6de6e571e8d9e62a68d2751555831",
"path": "houseplan-assets/backdrop-pick-BrG8E7mX.js",
"sha256": "1a5790f771b8249878e391b7f25cfc71e437dc4523a108b7bc2fb897cc946419",
"rawBytes": 21418,
"gzipBytes": 7277,
"gzipBytes": 7280,
"isEntry": false,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/de-COsCm3SF.js",
"sha256": "6c5d45960334fe1301fab5b63f7891b0871634247476c3856b42bb5a2cf032d3",
"path": "houseplan-assets/de-BYtQLjKR.js",
"sha256": "4ffd405d1f457c9e9a3b4e336146d9b8c6ff1d51249d05031795fa70b1b0b900",
"rawBytes": 82140,
"gzipBytes": 24800,
"gzipBytes": 24807,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
"path": "houseplan-assets/editor-C-B62kvE.js",
"sha256": "b71578f1e4429ca34075051a8d30b3671a57913cff828d5cb42436d0ec866369",
"path": "houseplan-assets/editor-CBKzO3A-.js",
"sha256": "befb2148960d06984b50947814a71587c947987b519c69c6805a4c06c394da4a",
"rawBytes": 3826,
"gzipBytes": 1578,
"gzipBytes": 1581,
"isEntry": false,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/fr-DoCVletV.js",
"sha256": "8ae84d4cba0655342ca85d922effac536ceaa1bbaa2e9ff199afe55b92893dd2",
"path": "houseplan-assets/fr-DQDe-eOF.js",
"sha256": "b5d0fff5dbd99982e1d4af67db8a60912b4383264c75a4b947b2f25487837440",
"rawBytes": 84267,
"gzipBytes": 24261,
"gzipBytes": 24269,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
"path": "houseplan-assets/houseplan-card-D6f_gZ66.js",
"sha256": "87cfd1651a8ddd024617faf74d5d6c3ec4673618d8e271e87358f5829c6f4cda",
"path": "houseplan-assets/houseplan-card-DmogMO2s.js",
"sha256": "443bfe22a4ab2d10e388414d7a7b924531042d7daa2363e50dfc2898300be3c2",
"rawBytes": 1039585,
"gzipBytes": 292173,
"gzipBytes": 292183,
"isEntry": false,
"imports": [],
"dynamicImports": [
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/fr-DoCVletV.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/fr-DQDe-eOF.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
]
},
{
"path": "houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"sha256": "ac04125377f244fa6e5a1b5a30b0bd3c95fb9ef0dc7acc06623a978b07eb373b",
"rawBytes": 590169,
"gzipBytes": 154924,
"path": "houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"sha256": "5aad9efb8986589344139b80bfd1c6f62c75f088685e4cf8939c8dd542e42035",
"rawBytes": 592159,
"gzipBytes": 155507,
"isEntry": false,
"imports": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js",
"sha256": "ff638913e1afb247814031fec9fb8ccb929152e44fbea4117fb34136fa423d1d",
"path": "houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js",
"sha256": "ef93152e8ca00829627b32269a07bf5d84a20db3b2cde2a510705505df43e9e1",
"rawBytes": 28088,
"gzipBytes": 6953,
"gzipBytes": 6952,
"isEntry": false,
"imports": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-card.js",
"sha256": "76c56ccbb61548fad508d0f7bd20a5689b95793198a50eeac825f4f713b4172d",
"sha256": "b52a2d3f16aaf1cef7d24cda20c66dc84858b60b8afcc849fd6354018929fbb8",
"rawBytes": 1183,
"gzipBytes": 794,
"gzipBytes": 795,
"isEntry": true,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
}
File diff suppressed because one or more lines are too long
@@ -1,14 +1,14 @@
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-D6f_gZ66.js";class f extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,f={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},h=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-DmogMO2s.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
.hass=${this.hass}
.data=${this._formData}
.schema=${e}
.computeLabel=${e=>f[e.name]||e.name}
.computeLabel=${e=>h[e.name]||e.name}
@value-changed=${this._valueChanged}
></ha-form>`;return c`
${d(h.slice(0,3))}
${d(f.slice(0,3))}
${_?c`<div class="default-floor-error" role="alert"
style="color:var(--error-color,#db4437);margin:-4px 0 12px;overflow-wrap:anywhere">
${t(s,"editor.default_floor_missing",{id:_})}
</div>`:a}
${d(h.slice(3))}
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}f.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",f);
${d(f.slice(3))}
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}h.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",h);
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4";try{await import("./houseplan-assets/houseplan-card-D6f_gZ66.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c";try{await import("./houseplan-assets/houseplan-card-DmogMO2s.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
+20
View File
@@ -84,6 +84,25 @@ const out = await page.evaluate(async () => {
await c.updateComplete; await new Promise((r) => setTimeout(r, 60));
o.unmappedNoGhostOnOtherFloor = !puck();
// Донастройка матрицы с высоким residual обязана открыться на этаже
// МАРШРУТА: она решалась против его геометрии, а не геометрии дока.
c._space = 'f1';
c._setMode('devices');
await c.updateComplete; await new Promise((r) => setTimeout(r, 120));
c._vacCalConfirm = {
markerId: 'e_vacuum_robo', source: 'camera.robo_map', mapId: 'm2',
routeId: 'vr2', space: 'garden', matrix: M2, rooms: 3, error: '80 см',
};
await c.updateComplete;
c._vacApplyCalibrationProposal(true);
await c.updateComplete; await new Promise((r) => setTimeout(r, 80));
o.manualFitSwitchedToRouteSpace = c._space === 'garden';
o.manualFitKeepsRoute = c._vacFit?.routeId === 'vr2';
c._vacFit = null;
c._setMode('view');
c._space = 'f1';
await c.updateComplete; await new Promise((r) => setTimeout(r, 80));
// Робот встал — предупреждение снимается: тревожить нечем.
c._space = 'f1';
c.hass = { ...c.hass, states: { ...c.hass.states,
@@ -101,6 +120,7 @@ checkAll(out, {
floor2PuckGoneAfterReturn: true, floor1PuckBack: true, routesUntouched: true,
unmappedNoPuck: true, unmappedWarns: true, unmappedWarnLabelled: true,
unmappedNoGhostOnOtherFloor: true,
manualFitSwitchedToRouteSpace: true, manualFitKeepsRoute: true,
dockedNoWarning: true,
});
await finish(browser);
+56 -56
View File
@@ -1,125 +1,125 @@
{
"schema": 1,
"fingerprint": "6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4",
"fingerprint": "55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c",
"entry": "houseplan-card.js",
"initialViewFiles": [
"houseplan-assets/houseplan-card-D6f_gZ66.js",
"houseplan-assets/houseplan-card-DmogMO2s.js",
"houseplan-card.js"
],
"initialViewGzipBytes": 292967,
"initialViewGzipBytes": 292978,
"lazyFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/fr-DoCVletV.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/fr-DQDe-eOF.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
],
"lazyGzipBytes": 219793,
"lazyGzipBytes": 220396,
"lazyEditorFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js"
],
"lazyEditorGzipBytes": 163779,
"lazyEditorGzipBytes": 164368,
"lazyOnboardingFiles": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
],
"lazyOnboardingGzipBytes": 14230,
"lazyOnboardingGzipBytes": 14232,
"lazyLocaleFiles": [
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/fr-DoCVletV.js"
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/fr-DQDe-eOF.js"
],
"lazyLocaleGzipBytes": 49061,
"lazyLocaleGzipBytes": 49076,
"files": [
{
"path": "houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"sha256": "b80d106e7eebe023bbffbb3d3a67ddec01c6de6e571e8d9e62a68d2751555831",
"path": "houseplan-assets/backdrop-pick-BrG8E7mX.js",
"sha256": "1a5790f771b8249878e391b7f25cfc71e437dc4523a108b7bc2fb897cc946419",
"rawBytes": 21418,
"gzipBytes": 7277,
"gzipBytes": 7280,
"isEntry": false,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/de-COsCm3SF.js",
"sha256": "6c5d45960334fe1301fab5b63f7891b0871634247476c3856b42bb5a2cf032d3",
"path": "houseplan-assets/de-BYtQLjKR.js",
"sha256": "4ffd405d1f457c9e9a3b4e336146d9b8c6ff1d51249d05031795fa70b1b0b900",
"rawBytes": 82140,
"gzipBytes": 24800,
"gzipBytes": 24807,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
"path": "houseplan-assets/editor-C-B62kvE.js",
"sha256": "b71578f1e4429ca34075051a8d30b3671a57913cff828d5cb42436d0ec866369",
"path": "houseplan-assets/editor-CBKzO3A-.js",
"sha256": "befb2148960d06984b50947814a71587c947987b519c69c6805a4c06c394da4a",
"rawBytes": 3826,
"gzipBytes": 1578,
"gzipBytes": 1581,
"isEntry": false,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/fr-DoCVletV.js",
"sha256": "8ae84d4cba0655342ca85d922effac536ceaa1bbaa2e9ff199afe55b92893dd2",
"path": "houseplan-assets/fr-DQDe-eOF.js",
"sha256": "b5d0fff5dbd99982e1d4af67db8a60912b4383264c75a4b947b2f25487837440",
"rawBytes": 84267,
"gzipBytes": 24261,
"gzipBytes": 24269,
"isEntry": false,
"imports": [],
"dynamicImports": []
},
{
"path": "houseplan-assets/houseplan-card-D6f_gZ66.js",
"sha256": "87cfd1651a8ddd024617faf74d5d6c3ec4673618d8e271e87358f5829c6f4cda",
"path": "houseplan-assets/houseplan-card-DmogMO2s.js",
"sha256": "443bfe22a4ab2d10e388414d7a7b924531042d7daa2363e50dfc2898300be3c2",
"rawBytes": 1039585,
"gzipBytes": 292173,
"gzipBytes": 292183,
"isEntry": false,
"imports": [],
"dynamicImports": [
"houseplan-assets/de-COsCm3SF.js",
"houseplan-assets/editor-C-B62kvE.js",
"houseplan-assets/fr-DoCVletV.js",
"houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js"
"houseplan-assets/de-BYtQLjKR.js",
"houseplan-assets/editor-CBKzO3A-.js",
"houseplan-assets/fr-DQDe-eOF.js",
"houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js"
]
},
{
"path": "houseplan-assets/houseplan-editor-runtime-3U3MWwcs.js",
"sha256": "ac04125377f244fa6e5a1b5a30b0bd3c95fb9ef0dc7acc06623a978b07eb373b",
"rawBytes": 590169,
"gzipBytes": 154924,
"path": "houseplan-assets/houseplan-editor-runtime-ma6TIZGX.js",
"sha256": "5aad9efb8986589344139b80bfd1c6f62c75f088685e4cf8939c8dd542e42035",
"rawBytes": 592159,
"gzipBytes": 155507,
"isEntry": false,
"imports": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-assets/houseplan-onboarding-runtime-DMZdaL_E.js",
"sha256": "ff638913e1afb247814031fec9fb8ccb929152e44fbea4117fb34136fa423d1d",
"path": "houseplan-assets/houseplan-onboarding-runtime-D8j3bC_e.js",
"sha256": "ef93152e8ca00829627b32269a07bf5d84a20db3b2cde2a510705505df43e9e1",
"rawBytes": 28088,
"gzipBytes": 6953,
"gzipBytes": 6952,
"isEntry": false,
"imports": [
"houseplan-assets/backdrop-pick-ZrVvI3-3.js",
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/backdrop-pick-BrG8E7mX.js",
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
},
{
"path": "houseplan-card.js",
"sha256": "76c56ccbb61548fad508d0f7bd20a5689b95793198a50eeac825f4f713b4172d",
"sha256": "b52a2d3f16aaf1cef7d24cda20c66dc84858b60b8afcc849fd6354018929fbb8",
"rawBytes": 1183,
"gzipBytes": 794,
"gzipBytes": 795,
"isEntry": true,
"imports": [
"houseplan-assets/houseplan-card-D6f_gZ66.js"
"houseplan-assets/houseplan-card-DmogMO2s.js"
],
"dynamicImports": []
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,14 +1,14 @@
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-D6f_gZ66.js";class f extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,f={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},h=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c";import{g as e,l as o,t,dm as s,A as a,dn as i,dp as l,dq as n,E as r,c}from"./houseplan-card-DmogMO2s.js";class h extends e{constructor(){super(...arguments),this._spaces=null,this._spacesLoading=!1,this._spacesAuthoritative=!1}setConfig(e){this._config=e}async _loadSpaces(){if(!this._spaces&&!this._spacesLoading&&this.hass){this._spacesLoading=!0;try{const e=await this.hass.callWS({type:"houseplan/config/get"});this._spaces=(e?.config?.spaces||[]).map(e=>({value:e.id,label:e.title||e.id})),this._spacesAuthoritative=!0}catch{this._spaces=[],this._spacesAuthoritative=!1}finally{this._spacesLoading=!1}}}get _lang(){return o(this.hass,this._config?.language)}get _floorToken(){const e=this._config?.floor;return"number"==typeof e?`__houseplan_yaml_floor_index__:${String(e)}`:null}get _formData(){const e={...this._config},o=this._floorToken;return o?e.floor=o:Object.prototype.hasOwnProperty.call(e,"floor")||(e.floor=""),e}get _schema(){const e=this._spaces||[],o=this._lang,a=[{value:"",label:t(o,"editor.floor_none")}],i=this._floorToken;i&&a.push({value:i,label:t(o,"editor.floor_index",{index:String(this._config?.floor)})});const l="string"==typeof this._config?.floor?this._config.floor:"";l&&!e.some(e=>e.value===l)&&a.push({value:l,label:l}),a.push(...e);const n="string"==typeof this._config?.default_floor?this._config.default_floor:"",r=[...e];return n&&!e.some(e=>e.value===n)&&r.unshift({value:n,label:n}),[{name:"title",selector:{text:{}}},{name:"floor",selector:{select:{mode:"dropdown",options:a}}},e.length?{name:"default_floor",selector:{select:{mode:"dropdown",options:r}}}:{name:"default_floor",selector:{text:{}}},{name:"language",selector:{select:{mode:"dropdown",options:s(t(o,"editor.lang_auto"),this._config?.language)}}},{name:"icon_size",selector:{number:{min:1,max:6,step:.1,mode:"box"}}},{name:"show_temperature",selector:{boolean:{}}},{name:"live_states",selector:{boolean:{}}},{name:"show_signal",selector:{boolean:{}}},{name:"kiosk",selector:{boolean:{}}},{name:"cycle",selector:{number:{min:0,max:3600,step:5,mode:"box"}}}]}render(){if(!this.hass||!this._config)return a;const e=i(this,l,o(this.hass,this._config.language));if("cold"===e)return n();if("warm"===e)return r;this._loadSpaces();const s=this._lang,h={title:t(s,"editor.title"),floor:t(s,"editor.floor"),default_floor:t(s,"editor.default_floor"),language:t(s,"editor.language"),icon_size:t(s,"editor.icon_size"),show_temperature:t(s,"editor.show_temperature"),live_states:t(s,"editor.live_states"),show_signal:t(s,"editor.show_signal"),kiosk:t(s,"editor.kiosk"),cycle:t(s,"editor.cycle")},f=this._schema,_=function(e,o,t){if(!t||null===o)return null;const s="string"==typeof e?.default_floor?e.default_floor:"";return!s||o.some(e=>e.value===s)?null:s}(this._config,this._spaces,this._spacesAuthoritative),d=e=>c`<ha-form
.hass=${this.hass}
.data=${this._formData}
.schema=${e}
.computeLabel=${e=>f[e.name]||e.name}
.computeLabel=${e=>h[e.name]||e.name}
@value-changed=${this._valueChanged}
></ha-form>`;return c`
${d(h.slice(0,3))}
${d(f.slice(0,3))}
${_?c`<div class="default-floor-error" role="alert"
style="color:var(--error-color,#db4437);margin:-4px 0 12px;overflow-wrap:anywhere">
${t(s,"editor.default_floor_missing",{id:_})}
</div>`:a}
${d(h.slice(3))}
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}f.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",f);
${d(f.slice(3))}
`}_valueChanged(e){const o={...this._config,...e.detail.value};""===o.floor?delete o.floor:o.floor===this._floorToken&&(o.floor=this._config?.floor);const t=new Event("config-changed",{bubbles:!0,composed:!0});t.detail={config:o},this.dispatchEvent(t)}}h.properties={hass:{attribute:!1},_config:{state:!0},_spaces:{state:!0}},customElements.get("houseplan-card-editor")||customElements.define("houseplan-card-editor",h);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="6cd0b6b16736f318772ed601e55de1524fc8ff7a900bfdf16ec3af62fc01e5c4";try{await import("./houseplan-assets/houseplan-card-D6f_gZ66.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
globalThis.__HOUSEPLAN_BUILD_FINGERPRINT__="55ef615ceb15a74bb98b9de6a0927016c5941a9cb158a447c2bf208eb74aa13c";try{await import("./houseplan-assets/houseplan-card-DmogMO2s.js")}catch(e){if(!customElements.get("houseplan-card")){const l=String(navigator.language||"en").toLowerCase();const m=l.startsWith("ru")?"House Plan обновился — перезагрузите страницу (Ctrl+F5).":l.startsWith("de")?"House Plan wurde aktualisiert — bitte laden Sie die Seite neu (Strg+F5).":l.startsWith("fr")?"House Plan a été mis à jour — veuillez recharger la page (Ctrl+F5).":"House Plan was updated — please reload the page (Ctrl+F5).";customElements.define("houseplan-card",class extends HTMLElement{setConfig(){}getCardSize(){return 1}connectedCallback(){this.style.cssText="display:block;box-sizing:border-box;padding:16px;border:1px solid var(--divider-color,#e0e0e0);border-radius:var(--ha-card-border-radius,12px);background:var(--card-background-color,#fff);color:var(--primary-text-color,#212121);font:14px/1.4 var(--paper-font-body1_-_font-family,sans-serif)";this.textContent=m}})}console.error("[houseplan] stale entry: the main chunk is unavailable",e)}
+5 -1
View File
@@ -80,7 +80,11 @@
[mutation: `scripts/mutation-gate.mjs`].
- [ ] Продакшен-бандл показывает робота на этаже активной карты, а на этаже дока
не показывает; предупреждение у дока появляется на движущемся роботе с
несопоставленной картой [auto: `demo/smoke_vacuum_multifloor.mjs`].
несопоставленной картой; донастройка предложения с высоким residual
открывается на этаже маршрута, а не дока
[auto: `demo/smoke_vacuum_multifloor.mjs`].
- [ ] Отдельная camera на карту: источник без читаемого id карты маршрута не
создаёт и объясняет причину [ручная проверка блока «Карты и этажи»].
## Vacuum trail smoothing (#209)
+11 -11
View File
@@ -3,7 +3,7 @@
"fixture": "synthetic-only",
"chromium": "151.0.7922.34",
"oxipng": "oxipng 10.2.0",
"sourceFingerprint": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceFingerprint": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"captureScriptSha256": "cadb8e1bcab9f1dcdd7d75b3b90ddcbaaeb2b8c2a098f575a21f39ff70f5c59c",
"command": "npm run build && node demo/docs/capture.mjs",
"scenarios": {
@@ -15,7 +15,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "80a70361dc18dd0461568df332062e6482c633af5d280954f8b675701418a76d"
},
"view-touch": {
@@ -26,7 +26,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "4106cc28847047505f46921ff95765d8abdf5b382d9d17d4c5e4ad129dd8f6be"
},
"space-create": {
@@ -37,7 +37,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "617b51b3648498787b5039980c9f3eceb75ba56ed63a1a20e616bc05bc304362"
},
"room-contour-close": {
@@ -48,7 +48,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "1dab6cc3b9d1bf7d8c40f0e5137f8c688683c9b7eabc5167da99d41ecfdd5b79"
},
"plan-context-tray": {
@@ -59,7 +59,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "94ef50762753c0ac6ddc84d2521c4232a3f9ecd89843810d2df61c517592bed7"
},
"device-editor": {
@@ -70,7 +70,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "7a601769de38aa19c2e280f6ff4cf3695b854b1d1c6d1f8de4e6b5e8f7eb1559"
},
"device-display-preview": {
@@ -81,7 +81,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "0939875f8631694f4de0ef4fd01032010ede8c7d49fb7c0a857612d4b3afff93"
},
"background-editor": {
@@ -92,7 +92,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "054170fd9ef45762b602b4d5c9c3b9ea9724858be61af137970c246f485c13bb"
},
"room-card": {
@@ -103,7 +103,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "2ae4a58853d98e10d12456b2078ec2f6a0b597722c8310d7b016abd2bc42561e"
},
"device-info": {
@@ -114,7 +114,7 @@
},
"theme": "dark",
"language": "en",
"sourceSha256": "d3f001c7eaa07e86550b6b3f22959181943cfe215356d6dba9f23e83f2d1c028",
"sourceSha256": "2b2a8b637c7a8d716ae2ba74e01723c7e8e3884e426e1f6c3e7402a0afc9b05c",
"imageSha256": "cb37f7eefd936f98ef44969b21dfe8e40ee27d1f558abe8d53c0223f6488b8a6"
}
}
+12
View File
@@ -405,6 +405,18 @@ const MUTANT_DEFINITIONS = [
replace: ' return { space: dockSpace, routeId: route?.id || \'\' };',
}],
},
{
id: 'vacuum-manual-fit-after-proposal-uses-the-dock',
guard: 'npm run bundle:sync && node demo/smoke_vacuum_multifloor.mjs',
because: 'the high-residual proposal is refined against the geometry the matrix was solved '
+ 'against — opening it on the dock floor fits the robot to the wrong plan (#162, AC8, '
+ 'the stateful half the pure calibrationTarget mutant cannot reach)',
patches: [{
file: 'src/houseplan-editor-runtime.ts',
find: ' const space = proposal.space || dev.space;',
replace: ' const space = dev.space;',
}],
},
{
id: 'area-snapshot-cleanup-ignores-authority',
guard: 'npx tsc -p tsconfig.test.json && node scripts/fix-test-build.mjs '
+39
View File
@@ -9,6 +9,7 @@
import { TemplateResult, html, nothing } from 'lit';
import type { HpConfirmRequest } from '../danger-confirm';
import type { DevItem } from '../types';
import type { VacSourceCandidate, VacSourceResolution } from '../vacuum';
import { langOf, type I18nKey } from '../i18n';
import { supportT, type SupportI18nKey } from '../i18n/support';
import { VacuumMapRoute, effectiveRoutes, observedMapIds, resolveRoute } from '../vacuum-routes';
@@ -49,6 +50,7 @@ const spaceName = (host: VacuumMapsCardHost, spaceId: string): string => {
*/
export function renderVacuumMapsSection(
runtime: VacuumMapsHost, dev: DevItem, setVac: (patch: Record<string, unknown>) => void,
sources: VacSourceResolution,
): TemplateResult | typeof nothing {
const host = runtime.host;
const lang = langOf(host.hass, host._config?.language);
@@ -96,6 +98,27 @@ export function renderVacuumMapsSection(
));
};
/**
* Second supported integration shape: one camera per map (spec 9.3).
*
* The map id is read from the picked source with the same fallback the rest
* of the card uses. A source that names no map cannot be told apart from
* another later, so no route is created and the reason is shown instead of
* a route that could never resolve.
*/
const addSource = (candidate: VacSourceCandidate) => {
const mapId = host._vacObservedMapId(dev, candidate.entityId);
if (mapId === undefined) return;
writeRoutes((current) => addRoute(
current,
{ source: candidate.entityId, map_id: mapId, space: current.length ? '' : dev.space },
newRouteId(takenIds()),
));
};
const spare = sources.candidates.filter((candidate) => candidate.entityId !== rootSource
&& !routes.some((route) => route.source === candidate.entityId));
const retarget = async (route: VacuumMapRoute, space: string) => {
if (!space || space === route.space) return;
const accepted = await host._confirmDanger({
@@ -186,6 +209,22 @@ export function renderVacuumMapsSection(
<button type="button" class="btn" ?disabled=${!canAddCurrent}
@click=${addCurrent}>${t('vac.route_add_current')}</button>
</div>
${spare.length ? html`<details class="vacroute-sources">
<summary class="btn ghostbtn">${t('vac.route_add_source')}</summary>
<div class="rhint">${t('vac.route_add_source_hint')}</div>
<div class="vacsource-list">
${spare.map((candidate) => {
const mapId = host._vacObservedMapId(dev, candidate.entityId);
return html`<button type="button" class="vacsource" ?disabled=${mapId === undefined}
@click=${() => addSource(candidate)}>
<span><b>${candidate.name}</b><small>${candidate.entityId}</small></span>
<span class="vacsource-meta">${mapId === undefined
? t('vac.route_source_no_map')
: (mapId || t('vac.route_map_default'))}</span>
</button>`;
})}
</div>
</details>` : nothing}
${rows.some((route) => !spaceIds.has(route.space)) ? html`
<div class="warn">${t('vac.route_missing_space_hint')}</div>` : nothing}
${routes.some((route) => route.map_id === 'default') ? html`
+1 -1
View File
@@ -2512,7 +2512,7 @@ export class HouseplanCard extends LitElement {
private _vacAllCameraCache: { devId: string; candidates: VacSourceCandidate[] } | null = null;
/** Proposed high-residual auto-calibration. Config remains untouched until Apply. */
private _vacCalConfirm: {
markerId: string; source: string; mapId: string; routeId?: string; matrix: Affine;
markerId: string; source: string; mapId: string; routeId?: string; space?: string; matrix: Affine;
rooms: number; error: string;
} | null = null;
private _kioskDots = false;
+9 -11
View File
@@ -1147,7 +1147,7 @@ export interface HouseplanEditorHostPort {
_undoPoint: () => void;
_vacAllCameraCache: { devId: string; candidates: VacSourceCandidate[]; } | null;
_vacAllCamerasFor: string | null;
_vacCalConfirm: { markerId: string; source: string; mapId: string; routeId?: string; matrix: Affine; rooms: number; error: string; } | null;
_vacCalConfirm: { markerId: string; source: string; mapId: string; routeId?: string; space?: string; matrix: Affine; rooms: number; error: string; } | null;
_vacEnsureMarker: (d: DevItem) => Marker | null;
_vacEntity: (d: DevItem) => string | null;
_vacMapId: (d: DevItem, tele: { mapId: string }, planHass?: any) => string;
@@ -10970,7 +10970,7 @@ public _renderVacSection(dlg: any): TemplateResult | typeof nothing {
${(['never', 'cleaning', 'always'] as const).map((mv) => html`
<option value=${mv} ?selected=${vacTrailMode(v) === mv}>${this.host._t(('vac.trail_' + mv) as any)}</option>`)}
</select>
${renderVacuumMapsSection(this, dev, setVac)}
${renderVacuumMapsSection(this, dev, setVac, resolution)}
` : nothing}
</div>`;
}
@@ -10981,9 +10981,7 @@ public _vacMapId(d: DevItem, tele: { mapId: string }, planHass = this.host._plan
return this.host._vacMapId(d, tele, planHass);
}
public _vacSaveMatrix(
markerId: string, source: string, mapId: string, matrix: Affine, routeId = '',
): boolean {
public _vacSaveMatrix(markerId: string, source: string, mapId: string, matrix: Affine, routeId = ''): boolean {
// HP-1540-01: a first-use vacuum has no marker yet — materialise it
const dev = this.host._devices.find((x) => x.id === markerId);
const m = dev ? this.host._vacEnsureMarker(dev)
@@ -11034,7 +11032,7 @@ public _vacAutoCalibrate(d: DevItem): void {
const residualCm = vacCalibrationResidualCm(res.residual, this.host._gridPitch, cellCm);
if (residualCm > VAC_CALIBRATION_WARN_CM) {
this.host._vacCalConfirm = {
markerId: d.id, source: src, mapId, routeId: target.routeId, matrix: res.matrix,
markerId: d.id, source: src, mapId, routeId: target.routeId, space: target.space, matrix: res.matrix,
rooms: res.matched.length,
error: formatLength(residualCm, this.host.hass?.config?.unit_system?.length === 'mi'),
};
@@ -11053,11 +11051,11 @@ public _vacApplyCalibrationProposal(manual: boolean): void {
const fit = fitFromMatrix(proposal.matrix);
if (!dev || !fit) return;
this.host._markerDialog = null;
if (dev.space !== this.host._space && !this.host._commitSpace(dev.space)) return;
this.host._vacFit = {
markerId: proposal.markerId, source: proposal.source, routeId: proposal.routeId,
mapId: proposal.mapId, p: fit, drag: null,
};
// #162: матрица решена против пространства МАРШРУТА, а не дока.
const space = proposal.space || dev.space;
if (space !== this.host._space && !this.host._commitSpace(space)) return;
this.host._vacFit = { markerId: proposal.markerId, source: proposal.source,
routeId: proposal.routeId, mapId: proposal.mapId, p: fit, drag: null };
return;
}
if (this._vacSaveMatrix(
+4 -1
View File
@@ -72,5 +72,8 @@
"vac.route_space_confirm": "Verschieben",
"vac.route_missing_space_hint": "Eine Karte verweist auf einen gelöschten Raum: neuen wählen oder Karte entfernen. Bis dahin wird der Roboter für diese Karte nicht gezeichnet.",
"vac.route_default_hint": "Die Quelle meldet keine stabile Karten-ID. Mehrere Etagen lassen sich ohne andere Quelle oder die vom Roboter gewählte Karte nicht unterscheiden.",
"vac.route_target_hint": "Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“."
"vac.route_target_hint": "Die Station bleibt unabhängig von der aktuellen Karte im Raum „{space}“.",
"vac.route_add_source": "Kartenquelle hinzufügen",
"vac.route_add_source_hint": "Für Integrationen, die jeder Karte eine eigene Kamera geben. Der Abschnitt „Alle Kameras“ oben erweitert diese Liste.",
"vac.route_source_no_map": "keine Karte gemeldet"
}
+4 -1
View File
@@ -72,5 +72,8 @@
"vac.route_space_confirm": "Move",
"vac.route_missing_space_hint": "One of the maps points at a deleted space: pick a new one or remove the map. Until then the robot is not drawn for that map.",
"vac.route_default_hint": "The source reports no stable map id. Several floors cannot be told apart without another source or the robot's own selected map.",
"vac.route_target_hint": "The dock stays in the “{space}” space regardless of the current map."
"vac.route_target_hint": "The dock stays in the “{space}” space regardless of the current map.",
"vac.route_add_source": "Add a map source",
"vac.route_add_source_hint": "For integrations that give each map its own camera. The “All cameras” section above widens this list.",
"vac.route_source_no_map": "no map reported"
}
+4 -1
View File
@@ -72,5 +72,8 @@
"vac.route_space_confirm": "Déplacer",
"vac.route_missing_space_hint": "Une carte pointe vers un espace supprimé : choisissez-en un autre ou supprimez la carte. D'ici là, le robot n'est pas dessiné pour cette carte.",
"vac.route_default_hint": "La source ne fournit pas d'identifiant de carte stable. Plusieurs étages ne peuvent pas être distingués sans une autre source ou la carte sélectionnée du robot.",
"vac.route_target_hint": "La station reste dans l'espace « {space} » quelle que soit la carte actuelle."
"vac.route_target_hint": "La station reste dans l'espace « {space} » quelle que soit la carte actuelle.",
"vac.route_add_source": "Ajouter une source de carte",
"vac.route_add_source_hint": "Pour les intégrations qui donnent à chaque carte sa propre caméra. La section « Toutes les caméras » ci-dessus élargit cette liste.",
"vac.route_source_no_map": "aucune carte signalée"
}
+4 -1
View File
@@ -72,5 +72,8 @@
"vac.route_space_confirm": "Перенести",
"vac.route_missing_space_hint": "Одна из карт ссылается на удалённое пространство: выберите новое или удалите карту. Пока ссылка не исправлена, робот на этой карте не рисуется.",
"vac.route_default_hint": "Источник не сообщает стабильный идентификатор карты. Несколько этажей нельзя различить без другого источника или собственной карты робота.",
"vac.route_target_hint": "Док остаётся в пространстве «{space}» независимо от текущей карты."
"vac.route_target_hint": "Док остаётся в пространстве «{space}» независимо от текущей карты.",
"vac.route_add_source": "Добавить источник карты",
"vac.route_add_source_hint": "Для интеграций, где у каждой карты своя камера. Список расширяется разделом «Все камеры» выше.",
"vac.route_source_no_map": "карта не читается"
}
+1 -1
View File
@@ -130,7 +130,7 @@ test('i18n: lazy editor dictionaries carry matching keys and placeholders', () =
const supportEn = supportDictionaries.get('en');
const keys = Object.keys(supportEn).sort();
const placeholders = (value) => (String(value).match(/\{\w+\}/gu) || []).sort();
assert.equal(keys.length, 74);
assert.equal(keys.length, 77);
assert.equal(Object.keys(en).filter((key) => key.startsWith('support.')).join(','), 'support.title');
for (const { code } of LANGUAGE_REGISTRY) {
const dictionary = supportDictionaries.get(code);