API: добавить online-флаг для ListSessions

This commit is contained in:
AidarKC 2026-06-13 15:49:34 +04:00
parent 0536a018c6
commit 96d292074b
7 changed files with 44 additions and 2 deletions

View File

@ -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-строка;

View File

@ -0,0 +1,16 @@
# online flag в ListSessions
- краткое описание:
- серверный `ListSessions` теперь возвращает флаг `isOnlineOnThisServer` для каждой сессии;
- клиентский UI показывает его и в списке устройств, и на подробной странице сеанса.
- что проверять:
- у текущего web-клиента в списке должен быть статус `Online now`;
- у активной `ESP32`-сессии должен быть статус `Online now`, пока устройство подключено;
- после ручного закрытия одной из сессий её статус должен стать `Offline`.
- ожидаемый результат:
- online-флаг соответствует живому наличию `WebSocket`-контекста на этом сервере, а не только данным БД.
- статус:
- in_progress

View File

@ -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();

View File

@ -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;
}

View File

@ -1,2 +1,2 @@
client.version=1.2.182
server.version=1.2.171
client.version=1.2.183
server.version=1.2.172

View File

@ -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 }) {
<div><p class="meta-muted">sessionId</p><p>${session.sessionId}</p></div>
<div><p class="meta-muted">sessionType</p><p>${formatSessionType(session.sessionType)}</p></div>
<div><p class="meta-muted">clientPlatform</p><p>${session.clientPlatform || '-'}</p></div>
<div><p class="meta-muted">onlineOnThisServer</p><p>${formatOnlineStatus(!!session.isOnlineOnThisServer)}</p></div>
<div><p class="meta-muted">clientInfoFromClient</p><p>${session.clientInfoFromClient || '-'}</p></div>
<div><p class="meta-muted">clientInfoFromRequest</p><p>${session.clientInfoFromRequest || '-'}</p></div>
<div><p class="meta-muted">geo</p><p>${session.geo || 'unknown'}</p></div>

View File

@ -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 = `
<div class="row" style="align-items:flex-start;">
<div class="stack" style="gap:4px; text-align:left;">
<strong>${session.clientInfoFromClient || 'unknown client'}</strong>
<span class="meta-muted"><strong>Type:</strong> ${sessionTypeText}${sessionPlatformText}</span>
<span class="meta-muted"><strong>Status:</strong> ${onlineStatusText}</span>
<span class="meta-muted">${session.geo || 'unknown'}</span>
</div>
<span class="meta-muted">${formatSessionTime(session.lastAuthenticatedAtMs || Date.now())}</span>