|
|
@@ -0,0 +1,161 @@
|
|
|
+package cn.muchinfo.rma.business.quote
|
|
|
+
|
|
|
+import cn.muchinfo.rma.business.account.adapter.AccountAdapter
|
|
|
+import cn.muchinfo.rma.business.quote.adapter.QuoteAdapter
|
|
|
+import cn.muchinfo.rma.global.GlobalDataCollection
|
|
|
+import cn.muchinfo.rma.netcore.packet.Packet40
|
|
|
+import cn.muchinfo.rma.netcore.packet.Packet50
|
|
|
+import cn.muchinfo.rma.netcore.socket.Callback
|
|
|
+import cn.muchinfo.rma.protobuf.classNumber.ClassNumber
|
|
|
+import cn.muchinfo.rma.view.MyApplication
|
|
|
+import cn.muchinfo.rma.view.autoWidget.guard
|
|
|
+import java.util.concurrent.ConcurrentHashMap
|
|
|
+import java.util.concurrent.ConcurrentSkipListSet
|
|
|
+
|
|
|
+/**
|
|
|
+ * 行情管理类
|
|
|
+ */
|
|
|
+class QuoteManager {
|
|
|
+ /** 当前已订阅行情商品列表 */
|
|
|
+ private var currentGoodsSet = ConcurrentSkipListSet<String>()
|
|
|
+
|
|
|
+ /** 订阅Map */
|
|
|
+ private var subcriptMap = ConcurrentHashMap<String, ConcurrentSkipListSet<String>>()
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按需订阅行情添加订阅商品
|
|
|
+ * @param tag String 订阅方标志,一般使用UUID生成的唯一码
|
|
|
+ * @param goodsCodeSet ConcurrentSkipListSet<String> 待订阅商品代码列表
|
|
|
+ * @param callback Function2<[@kotlin.ParameterName] Boolean, [@kotlin.ParameterName] Error?, Unit>? 回调
|
|
|
+ */
|
|
|
+ fun addSubscriptQuote(
|
|
|
+ tag: String,
|
|
|
+ goodsCodeSet: ConcurrentSkipListSet<String>,
|
|
|
+ callback: ((isCompleted: Boolean, err: Error?) -> Unit)?
|
|
|
+ ) {
|
|
|
+ val app = MyApplication.getInstance().guard {
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, Error("Application未初始化"))
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ val quoteSocketManager = app.quoteSocketManager.guard {
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, Error("行情链路未初始化"))
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 判断当前是否已经连接行情链路
|
|
|
+ if (quoteSocketManager.connState != 2) {
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, Error("行情链路未连接"))
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 添加到当前订阅列表中
|
|
|
+ subcriptMap[tag] = goodsCodeSet
|
|
|
+ val addSet = HashSet<String>()
|
|
|
+ for (item in goodsCodeSet) {
|
|
|
+ if (item !in currentGoodsSet) {
|
|
|
+ addSet.add(item)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断是否要重新订阅
|
|
|
+ if (addSet.count() > 0) {
|
|
|
+ currentGoodsSet.addAll(addSet)
|
|
|
+ // 重新订阅行情
|
|
|
+ subscriptQuote(callback)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 按需订阅行情移除订阅商品
|
|
|
+ * @param tag String 订阅方标志,一般使用UUID生成的唯一码
|
|
|
+ */
|
|
|
+ fun removeSubscriptQuote(tag: String) {
|
|
|
+ val app = MyApplication.getInstance().guard {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ val quoteSocketManager = app.quoteSocketManager.guard {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 判断当前是否已经连接行情链路
|
|
|
+ if (quoteSocketManager.connState != 2) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (subcriptMap.contains(tag)) {
|
|
|
+ subcriptMap.remove(tag)
|
|
|
+ // 构建当前需订阅的商品列表
|
|
|
+ val needSet = HashSet<String>()
|
|
|
+ for (items in subcriptMap.values) {
|
|
|
+ for (goodsCode in items) {
|
|
|
+ if (goodsCode !in needSet) {
|
|
|
+ needSet.add(goodsCode)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 判断与当前订阅列表是否一样
|
|
|
+ if (currentGoodsSet != needSet) {
|
|
|
+ currentGoodsSet.clear()
|
|
|
+ currentGoodsSet.addAll(needSet)
|
|
|
+
|
|
|
+ // 重新订阅行情
|
|
|
+ subscriptQuote(null)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 订阅商品实时行情
|
|
|
+ * @param callback Function2<[@kotlin.ParameterName] Boolean, [@kotlin.ParameterName] Error?, Unit>?
|
|
|
+ */
|
|
|
+ private fun subscriptQuote(callback: ((isCompleted: Boolean, err: Error?) -> Unit)?) {
|
|
|
+ // 当前是否已经登陆
|
|
|
+ val loginRsp = GlobalDataCollection.instance?.loginRsp.guard {
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, Error("当前未登录"))
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ val reqPacket = QuoteAdapter.buildSubscriptPacket(
|
|
|
+ currentGoodsSet.toSet(),
|
|
|
+ loginRsp.token,
|
|
|
+ loginRsp.loginID.toInt()
|
|
|
+ )
|
|
|
+ // 发送订阅请求
|
|
|
+ val quoteSocketManager = MyApplication.getInstance()?.quoteSocketManager
|
|
|
+ quoteSocketManager?.send(
|
|
|
+ reqPacket,
|
|
|
+ ClassNumber.MainClassNumber_Quota_SubscriptRsp,
|
|
|
+ object :
|
|
|
+ Callback<Packet40> {
|
|
|
+ override fun onSuccess(rsp: Packet40?) {
|
|
|
+ val rst = QuoteAdapter.analySubscriptRsp(rsp!!)
|
|
|
+ if (!rst.first) {
|
|
|
+ // 订阅失败
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, Error("行情订阅失败"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 订阅成功后通知网络开始发送心跳
|
|
|
+ quoteSocketManager.startBeatTime()
|
|
|
+ // 通知网络可进行断网重连
|
|
|
+ quoteSocketManager.canReconnect = true
|
|
|
+
|
|
|
+ if (callback != null) {
|
|
|
+ callback(true, null)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ override fun onFail(err: java.lang.Error?) {
|
|
|
+ if (callback != null) {
|
|
|
+ callback(false, err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|