Просмотр исходного кода

feat(websocket):
- 新增 WebSocket 客户端连接、消息处理及日志记录功能
- `WebSocketConfig`: 配置 WebSocket 连接参数,包括服务器地址、消息监听器和日志插件
- `CustomMessageListener`: 处理接收到的 WebSocket 消息,使用 Gson 解析 JSON 格式的消息,并分发给 `MessageBusinessManager` 处理
- `MessageBusinessManager`: 根据消息类型处理业务逻辑,目前支持 `commandToLog` 类型,用于执行 Shell 命令并将结果输出到日志
- `WebsocketLoggerPlugin`: Netty 插件,用于记录 WebSocket 连接、断开、消息收发及异常等事件
- `MessageEntity`: WebSocket 消息的数据模型
- 在 `MyApplication` 启动时初始化并连接 WebSocket
- 更新 `NetHttpManager` 中 OkHttpClient 连接池的清理方式
- 修改 `strings.xml` 中 `motor_map` 文本,由 "开关电机" / "Motor" 改为 "电机开关布局图" / "Motor Switch Map"
- 升级 `SIKExtension` 依赖版本至 `1.1.72`
- `build.gradle` 中增加 `packagingOptions` 以解决 Netty 相关的资源冲突

周文健 1 месяц назад
Родитель
Сommit
f76d0017ed

+ 8 - 3
app/build.gradle

@@ -69,7 +69,6 @@ android {
     }
 
 
-
     compileOptions {
         sourceCompatibility JavaVersion.VERSION_1_8
         targetCompatibility JavaVersion.VERSION_1_8
@@ -87,6 +86,13 @@ android {
         }
     }
 
+    packaging {
+        resources {
+            pickFirsts += "META-INF/versions/9/OSGI-INF/MANIFEST.MF"
+            pickFirsts += "META-INF/INDEX.LIST"
+            pickFirsts += "META-INF/io.netty.versions.properties"
+        }
+    }
 }
 
 dependencies {
@@ -162,8 +168,7 @@ dependencies {
 
     implementation 'io.github.razerdp:BasePopup:3.2.1'
 
-    implementation 'com.github.SilverIceKey.SIKExtension:SIKCore:1.1.56'
-    implementation 'com.github.SilverIceKey.SIKExtension:SIKAndroid:1.1.56'
+    implementation 'com.github.SilverIceKey:SIKExtension:1.1.72'
     implementation 'com.github.liangjingkanji:BRV:1.6.1'
     implementation("com.github.SilverIceKey:SIKCronJob:1.0.5")
 }

+ 2 - 0
app/src/main/java/com/grkj/iscs_mars/MyApplication.kt

@@ -15,6 +15,7 @@ import com.grkj.iscs_mars.util.NetApi
 import com.grkj.iscs_mars.util.NetHttpManager
 import com.grkj.iscs_mars.util.SPUtils
 import com.grkj.iscs_mars.util.log.LogUtil
+import com.grkj.iscs_mars.websocket.WebSocketConfig
 import com.sik.cronjob.managers.CronJobManager
 import com.sik.sikcore.SIKCore
 
@@ -49,6 +50,7 @@ class MyApplication : Application() {
 
         Executor.runOnIO {
             BusinessManager.registerMainListener()
+            WebSocketConfig.instance.connect()
         }
         LogUtil.i("App start : ${serialNo()}")
 

+ 2 - 2
app/src/main/java/com/grkj/iscs_mars/util/NetHttpManager.kt

@@ -66,7 +66,7 @@ class NetHttpManager {
                 true
             }
             .config {
-                it.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
+//                it.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
             }
             .addSerialPreprocessor { itPreChain ->
                 itPreChain.task.addHeader(
@@ -284,7 +284,7 @@ class NetHttpManager {
                 exceptionCount += 1
                 if (exceptionCount >= 5) {
                     exceptionCount = 0
-                    (myHttp as OkHttpClientWrapper).okClient().connectionPool().evictAll()
+                    (myHttp as OkHttpClientWrapper).okClient().connectionPool.evictAll()
                 }
             } else {
                 exceptionCount = 0

+ 30 - 0
app/src/main/java/com/grkj/iscs_mars/websocket/CustomMessageListener.kt

@@ -0,0 +1,30 @@
+package com.grkj.iscs_mars.websocket
+
+import com.google.gson.Gson
+import com.grkj.iscs_mars.util.log.LogUtil
+import com.sik.siknet.tcp.netty.ws.MessageListener
+
+class CustomMessageListener : MessageListener {
+    private val heartbeatStr = "heartbeat"
+
+    /**
+     * gson转换
+     */
+    private val gson = Gson()
+
+    override fun onMessage(message: String) {
+        LogUtil.i("收到消息:$message")
+        try {
+            val messageEntity = gson.fromJson(message, MessageEntity::class.java)
+            MessageBusinessManager.handleMessage(messageEntity)
+        } catch (e: Exception) {
+            if (message != heartbeatStr) {
+                LogUtil.i("消息解析异常:${message}")
+            }
+        }
+    }
+
+    override fun onRawMessage(message: ByteArray) {
+
+    }
+}

+ 29 - 0
app/src/main/java/com/grkj/iscs_mars/websocket/MessageBusinessManager.kt

@@ -0,0 +1,29 @@
+package com.grkj.iscs_mars.websocket
+
+import com.grkj.iscs_mars.util.log.LogUtil
+import com.sik.sikcore.shell.ShellUtils
+
+/**
+ * 消息业务处理
+ */
+object MessageBusinessManager {
+    /**
+     * 消息类型,执行命令,输出结果到日志
+     */
+    const val MESSAGE_TYPE_COMMAND_TO_LOG = "commandToLog"
+
+    /**
+     * 处理消息
+     */
+    fun handleMessage(messageEntity: MessageEntity) {
+        if (messageEntity.type == null || messageEntity.content == null) {
+            return
+        }
+        when (messageEntity.type) {
+            MESSAGE_TYPE_COMMAND_TO_LOG -> {
+                val result = ShellUtils.execCmd(messageEntity.content!!)
+                LogUtil.i("执行结果:${result.successMsg}")
+            }
+        }
+    }
+}

+ 21 - 0
app/src/main/java/com/grkj/iscs_mars/websocket/MessageEntity.kt

@@ -0,0 +1,21 @@
+package com.grkj.iscs_mars.websocket
+
+/**
+ * 消息实体
+ */
+class MessageEntity {
+    /**
+     * 内容
+     */
+    var content: String? = ""
+
+    /**
+     * 类型
+     */
+    var type: String? = ""
+
+    /**
+     * 序列号
+     */
+    var lotoSerialNumber: String? = ""
+}

+ 44 - 0
app/src/main/java/com/grkj/iscs_mars/websocket/WebSocketConfig.kt

@@ -0,0 +1,44 @@
+package com.grkj.iscs_mars.websocket
+
+import com.grkj.iscs_mars.extentions.serialNo
+import com.grkj.iscs_mars.util.SPUtils
+import com.sik.sikcore.SIKCore
+import com.sik.siknet.tcp.netty.core.manager.NettyClientManager
+import com.sik.siknet.tcp.netty.core.plugin.NettyPlugin
+import com.sik.siknet.tcp.netty.ws.WebSocketClientConfig
+
+class WebSocketConfig(override val plugins: List<NettyPlugin> = listOf(WebsocketLoggerPlugin())) :
+    WebSocketClientConfig(
+        wsUrl = "${
+            SPUtils.getBaseUrl(SIKCore.getApplication()).replace("http://", "ws://")
+                .replace("https://", "wss://")
+        }/websocket/android/${SIKCore.getApplication().serialNo()}",
+        messageListener = CustomMessageListener(),
+    ) {
+    companion object {
+
+        @JvmStatic
+        val instance: WebSocketConfig by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
+            WebSocketConfig()
+        }
+    }
+
+    private val clientManager: NettyClientManager by lazy {
+        NettyClientManager(this)
+    }
+
+
+    /**
+     * 连接
+     */
+    fun connect() {
+        clientManager.start()
+    }
+
+    /**
+     * 停止
+     */
+    fun stop() {
+        clientManager.stop()
+    }
+}

+ 62 - 0
app/src/main/java/com/grkj/iscs_mars/websocket/WebsocketLoggerPlugin.kt

@@ -0,0 +1,62 @@
+package com.grkj.iscs_mars.websocket
+
+import com.grkj.iscs_mars.util.log.LogUtil
+import com.sik.siknet.tcp.netty.core.common.BaseNettyManager
+import com.sik.siknet.tcp.netty.core.plugin.simple.SimplePlugin
+import io.netty.channel.ChannelHandlerContext
+
+/**
+ * 日志插件
+ */
+class WebsocketLoggerPlugin : SimplePlugin() {
+    override fun onStarted(manager: BaseNettyManager) {
+        super.onStarted(manager)
+        LogUtil.i("开始连接")
+    }
+
+    override fun onStopping(manager: BaseNettyManager) {
+        super.onStopping(manager)
+        LogUtil.i("停止连接")
+    }
+
+    override fun beforeWrite(ctx: ChannelHandlerContext, msg: Any) {
+        super.beforeWrite(ctx, msg)
+        LogUtil.i("发送消息:$msg")
+    }
+
+    override fun afterWrite(
+        ctx: ChannelHandlerContext,
+        msg: Any,
+        success: Boolean,
+        cause: Throwable?
+    ) {
+        super.afterWrite(ctx, msg, success, cause)
+        LogUtil.i("发送消息成功:$success")
+    }
+
+    override fun beforeRead(ctx: ChannelHandlerContext, msg: Any) {
+        super.beforeRead(ctx, msg)
+        LogUtil.i("收到消息:$msg")
+    }
+
+    override fun afterRead(ctx: ChannelHandlerContext, msg: Any) {
+        super.afterRead(ctx, msg)
+        LogUtil.i("收到消息成功")
+    }
+
+    override fun onConnect(ctx: ChannelHandlerContext) {
+        super.onConnect(ctx)
+        LogUtil.i("连接成功")
+    }
+
+    override fun onDisconnect(ctx: ChannelHandlerContext) {
+        super.onDisconnect(ctx)
+        LogUtil.i("断开连接")
+    }
+
+    override fun onException(ctx: ChannelHandlerContext, cause: Throwable) {
+        super.onException(ctx, cause)
+        LogUtil.i("异常:$cause")
+    }
+
+}

+ 1 - 1
app/src/main/res/values-en/strings.xml

@@ -412,5 +412,5 @@
     <string name="switch_id">ID:%1$s</string>
     <string name="switch_status_tv">Switch Status:</string>
     <string name="device_inputting">Hardware inputting……</string>
-    <string name="motor_map">Motor</string>
+    <string name="motor_map">Motor Switch Map</string>
 </resources>

+ 1 - 1
app/src/main/res/values-zh/strings.xml

@@ -412,5 +412,5 @@
     <string name="switch_id">编号:%1$s</string>
     <string name="switch_status_tv">电机状态:</string>
     <string name="device_inputting">硬件录入中……</string>
-    <string name="motor_map">开关电机</string>
+    <string name="motor_map">电机开关布局图</string>
 </resources>

+ 1 - 1
app/src/main/res/values/strings.xml

@@ -412,5 +412,5 @@
     <string name="switch_id">编号:%1$s</string>
     <string name="switch_status_tv">电机状态:</string>
     <string name="device_inputting">硬件录入中……</string>
-    <string name="motor_map">开关电机</string>
+    <string name="motor_map">电机开关布局图</string>
 </resources>

+ 1 - 1
gradle/libs.versions.toml

@@ -11,7 +11,7 @@ activity = "1.8.0"
 constraintlayout = "2.1.4"
 mvvmhabit = "4.0.0"
 okhttps = "4.1.0"
-log-interceptor = "3.14.9"
+log-interceptor = "4.1.0"
 autosize = "v1.2.1"
 fastble = "1.4.2"
 lifecycle-version = "2.9.0"