Skip to content

Commit 0744edb

Browse files
committed
chore: bump version to v0.16.14
1 parent 3a8b372 commit 0744edb

10 files changed

Lines changed: 64 additions & 15 deletions

File tree

VERSION.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
padspanHA package version: 0.16.13
1+
padspanHA package version: 0.16.14

custom_components/padspan_ha/build_info.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
# See LICENSE file or https://www.gnu.org/licenses/gpl-3.0.html
55
"""Generated at build time. Used to prove what version is actually installed."""
66

7-
BUILD_VERSION = "0.16.13"
8-
BUILD_ID = "20260322T010510Z"
9-
CHANNEL = "beta"
7+
BUILD_VERSION = "0.16.14"
8+
BUILD_ID = "20260322T011203Z"
9+
CHANNEL = "stable"
1010

1111
# Backwards/for convenience
1212
VERSION = BUILD_VERSION

custom_components/padspan_ha/const.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
DOMAIN = "padspan_ha"
2121
NAME = "PadSpan HA"
22-
VERSION = "0.16.13"
22+
VERSION = "0.16.14"
2323

2424
# ── Config-flow option keys ───────────────────────────────────────────────────
2525
CONF_ENABLE_CLOUD = "enable_cloud"

custom_components/padspan_ha/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@
2020
"issue_tracker": "https://github.com/gbroeckling/padspanHA/issues",
2121
"requirements": [],
2222
"single_config_entry": true,
23-
"version": "0.16.13"
23+
"version": "0.16.14"
2424
}

custom_components/padspan_ha/www/padspan-ha/lights_panel.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
BUILD_ID / APP_VERSION updated automatically by scripts/release.py.
1313
*/
1414

15-
const APP_VERSION = "0.16.13";
16-
const BUILD_ID = "20260322T010510Z";
15+
const APP_VERSION = "0.16.14";
16+
const BUILD_ID = "20260322T011203Z";
1717

1818
// ── DOM helpers ──────────────────────────────────────────────────────────────
1919
function el(tag, attrs={}, children=[]){

custom_components/padspan_ha/www/padspan-ha/panel.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ If UI changes don't show:
2222
// BUILD_ID (YYYYMMDDTHHMMSSZ) is appended to all JS import URLs as a cache-buster
2323
// so browsers always load the latest code after a release.
2424
// CHANNEL controls the sidebar badge and maps to GitHub release types (beta=pre-release).
25-
const APP_VERSION = "0.16.13";
26-
const BUILD_ID = "20260322T010510Z";
27-
const CHANNEL = "beta";
25+
const APP_VERSION = "0.16.14";
26+
const BUILD_ID = "20260322T011203Z";
27+
const CHANNEL = "stable";
2828

2929
// ── Dynamic view imports ─────────────────────────────────────────────────────
3030
// Two-phase loading for fast first paint:

custom_components/padspan_ha/www/padspan-ha/views/health.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,39 @@ function _renderFabric(ctx, container, data) {
139139
container.innerHTML = "";
140140
const { summary, checks, scanners, scanner_positions_m, room_geometry_m, adjacency } = data;
141141

142+
// ── Migration prompt for old system users ───────────────────────────────
143+
const _maps = data.maps || [];
144+
const _hasMapsData = _maps.some(m => m.has_receivers > 0 || m.has_room_bounds > 0);
145+
const _noFabric = !scanner_positions_m?.length && !room_geometry_m?.length;
146+
if (_hasMapsData && _noFabric) {
147+
const _mb = el("div",{class:"card",style:"border:2px solid #f59e0b;background:rgba(245,158,11,.08);margin-bottom:12px;padding:16px"});
148+
_mb.appendChild(el("div",{style:"font-weight:800;font-size:14px;color:#fbbf24;margin-bottom:8px"},"\u26a0 Migration Required"));
149+
_mb.appendChild(el("div",{style:"font-size:12px;color:#e2e8f0;margin-bottom:12px"},
150+
"Your maps have spatial data that needs to be migrated to the positioning fabric. This is a one-time process."));
151+
const _mr = el("div",{style:"display:flex;align-items:center;gap:8px"});
152+
const _mi = document.createElement("input");
153+
_mi.type="number";_mi.value="20";_mi.min="5";_mi.max="200";_mi.step="1";
154+
_mi.style.cssText="width:80px;padding:4px 8px;border:1px solid #334155;border-radius:4px;background:#1e293b;color:#e2e8f0;font-size:12px";
155+
_mr.appendChild(el("span",{style:"font-size:11px;color:#94a3b8"},"Floor width:"));
156+
_mr.appendChild(_mi);
157+
_mr.appendChild(el("span",{style:"font-size:11px;color:#94a3b8"},"m"));
158+
const _mbtn = el("button",{class:"btn save-pulse",style:"width:auto;padding:6px 16px;font-size:12px;background:#92400e;border-color:#f59e0b;color:#fbbf24;font-weight:700"},"\ud83d\udcbe Migrate to Fabric");
159+
_mbtn.addEventListener("click", async () => {
160+
const w = parseFloat(_mi.value);
161+
if (!w || w < 1) { ctx.actions.toast("Enter a valid floor width"); return; }
162+
_mbtn.disabled = true; _mbtn.textContent = "Migrating\u2026"; _mbtn.classList.remove("save-pulse");
163+
try {
164+
const res = await ctx.actions.callWS({type:"padspan_ha/fabric_migrate_from_maps", default_floor_width_m: w});
165+
try { await ctx.actions.callWS({type:"padspan_ha/calibration_retrain_rf"}); } catch(e){}
166+
ctx.actions.toast(`Migrated: ${res.transforms_computed} transforms, ${res.scanners_migrated} scanners, ${res.rooms_migrated} rooms`);
167+
_fabricCache = null; _fabricFetchTs = 0; _fetchAndRenderFabric(ctx, container);
168+
} catch(e) { ctx.actions.toast("Failed: "+(e.message||e)); _mbtn.disabled=false; _mbtn.textContent="Migrate to Fabric"; _mbtn.classList.add("save-pulse"); }
169+
});
170+
_mr.appendChild(_mbtn);
171+
_mb.appendChild(_mr);
172+
container.appendChild(_mb);
173+
}
174+
142175
// ── Summary banner ─────────────────────────────────────────────────────
143176
const color = summary.healthy ? "#52b788" : summary.failed > 2 ? "#f87171" : "#f59e0b";
144177
const bg = summary.healthy ? "rgba(82,183,136,.08)" : "rgba(248,113,113,.08)";

custom_components/padspan_ha/www/padspan-ha/views/maps.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,12 +340,26 @@ function _library(ctx, maps, activeId, helpBtn, isBasic){
340340
}
341341
}
342342

343-
// Masters first, then by name
344-
const sortedMaps = [...maps].sort((a,b) => (b.stack?.is_master?1:0) - (a.stack?.is_master?1:0));
343+
// Group maps by floor
344+
const _floors = ctx.state.model?.floors || [];
345+
const _floorMap = new Map();
346+
for (const m of maps) { const fid = m.floor_id || "main"; if (!_floorMap.has(fid)) _floorMap.set(fid, []); _floorMap.get(fid).push(m); }
347+
const _floorOrder = _floors.map(f => f.id);
348+
const _sortedFloors = [..._floorMap.keys()].sort((a, b) => { const ia = _floorOrder.indexOf(a), ib = _floorOrder.indexOf(b); return (ia < 0 ? 999 : ia) - (ib < 0 ? 999 : ib); });
349+
345350
const currentMaster = maps.find(m => !!(m.stack?.is_master)) || null;
346351
const list = el("div",{style:"margin-top:10px;display:flex;flex-direction:column;gap:8px"});
347352
const wizardContainer = el("div",{});
348-
for(const m of sortedMaps){
353+
354+
for (const fid of _sortedFloors) {
355+
const floorMaps = _floorMap.get(fid) || [];
356+
floorMaps.sort((a, b) => (b.stack?.is_master ? 1 : 0) - (a.stack?.is_master ? 1 : 0));
357+
const floorObj = _floors.find(f => f.id === fid);
358+
const floorName = floorObj ? (floorObj.name || fid) : fid;
359+
list.appendChild(el("div",{style:"font-weight:700;font-size:13px;color:#52b788;margin-top:8px;margin-bottom:2px;text-transform:uppercase;letter-spacing:.5px"},
360+
`${floorName} (${floorMaps.length})`));
361+
362+
for(const m of floorMaps){
349363
const row = el("div",{class:"maprow" + (m.id===activeId ? " active" : "")});
350364

351365
// Thumbnail with room bounds + recommendation overlay
@@ -435,6 +449,7 @@ function _library(ctx, maps, activeId, helpBtn, isBasic){
435449
row.appendChild(actions);
436450
list.appendChild(row);
437451
}
452+
} // end floor loop
438453
wrap.appendChild(list);
439454
wrap.appendChild(wizardContainer);
440455
return wrap;

custom_components/padspan_ha/www/padspan-ha/views/overview.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1843,7 +1843,8 @@ export function render(ctx){
18431843
[bx,by]=iso(lwx, lwy, tf.z);
18441844
posConf = o.knn_confidence || 0;
18451845
}
1846-
// Priority 2: Client-side fingerprint — only if no server k-NN AND confidence > 40%
1846+
// Priority 2: Client-side fingerprint fallback — server k-NN is authoritative,
1847+
// this only fires when the server didn't provide a position (e.g., no calibration data).
18471848
if(bx == null){
18481849
const readings = _getObjReadings(o);
18491850
const match = _matchFingerprint(readings);

dist/padspan_ha.zip

846 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)