나의 찾기 화면을 자동 생성하도록 정리

This commit is contained in:
seo
2026-06-29 05:36:52 +09:00
parent ddbd193276
commit ba6fdbdf54
2 changed files with 85 additions and 11 deletions
+6 -2
View File
@@ -4,7 +4,9 @@ Home Assistant에 기록된 Galaxy Z Fold7의 위치, 배터리, 활동 상태,
```html ```html
<meta charset="UTF-8"> <meta charset="UTF-8">
<link href="/custom/common/css/findmydevice.css" rel="stylesheet" /> <link href="/custom/findmydevice/css/style.css" rel="stylesheet" />
<div id="findmydevice"></div>
<script src="https://oapi.map.naver.com/openapi/v3/maps.js?ncpKeyId=g3btu2qfeb"></script>
<script src="/custom/findmydevice/js/main.js"></script> <script src="/custom/findmydevice/js/main.js"></script>
``` ```
@@ -27,7 +29,7 @@ Home Assistant에 기록된 Galaxy Z Fold7의 위치, 배터리, 활동 상태,
## 구조 ## 구조
- `php/api.php`: Home Assistant 상태/히스토리 조회 API - `php/api.php`: Home Assistant 상태/히스토리 조회 API
- `js/main.js`: 지도 렌더링, 상태 갱신, 히스토리 표시 - `js/main.js`: 화면 뼈대 자동 생성, 지도 렌더링, 상태 갱신, 히스토리 표시
- `css/style.css`: 기존 삽입 코드 호환용 공용 CSS import - `css/style.css`: 기존 삽입 코드 호환용 공용 CSS import
- `img/`: 지도 마커 및 언어 아이콘 - `img/`: 지도 마커 및 언어 아이콘
@@ -39,6 +41,8 @@ Home Assistant에 기록된 Galaxy Z Fold7의 위치, 배터리, 활동 상태,
표시할 모바일 앱 센서 목록은 `/custom/common/config.php``findmydevice_sensor_sections`에서 섹션 단위로 관리합니다. 화면 CSS 원본은 `/custom/common/css/findmydevice.css`를 사용합니다. 기존 운영 HTML이 `/custom/findmydevice/css/style.css`를 참조해도 호환 파일이 공용 CSS를 import합니다. 표시할 모바일 앱 센서 목록은 `/custom/common/config.php``findmydevice_sensor_sections`에서 섹션 단위로 관리합니다. 화면 CSS 원본은 `/custom/common/css/findmydevice.css`를 사용합니다. 기존 운영 HTML이 `/custom/findmydevice/css/style.css`를 참조해도 호환 파일이 공용 CSS를 import합니다.
페이지 본문에는 `<div id="findmydevice"></div>`만 두면 됩니다. `main.js``#mySettingContainer`가 없을 때 지도, 헤더, 설정/기록/위치/업데이트/배터리/활동 섹션과 iOS PWA 안내 영역을 자동으로 생성합니다. 기존처럼 전체 HTML을 직접 넣어둔 페이지에서는 이미 존재하는 `#mySettingContainer`를 그대로 사용합니다.
위치 갱신 명령은 `/custom/common/config.php``findmydevice_location_refresh` 설정을 사용합니다. `seoul`, `main` Home Assistant 프로필의 `notify.mobile_app_seocaegeonyi_z_fold7` 서비스로 Companion App notification command를 보냅니다. 자동 업데이트가 켜지면 Android high accuracy mode를 5초 간격으로 설정하고 `force_on`을 보낸 뒤 `request_location_update``command_update_sensors`를 함께 호출합니다. 자동 업데이트 중에는 10초마다 위치 요청과 센서 업데이트 요청을 반복하고, 자동 업데이트를 끄거나 페이지를 벗어나면 `force_off`를 보냅니다. 위치 갱신 명령은 `/custom/common/config.php``findmydevice_location_refresh` 설정을 사용합니다. `seoul`, `main` Home Assistant 프로필의 `notify.mobile_app_seocaegeonyi_z_fold7` 서비스로 Companion App notification command를 보냅니다. 자동 업데이트가 켜지면 Android high accuracy mode를 5초 간격으로 설정하고 `force_on`을 보낸 뒤 `request_location_update``command_update_sensors`를 함께 호출합니다. 자동 업데이트 중에는 10초마다 위치 요청과 센서 업데이트 요청을 반복하고, 자동 업데이트를 끄거나 페이지를 벗어나면 `force_off`를 보냅니다.
집 판정 중심은 `/custom/common/config.php``findmydevice_home` 설정을 사용합니다. 현재 집 좌표는 `37.558181, 127.204440`, 반경은 `50m`입니다. API 응답의 `home` 값을 브라우저가 사용하므로 설정 변경 시 집 원, 체류/외출 판정, GPS 튐 흡수 기준이 같은 좌표로 적용됩니다. 집 판정 중심은 `/custom/common/config.php``findmydevice_home` 설정을 사용합니다. 현재 집 좌표는 `37.558181, 127.204440`, 반경은 `50m`입니다. API 응답의 `home` 값을 브라우저가 사용하므로 설정 변경 시 집 원, 체류/외출 판정, GPS 튐 흡수 기준이 같은 좌표로 적용됩니다.
+79 -9
View File
@@ -445,8 +445,8 @@ const deviceLang = (navigator.language || navigator.userLanguage || "en").starts
initialInfoOpened: false, initialInfoOpened: false,
historyBoundsFitted: false, historyBoundsFitted: false,
}; };
let langCode = localStorage.getItem("currentLang") || deviceLang, let langCode = localStorage.getItem("currentLang") || deviceLang,
lastAutoSwitchChecked, lastAutoSwitchChecked,
lastUpdateSwitchChecked, lastUpdateSwitchChecked,
lastHash, lastHash,
lastLat, lastLat,
@@ -455,13 +455,83 @@ let langCode = localStorage.getItem("currentLang") || deviceLang,
map, map,
marker, marker,
circle, circle,
radiusInterval, radiusInterval,
_overrideRange, _overrideRange,
wakeLock = null; wakeLock = null;
applyLanguage(langCode); function ensureFindMyDeviceShell() {
if (document.getElementById('mySettingContainer')) return;
document.querySelectorAll('.locateRow').forEach(row => {
let mount = document.getElementById('findmydevice');
if (!mount) {
mount = document.createElement('div');
mount.id = 'findmydevice';
document.body.prepend(mount);
}
mount.innerHTML = `
<div id="mySettingContainer" style="user-select: none;">
<div id="settingsHeader">
<a id="blogBackLink"></a>
<div id="langToggle"><img alt="Language Toggle" src="/custom/findmydevice/img/language-empty.svg" /></div>
</div>
<div id="toggleContent" style="padding-bottom:80px;">
<div id="mapContainer"><div id="map" style="width:100%; height:100%;">&nbsp;</div></div>
<div class="settingTitle"><span id="titleSettings"></span></div>
<div class="settingSection">
<div class="settingRow" id="wakeLockRow"><span id="labelKeepScreenOn"></span><label class="iosSwitch"><input id="wakeLockSwitch" type="checkbox" /></label></div>
</div>
<div class="settingTitle"><span id="titleHistory"></span></div>
<div class="settingSection">
<div class="settingRow"><span id="labelStartTime"></span><input class="dth" id="rangeStart" type="datetime-local" /></div>
<div class="settingRow"><span id="labelEndTime"></span><input class="dth" id="rangeEnd" type="datetime-local" /></div>
<div class="settingRow locateRow" id="HistoryResetBtn"><span id="labelHistoryReset"></span></div>
</div>
<div class="settingTitle"><span id="titleLocation"></span></div>
<div class="settingSection">
<div class="settingRow"><span id="labelCurrentPosition"></span><span id="currentPosition"></span></div>
<div class="settingRow"><span id="labelGpsAccuracy"></span><span id="accuracyValue"></span></div>
<div class="settingRow" id="autoLocateBtn"><span id="labelCurrentAutoPosition"></span><label class="iosSwitch"><input id="autoPositionSwitch" type="checkbox" /></label></div>
<div class="settingRow locateRow" id="locateBtn"><span id="labelMoveToCurrent"></span></div>
</div>
<div class="settingTitle"><span id="titleUpdate"></span></div>
<div class="settingSection">
<div class="settingRow"><span id="labelLastUpdate"></span><span id="lastUpdateTime"></span></div>
<div class="settingRow"><span id="labelUpdateTrigger"></span><span id="updateTrigger"></span></div>
<div class="settingRow" id="autoUpdateBtn"><span id="labelAutoUpdate"></span><label class="iosSwitch"><input id="autoUpdateSwitch" type="checkbox" /></label></div>
<div class="settingRow locateRow" id="updateBtn"><span id="labelForceUpdate"></span></div>
</div>
<div class="settingTitle"><span id="titleBattery"></span></div>
<div class="settingSection">
<div class="settingRow"><span id="labelBatteryState"></span><span id="batteryStatus"></span></div>
<div class="settingRow"><span id="labelBatteryLevel"></span><span id="Battery"></span></div>
<div class="settingRow"><span id="labelWatchBatteryState"></span><span id="WbatteryStatus"></span></div>
<div class="settingRow"><span id="labelWatchBatteryLevel"></span><span id="WBattery"></span></div>
</div>
<div class="settingTitle"><span id="titleActivity"></span></div>
<div class="settingSection">
<div class="settingRow"><span id="labelCurrentActivity"></span><span id="nowActivity"></span></div>
<div class="settingRow"><span id="labelDistance"></span><span id="todayDistance"></span></div>
<div class="settingRow"><span id="labelSteps"></span><span id="todaySteps"></span></div>
<div class="settingRow"><span id="labelAscended"></span><span id="todayAscended"></span></div>
<div class="settingRow"><span id="labelDescended"></span><span id="todayDescended"></span></div>
</div>
</div>
</div>
<div id="ios-pwa-tooltip">
<span class="close-btn" id="close-tooltip">✕</span>
<span style="width:18px;height:18px;display:inline-block;vertical-align:middle;margin-right:5px;transform:translateZ(0);will-change:transform;">
<svg height="18" viewBox="0 0 50 50" width="18" xmlns="http://www.w3.org/2000/svg"><path d="M30.3 13.7L25 8.4l-5.3 5.3-1.4-1.4L25 5.6l6.7 6.7z"></path><path d="M24 7h2v21h-2z"></path><path d="M35 40H15c-1.7 0-3-1.3-3-3V19c0-1.7 1.3-3 3-3h7v2h-7c-.6 0-1 .4-1 1v18c0 .6.4 1 1 1h20c.6 0 1-.4 1-1V19c0-.6-.4-1-1-1h-7v-2h7c1.7 0 3 1.3 3 3v18c0 1.7-1.3 3-3 3z"></path></svg>
</span>
<span id="labelPwa"></span>
</div>
`;
}
ensureFindMyDeviceShell();
applyLanguage(langCode);
document.querySelectorAll('.locateRow').forEach(row => {
row.addEventListener('pointerdown', () => { row.addEventListener('pointerdown', () => {
row.style.background = '#d3d3d3'; row.style.background = '#d3d3d3';
}); });