From 6626237c8093d2d11cd982ef97874fad9351c3af Mon Sep 17 00:00:00 2001 From: heavyrian2012 Date: Fri, 6 Mar 2026 19:15:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=8F=AF=E7=A9=BF=E6=88=B4?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E5=92=8CTV=E7=AB=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- broker/config/wildfirechat.conf | 6 ++++ .../java/cn/wildfirechat/push/PushServer.java | 11 ++++++-- .../java/io/moquette/BrokerConstants.java | 2 ++ .../moquette/imhandler/GetTokenHandler.java | 2 +- .../moquette/persistence/DatabaseStore.java | 11 ++++++++ .../persistence/MemoryMessagesStore.java | 21 ++++++++++++++ .../persistence/MemorySessionStore.java | 28 +++++++++++++++++++ .../cn/wildfirechat/proto/ProtoConstants.java | 9 +++++- .../src/main/resources/wildfirechat.conf | 6 ++++ 9 files changed, 91 insertions(+), 5 deletions(-) diff --git a/broker/config/wildfirechat.conf b/broker/config/wildfirechat.conf index 3fd51ef1..9f0a6d9c 100755 --- a/broker/config/wildfirechat.conf +++ b/broker/config/wildfirechat.conf @@ -381,6 +381,12 @@ server.multi_pc_endpoint false ## 是否支持PAD多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开PAD端多端登录。 server.multi_pad_endpoint false +## 是否支持可穿戴设备多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开可穿戴设备多端登录。 +server.multi_wearable_endpoint false + +## 是否支持TV设备多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开TV多端登录。 +server.multi_tv_endpoint false + # 多平台连接状态通知(仅当multi_endpoint为false时有效),true时移动端可以收到pc或pad或web端登录的通知。 server.multi_platform_notification true diff --git a/broker/src/main/java/cn/wildfirechat/push/PushServer.java b/broker/src/main/java/cn/wildfirechat/push/PushServer.java index 3c795429..ceb69628 100644 --- a/broker/src/main/java/cn/wildfirechat/push/PushServer.java +++ b/broker/src/main/java/cn/wildfirechat/push/PushServer.java @@ -96,13 +96,18 @@ public class PushServer { session.getPlatform() == ProtoConstants.Platform.Platform_Android || session.getPlatform() == ProtoConstants.Platform.Platform_APad || session.getPlatform() == ProtoConstants.Platform.Platform_Harmony || - session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad + session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad || + session.getPlatform() == ProtoConstants.Platform.Platform_AppleTV || + session.getPlatform() == ProtoConstants.Platform.Platform_AndroidTV || + session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyTV || + session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyWearable || + session.getPlatform() == ProtoConstants.Platform.Platform_AndroidWearable ) { String url = androidPushServerUrl; - if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS || session.getPlatform() == ProtoConstants.Platform.Platform_iPad) { + if (session.getPlatform() == ProtoConstants.Platform.Platform_iOS || session.getPlatform() == ProtoConstants.Platform.Platform_iPad || session.getPlatform() == ProtoConstants.Platform.Platform_AppleTV) { url = iOSPushServerUrl; pushMessage.voipDeviceToken = session.getVoipDeviceToken(); - } else if (session.getPlatform() == ProtoConstants.Platform.Platform_Harmony || session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad) { + } else if (session.getPlatform() == ProtoConstants.Platform.Platform_Harmony || session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPad || session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyWearable || session.getPlatform() == ProtoConstants.Platform.Platform_HarmonyTV) { url = harmonyPushServerUrl; } HttpUtils.httpJsonPost(url, gson.toJson(pushMessage, pushMessage.getClass()), POST_TYPE_Push); diff --git a/broker/src/main/java/io/moquette/BrokerConstants.java b/broker/src/main/java/io/moquette/BrokerConstants.java index 7ea6ac5f..1d7096b0 100755 --- a/broker/src/main/java/io/moquette/BrokerConstants.java +++ b/broker/src/main/java/io/moquette/BrokerConstants.java @@ -148,6 +148,8 @@ public final class BrokerConstants { public static final String SERVER_MULTI_ENDPOINT = "server.multi_endpoint"; public static final String SERVER_MULTI_PC_ENDPOINT = "server.multi_pc_endpoint"; public static final String SERVER_MULTI_PAD_ENDPOINT = "server.multi_pad_endpoint"; + public static final String SERVER_MULTI_WEARABLE_ENDPOINT = "server.multi_wearable_endpoint"; + public static final String SERVER_MULTI_TV_ENDPOINT = "server.multi_tv_endpoint"; public static final String SERVER_MULTI_PLATFROM_NOTIFICATION = "server.multi_platform_notification"; public static final String SERVER_MOBILE_DEFAULT_SILENT_WHEN_PC_ONLINE = "server.mobile_default_silent_when_pc_online"; public static final String SERVER_CLIENT_SUPPORT_KICKOFF_EVENT = "server.client_support_kickoff_event"; diff --git a/broker/src/main/java/io/moquette/imhandler/GetTokenHandler.java b/broker/src/main/java/io/moquette/imhandler/GetTokenHandler.java index 2780a733..6518c8fb 100644 --- a/broker/src/main/java/io/moquette/imhandler/GetTokenHandler.java +++ b/broker/src/main/java/io/moquette/imhandler/GetTokenHandler.java @@ -27,7 +27,7 @@ public class GetTokenHandler extends IMHandler { if(userInfo != null && userInfo.getType() == 1) { return ErrorCode.ERROR_CODE_ROBOT_NO_TOKEN; } - if((session.isPcClient() || session.isPadClient())) { + if(session.isPcClient() || session.isPadClient() || session.isTVClient()) { if(m_messagesStore.isLocked(session.getUsername(), session.getClientID())) { m_messagesStore.updateUserSettings(session.getUsername(), WFCMessage.ModifyUserSettingReq.newBuilder().setScope(UserSettingScope.UserSettingScopeLockPC).setKey(session.getClientID()).setValue("0").build(), null); } diff --git a/broker/src/main/java/io/moquette/persistence/DatabaseStore.java b/broker/src/main/java/io/moquette/persistence/DatabaseStore.java index bee02851..af1dcea1 100644 --- a/broker/src/main/java/io/moquette/persistence/DatabaseStore.java +++ b/broker/src/main/java/io/moquette/persistence/DatabaseStore.java @@ -1870,6 +1870,10 @@ public class DatabaseStore { sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0"; } else if(platform == ProtoConstants.Platform.Platform_iPad || platform == ProtoConstants.Platform.Platform_APad || platform == ProtoConstants.Platform.Platform_HarmonyPad) { sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0"; + } else if(platform == ProtoConstants.Platform.Platform_AndroidWearable || platform == ProtoConstants.Platform.Platform_HarmonyWearable) { + sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0"; + } else if(platform == ProtoConstants.Platform.Platform_AndroidTV || platform == ProtoConstants.Platform.Platform_AppleTV || platform == ProtoConstants.Platform.Platform_HarmonyTV) { + sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and (`_platform` = ? or `_platform` = ? or `_platform` = ?) and `_cid` <> ? and `_deleted` = 0"; } else { sql = "update t_user_session set `_deleted` = ?, `_token` = ?, `_voip_token` = ?, `_dt` = ? where `_uid`=? and `_platform` = ? and `_cid` <> ? and `_deleted` = 0"; } @@ -1897,6 +1901,13 @@ public class DatabaseStore { statement.setInt(index++, ProtoConstants.Platform.Platform_iPad); statement.setInt(index++, ProtoConstants.Platform.Platform_APad); statement.setInt(index++, ProtoConstants.Platform.Platform_HarmonyPad); + } else if(platform == ProtoConstants.Platform.Platform_AndroidWearable || platform == ProtoConstants.Platform.Platform_HarmonyWearable) { + statement.setInt(index++, ProtoConstants.Platform.Platform_AndroidWearable); + statement.setInt(index++, ProtoConstants.Platform.Platform_HarmonyWearable); + } else if(platform == ProtoConstants.Platform.Platform_AndroidTV || platform == ProtoConstants.Platform.Platform_AppleTV || platform == ProtoConstants.Platform.Platform_HarmonyTV) { + statement.setInt(index++, ProtoConstants.Platform.Platform_AndroidTV); + statement.setInt(index++, ProtoConstants.Platform.Platform_AppleTV); + statement.setInt(index++, ProtoConstants.Platform.Platform_HarmonyTV); } else { statement.setInt(index++, platform); } diff --git a/broker/src/main/java/io/moquette/persistence/MemoryMessagesStore.java b/broker/src/main/java/io/moquette/persistence/MemoryMessagesStore.java index 2571a52d..0e9251eb 100755 --- a/broker/src/main/java/io/moquette/persistence/MemoryMessagesStore.java +++ b/broker/src/main/java/io/moquette/persistence/MemoryMessagesStore.java @@ -3026,6 +3026,8 @@ public class MemoryMessagesStore implements IMessagesStore { String pcValue = null; String padValue = null; + String wearableValue = null; + String tvValue = null; for (MemorySessionStore.Session s : m_Server.getStore().sessionsStore().sessionForUser(session.username)) { if (s.getDeleted() != 0 || !m_Server.getConnectionsManager().isConnected(s.getClientID())) { continue; @@ -3043,6 +3045,15 @@ public class MemoryMessagesStore implements IMessagesStore { case Platform_HarmonyPad: padValue = System.currentTimeMillis() + "|" + s.getPlatform() + "|" + s.getClientID() + "|" + s.getPhoneName(); break; + case Platform_AndroidWearable: + case Platform_HarmonyWearable: + wearableValue = System.currentTimeMillis() + "|" + s.getPlatform() + "|" + s.getClientID() + "|" + s.getPhoneName(); + break; + case Platform_AndroidTV: + case Platform_AppleTV: + case Platform_HarmonyTV: + tvValue = System.currentTimeMillis() + "|" + s.getPlatform() + "|" + s.getClientID() + "|" + s.getPhoneName(); + break; default: break; } @@ -3057,6 +3068,16 @@ public class MemoryMessagesStore implements IMessagesStore { if (!isOnlineValueEqual(padentry, padValue)) { updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("Pad").setValue(padValue==null?"":padValue).build(), session.clientID); } + + WFCMessage.UserSettingEntry wearableEntry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "Wearable"); + if (!isOnlineValueEqual(wearableEntry, wearableValue)) { + updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("Wearable").setValue(wearableValue==null?"":wearableValue).build(), session.clientID); + } + + WFCMessage.UserSettingEntry tvEntry = getUserSetting(session.getUsername(), kUserSettingPCOnline, "TV"); + if (!isOnlineValueEqual(tvEntry, tvValue)) { + updateUserSettings(session.username, WFCMessage.ModifyUserSettingReq.newBuilder().setScope(kUserSettingPCOnline).setKey("TV").setValue(tvValue==null?"":tvValue).build(), session.clientID); + } } @Override diff --git a/broker/src/main/java/io/moquette/persistence/MemorySessionStore.java b/broker/src/main/java/io/moquette/persistence/MemorySessionStore.java index 69572724..8936c3e7 100755 --- a/broker/src/main/java/io/moquette/persistence/MemorySessionStore.java +++ b/broker/src/main/java/io/moquette/persistence/MemorySessionStore.java @@ -41,6 +41,8 @@ public class MemorySessionStore implements ISessionsStore { private boolean supportMultiEndpoint = false; private boolean supportMultiPCEndpoint = false; private boolean supportMultiPadEndpoint = false; + private boolean supportMultiWearableEndpoint = false; + private boolean supportMultiTVEndpoint = false; private boolean clientSupportKickoff = false; public static class Session implements Comparable{ @@ -101,6 +103,9 @@ public class MemorySessionStore implements ISessionsStore { return platform == ProtoConstants.Platform.Platform_iPad || platform == ProtoConstants.Platform.Platform_APad || platform == ProtoConstants.Platform.Platform_HarmonyPad; } + public boolean isTVClient() { + return platform == ProtoConstants.Platform.Platform_AppleTV || platform == ProtoConstants.Platform.Platform_AndroidTV || platform == ProtoConstants.Platform.Platform_HarmonyTV; + } public int getPushType() { return pushType; @@ -312,6 +317,16 @@ public class MemorySessionStore implements ISessionsStore { } catch (Exception e) { } + try { + supportMultiWearableEndpoint = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_WEARABLE_ENDPOINT, "false")); + } catch (Exception e) { + } + + try { + supportMultiTVEndpoint = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_MULTI_TV_ENDPOINT, "false")); + } catch (Exception e) { + } + try { clientSupportKickoff = Boolean.parseBoolean(server.getConfig().getProperty(BrokerConstants.SERVER_CLIENT_SUPPORT_KICKOFF_EVENT, "false")); } catch (Exception e) { @@ -419,6 +434,11 @@ public class MemorySessionStore implements ISessionsStore { && !(platform == ProtoConstants.Platform.Platform_iPad && supportMultiPadEndpoint) && !(platform == ProtoConstants.Platform.Platform_APad && supportMultiPadEndpoint) && !(platform == ProtoConstants.Platform.Platform_HarmonyPad && supportMultiPadEndpoint) + && !(platform == ProtoConstants.Platform.Platform_AndroidWearable && supportMultiWearableEndpoint) + && !(platform == ProtoConstants.Platform.Platform_HarmonyWearable && supportMultiWearableEndpoint) + && !(platform == ProtoConstants.Platform.Platform_AndroidTV && supportMultiTVEndpoint) + && !(platform == ProtoConstants.Platform.Platform_AppleTV && supportMultiTVEndpoint) + && !(platform == ProtoConstants.Platform.Platform_HarmonyTV && supportMultiTVEndpoint) ) { databaseStore.clearMultiEndpoint(username, clientID, platform); if (userSessions.get(username) != null) { @@ -445,6 +465,14 @@ public class MemorySessionStore implements ISessionsStore { if (s.getPlatform() == ProtoConstants.Platform.Platform_OSX || s.getPlatform() == ProtoConstants.Platform.Platform_Windows || s.getPlatform() == ProtoConstants.Platform.Platform_LINUX || s.getPlatform() == ProtoConstants.Platform.Platform_HarmonyPC) { remove = true; } + } else if(platform == ProtoConstants.Platform.Platform_AndroidWearable || platform == ProtoConstants.Platform.Platform_HarmonyWearable) { + if (s.getPlatform() == ProtoConstants.Platform.Platform_AndroidWearable || s.getPlatform() == ProtoConstants.Platform.Platform_HarmonyWearable) { + remove = true; + } + } else if(platform == ProtoConstants.Platform.Platform_AndroidTV || platform == ProtoConstants.Platform.Platform_AppleTV || platform == ProtoConstants.Platform.Platform_HarmonyTV) { + if (s.getPlatform() == ProtoConstants.Platform.Platform_AndroidTV || s.getPlatform() == ProtoConstants.Platform.Platform_AppleTV || s.getPlatform() == ProtoConstants.Platform.Platform_HarmonyTV) { + remove = true; + } } else { //web, microapp if (s.getPlatform() ==platform) { remove = true; diff --git a/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java b/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java index 45b74b67..79fa2892 100644 --- a/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java +++ b/common/src/main/java/cn/wildfirechat/proto/ProtoConstants.java @@ -56,7 +56,14 @@ public class ProtoConstants { int Platform_Harmony = 10; int Platform_HarmonyPad = 11; int Platform_HarmonyPC = 12; - int Platform_MAX = Platform_HarmonyPC; + // 穿戴端 (Wearable) + int Platform_AndroidWearable = 13; + int Platform_HarmonyWearable = 14; + // TV端 + int Platform_AndroidTV = 15; + int Platform_AppleTV = 16; + int Platform_HarmonyTV = 17; + int Platform_MAX = Platform_HarmonyTV; } //message NotifyMessage & PullMessageRequest -> type diff --git a/distribution/src/main/resources/wildfirechat.conf b/distribution/src/main/resources/wildfirechat.conf index 7374f8e1..ee32f43b 100755 --- a/distribution/src/main/resources/wildfirechat.conf +++ b/distribution/src/main/resources/wildfirechat.conf @@ -382,6 +382,12 @@ server.multi_pc_endpoint false ## 是否支持PAD多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开PAD端多端登录。 server.multi_pad_endpoint false +## 是否支持可穿戴设备多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开可穿戴设备多端登录。 +server.multi_wearable_endpoint false + +## 是否支持TV设备多端登陆,当server.multi_endpoint为true时,此开关无意义,当为false时,可以单独打开TV多端登录。 +server.multi_tv_endpoint false + # 多平台连接状态通知(仅当multi_endpoint为false时有效),true时移动端可以收到pc或pad或web端登录的通知。 server.multi_platform_notification true