From 96d292074b147e1ebc7646194d3a60d7e18c1474df71d633af6e01f3396e3303 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Sat, 13 Jun 2026 15:49:34 +0400 Subject: [PATCH] =?UTF-8?q?API:=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20online-=D1=84=D0=BB=D0=B0=D0=B3=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20ListSessions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dev_Docs/API/03_Session_Management_API.md | 2 ++ ...026-06-13_1540_online_flag_в_list_sessions.md | 16 ++++++++++++++++ .../handlers/auth/Net_ListSessions_Handler.java | 2 ++ .../auth/entyties/Net_ListSessions_Response.java | 11 +++++++++++ VERSION.properties | 4 ++-- shine-UI/js/pages/device-session-view.js | 5 +++++ shine-UI/js/pages/device-view.js | 6 ++++++ 7 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 Dev_Docs/Pending_Features/2026-06-13_1540_online_flag_в_list_sessions.md diff --git a/Dev_Docs/API/03_Session_Management_API.md b/Dev_Docs/API/03_Session_Management_API.md index d67e2ae..8a11287 100644 --- a/Dev_Docs/API/03_Session_Management_API.md +++ b/Dev_Docs/API/03_Session_Management_API.md @@ -44,6 +44,7 @@ "sessionId": "sess_7c5e5c4b", "sessionType": 1, "clientPlatform": "Web", + "isOnlineOnThisServer": true, "clientInfoFromClient": "Android 15; Pixel 9", "clientInfoFromRequest": "UA=Java-http-client/17.0.18; remote=127.0.0.1", "geo": "RU/Moscow", @@ -68,6 +69,7 @@ - `50` — кошелёк; - `100` — homeserver; - `clientPlatform` — строка платформы, как её прислал клиент; +- `isOnlineOnThisServer` — `true`, если эта сессия сейчас держит живое WebSocket-подключение именно к данному серверу; - `clientInfoFromClient` — краткая строка клиента; - `clientInfoFromRequest` — строка, собранная сервером из запроса; - `geo` — страна/город или fallback-строка; diff --git a/Dev_Docs/Pending_Features/2026-06-13_1540_online_flag_в_list_sessions.md b/Dev_Docs/Pending_Features/2026-06-13_1540_online_flag_в_list_sessions.md new file mode 100644 index 0000000..bb4bc88 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-06-13_1540_online_flag_в_list_sessions.md @@ -0,0 +1,16 @@ +# online flag в ListSessions + +- краткое описание: + - серверный `ListSessions` теперь возвращает флаг `isOnlineOnThisServer` для каждой сессии; + - клиентский UI показывает его и в списке устройств, и на подробной странице сеанса. + +- что проверять: + - у текущего web-клиента в списке должен быть статус `Online now`; + - у активной `ESP32`-сессии должен быть статус `Online now`, пока устройство подключено; + - после ручного закрытия одной из сессий её статус должен стать `Offline`. + +- ожидаемый результат: + - online-флаг соответствует живому наличию `WebSocket`-контекста на этом сервере, а не только данным БД. + +- статус: + - in_progress diff --git a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/Net_ListSessions_Handler.java b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/Net_ListSessions_Handler.java index 6c47505..e53a24d 100644 --- a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/Net_ListSessions_Handler.java +++ b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/Net_ListSessions_Handler.java @@ -2,6 +2,7 @@ package server.logic.ws_protocol.JSON.handlers.auth; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import server.logic.ws_protocol.JSON.ActiveConnectionsRegistry; import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.entyties.Net_Request; import server.logic.ws_protocol.JSON.entyties.Net_Response; @@ -68,6 +69,7 @@ public class Net_ListSessions_Handler implements JsonMessageHandler { info.setClientInfoFromRequest(s.getClientInfoFromRequest()); info.setSessionType(s.getSessionType()); info.setClientPlatform(s.getClientPlatform()); + info.setOnlineOnThisServer(ActiveConnectionsRegistry.getInstance().getBySessionId(s.getSessionId()) != null); info.setLastAuthenticatedAtMs(s.getLastAuthirificatedAtMs()); String ip = s.getClientIp(); diff --git a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/entyties/Net_ListSessions_Response.java b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/entyties/Net_ListSessions_Response.java index 2bd3571..00ae36b 100644 --- a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/entyties/Net_ListSessions_Response.java +++ b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/auth/entyties/Net_ListSessions_Response.java @@ -58,6 +58,9 @@ public class Net_ListSessions_Response extends Net_Response { /** Свободная строка платформы, как её прислал клиент. */ private String clientPlatform; + /** Подключена ли эта сессия прямо сейчас к данному серверу. */ + private boolean onlineOnThisServer; + /** Строка геолокации вида "Country, City" или "unknown". */ private String geo; @@ -106,6 +109,14 @@ public class Net_ListSessions_Response extends Net_Response { this.clientPlatform = clientPlatform; } + public boolean isOnlineOnThisServer() { + return onlineOnThisServer; + } + + public void setOnlineOnThisServer(boolean onlineOnThisServer) { + this.onlineOnThisServer = onlineOnThisServer; + } + public String getGeo() { return geo; } diff --git a/VERSION.properties b/VERSION.properties index 26cb229..26d0b3d 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.182 -server.version=1.2.171 +client.version=1.2.183 +server.version=1.2.172 diff --git a/shine-UI/js/pages/device-session-view.js b/shine-UI/js/pages/device-session-view.js index c8cb4df..6404560 100644 --- a/shine-UI/js/pages/device-session-view.js +++ b/shine-UI/js/pages/device-session-view.js @@ -27,6 +27,10 @@ function formatSessionTime(ms) { }); } +function formatOnlineStatus(isOnlineOnThisServer) { + return isOnlineOnThisServer ? 'Online now on this server' : 'Offline on this server'; +} + export function render({ navigate, route }) { const screen = document.createElement('section'); screen.className = 'stack'; @@ -55,6 +59,7 @@ export function render({ navigate, route }) {

sessionId

${session.sessionId}

sessionType

${formatSessionType(session.sessionType)}

clientPlatform

${session.clientPlatform || '-'}

+

onlineOnThisServer

${formatOnlineStatus(!!session.isOnlineOnThisServer)}

clientInfoFromClient

${session.clientInfoFromClient || '-'}

clientInfoFromRequest

${session.clientInfoFromRequest || '-'}

geo

${session.geo || 'unknown'}

diff --git a/shine-UI/js/pages/device-view.js b/shine-UI/js/pages/device-view.js index 870a00f..12401f0 100644 --- a/shine-UI/js/pages/device-view.js +++ b/shine-UI/js/pages/device-view.js @@ -28,6 +28,10 @@ function formatSessionTime(ms) { }); } +function formatOnlineStatus(isOnlineOnThisServer) { + return isOnlineOnThisServer ? 'Online now' : 'Offline'; +} + export function render({ navigate }) { const screen = document.createElement('section'); screen.className = 'stack'; @@ -65,11 +69,13 @@ export function render({ navigate }) { item.type = 'button'; const sessionTypeText = formatSessionType(session.sessionType); const sessionPlatformText = session.clientPlatform ? ` · ${session.clientPlatform}` : ''; + const onlineStatusText = formatOnlineStatus(!!session.isOnlineOnThisServer); item.innerHTML = `
${session.clientInfoFromClient || 'unknown client'} Type: ${sessionTypeText}${sessionPlatformText} + Status: ${onlineStatusText} ${session.geo || 'unknown'}
${formatSessionTime(session.lastAuthenticatedAtMs || Date.now())}