Pārlūkot izejas kodu

tcp callback修改

weizhengliang 2 gadi atpakaļ
vecāks
revīzija
de15509e7d
52 mainītis faili ar 2870 papildinājumiem un 1193 dzēšanām
  1. 28 3
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/ChannelImActivity.kt
  2. 2 0
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/TakeoverActivity.kt
  3. 25 3
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/VoiceMsgActivity.kt
  4. 16 4
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchCallRecordsActivity.kt
  5. 2 0
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchContactsActivity.kt
  6. 2 7
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchHome2Activity.kt
  7. 21 5
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchUserSettingActivity.java
  8. 20 5
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/ChannelImItemAdapter.kt
  9. 99 9
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/NewEventItemAdapter.kt
  10. 51 15
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemAdapter.kt
  11. 54 15
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemSearchAdapter.kt
  12. 16 4
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/WatchContactsItemAdapter.kt
  13. 5 1
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/FloatingService.java
  14. 33 6
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/PhoneStateReceiver.java
  15. 139 52
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt
  16. 1 1
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java
  17. 40 11
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/CallSingleActivity.java
  18. 85 6
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/FragmentAudio.java
  19. 33 13
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/SingleCallFragment.java
  20. 0 0
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt.bak
  21. 12 4
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/NetWorkChangeReceiver.kt
  22. 48 27
      android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/RecordHelper.java
  23. 1 1
      build.gradle
  24. 3 2
      janus/src/main/java/com/wdkl/rtc/janus/JanusClient.java
  25. 2 0
      middleware/build.gradle
  26. 11 11
      middleware/src/main/code/com/wdkl/ncs/android/middleware/common/Constants.kt
  27. 587 30
      middleware/src/main/code/com/wdkl/ncs/android/middleware/model/dos/InteractionDO.java
  28. 49 3
      middleware/src/main/code/com/wdkl/ncs/android/middleware/model/dos/RoleDO.java
  29. 45 695
      middleware/src/main/code/com/wdkl/ncs/android/middleware/model/vo/InteractionVO.java
  30. 0 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/NettyClient.kt.bak
  31. 244 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TaskSchedule.java
  32. 188 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TcpClient.java
  33. 150 74
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TcpClientHandler.java
  34. 8 3
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/ChannelImUtil.java
  35. 12 41
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceChannel.java
  36. 5 5
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceUtil.java
  37. 43 7
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/EventUtil.java
  38. 17 4
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/ImUtil.java
  39. 2 2
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/OtherUtil.java
  40. 5 5
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/PhoneUtil.java
  41. 33 29
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/VoiceUtil.java
  42. 33 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpCallback.java
  43. 39 77
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpModel.java
  44. 49 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpSendModel.java
  45. 106 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/RoleTypeEnum.java
  46. 13 6
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/TcpAction.java
  47. 6 3
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/TcpType.java
  48. 483 0
      middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/util/DateUtil.java
  49. 1 1
      resource/src/main/res/values-es/strings.xml
  50. 1 1
      resource/src/main/res/values-ru/strings.xml
  51. 1 1
      resource/src/main/res/values-zh/strings.xml
  52. 1 1
      resource/src/main/res/values/strings.xml

+ 28 - 3
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/ChannelImActivity.kt

@@ -8,6 +8,7 @@ import android.view.MotionEvent
 import android.view.View
 import com.alibaba.android.vlayout.DelegateAdapter
 import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
@@ -27,8 +28,9 @@ import com.wdkl.ncs.android.middleware.logic.contract.home.ChannelImContract
 import com.wdkl.ncs.android.middleware.logic.presenter.home.ChannelImPresenter
 import com.wdkl.ncs.android.middleware.model.dos.ChannelImDO
 import com.wdkl.ncs.android.middleware.model.vo.ChannelIMVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient.Companion.instance
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.ChannelImUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import kotlinx.android.synthetic.main.activity_channel_im_list.*
 import okhttp3.MediaType
 import okhttp3.MultipartBody
@@ -187,7 +189,30 @@ class ChannelImActivity : BaseActivity<ChannelImPresenter, ActivityChannelImList
         channelImDO.senderMemberId = memberId
         channelImDO.audioPath = result
         val tcpModel = ChannelImUtil.channelImMsg(deviceId, channelImDO)
-        instance.sendMsg(tcpModel.toJson()).subscribe { it: Boolean ->
+        val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+            override fun onSuccess(jsonObject: JSONObject) {
+                SoundPoolManager.getInstance().playSound(3)
+
+                activity.runOnUiThread {
+                    showMessage("留言发送成功!")
+                    //刷新列表
+                    page = 1
+                    presenter.getChannelIm(page, page_size, memberId!!, channelId)
+                }
+            }
+
+            override fun onFailed(jsonObject: JSONObject) {
+                // 这里写发送失败的方法
+                SoundPoolManager.getInstance().playSound(6)
+                val callbackString = jsonObject.getString(CALLBACK)
+                activity.runOnUiThread {
+                    showMessage("Failed: $callbackString")
+                }
+            }
+        }
+        TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+        /*instance.sendMsg(tcpModel.toJson()).subscribe { it: Boolean ->
             if (it) {
                 if (Locale.CHINESE.getLanguage().equals(language)) {
                     SoundPoolManager.getInstance().playSound(3)
@@ -199,7 +224,7 @@ class ChannelImActivity : BaseActivity<ChannelImPresenter, ActivityChannelImList
             } else {
                 showMessage(R.string.str_voice_msg_send_fail)
             }
-        }
+        }*/
     }
 
     private fun uploadCheck() {

+ 2 - 0
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/TakeoverActivity.kt

@@ -155,6 +155,8 @@ class TakeoverActivity: BaseActivity<TakeoverPresenter, ActivityTakeoverBinding>
             } else if (resTcpModel.action == TcpAction.VoiceAction.CALLING){
                 showMessage(R.string.call_busy)
             }
+        } else if (messageEvent.tag == 4) {
+            presenter.loadList(partId)
         }
     }
 

+ 25 - 3
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/VoiceMsgActivity.kt

@@ -6,6 +6,7 @@ import android.os.PowerManager
 import android.os.SystemClock
 import android.util.Log
 import android.view.MotionEvent
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.android.jrouter.external.annotation.Autowired
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.utils.base.tool.CommonTool
@@ -21,8 +22,9 @@ import com.wdkl.ncs.android.lib.vo.filter
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.logic.contract.home.VoiceMsgContract
 import com.wdkl.ncs.android.middleware.logic.presenter.home.VoiceMsgPresenter
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.ImUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
@@ -200,7 +202,27 @@ class VoiceMsgActivity:BaseActivity<VoiceMsgPresenter,ActivityVoiceMsgBinding>()
 
         RecordHelper.getInstance().deleteAudioFile(voiceFile)
         val tcpModel = ImUtil.imMsg(Constants.deviceId, toDeviceId, result)
-        NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe{
+        val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+            override fun onSuccess(jsonObject: JSONObject) {
+                SoundPoolManager.getInstance().playSound(3)
+                runOnUiThread {
+                    showMessage("留言发送成功!")
+                }
+                finish()
+            }
+
+            override fun onFailed(jsonObject: JSONObject) {
+                // 这里写发送失败的方法
+                SoundPoolManager.getInstance().playSound(6)
+                val callbackString = jsonObject.getString(CALLBACK)
+                runOnUiThread {
+                    showMessage("Failed: $callbackString")
+                }
+            }
+        }
+        TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+        /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe{
             if (it){
                 if (Locale.CHINESE.getLanguage().equals(language)) {
                     SoundPoolManager.getInstance().playSound(3)
@@ -210,7 +232,7 @@ class VoiceMsgActivity:BaseActivity<VoiceMsgPresenter,ActivityVoiceMsgBinding>()
                 showMessage(R.string.str_voice_msg_send_fail)
             }
             finish()
-        }
+        }*/
     }
 
     override fun onError(message: String, type: Int) {

+ 16 - 4
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchCallRecordsActivity.kt

@@ -7,6 +7,7 @@ import android.util.Log
 import android.view.View
 import com.alibaba.android.vlayout.DelegateAdapter
 import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.android.jrouter.external.annotation.Router
 import com.enation.javashop.net.engine.model.NetState
 import com.enation.javashop.utils.base.widget.LoadingDialog
@@ -16,7 +17,6 @@ import com.wdkl.ncs.android.component.home.adapter.WatchCallRecordsItemAdapter
 import com.wdkl.ncs.android.component.home.databinding.WatchActivityCallRecordsBinding
 import com.wdkl.ncs.android.component.home.launch.HomeLaunch
 import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.logic.contract.home.WatchCallRecordsFragmentContract
@@ -29,8 +29,9 @@ import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.lib.vo.MessageEvent
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import kotlinx.android.synthetic.main.watch_activity_call_records.*
 import kotlinx.android.synthetic.main.watch_activity_call_records.refresh
@@ -147,7 +148,18 @@ class WatchCallRecordsActivity : BaseActivity<WatchCallRecordsFragmentPresenter,
 
                                 //发送tcp
                                 val tcpModel = PhoneUtil.phoneCall(Constants.deviceId, receivedData!!.deviceId)
-                                NettyClient.instance.sendMsg(tcpModel.toJson())
+                                val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                    override fun onSuccess(jsonObject: JSONObject) {
+                                        //
+                                    }
+
+                                    override fun onFailed(jsonObject: JSONObject) {
+                                        // 这里写发送失败的方法
+                                    }
+                                }
+                                TcpClient.getInstance().sendTcp(tcpModel, true, transaction)
+
+                                /*NettyClient.instance.sendMsg(tcpModel.toJson())
                                     .subscribe { res: Boolean ->
                                         if (res) {
                                             Log.d(TAG, "TCP.发送消息完成")
@@ -155,7 +167,7 @@ class WatchCallRecordsActivity : BaseActivity<WatchCallRecordsFragmentPresenter,
                                             Log.e(TAG, "TCP.发送消息失败")
                                             HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                         }
-                                    }
+                                    }*/
                             } else {
                                 showMessage(R.string.call_phone_failed)
                             }

+ 2 - 0
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchContactsActivity.kt

@@ -154,6 +154,8 @@ class WatchContactsActivity : BaseActivity<WatchActivityPresenter, WatchContacts
             } else if (resTcpModel.action == TcpAction.VoiceAction.CALLING){
                 showMessage(R.string.call_busy)
             }
+        } else if (messageEvent.tag == 4) {
+            presenter.loadData(page, Constants.deviceId)
         }
     }
 }

+ 2 - 7
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchHome2Activity.kt

@@ -45,7 +45,6 @@ import com.wdkl.ncs.android.middleware.model.dto.TcpSeverDTO
 import com.wdkl.ncs.android.middleware.model.vo.DeviceVO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.WatchContactVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
 import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 import com.wdkl.ncs.android.middleware.utils.CommonUtils
 import com.wdkl.ncs.android.middleware.utils.ContactHelper
@@ -582,9 +581,9 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
         })
 
         //等30秒
-        var waitSeconds = 0;
+        var waitSeconds = 0
         Thread {
-            while (!NettyClient.instance.isConnect()) {
+            while (!TcpClientHandler.getConnected()) {
                 Log.w(TAG, "无网络" + waitSeconds)
                 waitSeconds++
                 if (waitSeconds > 30) {
@@ -592,10 +591,6 @@ class WatchHome2Activity : BaseActivity<WatchHomeActivityPresenter, WatchActivit
                 }
                 Thread.sleep(5000)
             }
-
-//            if (NettyClient.instance.isConnect()) {
-//                onTcpConnectSuccess()
-//            }
         }.start()
     }
 

+ 21 - 5
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/activity/WatchUserSettingActivity.java

@@ -18,6 +18,7 @@ import android.widget.Toast;
 
 import androidx.annotation.Nullable;
 
+import com.alibaba.fastjson.JSONObject;
 import com.wdkl.ncs.android.component.home.BuildConfig;
 import com.wdkl.ncs.android.component.home.R;
 import com.wdkl.ncs.android.component.home.service.WdKeepAliveService;
@@ -29,8 +30,9 @@ import com.wdkl.ncs.android.component.home.util.PingUtil;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.lib.base.BaseApplication;
 import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.utils.CommonUtils;
 
@@ -91,7 +93,7 @@ public class WatchUserSettingActivity extends Activity {
         String type = getString(R.string.phone_type, Constants.Companion.getPhoneType(), Constants.Companion.getBedPhoneType(), Constants.Companion.getNursePhoneType());
         tvPhoneType.setText(type);
 
-        if (SettingConfig.getVoiceCallType(BaseApplication.appContext) == SettingConfig.VOICE_CALL) {
+        if (SettingConfig.getVoiceCallType(BaseApplication.appContext) == SettingConfig.PHONE_CALL) {
             callYes.setChecked(true);
         } else {
             callNo.setChecked(true);
@@ -154,7 +156,21 @@ public class WatchUserSettingActivity extends Activity {
             @Override
             public void onClick(View view) {
                 TcpModel userChangeModel = DeviceUtil.userChange(Constants.Companion.getDeviceId());
-                NettyClient.Companion.getInstance().sendMsg(userChangeModel.toJson()).subscribe(it->{
+                TcpCallback transaction = new TcpCallback(userChangeModel.getTid()) {
+                    @Override
+                    public void onSuccess(JSONObject jsonObject) {
+                        runOnUiThread(() -> ExtendMethodsKt.showMessage(R.string.user_change_success));
+                        WatchUserSettingActivity.this.finish();
+                    }
+
+                    @Override
+                    public void onFailed(JSONObject jsonObject) {
+                        runOnUiThread(() -> ExtendMethodsKt.showMessage(R.string.user_change_failed));
+                    }
+                };
+                TcpClient.getInstance().sendTcp(userChangeModel, false, transaction);
+
+                /*NettyClient.Companion.getInstance().sendMsg(userChangeModel.toJson()).subscribe(it->{
                     if (it) {
                         Log.d(TAG, "TCP.发送消息完成");
                         ExtendMethodsKt.showMessage(R.string.user_change_success);
@@ -163,7 +179,7 @@ public class WatchUserSettingActivity extends Activity {
                         Log.e(TAG, "TCP.发送消息失败");
                         ExtendMethodsKt.showMessage(R.string.user_change_failed);
                     }
-                });
+                });*/
             }
         });
 
@@ -200,7 +216,7 @@ public class WatchUserSettingActivity extends Activity {
             public void onCheckedChanged(RadioGroup group, int checkedId) {
                 if (checkedId == R.id.rb_call_yes) {
                     //普通电话
-                    SettingConfig.setVoiceCallType(BaseApplication.appContext, SettingConfig.VOICE_CALL);
+                    SettingConfig.setVoiceCallType(BaseApplication.appContext, SettingConfig.PHONE_CALL);
                 } else {
                     //网络电话
                     SettingConfig.setVoiceCallType(BaseApplication.appContext, SettingConfig.SIP_CALL);

+ 20 - 5
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/ChannelImItemAdapter.kt

@@ -6,9 +6,9 @@ import android.view.View
 import android.view.ViewGroup
 import com.alibaba.android.vlayout.LayoutHelper
 import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.alibaba.fastjson.JSONObject
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.databinding.AdapterChannelImRecordsItemBinding
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.component.home.util.ImPlayDialogHelper
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper
 import com.wdkl.ncs.android.component.home.util.TimeTransition
@@ -20,8 +20,9 @@ import com.wdkl.ncs.android.middleware.api.ApiManager
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.middleware.model.dos.ChannelImDO
 import com.wdkl.ncs.android.middleware.model.vo.ChannelIMVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.ChannelImUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import org.greenrobot.eventbus.EventBus
 
 
@@ -72,7 +73,8 @@ class ChannelImItemAdapter(val data: ArrayList<ChannelIMVO>, val imActivity: Act
      */
     override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterChannelImRecordsItemBinding>, position: Int) {
         holder.bind { binding ->
-            val itemData = getItem(position)
+            val pos = holder.adapterPosition
+            val itemData = getItem(pos)
 
             binding.imCallTimeTv.text = TimeTransition().stampToTime(itemData.sendTime*1000)
             binding.imSickbedTv.text = itemData.senderMemberName
@@ -99,7 +101,20 @@ class ChannelImItemAdapter(val data: ArrayList<ChannelIMVO>, val imActivity: Act
                 //如果是未读留言则回复已读tcp
                 if (!itemData.readed) {
                     val imTcpModel = ChannelImUtil.channelImRead(Constants.deviceId, itemData as ChannelImDO)
-                    NettyClient.instance.sendMsg(imTcpModel.toJson()).subscribe {
+                    val transaction: TcpCallback = object : TcpCallback(imTcpModel.tid) {
+                        override fun onSuccess(jsonObject: JSONObject) {
+                            if (imCallBack != null) {
+                                imCallBack!!.onChannelImRead(itemData, pos)
+                            }
+                        }
+
+                        override fun onFailed(jsonObject: JSONObject) {
+                            // 这里写发送失败的方法
+                        }
+                    }
+                    TcpClient.getInstance().sendTcp(imTcpModel, false, transaction)
+
+                    /*NettyClient.instance.sendMsg(imTcpModel.toJson()).subscribe {
                         if (it) {
                             Log.d(TAG, "TCP.发送消息完成")
                             //EventBus.getDefault().post(MessageEvent("im_update", Constants.EVENT_CHANNEL_IM_UPDATE))
@@ -110,7 +125,7 @@ class ChannelImItemAdapter(val data: ArrayList<ChannelIMVO>, val imActivity: Act
                             Log.e(TAG, "TCP.发送消息失败")
                             HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                         }
-                    }
+                    }*/
                 }
             }
         }

+ 99 - 9
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/NewEventItemAdapter.kt

@@ -8,6 +8,7 @@ import android.view.View
 import android.view.ViewGroup
 import com.alibaba.android.vlayout.LayoutHelper
 import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.google.gson.Gson
@@ -16,7 +17,6 @@ import com.wdkl.ncs.android.component.home.activity.VoiceMsgActivity
 import com.wdkl.ncs.android.component.home.databinding.EventListItemBinding
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.component.home.util.ImPlayDialogHelper
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper
 import com.wdkl.ncs.android.middleware.common.Constants
@@ -27,10 +27,11 @@ import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.api.ApiManager
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
 import com.wdkl.ncs.android.lib.vo.MessageEvent
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.*
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import org.greenrobot.eventbus.EventBus
 
 
@@ -89,7 +90,7 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                     binding.eliImRead.visibility = View.GONE
                     binding.eliEventResponse.visibility = View.VISIBLE
                     binding.eliEventName.text = itemData.data
-                    if (itemData.actionEnd!=null){
+                    if (itemData.actionEndMemberId!=null){
                         binding.eliEventResponse.visibility = View.GONE
                         binding.eliEventName.setTextColor(Color.GREEN)
                     } else {
@@ -97,7 +98,33 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                         binding.eliEventResponse.setOnClickListener {
                             loadingDialog.show()
                             val tcpModel = EventUtil.eventResponse(Constants.deviceId, itemData.fromDeviceId, itemData.id)
-                            NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
+                            val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    //操作成功,更新事件列表界面
+                                    updateEventItem(itemData)
+
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            showMessage("操作成功")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                    val callbackString = jsonObject.getString(CALLBACK)
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            showMessage("Failed: $callbackString")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+                            /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
                                 if (it) {
                                     Log.d(TAG, "TCP.发送消息完成")
                                 } else {
@@ -105,7 +132,7 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                                     HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                 }
                                 loadingDialog.dismiss()
-                            }
+                            }*/
                         }
                     }
 
@@ -140,14 +167,37 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                             //如果是自己发的留言则不发送已读tcp
                             if (Constants.memberId != itemData.fromDeviceMemberId) {
                                 val tcpModel = ImUtil.imRead(Constants.deviceId, itemData.fromDeviceId, itemData.id)
-                                NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
+                                val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                    override fun onSuccess(jsonObject: JSONObject) {
+                                        //操作成功,更新事件列表界面
+                                        updateEventItem(itemData)
+
+                                        if (activity != null) {
+                                            activity.runOnUiThread {
+                                                showMessage("消息已读")
+                                            }
+                                        }
+                                    }
+
+                                    override fun onFailed(jsonObject: JSONObject) {
+                                        // 这里写发送失败的方法
+                                        if (activity != null) {
+                                            activity.runOnUiThread {
+                                                showMessage("网络异常,请重试")
+                                            }
+                                        }
+                                    }
+                                }
+                                TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+                                /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
                                     if (it) {
                                         Log.d(TAG, "TCP.发送消息完成")
                                     } else {
                                         Log.e(TAG, "TCP.发送消息失败")
                                         HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                     }
-                                }
+                                }*/
                             }
                         }
                     }
@@ -165,7 +215,36 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                         binding.eliEventResponse.setOnClickListener {
                             loadingDialog.show()
                             val tcpModel = OtherUtil.SOSCancel(Constants.deviceId, itemData.fromDeviceId, itemData.id)
-                            NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
+                            val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    //操作成功,更新事件列表界面
+                                    updateEventItem(itemData)
+
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            tcpModel.data = Gson().toJson(itemData)
+                                            EventBus.getDefault().post(MessageEvent(tcpModel, 999))
+
+                                            showMessage("操作成功")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                    val callbackString = jsonObject.getString(CALLBACK)
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            showMessage("Failed: $callbackString")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+                            /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
                                 if (it) {
                                     Log.d(TAG, "TCP.发送消息完成")
                                     tcpModel.data = Gson().toJson(itemData)
@@ -176,7 +255,7 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
                                     HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                 }
                                 loadingDialog.dismiss()
-                            }
+                            }*/
                         }
                     }
                 }
@@ -222,4 +301,15 @@ class NewEventItemAdapter(var data:ArrayList<InteractionVO>, val activity: Activ
         }
     }
 
+    private fun updateEventItem(responseInteractionVO: InteractionVO) {
+        val iterator = Constants.eventList.iterator()
+        while (iterator.hasNext()) {
+            val it = iterator.next()
+            if (it.id == responseInteractionVO.id) {
+                iterator.remove()
+            }
+        }
+
+        EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
+    }
 }

+ 51 - 15
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemAdapter.kt

@@ -1,5 +1,6 @@
 package com.wdkl.ncs.android.component.home.adapter
 
+import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
@@ -8,6 +9,7 @@ import android.view.View
 import android.view.ViewGroup
 import com.alibaba.android.vlayout.LayoutHelper
 import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.google.common.base.Strings
@@ -17,21 +19,21 @@ import com.wdkl.ncs.android.component.home.activity.VoiceMsgActivity
 import com.wdkl.ncs.android.component.home.databinding.TakeoverItemBinding
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig
 import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
 import com.wdkl.ncs.android.lib.base.BaseApplication
 import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
 import com.wdkl.ncs.android.lib.utils.showMessage
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import com.wdkl.ncs.android.middleware.utils.StringUtil
 
-class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val context: Context) : BaseDelegateAdapter<BaseRecyclerViewHolder<TakeoverItemBinding>, JsonObject>(){
+class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val activity: Activity) : BaseDelegateAdapter<BaseRecyclerViewHolder<TakeoverItemBinding>, JsonObject>(){
     val TAG = "TakeoverItemAdapter"
 
     private lateinit var loadingDialog: LoadingDialog
@@ -50,7 +52,7 @@ class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val context: Context)
 
     override fun onCreateLayoutHelper(): LayoutHelper {
         Log.i(TAG,data.toString())
-        loadingDialog = CommonTool.createLoadingDialog(context, R.layout.custom_loading,R.id.loadding_image)
+        loadingDialog = CommonTool.createLoadingDialog(activity, R.layout.custom_loading,R.id.loadding_image)
         return LinearLayoutHelper(0,data.size)
     }
 
@@ -78,18 +80,41 @@ class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val context: Context)
                         StringUtil.getResString(R.string.device_change_check),
                         StringUtil.getResString(R.string.str_cancel),
                         StringUtil.getResString(R.string.str_confirm),
-                        context,object : CommonTool.DialogInterface{
+                        activity, object : CommonTool.DialogInterface{
                             override fun yes() {
                                 showMessage(R.string.device_change_tips)
-                                var tcpModel = DeviceUtil.deviceChange(Constants.deviceId, itemData.get("id").asInt)
-                                NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
+                                val tcpModel = DeviceUtil.deviceChange(Constants.deviceId, itemData.get("id").asInt)
+                                val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                    override fun onSuccess(jsonObject: JSONObject) {
+                                        if (activity != null) {
+                                            activity.runOnUiThread {
+                                                showMessage("操作成功")
+                                                loadingDialog.dismiss()
+                                            }
+                                        }
+                                    }
+
+                                    override fun onFailed(jsonObject: JSONObject) {
+                                        // 这里写发送失败的方法
+                                        val callbackString = jsonObject.getString(CALLBACK)
+                                        if (activity != null) {
+                                            activity.runOnUiThread {
+                                                showMessage("Failed: $callbackString")
+                                                loadingDialog.dismiss()
+                                            }
+                                        }
+                                    }
+                                }
+                                TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+                                /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
                                     if (it) {
                                         Log.d(TAG, "TCP.发送消息完成")
                                     } else {
                                         Log.e(TAG, "TCP.发送消息失败")
                                         HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                     }
-                                }
+                                }*/
                             }
                             override fun no() {
                             }
@@ -104,19 +129,30 @@ class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val context: Context)
                         try {
                             val number = itemData.get("phone_number")
                             val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:" + number.asString))
-                            context.startActivity(intent)
+                            activity.startActivity(intent)
                             //Constants.phoneState = Constants.PHONE_OUTGOING
 
                             //发送tcp
                             val tcpModel = PhoneUtil.phoneCall(Constants.deviceId, itemData.get("id").asInt)
-                            NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe { res: Boolean ->
+                            val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    //
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(tcpModel, true, transaction)
+
+                            /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe { res: Boolean ->
                                 if (res) {
                                     Log.d(TAG, "TCP.发送消息完成")
                                 } else {
                                     Log.e(TAG, "TCP.发送消息失败")
                                     HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                 }
-                            }
+                            }*/
                         } catch (e: Exception) {
                             showMessage(R.string.call_phone_failed)
                         }
@@ -129,22 +165,22 @@ class TakeoverItemAdapter(var data:ArrayList<JsonObject>, val context: Context)
                     } else {
                         //网络电话
                         val tcpModel = VoiceUtil.voiceCall(Constants.deviceId, itemData.get("id").asInt)
-                        val intent = Intent(context, CallSingleActivity::class.java)
+                        val intent = Intent(activity, CallSingleActivity::class.java)
                         intent.putExtra(CallSingleActivity.EXTRA_ROOM_ID, Constants.sipId)
                         intent.putExtra(CallSingleActivity.EXTRA_MO, true)
                         intent.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY, true)
                         intent.putExtra(CallSingleActivity.EXTRA_TCPMODEL, tcpModel);
                         intent.putExtra(CallSingleActivity.EXTRA_SHOWNAME, itemData.get("clerk_name").asString)
                         //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                        context.startActivity(intent)
+                        activity.startActivity(intent)
                     }
                 }
 
                 binding.tiVoiceRecorder.visibility = View.VISIBLE
                 binding.tiVoiceRecorder.setOnClickListener{
-                    var intent = Intent(context, VoiceMsgActivity::class.java)
+                    var intent = Intent(activity, VoiceMsgActivity::class.java)
                     intent.putExtra(VoiceMsgActivity.TO_DEVICE_ID,itemData.get("id").asInt)
-                    context.startActivity(intent)
+                    activity.startActivity(intent)
                 }
             }
         }

+ 54 - 15
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/TakeoverItemSearchAdapter.kt

@@ -1,5 +1,6 @@
 package com.wdkl.ncs.android.component.home.adapter
 
+import android.app.Activity
 import android.content.Context
 import android.content.Intent
 import android.net.Uri
@@ -11,7 +12,9 @@ import android.widget.Button
 import android.widget.ImageView
 import android.widget.TextView
 import androidx.recyclerview.widget.RecyclerView
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.utils.base.tool.CommonTool
+import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.google.common.base.Strings
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.activity.VoiceMsgActivity
@@ -19,20 +22,21 @@ import com.wdkl.ncs.android.component.home.entity.ContactItemEntity
 import com.wdkl.ncs.android.component.home.search.FuzzySearchBaseAdapter
 import com.wdkl.ncs.android.component.home.search.IFuzzySearchRule
 import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.common.Constants
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import com.wdkl.ncs.android.middleware.utils.StringUtil
 
 class TakeoverItemSearchAdapter : FuzzySearchBaseAdapter<ContactItemEntity, TakeoverItemSearchAdapter.ItemHolder> {
     val TAG = "TakeoverItem"
 
-    lateinit var context: Context
+    lateinit var activity: Activity
+    private lateinit var loadingDialog: LoadingDialog
 
     constructor() : super(null)
 
@@ -40,12 +44,13 @@ class TakeoverItemSearchAdapter : FuzzySearchBaseAdapter<ContactItemEntity, Take
 
     constructor(data: ArrayList<ContactItemEntity>) : super(null, data)
 
-    constructor(rule: IFuzzySearchRule?, data: ArrayList<ContactItemEntity>, context: Context) : super(rule, data) {
-        this.context = context
+    constructor(rule: IFuzzySearchRule?, data: ArrayList<ContactItemEntity>, activity: Activity) : super(rule, data) {
+        this.activity = activity
     }
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemHolder {
         val view = LayoutInflater.from(parent.getContext()).inflate(R.layout.takeover_item, parent, false)
+        loadingDialog = CommonTool.createLoadingDialog(activity, R.layout.custom_loading,R.id.loadding_image)
         return ItemHolder(view)
     }
 
@@ -68,18 +73,41 @@ class TakeoverItemSearchAdapter : FuzzySearchBaseAdapter<ContactItemEntity, Take
                     StringUtil.getResString(R.string.device_change_check),
                     StringUtil.getResString(R.string.str_cancel),
                     StringUtil.getResString(R.string.str_confirm),
-                    context,object : CommonTool.DialogInterface{
+                    activity, object : CommonTool.DialogInterface{
                         override fun yes() {
                             showMessage(R.string.device_change_tips)
                             val tcpModel = DeviceUtil.deviceChange(Constants.deviceId, itemData.id)
-                            NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
+                            val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            showMessage("Success")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                    val callbackString = jsonObject.getString(CALLBACK)
+                                    if (activity != null) {
+                                        activity.runOnUiThread {
+                                            showMessage("Failed: $callbackString")
+                                            loadingDialog.dismiss()
+                                        }
+                                    }
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(tcpModel, false, transaction)
+
+                            /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe {
                                 if (it) {
                                     Log.d(TAG, "TCP.发送消息完成")
                                 } else {
                                     Log.e(TAG, "TCP.发送消息失败")
                                     HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                 }
-                            }
+                            }*/
                         }
                         override fun no() {
                         }
@@ -94,19 +122,30 @@ class TakeoverItemSearchAdapter : FuzzySearchBaseAdapter<ContactItemEntity, Take
                     try {
                         val number = itemData.number
                         val intent = Intent(Intent.ACTION_CALL, Uri.parse("tel:$number"))
-                        context.startActivity(intent)
+                        activity.startActivity(intent)
                         //Constants.phoneState = Constants.PHONE_OUTGOING
 
                         //发送tcp
                         val tcpModel = PhoneUtil.phoneCall(Constants.deviceId, itemData.id)
-                        NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe { res: Boolean ->
+                        val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                            override fun onSuccess(jsonObject: JSONObject) {
+                                //
+                            }
+
+                            override fun onFailed(jsonObject: JSONObject) {
+                                // 这里写发送失败的方法
+                            }
+                        }
+                        TcpClient.getInstance().sendTcp(tcpModel, true, transaction)
+
+                        /*NettyClient.instance.sendMsg(tcpModel.toJson()).subscribe { res: Boolean ->
                             if (res) {
                                 Log.d(TAG, "TCP.发送消息完成")
                             } else {
                                 Log.e(TAG, "TCP.发送消息失败")
                                 HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                             }
-                        }
+                        }*/
                     } catch (e: Exception) {
                         showMessage(R.string.call_phone_failed)
                     }
@@ -119,22 +158,22 @@ class TakeoverItemSearchAdapter : FuzzySearchBaseAdapter<ContactItemEntity, Take
                 } else {
                     //网络电话
                     val tcpModel = VoiceUtil.voiceCall(Constants.deviceId, itemData.id)
-                    val intent = Intent(context, CallSingleActivity::class.java)
+                    val intent = Intent(activity, CallSingleActivity::class.java)
                     intent.putExtra(CallSingleActivity.EXTRA_ROOM_ID, Constants.sipId)
                     intent.putExtra(CallSingleActivity.EXTRA_MO, true)
                     intent.putExtra(CallSingleActivity.EXTRA_AUDIO_ONLY, true)
                     intent.putExtra(CallSingleActivity.EXTRA_TCPMODEL, tcpModel);
                     intent.putExtra(CallSingleActivity.EXTRA_SHOWNAME, itemData.value)
                     //intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                    context.startActivity(intent)
+                    activity.startActivity(intent)
                 }
             }
 
             p0.tiVoiceRecorder.visibility = View.VISIBLE
             p0.tiVoiceRecorder.setOnClickListener{
-                val intent = Intent(context, VoiceMsgActivity::class.java)
+                val intent = Intent(activity, VoiceMsgActivity::class.java)
                 intent.putExtra(VoiceMsgActivity.TO_DEVICE_ID,itemData.id)
-                context.startActivity(intent)
+                activity.startActivity(intent)
             }
         }
     }

+ 16 - 4
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/adapter/WatchContactsItemAdapter.kt

@@ -8,22 +8,23 @@ import android.view.ViewGroup
 import androidx.recyclerview.widget.RecyclerView
 import com.alibaba.android.vlayout.LayoutHelper
 import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.alibaba.fastjson.JSONObject
 import com.enation.javashop.utils.base.tool.CommonTool
 import com.enation.javashop.utils.base.widget.LoadingDialog
 import com.wdkl.ncs.android.component.home.R
 import com.wdkl.ncs.android.component.home.activity.VoiceMsgActivity
 import com.wdkl.ncs.android.component.home.databinding.AdapterWatchContactsItemBinding
 import com.wdkl.ncs.android.component.home.ui.CallSingleActivity
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect
 import com.wdkl.ncs.android.middleware.common.Constants
 import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
 import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
 import com.wdkl.ncs.android.lib.utils.showMessage
 import com.wdkl.ncs.android.middleware.model.vo.WatchContactsVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback
 import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 
 class WatchContactsItemAdapter(val data:ArrayList<WatchContactsVO>, val context: Context) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterWatchContactsItemBinding>, WatchContactsVO>(){
@@ -89,7 +90,18 @@ class WatchContactsItemAdapter(val data:ArrayList<WatchContactsVO>, val context:
 
                             //发送tcp
                             val tcpModel = PhoneUtil.phoneCall(Constants.deviceId, itemData.deviceId)
-                            NettyClient.instance.sendMsg(tcpModel.toJson())
+                            val transaction: TcpCallback = object : TcpCallback(tcpModel.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    //
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(tcpModel, true, transaction)
+
+                            /*NettyClient.instance.sendMsg(tcpModel.toJson())
                                 .subscribe { res: Boolean ->
                                     if (res) {
                                         Log.d(TAG, "TCP.发送消息完成")
@@ -97,7 +109,7 @@ class WatchContactsItemAdapter(val data:ArrayList<WatchContactsVO>, val context:
                                         Log.e(TAG, "TCP.发送消息失败")
                                         HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                                     }
-                                }
+                                }*/
                         } else {
                             showMessage(R.string.call_phone_failed)
                         }

+ 5 - 1
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/FloatingService.java

@@ -23,6 +23,7 @@ import com.wdkl.ncs.android.component.home.ui.CallSingleActivity;
 import com.wdkl.ncs.android.component.home.util.ActivityStackUtil;
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper;
 import com.wdkl.ncs.android.component.home.util.RingPlayHelper;
+import com.wdkl.ncs.android.component.home.util.SpeechUtil;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.lib.vo.MessageEvent;
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
@@ -203,6 +204,7 @@ public class FloatingService extends Service {
                 if (curInteractionId == Constants.Companion.getInteractionId()) {
                     MediaPlayHelper.getInstance().stopMusic(true);
                     RingPlayHelper.stopRingTone();
+                    SpeechUtil.getInstance().stopSpeak();
                     Log.i(TAG, "对方接听电话啦");
                     //对方接听电话,恢复到call界面
                     resumeCallActivity();
@@ -235,8 +237,10 @@ public class FloatingService extends Service {
                         callSingleActivity.finish();
                     }
                 }
-            } else if (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
+            } else if (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL || tcpModel.getAction() == TcpAction.VoiceAction.VOICE_OFF) {
                 if (curInteractionId == Constants.Companion.getInteractionId()) {
+                    RingPlayHelper.stopRingTone();
+                    SpeechUtil.getInstance().stopSpeak();
                     CallSingleActivity callSingleActivity = ActivityStackUtil.getCallSingleActivity();
                     if (callSingleActivity != null) {
                         callSingleActivity.finish();

+ 33 - 6
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/PhoneStateReceiver.java

@@ -6,15 +6,16 @@ import android.content.Intent;
 import android.telephony.TelephonyManager;
 import android.util.Log;
 
+import com.alibaba.fastjson.JSONObject;
 import com.wdkl.ncs.android.component.home.R;
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect;
 import com.wdkl.ncs.android.component.home.util.PhoneCallUtil;
 import com.wdkl.ncs.android.component.home.util.RecordHelper;
 import com.wdkl.ncs.android.lib.vo.MessageEvent;
 import com.wdkl.ncs.android.middleware.common.Constants;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel;
 import com.wdkl.ncs.android.middleware.tcp.channel.PhoneUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 
 import org.greenrobot.eventbus.EventBus;
@@ -45,14 +46,27 @@ public class PhoneStateReceiver extends BroadcastReceiver {
                     //发送tcp
                     if (Constants.Companion.getPhoneDataVO() != null) {
                         TcpModel tcpModel = PhoneUtil.phoneHandoff(Constants.Companion.getDeviceId(), Constants.Companion.getPhoneDataVO());
-                        NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
+                        TcpCallback transaction = new TcpCallback(tcpModel.getTid()) {
+                            @Override
+                            public void onSuccess(JSONObject jsonObject) {
+                                //
+                            }
+
+                            @Override
+                            public void onFailed(JSONObject jsonObject) {
+                                //
+                            }
+                        };
+                        TcpClient.getInstance().sendTcp(tcpModel, true, transaction);
+
+                        /*NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
                             if (it) {
                                 Log.d(TAG, "TCP.发送消息完成");
                             } else {
                                 Log.e(TAG, "TCP.发送消息失败");
                                 HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
                             }
-                        });
+                        });*/
                     }
                 }
                 DeviceChannel.calling = false;
@@ -88,14 +102,27 @@ public class PhoneStateReceiver extends BroadcastReceiver {
                     //发送tcp
                     if (Constants.Companion.getPhoneDataVO() != null) {
                         TcpModel tcpModel = PhoneUtil.phoneAccept(Constants.Companion.getDeviceId(), Constants.Companion.getPhoneDataVO());
-                        NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
+                        TcpCallback transaction = new TcpCallback(tcpModel.getTid()) {
+                            @Override
+                            public void onSuccess(JSONObject jsonObject) {
+                                //
+                            }
+
+                            @Override
+                            public void onFailed(JSONObject jsonObject) {
+                                //
+                            }
+                        };
+                        TcpClient.getInstance().sendTcp(tcpModel, true, transaction);
+
+                        /*NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
                             if (it) {
                                 Log.d(TAG, "TCP.发送消息完成");
                             } else {
                                 Log.e(TAG, "TCP.发送消息失败");
                                 HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
                             }
-                        });
+                        });*/
                     }
                 } else if (Constants.Companion.getPhoneState() == Constants.PHONE_IDLE) {
                     Constants.Companion.setPhoneState(Constants.PHONE_OUTGOING);

+ 139 - 52
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/service/WdKeepAliveService.kt

@@ -35,11 +35,13 @@ import com.wdkl.ncs.android.middleware.model.dos.ChannelImDO
 import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
 import com.wdkl.ncs.android.middleware.model.vo.WatchContactVO
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 import com.wdkl.ncs.android.middleware.tcp.channel.ChannelImUtil
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel
 import com.wdkl.ncs.android.middleware.tcp.channel.ImUtil
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.CommunicationEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
@@ -100,7 +102,8 @@ class WdKeepAliveService : AbsWorkService() {
             while (TextUtils.isEmpty(Constants.tcpServer)) {
                 Thread.sleep(1000)
             }
-            HandleTcpConnect.instance.tcpInitConnect()
+            //HandleTcpConnect.instance.tcpInitConnect()
+            TcpClient.getInstance().init(Constants.tcpServer, Constants.tcpPort, Constants.heartBeat)
             instanceCreated = true
         }.start()
 
@@ -353,11 +356,12 @@ class WdKeepAliveService : AbsWorkService() {
                         EventBus.getDefault().post(MessageEvent(tcpModel, 1))
                     }
                 } else if (tcpModel.getAction() == TcpAction.VoiceAction.ACCEPT //我方呼出,对方接受
-                        || tcpModel.getAction() == TcpAction.VoiceAction.REJECT //我方呼出,对方拒绝
-                        || tcpModel.getAction() == TcpAction.VoiceAction.CALLING //我方呼出,对方通话中
-                        || tcpModel.getAction() == TcpAction.VoiceAction.HANDOFF
-                        || tcpModel.getAction() == TcpAction.VoiceAction.FAILED //我方呼出,对方不在线,设备离线或其它错误
-                        || tcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
+                    || tcpModel.getAction() == TcpAction.VoiceAction.REJECT //我方呼出,对方拒绝
+                    || tcpModel.getAction() == TcpAction.VoiceAction.CALLING //我方呼出,对方通话中
+                    || tcpModel.getAction() == TcpAction.VoiceAction.HANDOFF
+                    || tcpModel.getAction() == TcpAction.VoiceAction.FAILED //我方呼出,对方不在线,设备离线或其它错误
+                    || tcpModel.getAction() == TcpAction.VoiceAction.CANCEL
+                    || tcpModel.getAction() == TcpAction.VoiceAction.VOICE_OFF) {
                     EventBus.getDefault().post(MessageEvent(tcpModel, 2))
                 }
             }
@@ -402,22 +406,29 @@ class WdKeepAliveService : AbsWorkService() {
                             }).start()
                         } else {
                             Util.wakeUpAndUnlock()
-                            EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_EVENT))
+                            EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
                         }
                     } else {
                         val interaction = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
                         playVoiceMsg(interaction)
                         val msgTcpModel = ImUtil.imRead(Constants.deviceId, interaction.fromDeviceId, interaction.id)
-                        NettyClient.instance.sendMsg(msgTcpModel.toJson()).subscribe {
+                        TcpClient.getInstance().sendTcp(msgTcpModel, false, null)
+
+                        /*NettyClient.instance.sendMsg(msgTcpModel.toJson()).subscribe {
                             if (it) {
                                 Log.d(TAG, "TCP.发送消息完成")
                             } else {
                                 Log.e(TAG, "TCP.发送消息失败")
                                 HandleTcpConnect.instance.tcpReConnectWithMsgShow()
                             }
-                        }
+                        }*/
                     }
                 } else if (tcpModel.action == TcpAction.EventAction.KEY_CLICK) { // 收到新事件
+                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                    if(Constants.eventList.contains(interactionVO)){ //断线重连会重新发送未处理的事件,所以如果当前事件列表中有重复事件,不需要添加
+                        return
+                    }
+
                     //取消掉语音留言录音
                     RecordHelper.getInstance().stopCancelRecordByOther(true)
 
@@ -426,7 +437,6 @@ class WdKeepAliveService : AbsWorkService() {
                     //震动提醒
                     handleVibrator()
 
-                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
                     if (Constants.oldEvent) {
                         Constants.eventList.clear()
                     }
@@ -449,7 +459,7 @@ class WdKeepAliveService : AbsWorkService() {
                             startActivity(intent)
                         }).start()
                     } else {
-                        EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_EVENT))
+                        EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
                     }
                 } else if (tcpModel.action == TcpAction.EventAction.CANCEL || tcpModel.action == TcpAction.EventAction.COMPLETED) { // 收到事件取消 或事件完成
                     //语音播报处理
@@ -467,12 +477,12 @@ class WdKeepAliveService : AbsWorkService() {
                     }
 
                     if (mNewEventListActive) {
-                        EventBus.getDefault().post(MessageEvent(tcpModel, Constants.EVENT_UPDATE_EVENT))
+                        EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
                     }
                 }
             }
 
-            4 -> { //更新通讯录,更新通话白名单列表
+            Constants.EVENT_DATA_REFRESH -> { //更新通讯录,更新通话白名单列表
                 Thread{
                     try {
                         var jsonStr = ""
@@ -517,33 +527,60 @@ class WdKeepAliveService : AbsWorkService() {
             999 -> {
                 Util.wakeUpAndUnlock()
                 val sosTcpModel = messageEvent.getMessage() as TcpModel
-                val sosInteractionVO = Gson().fromJson(sosTcpModel.data.toString(), InteractionVO::class.java)
-                if (sosTcpModel.action === TcpAction.SOSAction.CANCEL) {
-                    //先停止铃声或其他音频播放
-                    SpeechUtil.getInstance().stopSpeak()
-                    MediaPlayHelper.getInstance().stopMusic(true)
-                    RingPlayHelper.stopRingTone()
+                if (sosTcpModel.action == TcpAction.SOSAction.CANCELED) {
+                    //紧急呼叫处理完成
+                    if (mNewEventListActive) {
+                        //先停止铃声或其他音频播放
+                        SpeechUtil.getInstance().stopSpeak()
+                        MediaPlayHelper.getInstance().stopMusic(true)
+                        RingPlayHelper.stopRingTone()
 
-                    if (mVibrator != null) {
-                        mVibrator.cancel()
+                        if (mVibrator != null) {
+                            mVibrator.cancel()
+                        }
                     }
 
-                    if (!Strings.isNullOrEmpty(sosInteractionVO.toRoleName)) {
-                        showMessage(sosInteractionVO.toRoleName + " " + sosInteractionVO.toMemberName + " " + StringUtil.getResString(R.string.event_responded))
-                    } else {
-                        showMessage(R.string.event_responded)
+                    Log.e(TAG, sosTcpModel.data.toString())
+                    val interactionId =  sosTcpModel.data.toString().toInt()
+                    val iterator = Constants.eventList.iterator()
+                    while (iterator.hasNext()) {
+                        val it = iterator.next()
+                        if (it.id == interactionId) {
+                            iterator.remove()
+                        }
                     }
+                    EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
 
-                    var iterator = Constants.eventList.iterator()
+                } else if (sosTcpModel.action == TcpAction.SOSAction.CANCEL) {
+                    val sosInteractionVO = Gson().fromJson(sosTcpModel.data.toString(), InteractionVO::class.java)
+                    if (mNewEventListActive) {
+                        //先停止铃声或其他音频播放
+                        SpeechUtil.getInstance().stopSpeak()
+                        MediaPlayHelper.getInstance().stopMusic(true)
+                        RingPlayHelper.stopRingTone()
+
+                        if (mVibrator != null) {
+                            mVibrator.cancel()
+                        }
+
+                        if (!Strings.isNullOrEmpty(sosInteractionVO.toRoleName)) {
+                            showMessage(sosInteractionVO.toRoleName + " " + sosInteractionVO.toMemberName + " 已响应")
+                        } else {
+                            showMessage("已响应")
+                        }
+                    }
+
+                    val iterator = Constants.eventList.iterator()
                     while (iterator.hasNext()) {
                         val it = iterator.next()
                         if (it.id == sosInteractionVO.id) {
-                            Constants.eventList.remove(it)
+                            iterator.remove()
                         }
                     }
-                    EventBus.getDefault().post(MessageEvent(sosTcpModel, Constants.EVENT_UPDATE_EVENT))
+                    EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
 
-                } else if (sosTcpModel.action == TcpAction.SOSAction.CALL || sosTcpModel.action == TcpAction.SOSAction.ROOM_CALL) {
+                } else if (sosTcpModel.action === TcpAction.SOSAction.CALL || sosTcpModel.action == TcpAction.SOSAction.ROOM_CALL) {
+                    val sosInteractionVO = Gson().fromJson(sosTcpModel.data.toString(), InteractionVO::class.java)
                     //取消掉语音留言录音
                     RecordHelper.getInstance().stopCancelRecordByOther(true)
 
@@ -573,7 +610,7 @@ class WdKeepAliveService : AbsWorkService() {
                             }
                         }.start()
                     } else {
-                        EventBus.getDefault().post(MessageEvent(sosTcpModel, Constants.EVENT_UPDATE_EVENT))
+                        EventBus.getDefault().post(MessageEvent("update_event", Constants.EVENT_UPDATE_EVENT))
                     }
                 }
             }
@@ -606,6 +643,12 @@ class WdKeepAliveService : AbsWorkService() {
                 }).start()
             }
 
+            Constants.EVENT_RESTART_APP -> {
+                //app重启
+                Util.wakeUpAndUnlock()
+                AppUtils.restartApp()
+            }
+
             //系统设置
             Constants.EVENT_DEVICE_SETTING -> {
                 Thread(Runnable {
@@ -618,14 +661,32 @@ class WdKeepAliveService : AbsWorkService() {
                     }.blockingSingle()
 
                     Log.i(TAG, "收到系统设置 " + jsonStr)
-                    if (partSettingDO != null && partSettingDO.transferDuration != null && partSettingDO.transferDurationLeader != null) {
-                        if (Constants.userRoleName != null) {
-                            if (!Constants.userRoleName!!.contains("护士组长") && Constants.userRoleName!!.contains("护士")) {
-                                SettingConfig.setCountdownTime(application, partSettingDO.transferDuration)
-                            } else if (Constants.userRoleName!!.contains("护士组长")) {
-                                SettingConfig.setCountdownTime(application, partSettingDO.transferDurationLeader)
+                    if (partSettingDO != null) {
+                        if (partSettingDO.transferDuration != null && partSettingDO.transferDurationLeader != null) {
+                            if (Constants.userRoleName != null) {
+                                if (!Constants.userRoleName!!.contains("护士组长") && Constants.userRoleName!!.contains("护士")) {
+                                    SettingConfig.setCountdownTime(application, partSettingDO.transferDuration)
+                                } else if (Constants.userRoleName!!.contains("护士组长")) {
+                                    SettingConfig.setCountdownTime(application, partSettingDO.transferDurationLeader)
+                                }
+                            }
+                        }
+
+                        //设置通话方式
+                        if (partSettingDO.communicationModeMobile != null) {
+                            Constants.phoneType = partSettingDO.communicationModeMobile
+                            if (Constants.phoneType == CommunicationEnum.MOBILE_PHONE.value()) {
+                                SettingConfig.setVoiceCallType(BaseApplication.appContext, SettingConfig.PHONE_CALL)
+                            } else {
+                                SettingConfig.setVoiceCallType(BaseApplication.appContext, SettingConfig.SIP_CALL)
                             }
                         }
+                        if (partSettingDO.communicationModeBed != null) {
+                            Constants.bedPhoneType = partSettingDO.communicationModeBed
+                        }
+                        if (partSettingDO.communicationModeNurse != null) {
+                            Constants.nursePhoneType = partSettingDO.communicationModeNurse
+                        }
                     }
                 }).start()
             }
@@ -741,11 +802,14 @@ class WdKeepAliveService : AbsWorkService() {
                     interactionVO.data + StringUtil.getResString(R.string.str_event_cancel)
 
             if (Constants.ttsState == 2) {
-                SpeechUtil.getInstance().newSpeech(eventStr, false)
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    SpeechUtil.getInstance().newSpeech(eventStr, false)
+                } else {
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
+                }
             } else {
                 AppTool.Time.delay(500) {
-                    //MediaPlayHelper.getInstance().playResMusic(R.raw.new_event, 1.0f, false)
-                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.new_event, false)
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
                 }
             }
         } else if (model.type == TcpType.EVENT && model.action == TcpAction.EventAction.COMPLETED) { //事件完成
@@ -753,11 +817,28 @@ class WdKeepAliveService : AbsWorkService() {
                     interactionVO.data + StringUtil.getResString(R.string.str_event_done)
 
             if (Constants.ttsState == 2) {
-                SpeechUtil.getInstance().newSpeech(eventStr, false)
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    SpeechUtil.getInstance().newSpeech(eventStr, false)
+                } else {
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
+                }
             } else {
                 AppTool.Time.delay(500) {
-                    //MediaPlayHelper.getInstance().playResMusic(R.raw.new_event, 1.0f, false)
-                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.new_event, false)
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
+                }
+            }
+        } else if(model.type==TcpType.EVENT && model.action==TcpAction.EventAction.RESPONSED){
+            val eventStr = Util.appendSpace(interactionVO.fromFrameFullName.replace("-", ",")) + ", " + interactionVO.data + "事件已由"+interactionVO.actionEndMemberName+"响应"
+
+            if (Constants.ttsState == 2) {
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    SpeechUtil.getInstance().newSpeech(eventStr, false)
+                } else {
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
+                }
+            } else {
+                AppTool.Time.delay(500) {
+                    RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.event, false)
                 }
             }
         }
@@ -787,14 +868,16 @@ class WdKeepAliveService : AbsWorkService() {
     @SuppressLint("CheckResult")
     private fun sendChannelImRead(channelIm: ChannelImDO) {
         val imTcpModel = ChannelImUtil.channelImRead(Constants.deviceId, channelIm)
-        NettyClient.instance.sendMsg(imTcpModel.toJson()).subscribe {
+        TcpClient.getInstance().sendTcp(imTcpModel, false, null)
+
+        /*NettyClient.instance.sendMsg(imTcpModel.toJson()).subscribe {
             if (it) {
                 Log.d(TAG, "TCP.发送消息完成")
             } else {
                 Log.e(TAG, "TCP.发送消息失败")
                 HandleTcpConnect.instance.tcpReConnectWithMsgShow()
             }
-        }
+        }*/
     }
 
     private fun initSpeech() {
@@ -850,16 +933,20 @@ class WdKeepAliveService : AbsWorkService() {
 
     fun reConnect() {
         if (NetHelper.getInstance().getNetworkState(this@WdKeepAliveService) != NetHelper.NETWORK_NONE) {
-            if (!NettyClient.instance.isConnect()) {
+            /*if (!NettyClient.instance.isConnect()) {
                 Log.w(TAG, "TCP.进入重新连接")
                 HandleTcpConnect.instance.tcpReConnect()
+            }*/
+
+            if (!TcpClientHandler.getConnected()) {
+                TcpClient.getInstance().doConnect()
             }
-        } else {
+        } /*else {
             Thread(Runnable {
                 Thread.sleep(5000)
                 reConnect()
             }).start()
-        }
+        }*/
     }
 
 
@@ -895,11 +982,11 @@ class WdKeepAliveService : AbsWorkService() {
                                     //通话中或者某些特定界面不响应耳机按键留言,未绑定用户时也不响应按键
                                     else if (!DeviceChannel.calling && Constants.allowVoiceMsg && !TextUtils.isEmpty(Constants.userName)) {
                                         if (SettingConfig.getImChannel(BaseApplication.appContext) == SettingConfig.IM_CHANNEL_ON) {
-                                            if (Constants.channelId == -1) {
-                                                showMessage(R.string.str_im_no_channel)
-                                            } else {
+                                            //if (Constants.channelId == -1) {
+                                            //    showMessage(R.string.str_im_no_channel)
+                                            //} else {
                                                 RecordHelper.getInstance().execRecordVoiceMsg()
-                                            }
+                                            //}
                                         } else {
                                             showMessage(R.string.str_im_no_media_button)
                                         }

+ 1 - 1
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/settingconfig/SettingConfig.java

@@ -14,7 +14,7 @@ public class SettingConfig {
     //电话功能类型
     private static final String KEY_SP_VOICE_CALL_TYPE = "KEY_SP_VOICE_CALL_TYPE";
     public static final int SIP_CALL = 1;  //网络电话
-    public static final int VOICE_CALL = 2;  //普通电话
+    public static final int PHONE_CALL = 2;  //普通电话
 
     private static final String KEY_SP_EVENT_FORWARD = "KEY_SP_EVENT_FORWARD";
     public static final int EVENT_FORWARD_ON = 1;

+ 40 - 11
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/CallSingleActivity.java

@@ -25,6 +25,7 @@ import android.widget.Toast;
 import androidx.appcompat.app.AppCompatActivity;
 import androidx.fragment.app.FragmentManager;
 
+import com.alibaba.fastjson.JSONObject;
 import com.enation.javashop.utils.base.tool.CommonTool;
 import com.enation.javashop.utils.base.widget.LoadingDialog;
 import com.google.gson.Gson;
@@ -32,18 +33,19 @@ import com.wdkl.ncs.android.component.home.R;
 import com.wdkl.ncs.android.component.home.service.FloatingService;
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig;
 import com.wdkl.ncs.android.component.home.util.ActivityStackUtil;
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect;
 import com.wdkl.ncs.android.component.home.util.HomeWatcher;
 import com.wdkl.ncs.android.component.home.util.LocaleMangerUtils;
 import com.wdkl.ncs.android.component.home.util.LogUpload;
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper;
 import com.wdkl.ncs.android.component.home.util.RecordHelper;
 import com.wdkl.ncs.android.component.home.util.RingPlayHelper;
+import com.wdkl.ncs.android.component.home.util.SpeechUtil;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel;
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
@@ -275,9 +277,9 @@ public class CallSingleActivity extends AppCompatActivity {
             //RingPlayHelper.playRingTone(this, R.raw.incoming_call, true);
             long[] pattern = new long[]{100L, 2000L, 1000L, 2000L, 1000L, 2000L};
             if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
-                mVibrator.vibrate(VibrationEffect.createWaveform(pattern, 0));
+                mVibrator.vibrate(VibrationEffect.createWaveform(pattern, -1));
             } else {
-                mVibrator.vibrate(pattern, 0);
+                mVibrator.vibrate(pattern, -1);
             }
         }
 
@@ -355,16 +357,29 @@ public class CallSingleActivity extends AppCompatActivity {
                 } else {
                     toId = interactionVO.getFromDeviceId();
                 }
-                TcpModel voiceUtilTcpModel = VoiceUtil.voiceHandoff(Constants.Companion.getDeviceId(), toId, interactionVO.getId());
 
-                NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
+                TcpModel voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                TcpCallback transaction = new TcpCallback(voiceUtilTcpModel.getTid()) {
+                    @Override
+                    public void onSuccess(JSONObject jsonObject) {
+                        //
+                    }
+
+                    @Override
+                    public void onFailed(JSONObject jsonObject) {
+                        //
+                    }
+                };
+                TcpClient.getInstance().sendTcp(voiceUtilTcpModel, false, transaction);
+
+                /*NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
                     if (it) {
                         Log.d(TAG, "TCP.发送消息完成");
                     } else {
                         Log.e(TAG, "TCP.发送消息失败");
                         HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
                     }
-                });
+                });*/
             } else if (recTcpModel.getAction() == TcpAction.VoiceAction.CALL) {
                 int toId;
                 if (interactionVO==null){
@@ -378,18 +393,31 @@ public class CallSingleActivity extends AppCompatActivity {
                 }
                 TcpModel voiceUtilTcpModel;
                 if (interactionVO == null){
-                    voiceUtilTcpModel = VoiceUtil.voiceCancel(Constants.Companion.getDeviceId(),recTcpModel.getToId());
+                    voiceUtilTcpModel = VoiceUtil.voiceCancel(recTcpModel.getTid(), Constants.Companion.getDeviceId(),recTcpModel.getToId(), null);
                 } else {
-                    voiceUtilTcpModel = VoiceUtil.voiceHandoff(Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+                    voiceUtilTcpModel = VoiceUtil.voiceHandoff(recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
                 }
-                NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
+                TcpCallback transaction = new TcpCallback(voiceUtilTcpModel.getTid()) {
+                    @Override
+                    public void onSuccess(JSONObject jsonObject) {
+                        //
+                    }
+
+                    @Override
+                    public void onFailed(JSONObject jsonObject) {
+                        //
+                    }
+                };
+                TcpClient.getInstance().sendTcp(voiceUtilTcpModel, false, transaction);
+
+                /*NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it-> {
                     if (it) {
                         Log.d(TAG, "TCP.发送消息完成");
                     } else {
                         Log.e(TAG, "TCP.发送消息失败");
                         HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
                     }
-                });
+                });*/
             }
         }
     }
@@ -438,6 +466,7 @@ public class CallSingleActivity extends AppCompatActivity {
         Log.d(TAG, "call activity destroyed");
         MediaPlayHelper.getInstance().stopMusic(true);
         RingPlayHelper.stopRingTone();
+        SpeechUtil.getInstance().stopSpeak();
         if (mHomeWatcher != null) {
             mHomeWatcher.stopWatch();
         }

+ 85 - 6
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/FragmentAudio.java

@@ -13,18 +13,23 @@ import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 
+import com.alibaba.fastjson.JSONObject;
 import com.blankj.utilcode.util.BarUtils;
 import com.enation.javashop.utils.base.tool.CommonTool;
 import com.google.gson.Gson;
 import com.wdkl.ncs.android.component.home.R;
 import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig;
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect;
+import com.wdkl.ncs.android.component.home.util.LocaleMangerUtils;
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper;
 import com.wdkl.ncs.android.component.home.util.RingPlayHelper;
+import com.wdkl.ncs.android.component.home.util.SpeechUtil;
+import com.wdkl.ncs.android.component.home.util.Util;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
 import com.wdkl.ncs.android.middleware.tcp.channel.VoiceUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.utils.StringUtil;
 import com.wdkl.rtc.entity.Publisher;
@@ -33,6 +38,8 @@ import com.wdkl.rtc.rtc.WebRTCEngine;
 import com.wdkl.rtc.util.EnumType;
 import com.wdkl.rtc.util.OSUtils;
 
+import java.util.Locale;
+
 /**
  * 语音通话控制界面
  */
@@ -108,6 +115,20 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
                 descTextView.setText(getShowName() + "\n" + StringUtil.getResString(R.string.call_incoming));
                 outgoingActionContainer.setVisibility(View.GONE);
                 incomingActionContainer.setVisibility(View.VISIBLE);
+
+                if (interactionVO != null) {
+                    String language = LocaleMangerUtils.getApplicationLocale().getLanguage();
+                    String frameName;
+                    if (Locale.CHINESE.getLanguage().equals(language)) {
+                        frameName = Util.INSTANCE.appendSpace(interactionVO.getFromFrameFullName().replace("-", ""));
+                    } else {
+                        frameName = interactionVO.getFromFrameFullName().replace("-", "");
+                    }
+
+                    String text = frameName + getString(R.string.call_incoming) + frameName + getString(R.string.call_incoming)
+                            + frameName + getString(R.string.call_incoming) + frameName + getString(R.string.call_incoming);
+                    SpeechUtil.getInstance().newSpeech(text, false);
+                }
             }
         }
     }
@@ -201,6 +222,7 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
 
         MediaPlayHelper.getInstance().stopMusic(true);
         RingPlayHelper.stopRingTone();
+        SpeechUtil.getInstance().stopSpeak();
 
         runOnUiThread(() -> {
             //callSingleActivity.loadingDialog.dismiss();
@@ -269,6 +291,7 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
         //callSingleActivity.loadingDialog.show();
         MediaPlayHelper.getInstance().stopMusic(true);
         RingPlayHelper.stopRingTone();
+        SpeechUtil.getInstance().stopSpeak();
 
         //给服务器发送转接 tcp
         InteractionVO interactionVO = new Gson().fromJson(callSingleActivity.recTcpModel.getData().toString(), InteractionVO.class);
@@ -278,7 +301,39 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
         } else {
             toId = interactionVO.getFromDeviceId();
         }
-        TcpModel voiceTransferTcpModel = VoiceUtil.voiceTransfer(Constants.Companion.getDeviceId(), toId, interactionVO);
+
+        TcpModel voiceTransferTcpModel = VoiceUtil.voiceTransfer(callSingleActivity.recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+        /*TcpCallback transaction = new TcpCallback(voiceTransferTcpModel.getTid()) {
+            @Override
+            public void onSuccess(JSONObject jsonObject) {
+                if (callSingleActivity != null) {
+                    callSingleActivity.runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            ExtendMethodsKt.showMessage("转接成功");
+                        }
+                    });
+                }
+                handler.sendEmptyMessageDelayed(FINISH_CURRENT, 500);
+            }
+
+            @Override
+            public void onFailed(JSONObject jsonObject) {
+                if (callSingleActivity != null) {
+                    callSingleActivity.runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            ExtendMethodsKt.showMessage("转接失败");
+                        }
+                    });
+                }
+            }
+        };*/
+        TcpClient.getInstance().sendTcp(voiceTransferTcpModel, false, null);
+
+        handler.sendEmptyMessageDelayed(FINISH_CURRENT, 500);
+
+        /*TcpModel voiceTransferTcpModel = VoiceUtil.voiceTransfer(Constants.Companion.getDeviceId(), toId, interactionVO);
         NettyClient.Companion.getInstance().sendMsg(voiceTransferTcpModel.toJson()).subscribe(it-> {
             if (it) {
                 Log.d(TAG, "TCP.发送消息完成");
@@ -287,7 +342,7 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
                 Log.e(TAG, "TCP.发送消息失败");
                 HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
             }
-        });
+        });*/
     }
 
     public void acceptCall(){
@@ -302,6 +357,7 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
             callSingleActivity.mVibrator.cancel();
             MediaPlayHelper.getInstance().stopMusic(true);
             RingPlayHelper.stopRingTone();
+            SpeechUtil.getInstance().stopSpeak();
             //发出accept
             InteractionVO interactionVO = new Gson().fromJson(callSingleActivity.recTcpModel.getData().toString(), InteractionVO.class);
             int toId;
@@ -310,7 +366,30 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
             } else {
                 toId = interactionVO.getFromDeviceId();
             }
-            TcpModel voiceUtilTcpModel = VoiceUtil.voiceAccept(Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+
+            TcpModel voiceUtilTcpModel = VoiceUtil.voiceAccept(callSingleActivity.recTcpModel.getTid(), Constants.Companion.getDeviceId(), toId, interactionVO.getId());
+            TcpCallback transaction = new TcpCallback(voiceUtilTcpModel.getTid()) {
+                @Override
+                public void onSuccess(JSONObject jsonObject) {
+                    //
+                }
+
+                @Override
+                public void onFailed(JSONObject jsonObject) {
+                    if (callSingleActivity != null) {
+                        callSingleActivity.runOnUiThread(new Runnable() {
+                            @Override
+                            public void run() {
+                                ExtendMethodsKt.showMessage("Failed");
+                                //callSingleActivity.loadingDialog.dismiss();
+                            }
+                        });
+                    }
+                }
+            };
+            TcpClient.getInstance().sendTcp(voiceUtilTcpModel, false, transaction);
+
+            /*TcpModel voiceUtilTcpModel = VoiceUtil.voiceAccept(Constants.Companion.getDeviceId(), toId, interactionVO.getId());
             NettyClient.Companion.getInstance().sendMsg(voiceUtilTcpModel.toJson()).subscribe(it->{
                 if (it) {
                     Log.d(TAG, "TCP.发送消息完成");
@@ -319,7 +398,7 @@ public class FragmentAudio extends SingleCallFragment implements View.OnClickLis
                     //callSingleActivity.loadingDialog.dismiss();
                     HandleTcpConnect.Companion.getInstance().tcpReConnectWithMsgShow();
                 }
-            });
+            });*/
 
             transHandler.sendEmptyMessageDelayed(CHECK, 6000);
         }

+ 33 - 13
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/ui/SingleCallFragment.java

@@ -25,15 +25,18 @@ import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
 
+import com.alibaba.fastjson.JSONObject;
 import com.google.gson.Gson;
-import com.wdkl.ncs.android.component.home.util.HandleTcpConnect;
 import com.wdkl.ncs.android.component.home.util.MediaPlayHelper;
 import com.wdkl.ncs.android.component.home.util.RingPlayHelper;
+import com.wdkl.ncs.android.component.home.util.SpeechUtil;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.lib.base.BaseApplication;
 import com.wdkl.ncs.android.lib.vo.MessageEvent;
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.rtc.janus.JanusClient;
@@ -200,7 +203,28 @@ public abstract class SingleCallFragment extends Fragment {
     @SuppressLint("CheckResult")
     private void startOutCall() {
         //发送tcp call
-        NettyClient.Companion.getInstance().sendMsg(callSingleActivity.recTcpModel.toJson()).subscribe(it -> {
+        TcpCallback transaction = new TcpCallback(callSingleActivity.recTcpModel.getTid()) {
+            @Override
+            public void onSuccess(JSONObject jsonObject) {
+                //
+            }
+
+            @Override
+            public void onFailed(JSONObject jsonObject) {
+                if (callSingleActivity != null) {
+                    callSingleActivity.runOnUiThread(new Runnable() {
+                        @Override
+                        public void run() {
+                            ExtendMethodsKt.showMessage("Failed");
+                        }
+                    });
+                    callSingleActivity.finish();
+                }
+            }
+        };
+        TcpClient.getInstance().sendTcp(callSingleActivity.recTcpModel, false, transaction);
+
+        /*NettyClient.Companion.getInstance().sendMsg(callSingleActivity.recTcpModel.toJson()).subscribe(it -> {
             if (it) {
                 Log.d(TAG, "TCP.发送消息完成");
             } else {
@@ -210,7 +234,7 @@ public abstract class SingleCallFragment extends Fragment {
                     callSingleActivity.finish();
                 }
             }
-        });
+        });*/
     }
 
     public void callOutSuccess(TcpModel tcpModel) {
@@ -417,14 +441,8 @@ public abstract class SingleCallFragment extends Fragment {
                     }
                 });
             }
-//            runOnUiThread(new Runnable() {
-//                @Override
-//                public void run() {
-//                    Toast.makeText(SingleCallFragment.this.getContext(),"对方挂断",Toast.LENGTH_SHORT).show();
-//                }
-//            });
-
-            //handler.sendEmptyMessageDelayed(FINISH_CURRENT, 1);
+
+            handler.sendEmptyMessageDelayed(FINISH_CURRENT, 1);
         } else if (code == JanusClient.CALLBACK_ROOM_ERROR) {
             runOnUiThread(new Runnable() {
                 @Override
@@ -438,6 +456,7 @@ public abstract class SingleCallFragment extends Fragment {
             //通话连接建立,停止铃声
             MediaPlayHelper.getInstance().stopMusic(true);
             RingPlayHelper.stopRingTone();
+            SpeechUtil.getInstance().stopSpeak();
             didChangeState(EnumType.CallState.Connected);
         } else if (code == JanusClient.CALLBACK_CONNECTED_TIMEOUT) {
             runOnUiThread(new Runnable() {
@@ -509,6 +528,7 @@ public abstract class SingleCallFragment extends Fragment {
                 if (curInteractionId == Constants.Companion.getInteractionId()) {
                     MediaPlayHelper.getInstance().stopMusic(true);
                     RingPlayHelper.stopRingTone();
+                    SpeechUtil.getInstance().stopSpeak();
                     callSingleActivity.recTcpModel = tcpModel;
                     Log.d(TAG, "voice#success =>" + callSingleActivity.recTcpModel.toJson());
                     Log.i(TAG, "对方接听电话啦");
@@ -557,7 +577,7 @@ public abstract class SingleCallFragment extends Fragment {
                         }
                     });
                 //}
-            } else if (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL) {
+            } else if (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL || tcpModel.getAction() == TcpAction.VoiceAction.VOICE_OFF) {
                 if (curInteractionId == Constants.Companion.getInteractionId()) {
                     handler.sendEmptyMessageDelayed(FINISH_CURRENT, 100);
                     runOnUiThread(new Runnable() {

android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt → android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/HandleTcpConnect.kt.bak


+ 12 - 4
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/NetWorkChangeReceiver.kt

@@ -8,8 +8,8 @@ import android.net.Network
 import android.net.NetworkInfo
 import android.os.Build
 import android.util.Log
-import com.wdkl.ncs.android.component.home.service.WdKeepAliveService
-import com.wdkl.ncs.android.middleware.tcp.NettyClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler
 
 class NetWorkChangeReceiver : BroadcastReceiver() {
     val TAG = NetWorkChangeReceiver::class.simpleName
@@ -34,9 +34,13 @@ class NetWorkChangeReceiver : BroadcastReceiver() {
             // 判断网络是否链接
             if (null != networkInfo && networkInfo.isConnected) {
                 //当前网络已经链接
-                if (!NettyClient.instance.isConnect() && WdKeepAliveService.instanceCreated){
+                /*if (!NettyClient.instance.isConnect() && WdKeepAliveService.instanceCreated){
                     Log.w(TAG,"TCP.进入重新连接")
                     HandleTcpConnect.instance.tcpReConnect()
+                }*/
+
+                if (!TcpClientHandler.getConnected()) {
+                    TcpClient.getInstance().doConnect()
                 }
             }
             // 判断网络是否正在链接
@@ -63,8 +67,12 @@ class NetWorkChangeReceiver : BroadcastReceiver() {
             if ((wifiNetworkInfo!=null && wifiNetworkInfo.isConnected) || (dataNetworkInfo!=null&&dataNetworkInfo.isConnected)) {
                 //WIFI已连接 或 移动数据已连接
                 Log.w(TAG,"TCP.进入重新连接")
-                if (!NettyClient.instance.isConnect()){
+                /*if (!NettyClient.instance.isConnect()){
                     HandleTcpConnect.instance.tcpReConnect()
+                }*/
+
+                if (!TcpClientHandler.getConnected()) {
+                    TcpClient.getInstance().doConnect()
                 }
             }
         }

+ 48 - 27
android_mobile/src/main/yd_w_qin2_2/code/com/wdkl/ncs/android/component/home/util/RecordHelper.java

@@ -14,21 +14,18 @@ import android.util.Log;
 
 import androidx.annotation.NonNull;
 
+import com.alibaba.fastjson.JSONObject;
 import com.wdkl.ncs.android.component.home.R;
 import com.wdkl.ncs.android.component.home.helper.HttpHelper;
-import com.wdkl.ncs.android.component.home.service.WdKeepAliveService;
-import com.wdkl.ncs.android.component.home.settingconfig.SettingConfig;
 import com.wdkl.ncs.android.lib.base.BaseApplication;
-import com.wdkl.ncs.android.lib.vo.MessageEvent;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.api.UrlManager;
 import com.wdkl.ncs.android.middleware.model.dos.ChannelImDO;
-import com.wdkl.ncs.android.middleware.tcp.NettyClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClient;
+import com.wdkl.ncs.android.middleware.tcp.TcpClientHandler;
 import com.wdkl.ncs.android.middleware.tcp.channel.ChannelImUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
-import com.wdkl.rtc.rtc.AudioFocusManager;
-
-import org.greenrobot.eventbus.EventBus;
 
 import java.io.File;
 import java.io.IOException;
@@ -162,23 +159,31 @@ public class RecordHelper {
         //连续点击2次开始留言
         long curTime = System.currentTimeMillis();
         if (!recordRunning && curTime - clickTime > 200 && curTime - clickTime < 1500 && curTime - pressDownTime > 3500 && curTime - pressUpTime > 2500) {
-            showMessage(R.string.str_voice_msg_start);
-            //先停止其他语音或铃声
-            RingPlayHelper.stopRingTone();
-            SpeechUtil.getInstance().stopSpeak();
-            MediaPlayHelper.getInstance().stopMusic(true);
-            //EventBus.getDefault().post(new MessageEvent(false, Constants.EVENT_CLEAR_IM));
-            //播放提示
-            if (Locale.CHINESE.getLanguage().equals(language)) {
-                SoundPoolManager.getInstance().playSound(2);
+            if (Constants.Companion.getChannelId() == -1) {
+                SoundPoolManager.getInstance().playSound(6);
+                showMessage(R.string.str_im_no_channel);
+            } else if (!TcpClientHandler.getConnected()) {
+                SoundPoolManager.getInstance().playSound(6);
+                showMessage(R.string.tcp_connect_failed);
             } else {
-                SoundPoolManager.getInstance().playSound(7);
+                showMessage(R.string.str_voice_msg_start);
+                //先停止其他语音或铃声
+                RingPlayHelper.stopRingTone();
+                SpeechUtil.getInstance().stopSpeak();
+                MediaPlayHelper.getInstance().stopMusic(true);
+                //EventBus.getDefault().post(new MessageEvent(false, Constants.EVENT_CLEAR_IM));
+                //播放提示
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    SoundPoolManager.getInstance().playSound(2);
+                } else {
+                    SoundPoolManager.getInstance().playSound(7);
+                }
+                recordRunning = true;
+                pressDownTime = curTime;
+                handler.removeCallbacksAndMessages(null);
+                handler.postDelayed(this::startRecord, 1200);
+                handler.sendEmptyMessageDelayed(1024, 45000);
             }
-            recordRunning = true;
-            pressDownTime = curTime;
-            handler.removeCallbacksAndMessages(null);
-            handler.postDelayed(this::startRecord, 1200);
-            handler.sendEmptyMessageDelayed(1024, 45000);
         } else {
             if (recordRunning) {
                 pressUpTime = curTime;
@@ -289,15 +294,31 @@ public class RecordHelper {
                 retry = 0;
                 //上传完成后删除本地文件
                 deleteAudioFile(file);
-                if (Locale.CHINESE.getLanguage().equals(language)) {
-                    SoundPoolManager.getInstance().playSound(3);
-                }
                 ChannelImDO channelImDO = new ChannelImDO();
                 channelImDO.setChannelId(Constants.Companion.getChannelId());
                 channelImDO.setSenderMemberId(Constants.Companion.getMemberId());
                 channelImDO.setAudioPath(data);
                 TcpModel tcpModel = ChannelImUtil.channelImMsg(Constants.Companion.getDeviceId(), channelImDO);
-                NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
+                TcpCallback transaction = new TcpCallback(tcpModel.getTid()) {
+                    @Override
+                    public void onSuccess(JSONObject jsonObject) {
+                        if (Locale.CHINESE.getLanguage().equals(language)) {
+                            SoundPoolManager.getInstance().playSound(3);
+                        }
+                        showMessage(R.string.str_voice_msg_send_success);
+                    }
+
+                    @Override
+                    public void onFailed(JSONObject jsonObject) {
+                        // 这里写发送失败的方法
+                        SoundPoolManager.getInstance().playSound(6);
+                        String callbackString = jsonObject.getString(CALLBACK);
+                        showMessage(R.string.str_voice_msg_send_fail + callbackString);
+                    }
+                };
+                TcpClient.getInstance().sendTcp(tcpModel, false, transaction);
+
+                /*NettyClient.Companion.getInstance().sendMsg(tcpModel.toJson()).subscribe(it -> {
                     handler.post(() -> {
                         if (it) {
                             showMessage(R.string.str_voice_msg_send_success);
@@ -305,7 +326,7 @@ public class RecordHelper {
                             showMessage(R.string.str_voice_msg_send_fail);
                         }
                     });
-                });
+                });*/
             }
         });
     }

+ 1 - 1
build.gradle

@@ -40,7 +40,7 @@ buildscript {
      * YD-S5-W_QIN2PRO-2: 多亲手机
      * ...
      */
-    ext.app_device_type = "yd_w_xiaomi_2"
+    ext.app_device_type = "yd_s5_w_qin2_2"
 
     if (app_device_type == "yd_s5_w_qin2_2") {
         /**

+ 3 - 2
janus/src/main/java/com/wdkl/rtc/janus/JanusClient.java

@@ -497,7 +497,7 @@ public class JanusClient implements WebSocketChannel.WebSocketCallback {
                     if (data.has("error")) {
                         if (data.getInt("error_code") == 427) {
                             //拨打
-                            if (EnumType.CallState.Outgoing == callState) {
+                            /*if (EnumType.CallState.Outgoing == callState) {
                                 destroyRoom(handleId, new DestroyRoomCallback() {
                                     @Override
                                     public void onSuccess() {
@@ -513,7 +513,8 @@ public class JanusClient implements WebSocketChannel.WebSocketCallback {
                             //接收
                             else if (EnumType.CallState.Incoming == callState) {
                                 janusCallback.onCreateRoom(handleId);
-                            }
+                            }*/
+                            janusCallback.onCreateRoom(handleId);
                         } else {
                             janusCallback.onError(ERROR_CREATE_ROOM,"创建房间失败");
                         }

+ 2 - 0
middleware/build.gradle

@@ -78,4 +78,6 @@ dependencies {
     implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
 
     //implementation 'com.github.tiann:FreeReflection:3.1.0'
+
+    compile 'org.mongodb:bson:3.6.3'
 }

+ 11 - 11
middleware/src/main/code/com/wdkl/ncs/android/middleware/common/Constants.kt

@@ -21,7 +21,7 @@ class Constants {
         var userRoleName: String? = "" //当前用户的角色
         var tcpServer: String = ""
         var tcpPort: Int = 5080   //tcp端口
-        var heartBeat: Int = 29    //tcp心跳
+        var heartBeat: Int = 40    //tcp心跳
         var ttsState: Int = 0
         var channelId: Int = -1  //频道id
 
@@ -67,20 +67,13 @@ class Constants {
 
         const val SYSTEM_REGISTERED = "SYSTEM_REGISTERED"
 
-        const val EVENT_BATTERY_PERCENT = 0x07 //电量
         var EVENT_BATTERY_ALARM = true
 
+        const val EVENT_BATTERY_PERCENT = 0x07 //电量
+        const val EVENT_RESTART_APP = 0x08
         const val EVENT_UNTREATED_QUANTITY = 0x10 //未处理数量
-
-        const val EVENT_TCP_BREAK = 0x15 //tcp掉线
-        const val EVENT_TCP_CONNECTED = 0x115 //tcp上线
-
-        const val EVENT_SOS_POLL = 0x55
-        const val EVENT_RTC_STATE = 0x66
-        const val EVENT_USER_CHANGE = 0x77
-        const val EVENT_DEVICE_CHANGE = 0x88 //切换设备
-        const val EVENT_DEVICE_SETTING = 0x99
         const val EVENT_APP_UPDATE  = 0x13 //app更新
+        const val EVENT_TCP_BREAK = 0x15 //tcp掉线
         const val EVENT_BLUETOOTH_ACCEPT_CALL = 0x44 //断网
         const val EVENT_UPDATE_EVENT = 0x45
         const val EVENT_IM_PLAY_DONE = 0x46
@@ -91,5 +84,12 @@ class Constants {
         const val EVENT_SERVER_CHANGE = 0x51
         const val EVENT_DATA_REFRESH = 0x52
         const val EVENT_CALL_END = 0x53
+        const val EVENT_SOS_POLL = 0x55
+        const val EVENT_RTC_STATE = 0x66
+        const val EVENT_USER_CHANGE = 0x77
+        const val EVENT_DEVICE_CHANGE = 0x88 //切换设备
+        const val EVENT_DEVICE_SETTING = 0x99
+
+        const val EVENT_TCP_CONNECTED = 0x115 //tcp上线
     }
 }

+ 587 - 30
middleware/src/main/code/com/wdkl/ncs/android/middleware/model/dos/InteractionDO.java

@@ -1,13 +1,17 @@
 package com.wdkl.ncs.android.middleware.model.dos;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
 import com.fasterxml.jackson.databind.annotation.JsonNaming;
+import com.google.common.base.Strings;
 import com.wdkl.ncs.android.middleware.model.annotation.Column;
 import com.wdkl.ncs.android.middleware.model.annotation.Id;
 import com.wdkl.ncs.android.middleware.model.annotation.PrimaryKeyField;
 import com.wdkl.ncs.android.middleware.model.annotation.Table;
 
 import java.io.Serializable;
+import java.util.ArrayList;
 
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -43,6 +47,12 @@ public class InteractionDO implements Serializable {
     @ApiModelProperty(value = "科室Id", required = false)
     private Integer partId;
     /**
+     * 科室名称
+     */
+    @Column(name = "part_name")
+    @ApiModelProperty(value = "科室名称", required = false)
+    private String partName;
+    /**
      * 交互类型(1:语音通话,2:视频通话,3:卫生间紧急呼叫,4:语音留言,5:文本消息,6:按键事件)
      */
     @Column(name = "action_type")
@@ -54,6 +64,8 @@ public class InteractionDO implements Serializable {
     @Column(name = "action_result")
     @ApiModelProperty(value = "0失败,1成功", required = false)
     private Integer actionResult;
+
+
     /**
      * 交互发起设备Id
      */
@@ -61,23 +73,63 @@ public class InteractionDO implements Serializable {
     @ApiModelProperty(value = "交互发起设备Id", required = false)
     private Integer fromDeviceId;
     /**
-     * 交互对象设备Id
+     * null
      */
-    @Column(name = "to_device_id")
-    @ApiModelProperty(value = "交互对象设备Id", required = false)
-    private Integer toDeviceId;
+    @Column(name = "from_eth_mac")
+    @ApiModelProperty(value = "发起端设备的有线以太网卡MAC地址", required = false)
+    private String fromEthMac;
+
+    @Column(name = "from_eth_ip")
+    @ApiModelProperty(value = "发起端设备的有线以太网卡分配的IP地址", required = false)
+    private String fromEthIp;
+    /**
+     * null
+     */
+    @Column(name = "from_sip_id")
+    @ApiModelProperty(value = "发起端设备的SIP账号", required = false)
+    private String fromSipId;
+    /**
+     * null
+     */
+    @Column(name = "from_device_type")
+    @ApiModelProperty(value = "发起端设备的设备类型", required = false)
+    private Integer fromDeviceType;
+
+    @Column(name = "from_device_name")
+    @ApiModelProperty(value = "发起端设备的名称", required = false)
+    private String fromDeviceName;
+    /**
+     * null
+     */
+    @Column(name = "from_device_phone_number")
+    @ApiModelProperty(value = "发起端设备号码", required = false)
+    private String fromDevicePhoneNumber;
     /**
      * 发起设备所在空间结构
      */
     @Column(name = "from_device_frame_id")
     @ApiModelProperty(value = "发起设备所在空间结构", required = false)
     private Integer fromDeviceFrameId;
+
+    @Column(name = "from_frame_type")
+    @ApiModelProperty(value = "发起端空间结构类型:0楼、1病房、2床位", required = false)
+    private Integer fromFrameType;
     /**
-     * 交互对象所在空间结果
+     * null
      */
-    @Column(name = "to_device_frame_id")
-    @ApiModelProperty(value = "交互对象所在空间结果", required = false)
-    private Integer toDeviceFrameId;
+    @Column(name = "from_frame_name")
+    @ApiModelProperty(value = "发起端空间结构名称", required = false)
+    private String fromFrameName;
+    /**
+     * null
+     */
+    @Column(name = "from_frame_full_name")
+    @ApiModelProperty(value = "发起端空间结构全名", required = false)
+    private String fromFrameFullName;
+
+    @Column(name = "from_frame_parent_id")
+    @ApiModelProperty(value = "发起端空间父级id", required = false)
+    private Integer fromFrameParentId;
     /**
      * 交互发起设备使用者member_id
      */
@@ -85,11 +137,132 @@ public class InteractionDO implements Serializable {
     @ApiModelProperty(value = "交互发起设备使用者member_id", required = false)
     private Integer fromDeviceMemberId;
     /**
+     * 用户
+     **/
+    @Column(name = "from_customer_id")
+    @ApiModelProperty(value = "发起端用户CustomId", required = false)
+    private Integer fromCustomerId;
+    /**
+     * null
+     */
+    @Column(name = "from_member_name")
+    @ApiModelProperty(value = "发起端用户姓名", required = false)
+    private String fromMemberName;
+    /**
+     * null
+     */
+    @Column(name = "from_member_face")
+    @ApiModelProperty(value = "发起端用户头像", required = false)
+    private String fromMemberFace;
+
+    @Column(name = "from_clerk_id")
+    @ApiModelProperty(value = "发起端用户成员Id,发起端为护士主机,腕表,医生机时才有", required = false)
+    private Integer fromClerkId;
+    /**
+     * null
+     */
+    @Column(name = "from_role_name")
+    @ApiModelProperty(value = "发起端用户角色名(医生、护士、护工)", required = false)
+    private String fromRoleName;
+
+
+    /**
+     * 交互对象设备Id
+     */
+    @Column(name = "to_device_id")
+    @ApiModelProperty(value = "交互对象设备Id", required = false)
+    private Integer toDeviceId;
+    /**
+     * null
+     */
+    @Column(name = "to_eth_mac")
+    @ApiModelProperty(value = "目的端设备的有线以太网卡MAC地址", required = false)
+    private String toEthMac;
+
+    @Column(name = "to_eth_ip")
+    @ApiModelProperty(value = "目的端设备的有线以太网卡分配的IP地址", required = false)
+    private String toEthIp;
+    /**
+     * null
+     */
+    @Column(name = "to_sip_id")
+    @ApiModelProperty(value = "目的端设备的SIP账号", required = false)
+    private String toSipId;
+    /**
+     * null
+     */
+    @Column(name = "to_device_type")
+    @ApiModelProperty(value = "目的端设备的设备类型", required = false)
+    private Integer toDeviceType;
+
+    @Column(name = "to_device_name")
+    @ApiModelProperty(value = "目的端设备的名称", required = false)
+    private String toDeviceName;
+    /**
+     * null
+     */
+    @Column(name = "to_device_phone_number")
+    @ApiModelProperty(value = "目的端设备号码", required = false)
+    private String toDevicePhoneNumber;
+    /**
+     * 交互对象所在空间结果
+     */
+    @Column(name = "to_device_frame_id")
+    @ApiModelProperty(value = "交互对象所在空间结果", required = false)
+    private Integer toDeviceFrameId;
+
+    @Column(name = "to_frame_type")
+    @ApiModelProperty(value = "目的端空间结构类型:0楼、1病房、2床位", required = false)
+    private Integer toFrameType;
+    /**
+     * null
+     */
+    @Column(name = "to_frame_name")
+    @ApiModelProperty(value = "目的端空间结构名称", required = false)
+    private String toFrameName;
+    /**
+     * null
+     */
+    @Column(name = "to_frame_full_name")
+    @ApiModelProperty(value = "目的端空间结构全名", required = false)
+    private String toFrameFullName;
+
+    @Column(name = "to_frame_parent_id")
+    @ApiModelProperty(value = "目的端空间父级id", required = false)
+    private Integer toFrameParentId;
+    /**
      * 交互对象设备使用者member_id
      */
     @Column(name = "to_device_member_id")
     @ApiModelProperty(value = "交互对象设备使用者member_id", required = false)
     private Integer toDeviceMemberId;
+
+    @Column(name = "to_customer_id")
+    @ApiModelProperty(value = "目的端用户CustomId", required = false)
+    private Integer toCustomerId;
+
+    /**
+     * null
+     */
+    @Column(name = "to_member_name")
+    @ApiModelProperty(value = "目的端用户姓名", required = false)
+    private String toMemberName;
+    /**
+     * null
+     */
+    @Column(name = "to_member_face")
+    @ApiModelProperty(value = "目的端用户头像", required = false)
+    private String toMemberFace;
+
+    @Column(name = "to_clerk_id")
+    @ApiModelProperty(value = "目的端用户成员Id,目的端为护士主机,腕表,医生机时才有", required = false)
+    private Integer toClerkId;
+    /**
+     * null
+     */
+    @Column(name = "to_role_name")
+    @ApiModelProperty(value = "目的端用户角色名(医生、护士、护工)", required = false)
+    private String toRoleName;
     /**
      * 是否为呼叫系统内部交互(如果是外部电话呼叫为true,否则为false)
      */
@@ -133,6 +306,24 @@ public class InteractionDO implements Serializable {
     @ApiModelProperty(value = "交互结束时间(通话时指通话挂断时间,通话挂断后要更新此字段)。事件响应时间、语音已读时间", required = false)
     private Long actionEnd;
     /**
+     * 交互处理者的member_id
+     */
+    @Column(name = "action_end_member_id")
+    @ApiModelProperty(value = "交互处理者的member_id", required = false)
+    private Integer actionEndMemberId;
+    /**
+     * null
+     */
+    @Column(name = "action_end_member_name")
+    @ApiModelProperty(value = "交互处理者的用户姓名", required = false)
+    private String actionEndMemberName;
+    /**
+     * 交互完成时间
+     */
+    @Column(name = "action_completed")
+    @ApiModelProperty(value = "交互完成时间", required = false)
+    private Long actionCompleted;
+    /**
      * 交互数据(类型1,2,3为空)(类型4为音频文件地址)(5为文本内容)(类型6为具体按键类型)
      */
     @Column(name = "data")
@@ -152,9 +343,51 @@ public class InteractionDO implements Serializable {
     private String errorMessage;
 
     @Column(name = "action_direction_type")
-    @ApiModelProperty(value = "交互方向类型(1:分机到主机、腕表、医生机,2:主机、腕表、医生机到分机,3主机、腕表、医生机之间互通,4:分机到分机)",required = false)
+    @ApiModelProperty(value = "交互方向类型(1:分机到主机、腕表、医生机,2:主机、腕表、医生机到分机,3主机、腕表、医生机之间互通,4:分机到分机)", required = false)
     private Integer actionDirectionType;
 
+    @Column(name = "action_status")
+    @ApiModelProperty(value = "事件类型的交互状态(包括:发出,响应,取消,完成)", required = false)
+    private String actionStatus;
+    /**
+     * null
+     */
+    @Column(name = "relative_id")
+    @ApiModelProperty(value = "亲属id,外部来电时,from_member亲属的memberId", required = false)
+    private Integer relativeId;
+    /**
+     * null
+     */
+    @Column(name = "relative_name")
+    @ApiModelProperty(value = "外部来电时,from_member亲属关系", required = false)
+    private String relativeName;
+
+
+    /**
+     *交互接收者的顺序,一个JS数组,一个交互可能同时给同一角色的多个用户,用JS数组可以个分多个层级
+     */
+    @Column(name = "spread_member_path")
+    @ApiModelProperty(value = "交互接收者的顺序", required = false)
+    private String spreadMemberPath;
+
+
+    /**
+     *交互接收的memberId,用逗号隔开,可以不考虑顺序,方便查询用户交互记录,把spread_member_path字段打散后用逗号连接
+     */
+    @Column(name = "spread_member_ids")
+    @ApiModelProperty(value = "交互接收的memberId,", required = false)
+    private String spreadMemberIds;
+
+
+    /**
+     *交互已触达的memberIds,交互被多人接收后,有任意一人处理,需要通知其他已触达的用户取消处理
+     */
+    @Column(name = "reached_member_ids")
+    @ApiModelProperty(value = "交互已触达的memberIds", required = false)
+    private String reachedMemberIds;
+
+    private ArrayList<Integer[]> spreadMemberPathArray;
+
 
     @PrimaryKeyField
     public Integer getId() {
@@ -165,7 +398,6 @@ public class InteractionDO implements Serializable {
         this.id = id;
     }
 
-
     public String getUnionId() {
         return unionId;
     }
@@ -174,7 +406,6 @@ public class InteractionDO implements Serializable {
         this.unionId = unionId;
     }
 
-
     public Long getCreateDate() {
         return createDate;
     }
@@ -183,7 +414,6 @@ public class InteractionDO implements Serializable {
         this.createDate = createDate;
     }
 
-
     public Integer getPartId() {
         return partId;
     }
@@ -192,6 +422,13 @@ public class InteractionDO implements Serializable {
         this.partId = partId;
     }
 
+    public String getPartName() {
+        return partName;
+    }
+
+    public void setPartName(String partName) {
+        this.partName = partName;
+    }
 
     public String getActionType() {
         return actionType;
@@ -201,7 +438,6 @@ public class InteractionDO implements Serializable {
         this.actionType = actionType;
     }
 
-
     public Integer getActionResult() {
         return actionResult;
     }
@@ -210,7 +446,6 @@ public class InteractionDO implements Serializable {
         this.actionResult = actionResult;
     }
 
-
     public Integer getFromDeviceId() {
         return fromDeviceId;
     }
@@ -219,15 +454,53 @@ public class InteractionDO implements Serializable {
         this.fromDeviceId = fromDeviceId;
     }
 
+    public String getFromEthMac() {
+        return fromEthMac;
+    }
 
-    public Integer getToDeviceId() {
-        return toDeviceId;
+    public void setFromEthMac(String fromEthMac) {
+        this.fromEthMac = fromEthMac;
     }
 
-    public void setToDeviceId(Integer toDeviceId) {
-        this.toDeviceId = toDeviceId;
+    public String getFromEthIp() {
+        return fromEthIp;
+    }
+
+    public void setFromEthIp(String fromEthIp) {
+        this.fromEthIp = fromEthIp;
+    }
+
+    public String getFromSipId() {
+        return fromSipId;
+    }
+
+    public void setFromSipId(String fromSipId) {
+        this.fromSipId = fromSipId;
     }
 
+    public Integer getFromDeviceType() {
+        return fromDeviceType;
+    }
+
+    public void setFromDeviceType(Integer fromDeviceType) {
+        this.fromDeviceType = fromDeviceType;
+    }
+
+    public String getFromDeviceName() {
+        return fromDeviceName;
+    }
+
+    public void setFromDeviceName(String fromDeviceName) {
+        this.fromDeviceName = fromDeviceName;
+    }
+
+    public String getFromDevicePhoneNumber() {
+        return fromDevicePhoneNumber;
+    }
+
+    public void setFromDevicePhoneNumber(String fromDevicePhoneNumber) {
+        this.fromDevicePhoneNumber = fromDevicePhoneNumber;
+    }
 
     public Integer getFromDeviceFrameId() {
         return fromDeviceFrameId;
@@ -237,15 +510,37 @@ public class InteractionDO implements Serializable {
         this.fromDeviceFrameId = fromDeviceFrameId;
     }
 
+    public Integer getFromFrameType() {
+        return fromFrameType;
+    }
 
-    public Integer getToDeviceFrameId() {
-        return toDeviceFrameId;
+    public void setFromFrameType(Integer fromFrameType) {
+        this.fromFrameType = fromFrameType;
     }
 
-    public void setToDeviceFrameId(Integer toDeviceFrameId) {
-        this.toDeviceFrameId = toDeviceFrameId;
+    public String getFromFrameName() {
+        return fromFrameName;
     }
 
+    public void setFromFrameName(String fromFrameName) {
+        this.fromFrameName = fromFrameName;
+    }
+
+    public String getFromFrameFullName() {
+        return fromFrameFullName;
+    }
+
+    public void setFromFrameFullName(String fromFrameFullName) {
+        this.fromFrameFullName = fromFrameFullName;
+    }
+
+    public Integer getFromFrameParentId() {
+        return fromFrameParentId;
+    }
+
+    public void setFromFrameParentId(Integer fromFrameParentId) {
+        this.fromFrameParentId = fromFrameParentId;
+    }
 
     public Integer getFromDeviceMemberId() {
         return fromDeviceMemberId;
@@ -255,6 +550,141 @@ public class InteractionDO implements Serializable {
         this.fromDeviceMemberId = fromDeviceMemberId;
     }
 
+    public Integer getFromCustomerId() {
+        return fromCustomerId;
+    }
+
+    public void setFromCustomerId(Integer fromCustomerId) {
+        this.fromCustomerId = fromCustomerId;
+    }
+
+    public String getFromMemberName() {
+        return fromMemberName;
+    }
+
+    public void setFromMemberName(String fromMemberName) {
+        this.fromMemberName = fromMemberName;
+    }
+
+    public String getFromMemberFace() {
+        return fromMemberFace;
+    }
+
+    public void setFromMemberFace(String fromMemberFace) {
+        this.fromMemberFace = fromMemberFace;
+    }
+
+    public Integer getFromClerkId() {
+        return fromClerkId;
+    }
+
+    public void setFromClerkId(Integer fromClerkId) {
+        this.fromClerkId = fromClerkId;
+    }
+
+    public String getFromRoleName() {
+        return fromRoleName;
+    }
+
+    public void setFromRoleName(String fromRoleName) {
+        this.fromRoleName = fromRoleName;
+    }
+
+    public Integer getToDeviceId() {
+        return toDeviceId;
+    }
+
+    public void setToDeviceId(Integer toDeviceId) {
+        this.toDeviceId = toDeviceId;
+    }
+
+    public String getToEthMac() {
+        return toEthMac;
+    }
+
+    public void setToEthMac(String toEthMac) {
+        this.toEthMac = toEthMac;
+    }
+
+    public String getToEthIp() {
+        return toEthIp;
+    }
+
+    public void setToEthIp(String toEthIp) {
+        this.toEthIp = toEthIp;
+    }
+
+    public String getToSipId() {
+        return toSipId;
+    }
+
+    public void setToSipId(String toSipId) {
+        this.toSipId = toSipId;
+    }
+
+    public Integer getToDeviceType() {
+        return toDeviceType;
+    }
+
+    public void setToDeviceType(Integer toDeviceType) {
+        this.toDeviceType = toDeviceType;
+    }
+
+    public String getToDeviceName() {
+        return toDeviceName;
+    }
+
+    public void setToDeviceName(String toDeviceName) {
+        this.toDeviceName = toDeviceName;
+    }
+
+    public String getToDevicePhoneNumber() {
+        return toDevicePhoneNumber;
+    }
+
+    public void setToDevicePhoneNumber(String toDevicePhoneNumber) {
+        this.toDevicePhoneNumber = toDevicePhoneNumber;
+    }
+
+    public Integer getToDeviceFrameId() {
+        return toDeviceFrameId;
+    }
+
+    public void setToDeviceFrameId(Integer toDeviceFrameId) {
+        this.toDeviceFrameId = toDeviceFrameId;
+    }
+
+    public Integer getToFrameType() {
+        return toFrameType;
+    }
+
+    public void setToFrameType(Integer toFrameType) {
+        this.toFrameType = toFrameType;
+    }
+
+    public String getToFrameName() {
+        return toFrameName;
+    }
+
+    public void setToFrameName(String toFrameName) {
+        this.toFrameName = toFrameName;
+    }
+
+    public String getToFrameFullName() {
+        return toFrameFullName;
+    }
+
+    public void setToFrameFullName(String toFrameFullName) {
+        this.toFrameFullName = toFrameFullName;
+    }
+
+    public Integer getToFrameParentId() {
+        return toFrameParentId;
+    }
+
+    public void setToFrameParentId(Integer toFrameParentId) {
+        this.toFrameParentId = toFrameParentId;
+    }
 
     public Integer getToDeviceMemberId() {
         return toDeviceMemberId;
@@ -264,6 +694,45 @@ public class InteractionDO implements Serializable {
         this.toDeviceMemberId = toDeviceMemberId;
     }
 
+    public Integer getToCustomerId() {
+        return toCustomerId;
+    }
+
+    public void setToCustomerId(Integer toCustomerId) {
+        this.toCustomerId = toCustomerId;
+    }
+
+    public String getToMemberName() {
+        return toMemberName;
+    }
+
+    public void setToMemberName(String toMemberName) {
+        this.toMemberName = toMemberName;
+    }
+
+    public String getToMemberFace() {
+        return toMemberFace;
+    }
+
+    public void setToMemberFace(String toMemberFace) {
+        this.toMemberFace = toMemberFace;
+    }
+
+    public Integer getToClerkId() {
+        return toClerkId;
+    }
+
+    public void setToClerkId(Integer toClerkId) {
+        this.toClerkId = toClerkId;
+    }
+
+    public String getToRoleName() {
+        return toRoleName;
+    }
+
+    public void setToRoleName(String toRoleName) {
+        this.toRoleName = toRoleName;
+    }
 
     public Boolean getOuteriorAction() {
         return outeriorAction;
@@ -273,7 +742,6 @@ public class InteractionDO implements Serializable {
         this.outeriorAction = outeriorAction;
     }
 
-
     public String getOuteriorActionNumber() {
         return outeriorActionNumber;
     }
@@ -282,7 +750,6 @@ public class InteractionDO implements Serializable {
         this.outeriorActionNumber = outeriorActionNumber;
     }
 
-
     public Long getOuteriorActionMemberId() {
         return outeriorActionMemberId;
     }
@@ -291,7 +758,6 @@ public class InteractionDO implements Serializable {
         this.outeriorActionMemberId = outeriorActionMemberId;
     }
 
-
     public Integer getRemarkId() {
         return remarkId;
     }
@@ -300,7 +766,6 @@ public class InteractionDO implements Serializable {
         this.remarkId = remarkId;
     }
 
-
     public Long getActionStart() {
         return actionStart;
     }
@@ -309,7 +774,6 @@ public class InteractionDO implements Serializable {
         this.actionStart = actionStart;
     }
 
-
     public Long getActionAccept() {
         return actionAccept;
     }
@@ -318,7 +782,6 @@ public class InteractionDO implements Serializable {
         this.actionAccept = actionAccept;
     }
 
-
     public Long getActionEnd() {
         return actionEnd;
     }
@@ -327,6 +790,29 @@ public class InteractionDO implements Serializable {
         this.actionEnd = actionEnd;
     }
 
+    public Integer getActionEndMemberId() {
+        return actionEndMemberId;
+    }
+
+    public void setActionEndMemberId(Integer actionEndMemberId) {
+        this.actionEndMemberId = actionEndMemberId;
+    }
+
+    public String getActionEndMemberName() {
+        return actionEndMemberName;
+    }
+
+    public void setActionEndMemberName(String actionEndMemberName) {
+        this.actionEndMemberName = actionEndMemberName;
+    }
+
+    public Long getActionCompleted() {
+        return actionCompleted;
+    }
+
+    public void setActionCompleted(Long actionCompleted) {
+        this.actionCompleted = actionCompleted;
+    }
 
     public String getData() {
         return data;
@@ -336,7 +822,6 @@ public class InteractionDO implements Serializable {
         this.data = data;
     }
 
-
     public String getErrorCode() {
         return errorCode;
     }
@@ -345,7 +830,6 @@ public class InteractionDO implements Serializable {
         this.errorCode = errorCode;
     }
 
-
     public String getErrorMessage() {
         return errorMessage;
     }
@@ -362,4 +846,77 @@ public class InteractionDO implements Serializable {
         this.actionDirectionType = actionDirectionType;
     }
 
+    public String getActionStatus() {
+        return actionStatus;
+    }
+
+    public void setActionStatus(String actionStatus) {
+        this.actionStatus = actionStatus;
+    }
+
+    public Integer getRelativeId() {
+        return relativeId;
+    }
+
+    public void setRelativeId(Integer relativeId) {
+        this.relativeId = relativeId;
+    }
+
+    public String getRelativeName() {
+        return relativeName;
+    }
+
+    public void setRelativeName(String relativeName) {
+        this.relativeName = relativeName;
+    }
+
+
+    public String getSpreadMemberPath() {
+        return spreadMemberPath;
+    }
+
+    public void setSpreadMemberPath(String spreadMemberPath) {
+        this.spreadMemberPath = spreadMemberPath;
+    }
+
+    public String getSpreadMemberIds() {
+        return spreadMemberIds;
+    }
+
+    public void setSpreadMemberIds(String spreadMemberIds) {
+        this.spreadMemberIds = spreadMemberIds;
+    }
+
+    public String getReachedMemberIds() {
+        return reachedMemberIds;
+    }
+
+    public void setReachedMemberIds(String reachedMemberIds) {
+        this.reachedMemberIds = reachedMemberIds;
+    }
+
+    public ArrayList<Integer[]> getSpreadMemberPathArray() {
+        if (spreadMemberPathArray != null) {
+            return spreadMemberPathArray;
+        }
+        if (!Strings.isNullOrEmpty(spreadMemberPath)){
+            ArrayList<Integer[]> arrayList = new ArrayList<>();
+            JSONArray jsonArray = JSON.parseArray(spreadMemberPath);
+            for(Object item:jsonArray){
+                JSONArray itemJsonArray = (JSONArray)item;
+                Integer[] itemArray = new Integer[itemJsonArray.size()];
+                for(int i=0;i<itemJsonArray.size();i++){
+                    itemArray[i] = itemJsonArray.getInteger(i);
+                }
+                arrayList.add(itemArray);
+            }
+            spreadMemberPathArray = arrayList;
+            return spreadMemberPathArray;
+        }
+        return null;
+    }
+
+    public void setSpreadMemberPathArray(ArrayList<Integer[]> spreadMemberPathArray) {
+        this.spreadMemberPathArray = spreadMemberPathArray;
+    }
 }

+ 49 - 3
middleware/src/main/code/com/wdkl/ncs/android/middleware/model/dos/RoleDO.java

@@ -2,8 +2,6 @@ package com.wdkl.ncs.android.middleware.model.dos;
 
 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
 import com.fasterxml.jackson.databind.annotation.JsonNaming;
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
 import com.wdkl.ncs.android.middleware.model.annotation.Column;
 import com.wdkl.ncs.android.middleware.model.annotation.Id;
 import com.wdkl.ncs.android.middleware.model.annotation.PrimaryKeyField;
@@ -11,6 +9,9 @@ import com.wdkl.ncs.android.middleware.model.annotation.Table;
 
 import java.io.Serializable;
 
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
 @Table(name = "ncs_role")
 @ApiModel
 @JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
@@ -19,7 +20,7 @@ public class RoleDO implements Serializable {
     /**
      * 角色主键
      */
-    @Column(name = "role_id")
+    @Id(name = "role_id")
     @ApiModelProperty(value = "角色主键", required = false)
     private Integer roleId;
     /**
@@ -58,6 +59,27 @@ public class RoleDO implements Serializable {
     @Column(name = "hidden_in_seller")
     @ApiModelProperty(value = "是否为隐藏角色,不可见,管理端可见", required = false)
     private Boolean hiddenInSeller;
+    /**
+     * 是否处理呼叫,唯一,相斥
+     */
+    @Column(name = "bool_main")
+    @ApiModelProperty(value = "是否处理呼叫,唯一,相斥", required = false)
+    private Boolean boolMain;
+
+    /**
+     * 上级领导角色Id
+     */
+    @Column(name = "leader_role_id",allowNullUpdate = true)
+    @ApiModelProperty(value = "上级领导角色Id", required = false)
+    private Integer leaderRoleId;
+
+
+    /**
+     * 角色类型,内置逻辑设置 RoleTypeEnum 名称
+     */
+    @Column(name = "role_type")
+    @ApiModelProperty(value = "角色描述", required = false)
+    private String roleType;
 
 
     @PrimaryKeyField
@@ -123,4 +145,28 @@ public class RoleDO implements Serializable {
         this.hiddenInSeller = hiddenInSeller;
     }
 
+    public Boolean getBoolMain() {
+        return boolMain;
+    }
+
+    public void setBoolMain(Boolean boolMain) {
+        this.boolMain = boolMain;
+    }
+
+
+    public Integer getLeaderRoleId() {
+        return leaderRoleId;
+    }
+
+    public void setLeaderRoleId(Integer leaderRoleId) {
+        this.leaderRoleId = leaderRoleId;
+    }
+
+    public String getRoleType() {
+        return roleType;
+    }
+
+    public void setRoleType(String roleType) {
+        this.roleType = roleType;
+    }
 }

+ 45 - 695
middleware/src/main/code/com/wdkl/ncs/android/middleware/model/vo/InteractionVO.java

@@ -1,13 +1,10 @@
 package com.wdkl.ncs.android.middleware.model.vo;
 
+import androidx.annotation.Nullable;
+
 import com.fasterxml.jackson.databind.PropertyNamingStrategy;
 import com.fasterxml.jackson.databind.annotation.JsonNaming;
-import com.wdkl.ncs.android.middleware.model.annotation.Column;
-import com.wdkl.ncs.android.middleware.model.annotation.Id;
-
-import io.swagger.annotations.ApiModelProperty;
-
-import java.io.Serializable;
+import com.wdkl.ncs.android.middleware.model.dos.InteractionDO;
 
 /**
  * @program nc
@@ -16,694 +13,47 @@ import java.io.Serializable;
  * @create: 2021/04/02 15:27
  */
 @JsonNaming(value = PropertyNamingStrategy.SnakeCaseStrategy.class)
-public class InteractionVO implements Serializable {
-
-    /**
-     * id
-     */
-    @Column(name = "id")
-    @ApiModelProperty(value = "id", required = false)
-    @Id(name = "id")
-    private Integer id;
-    /**
-     * 创建时间
-     */
-    @Column(name = "create_date")
-    @ApiModelProperty(value = "创建时间", required = false)
-    private Long createDate;
-    /**
-     * 科室Id
-     */
-    @Column(name = "part_id")
-    @ApiModelProperty(value = "科室Id", required = false)
-    private Integer partId;
-    /**
-     * 交互类型(1:语音通话,2:视频通话,3:卫生间紧急呼叫,4:语音留言,5:文本消息,6:按键事件)
-     */
-    @Column(name = "action_type")
-    @ApiModelProperty(value = "交互类型(1:语音通话,2:视频通话,3:卫生间紧急呼叫,4:语音留言,5:文本消息,6:按键事件)", required = false)
-    private String actionType;
-    /**
-     * SUCCESS、FAILED
-     */
-    @Column(name = "action_result")
-    @ApiModelProperty(value = "0失败,1成功", required = false)
-    private Integer actionResult;
-    /**
-     * 交互发起设备Id
-     */
-    @Column(name = "from_device_id")
-    @ApiModelProperty(value = "交互发起设备Id", required = false)
-    private Integer fromDeviceId;
-    /**
-     * 交互对象设备Id
-     */
-    @Column(name = "to_device_id")
-    @ApiModelProperty(value = "交互对象设备Id", required = false)
-    private Integer toDeviceId;
-    /**
-     * 发起设备所在空间结构
-     */
-    @Column(name = "from_device_frame_id")
-    @ApiModelProperty(value = "发起设备所在空间结构", required = false)
-    private Integer fromDeviceFrameId;
-    /**
-     * 交互对象所在空间结果
-     */
-    @Column(name = "to_device_frame_id")
-    @ApiModelProperty(value = "交互对象所在空间结果", required = false)
-    private Integer toDeviceFrameId;
-    /**
-     * 交互发起设备使用者member_id
-     */
-    @Column(name = "from_device_member_id")
-    @ApiModelProperty(value = "交互发起设备使用者member_id", required = false)
-    private Integer fromDeviceMemberId;
-    /**
-     * 交互对象设备使用者member_id
-     */
-    @Column(name = "to_device_member_id")
-    @ApiModelProperty(value = "交互对象设备使用者member_id", required = false)
-    private Integer toDeviceMemberId;
-    /**
-     * 交互开始时间(通话时指通话接通时间,与create_time相同)
-     */
-    @Column(name = "action_start")
-    @ApiModelProperty(value = "交互开始时间(通话时指通话接通时间,与create_time相同)", required = false)
-    private Long actionStart;
-    /**
-     * 应答时间
-     */
-    @Column(name = "action_accept")
-    @ApiModelProperty(value = "应答时间", required = false)
-    private Long actionAccept;
-    /**
-     * 交互结束时间(通话时指通话挂断时间,通话挂断后要更新此字段)。事件响应时间、语音已读时间
-     */
-    @Column(name = "action_end")
-    @ApiModelProperty(value = "交互结束时间(通话时指通话挂断时间,通话挂断后要更新此字段)。事件响应时间、语音已读时间", required = false)
-    private Long actionEnd;
-    /**
-     * 交互处理者的member_id
-     */
-    @Column(name = "action_end_member_id")
-    @ApiModelProperty(value = "交互处理者的member_id", required = false)
-    private Integer actionEndMemberId;
-    /**
-     *	交互完成时间
-     */	@Column(name = "action_completed" )
-    @ApiModelProperty(value="交互完成时间",required=false)
-    private Long actionCompleted;
-    /**
-     * 交互数据(类型1,2,3为空)(类型4为音频文件地址)(5为文本内容)(类型6为具体按键类型)
-     */
-    @Column(name = "data")
-    @ApiModelProperty(value = "交互数据(类型1,2,3为空)(类型4为音频文件地址)(5为文本内容)(类型6为具体按键类型)", required = false)
-    private String data;
-
-    @Column(name = "action_direction_type")
-    @ApiModelProperty(value = "交互方向类型(1:分机到主机、腕表、医生机,2:主机、腕表、医生机到分机,3主机、腕表、医生机之间互通,4:分机到分机)",required = false)
-    private Integer actionDirectionType;
-
-    /** 用户 **/
-    @Column(name = "from_customer_id")
-    @ApiModelProperty(value = "发起端用户CustomId", required = false)
-    private Integer fromCustomerId;
-
-    @Column(name = "from_member_name")
-    @ApiModelProperty(value = "发起端用户姓名", required = false)
-    private String fromMemberName;
-
-    @Column(name = "from_member_face")
-    @ApiModelProperty(value = "发起端用户头像", required = false)
-    private String fromMemberFace;
-
-    @Column(name = "from_clerk_id")
-    @ApiModelProperty(value = "发起端用户成员Id,发起端为护士主机,腕表,医生机时才有", required = false)
-    private Integer fromClerkId;
-
-    @Column(name = "from_role_name")
-    @ApiModelProperty(value = "发起端用户角色名(医生、护士、护工)", required = false)
-    private String fromRoleName;
-
-
-    @Column(name = "to_customer_id")
-    @ApiModelProperty(value = "目的端用户CustomId", required = false)
-    private Integer toCustomerId;
-
-    @Column(name = "to_member_name")
-    @ApiModelProperty(value = "目的端用户姓名", required = false)
-    private String toMemberName;
-
-    @Column(name = "to_member_face")
-    @ApiModelProperty(value = "目的端用户头像", required = false)
-    private String toMemberFace;
-
-    @Column(name = "to_clerk_id")
-    @ApiModelProperty(value = "目的端用户成员Id,目的端为护士主机,腕表,医生机时才有", required = false)
-    private Integer toClerkId;
-
-    @Column(name = "to_role_name")
-    @ApiModelProperty(value = "目的端用户角色名(医生、护士、护工)", required = false)
-    private String toRoleName;
-
-
-    /** 设备 **/
-    @Column(name = "from_eth_mac")
-    @ApiModelProperty(value = "发起端设备的有线以太网卡MAC地址", required = false)
-    private String fromEthMac;
-
-    @Column(name = "from_eth_ip")
-    @ApiModelProperty(value = "发起端设备的有线以太网卡分配的IP地址", required = false)
-    private String fromEthIp;
-
-
-    @Column(name = "from_sip_id")
-    @ApiModelProperty(value = "发起端设备的SIP账号", required = false)
-    private String fromSipId;
-
-    @Column(name = "from_device_type")
-    @ApiModelProperty(value = "发起端设备的设备类型", required = false)
-    private Integer fromDeviceType;
-
-    @Column(name = "from_device_name")
-    @ApiModelProperty(value = "发起端设备的名称", required = false)
-    private String fromDeviceName;
-
-    @Column(name = "from_device_phone_number" )
-    @ApiModelProperty(value="发起端设备号码",required=false)
-    private String fromDevicePhoneNumber;
-
-
-    @Column(name = "to_eth_mac")
-    @ApiModelProperty(value = "目的端设备的有线以太网卡MAC地址", required = false)
-    private String toEthMac;
-
-    @Column(name = "to_eth_ip")
-    @ApiModelProperty(value = "目的端设备的有线以太网卡分配的IP地址", required = false)
-    private String toEthIp;
-
-
-    @Column(name = "to_sip_id")
-    @ApiModelProperty(value = "目的端设备的SIP账号", required = false)
-    private String toSipId;
-
-    @Column(name = "to_device_type")
-    @ApiModelProperty(value = "目的端设备的设备类型", required = false)
-    private Integer toDeviceType;
-
-    @Column(name = "to_device_name")
-    @ApiModelProperty(value = "目的端设备的名称", required = false)
-    private String toDeviceName;
-
-    @Column(name = "to_device_phone_number" )
-    @ApiModelProperty(value="目的端设备号码",required=false)
-    private String toDevicePhoneNumber;
-
-
-    /** 空间结构 **/
-
-    @Column(name = "from_frame_type")
-    @ApiModelProperty(value = "发起端空间结构类型:0楼、1病房、2床位", required = false)
-    private Integer fromFrameType;
-
-
-    @Column(name = "from_frame_name")
-    @ApiModelProperty(value = "发起端空间结构名称", required = false)
-    private String fromFrameName;
-
-    @Column(name = "from_frame_full_name")
-    @ApiModelProperty(value = "发起端空间结构全名", required = false)
-    private String fromFrameFullName;
-
-    @Column(name = "from_frame_parent_id")
-    @ApiModelProperty(value = "发起端空间父级id", required = false)
-    private String fromFrameParentId;
-
-
-    @Column(name = "to_frame_type")
-    @ApiModelProperty(value = "目的端空间结构类型:0楼、1病房、2床位", required = false)
-    private Integer toFrameType;
-
-
-    @Column(name = "to_frame_name")
-    @ApiModelProperty(value = "目的端空间结构名称", required = false)
-    private String toFrameName;
-
-    @Column(name = "to_frame_full_name")
-    @ApiModelProperty(value = "目的端空间结构全名", required = false)
-    private String toFrameFullName;
-
-    @Column(name = "to_frame_parent_id")
-    @ApiModelProperty(value = "目的端空间父级id", required = false)
-    private String toFrameParentId;
-
-
-    @Column(name = "part_name")
-    @ApiModelProperty(value = "科室名称", required = false)
-    private String partName;
-
-
-    @Column(name = "relative_id")
-    @ApiModelProperty(value = "亲属id,外部来电时,from_member亲属的memberId", required = false)
-    private Integer relativeId;
-
-    @Column(name = "relative_name")
-    @ApiModelProperty(value = "外部来电时,from_member亲属关系", required = false)
-    private String relativeName;
-
-    @Column(name = "action_end_member_name")
-    @ApiModelProperty(value = "交互处理者的用户姓名", required = false)
-    private String actionEndMemberName;
-
-
-    @Column(name = "action_status")
-    @ApiModelProperty(value = "事件类型的交互状态(包括:发出,响应,取消,完成)",required = false)
-    private String actionStatus;
-
-
-
-    public Integer getId() {
-        return id;
-    }
-
-    public void setId(Integer id) {
-        this.id = id;
-    }
-
-    public Long getCreateDate() {
-        return createDate;
-    }
-
-    public void setCreateDate(Long createDate) {
-        this.createDate = createDate;
-    }
-
-    public Integer getPartId() {
-        return partId;
-    }
-
-    public void setPartId(Integer partId) {
-        this.partId = partId;
-    }
-
-    public String getActionType() {
-        return actionType;
-    }
-
-    public void setActionType(String actionType) {
-        this.actionType = actionType;
-    }
-
-    public Integer getActionResult() {
-        return actionResult;
-    }
-
-    public void setActionResult(Integer actionResult) {
-        this.actionResult = actionResult;
-    }
-
-    public Integer getFromDeviceId() {
-        return fromDeviceId;
-    }
-
-    public void setFromDeviceId(Integer fromDeviceId) {
-        this.fromDeviceId = fromDeviceId;
-    }
-
-    public Integer getToDeviceId() {
-        return toDeviceId;
-    }
-
-    public void setToDeviceId(Integer toDeviceId) {
-        this.toDeviceId = toDeviceId;
-    }
-
-    public Integer getFromDeviceFrameId() {
-        return fromDeviceFrameId;
-    }
-
-    public void setFromDeviceFrameId(Integer fromDeviceFrameId) {
-        this.fromDeviceFrameId = fromDeviceFrameId;
-    }
-
-    public Integer getToDeviceFrameId() {
-        return toDeviceFrameId;
-    }
-
-    public void setToDeviceFrameId(Integer toDeviceFrameId) {
-        this.toDeviceFrameId = toDeviceFrameId;
-    }
-
-    public Integer getFromDeviceMemberId() {
-        return fromDeviceMemberId;
-    }
-
-    public void setFromDeviceMemberId(Integer fromDeviceMemberId) {
-        this.fromDeviceMemberId = fromDeviceMemberId;
-    }
-
-    public Integer getToDeviceMemberId() {
-        return toDeviceMemberId;
-    }
-
-    public void setToDeviceMemberId(Integer toDeviceMemberId) {
-        this.toDeviceMemberId = toDeviceMemberId;
-    }
-
-    public Long getActionStart() {
-        return actionStart;
-    }
-
-    public void setActionStart(Long actionStart) {
-        this.actionStart = actionStart;
-    }
-
-    public Long getActionAccept() {
-        return actionAccept;
-    }
-
-    public void setActionAccept(Long actionAccept) {
-        this.actionAccept = actionAccept;
-    }
-
-    public Long getActionEnd() {
-        return actionEnd;
-    }
-
-    public void setActionEnd(Long actionEnd) {
-        this.actionEnd = actionEnd;
-    }
-
-    public Integer getActionEndMemberId() {
-        return actionEndMemberId;
-    }
-
-    public void setActionEndMemberId(Integer actionEndMemberId) {
-        this.actionEndMemberId = actionEndMemberId;
-    }
-
-    public Long getActionCompleted() {
-        return actionCompleted;
-    }
-
-    public void setActionCompleted(Long actionCompleted) {
-        this.actionCompleted = actionCompleted;
-    }
-
-    public String getData() {
-        return data;
-    }
-
-    public void setData(String data) {
-        this.data = data;
-    }
-
-    public Integer getActionDirectionType() {
-        return actionDirectionType;
-    }
-
-    public void setActionDirectionType(Integer actionDirectionType) {
-        this.actionDirectionType = actionDirectionType;
-    }
-
-    public Integer getFromCustomerId() {
-        return fromCustomerId;
-    }
-
-    public void setFromCustomerId(Integer fromCustomerId) {
-        this.fromCustomerId = fromCustomerId;
-    }
-
-    public String getFromMemberName() {
-        return fromMemberName;
-    }
-
-    public void setFromMemberName(String fromMemberName) {
-        this.fromMemberName = fromMemberName;
-    }
-
-    public String getFromMemberFace() {
-        return fromMemberFace;
-    }
-
-    public void setFromMemberFace(String fromMemberFace) {
-        this.fromMemberFace = fromMemberFace;
-    }
-
-    public Integer getFromClerkId() {
-        return fromClerkId;
-    }
-
-    public void setFromClerkId(Integer fromClerkId) {
-        this.fromClerkId = fromClerkId;
-    }
-
-    public String getFromRoleName() {
-        return fromRoleName;
-    }
-
-    public void setFromRoleName(String fromRoleName) {
-        this.fromRoleName = fromRoleName;
-    }
-
-    public Integer getToCustomerId() {
-        return toCustomerId;
-    }
-
-    public void setToCustomerId(Integer toCustomerId) {
-        this.toCustomerId = toCustomerId;
-    }
-
-    public String getToMemberName() {
-        return toMemberName;
-    }
-
-    public void setToMemberName(String toMemberName) {
-        this.toMemberName = toMemberName;
-    }
-
-    public String getToMemberFace() {
-        return toMemberFace;
-    }
-
-    public void setToMemberFace(String toMemberFace) {
-        this.toMemberFace = toMemberFace;
-    }
-
-    public Integer getToClerkId() {
-        return toClerkId;
-    }
-
-    public void setToClerkId(Integer toClerkId) {
-        this.toClerkId = toClerkId;
-    }
-
-    public String getToRoleName() {
-        return toRoleName;
-    }
-
-    public void setToRoleName(String toRoleName) {
-        this.toRoleName = toRoleName;
-    }
-
-    public String getFromEthMac() {
-        return fromEthMac;
-    }
-
-    public void setFromEthMac(String fromEthMac) {
-        this.fromEthMac = fromEthMac;
-    }
-
-    public String getFromEthIp() {
-        return fromEthIp;
-    }
-
-    public void setFromEthIp(String fromEthIp) {
-        this.fromEthIp = fromEthIp;
-    }
-
-    public String getFromSipId() {
-        return fromSipId;
-    }
-
-    public void setFromSipId(String fromSipId) {
-        this.fromSipId = fromSipId;
-    }
-
-    public Integer getFromDeviceType() {
-        return fromDeviceType;
-    }
-
-    public void setFromDeviceType(Integer fromDeviceType) {
-        this.fromDeviceType = fromDeviceType;
-    }
-
-    public String getFromDeviceName() {
-        return fromDeviceName;
-    }
-
-    public void setFromDeviceName(String fromDeviceName) {
-        this.fromDeviceName = fromDeviceName;
-    }
-
-    public String getFromDevicePhoneNumber() {
-        return fromDevicePhoneNumber;
-    }
-
-    public void setFromDevicePhoneNumber(String fromDevicePhoneNumber) {
-        this.fromDevicePhoneNumber = fromDevicePhoneNumber;
-    }
-
-    public String getToEthMac() {
-        return toEthMac;
-    }
-
-    public void setToEthMac(String toEthMac) {
-        this.toEthMac = toEthMac;
-    }
-
-    public String getToEthIp() {
-        return toEthIp;
-    }
-
-    public void setToEthIp(String toEthIp) {
-        this.toEthIp = toEthIp;
-    }
-
-    public String getToSipId() {
-        return toSipId;
-    }
-
-    public void setToSipId(String toSipId) {
-        this.toSipId = toSipId;
-    }
-
-    public Integer getToDeviceType() {
-        return toDeviceType;
-    }
-
-    public void setToDeviceType(Integer toDeviceType) {
-        this.toDeviceType = toDeviceType;
-    }
-
-    public String getToDeviceName() {
-        return toDeviceName;
-    }
-
-    public void setToDeviceName(String toDeviceName) {
-        this.toDeviceName = toDeviceName;
-    }
-
-    public String getToDevicePhoneNumber() {
-        return toDevicePhoneNumber;
-    }
-
-    public void setToDevicePhoneNumber(String toDevicePhoneNumber) {
-        this.toDevicePhoneNumber = toDevicePhoneNumber;
-    }
-
-    public Integer getFromFrameType() {
-        return fromFrameType;
-    }
-
-    public void setFromFrameType(Integer fromFrameType) {
-        this.fromFrameType = fromFrameType;
-    }
-
-    public String getFromFrameName() {
-        return fromFrameName;
-    }
-
-    public void setFromFrameName(String fromFrameName) {
-        this.fromFrameName = fromFrameName;
-    }
-
-    public String getFromFrameFullName() {
-        return fromFrameFullName;
-    }
-
-    public void setFromFrameFullName(String fromFrameFullName) {
-        this.fromFrameFullName = fromFrameFullName;
-    }
-
-    public String getFromFrameParentId() {
-        return fromFrameParentId;
-    }
-
-    public void setFromFrameParentId(String fromFrameParentId) {
-        this.fromFrameParentId = fromFrameParentId;
-    }
-
-    public Integer getToFrameType() {
-        return toFrameType;
-    }
-
-    public void setToFrameType(Integer toFrameType) {
-        this.toFrameType = toFrameType;
-    }
-
-    public String getToFrameName() {
-        return toFrameName;
-    }
-
-    public void setToFrameName(String toFrameName) {
-        this.toFrameName = toFrameName;
-    }
-
-    public String getToFrameFullName() {
-        return toFrameFullName;
-    }
-
-    public void setToFrameFullName(String toFrameFullName) {
-        this.toFrameFullName = toFrameFullName;
-    }
-
-    public String getToFrameParentId() {
-        return toFrameParentId;
-    }
-
-    public void setToFrameParentId(String toFrameParentId) {
-        this.toFrameParentId = toFrameParentId;
-    }
-
-    public String getPartName() {
-        return partName;
-    }
-
-    public void setPartName(String partName) {
-        this.partName = partName;
-    }
-
-    public Integer getRelativeId() {
-        return relativeId;
-    }
-
-    public void setRelativeId(Integer relativeId) {
-        this.relativeId = relativeId;
-    }
-
-    public String getRelativeName() {
-        return relativeName;
-    }
-
-    public void setRelativeName(String relativeName) {
-        this.relativeName = relativeName;
-    }
-
-    public String getActionEndMemberName() {
-        return actionEndMemberName;
-    }
-
-    public void setActionEndMemberName(String actionEndMemberName) {
-        this.actionEndMemberName = actionEndMemberName;
-    }
-
-    public String getActionStatus() {
-        return actionStatus;
-    }
-
-    public void setActionStatus(String actionStatus) {
-        this.actionStatus = actionStatus;
+public class InteractionVO extends InteractionDO {
+
+    @Override
+    public String toString() {
+        return "InteractionVO{" +
+                "fromCustomerId=" + getFromCustomerId() +
+                ", fromMemberName='" + getFromDeviceType() + '\'' +
+                ", fromMemberFace='" + getFromMemberFace() + '\'' +
+                ", fromClerkId=" + getFromClerkId() +
+                ", fromRoleName='" + getFromRoleName() + '\'' +
+                ", toCustomerId=" + getToCustomerId() +
+                ", toMemberName='" + getToMemberName() + '\'' +
+                ", toMemberFace='" + getToMemberFace() + '\'' +
+                ", toClerkId=" + getToClerkId() +
+                ", toRoleName='" + getToRoleName() + '\'' +
+                ", fromEthMac='" + getFromEthMac() + '\'' +
+                ", fromEthIp='" + getFromEthIp() + '\'' +
+                ", fromSipId='" + getFromSipId() + '\'' +
+                ", fromDeviceType=" + getFromDeviceType() +
+                ", toEthMac='" + getToEthMac() + '\'' +
+                ", toEthIp='" + getToEthIp() + '\'' +
+                ", toSipId='" + getToSipId() + '\'' +
+                ", toDeviceType=" + getToDeviceType() +
+                ", fromFrameType=" + getFromFrameType() +
+                ", fromFrameName='" + getFromFrameName() + '\'' +
+                ", fromFrameFullName='" + getFromFrameFullName() + '\'' +
+                ", toFrameType=" + getToFrameType() +
+                ", toFrameName='" + getToFrameName() + '\'' +
+                ", toFrameFullName='" + getToFrameFullName() + '\'' +
+                ", relativeId=" + getRelativeId() +
+                ", relativeName='" + getRelativeName() + '\'' +
+                ", actionStatus='" + getActionStatus() + '\'' +
+                ", actionEndMemberId=" + getActionEndMemberId() +
+                ", actionEndMemberName='" + getActionEndMemberName() + '\'' +
+                '}';
+    }
+
+    @Override
+    public boolean equals(@Nullable Object obj) {
+        InteractionVO other= (InteractionVO)obj;
+        return this.getId().equals(other.getId());
     }
 }
+

middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/NettyClient.kt → middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/NettyClient.kt.bak


+ 244 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TaskSchedule.java

@@ -0,0 +1,244 @@
+package com.wdkl.ncs.android.middleware.tcp;
+
+import com.wdkl.ncs.android.middleware.tcp.util.DateUtil;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 描述
+ *
+ * @author allen
+ * 2022-11-28 10:15
+ */
+public class TaskSchedule {
+    private final String TAG = getClass().getSimpleName();
+
+    private ScheduledThreadPoolExecutor pool;
+    //任务池
+    private final ConcurrentHashMap<String, ScheduledFuture<?>> taskFutures = new ConcurrentHashMap<>();
+
+    private TaskSchedule() {
+        pool = (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(5);
+        pool.setRemoveOnCancelPolicy(true);
+    }
+
+    //单例
+    private static class TaskScheduleHolder {
+        private static final TaskSchedule instance = new TaskSchedule();
+    }
+
+    public static TaskSchedule getInstance() {
+        return TaskScheduleHolder.instance;
+    }
+
+    /**
+     * Submits a one-shot task that becomes enabled after the given delay.
+     *
+     * @param command the task to execute
+     * @param delay the time from now to delay execution
+     * @param unit the time unit of the delay parameter
+     * @return a ScheduledFuture representing pending completion of
+     *         the task and whose {@code get()} method will return
+     *         {@code null} upon completion
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if command or unit is null
+     */
+    public ScheduledFuture<?> runDelay(Runnable command,
+                                       long delay, TimeUnit unit){
+        if (pool!=null){
+            return pool.schedule(command, delay, unit);
+        }
+        return null;
+    }
+
+    /**
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given period;
+     * that is, executions will commence after
+     * {@code initialDelay}, then {@code initialDelay + period}, then
+     * {@code initialDelay + 2 * period}, and so on.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>The executor terminates, also resulting in task cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
+     *
+     * <p>If any execution of this task takes longer than its period, then
+     * subsequent executions may start late, but will not concurrently
+     * execute.
+     *
+     * @param command the task to execute
+     * @param initialDelay the time to delay first execution
+     * @param period the period between successive executions
+     * @param unit the time unit of the initialDelay and period parameters
+     * @return a ScheduledFuture representing pending completion of
+     *         the series of repeated tasks.  The future's {@link
+     *         Future#get() get()} method will never return normally,
+     *         and will throw an exception upon task cancellation or
+     *         abnormal termination of a task execution.
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if command or unit is null
+     * @throws IllegalArgumentException if period less than or equal to zero
+     */
+    public ScheduledFuture<?> runAtFixedRate(Runnable command,
+                                  long initialDelay,
+                                  long period,
+                                  TimeUnit unit){
+        if (pool != null){
+            return pool.scheduleAtFixedRate(command, initialDelay, period, unit);
+        }
+        return null;
+    }
+
+    public ScheduledFuture<?> scheduleTask(@NotNull String taskName, @NotNull Runnable task, @NotNull Long startTime, Long period) {
+        if (pool != null){
+            ScheduledFuture<?> future = pool.scheduleAtFixedRate(task, startTime, period, TimeUnit.MILLISECONDS);
+            cancelTask(taskName);
+            this.taskFutures.put(taskName, future);
+            return future;
+        }
+        return null;
+    }
+
+    /**
+     * 取消任务
+     *
+     * @param taskName
+     */
+    public void cancelTask(String taskName) {
+        if (pool != null) {
+            ScheduledFuture<?> future = this.taskFutures.get(taskName);
+            if (future != null) {
+                future.cancel(true);
+            }
+            this.taskFutures.remove(taskName);
+        }
+    }
+
+    /**
+     * Submits a periodic action that becomes enabled first after the
+     * given initial delay, and subsequently with the given delay
+     * between the termination of one execution and the commencement of
+     * the next.
+     *
+     * <p>The sequence of task executions continues indefinitely until
+     * one of the following exceptional completions occur:
+     * <ul>
+     * <li>The task is {@linkplain Future#cancel explicitly cancelled}
+     * via the returned future.
+     * <li>The executor terminates, also resulting in task cancellation.
+     * <li>An execution of the task throws an exception.  In this case
+     * calling {@link Future#get() get} on the returned future will throw
+     * {@link ExecutionException}, holding the exception as its cause.
+     * </ul>
+     * Subsequent executions are suppressed.  Subsequent calls to
+     * {@link Future#isDone isDone()} on the returned future will
+     * return {@code true}.
+     *
+     * @param command the task to execute
+     * @param initialDelay the time to delay first execution
+     * @param delay the delay between the termination of one
+     * execution and the commencement of the next
+     * @param unit the time unit of the initialDelay and delay parameters
+     * @return a ScheduledFuture representing pending completion of
+     *         the series of repeated tasks.  The future's {@link
+     *         Future#get() get()} method will never return normally,
+     *         and will throw an exception upon task cancellation or
+     *         abnormal termination of a task execution.
+     * @throws RejectedExecutionException if the task cannot be
+     *         scheduled for execution
+     * @throws NullPointerException if command or unit is null
+     * @throws IllegalArgumentException if delay less than or equal to zero
+     */
+    public ScheduledFuture<?> runWithFixedDelay(Runnable command,
+                                             long initialDelay,
+                                             long delay,
+                                             TimeUnit unit){
+        if (pool != null){
+            return pool.scheduleWithFixedDelay(command, initialDelay, delay, unit);
+        }
+        return null;
+    }
+
+    public void shutDown(Integer seconds) {
+        if (pool != null) {
+            try {
+                pool.awaitTermination(seconds, TimeUnit.SECONDS);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            pool.shutdown();
+        }
+    }
+
+    //测试
+    public static void main(String[] args) {
+        System.out.println(DateUtil.getDateline() + "     main " + Thread.currentThread().getId());
+        Runnable task1 = new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(DateUtil.getDateline() + "     1 " + Thread.currentThread().getId());
+            }
+        };
+
+        Runnable task2 = new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(DateUtil.getDateline() + "     2 " + Thread.currentThread().getId());
+            }
+        };
+
+        Runnable task3 = new Runnable() {
+            @Override
+            public void run() {
+                System.out.println(DateUtil.getDateline() + "     3 " + Thread.currentThread().getId());
+            }
+        };
+
+        ScheduledFuture<?> task1Result = TaskSchedule.getInstance().runAtFixedRate(task1,0, 1000, TimeUnit.MILLISECONDS);
+        ScheduledFuture<?> task2Result = TaskSchedule.getInstance().runAtFixedRate(task2,0, 1000, TimeUnit.MILLISECONDS);
+        ScheduledFuture<?> task3Result = TaskSchedule.getInstance().runAtFixedRate(task3,0, 1000, TimeUnit.MILLISECONDS);
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                try{
+                    Thread.sleep(1000);
+                    task1Result.cancel(true);
+
+                    Thread.sleep(2000);
+                    task2Result.cancel(true);
+
+                    Thread.sleep(3000);
+                    task3Result.cancel(true);
+
+                    TaskSchedule.getInstance().runAtFixedRate(task1,0, 1000, TimeUnit.MILLISECONDS);
+
+                    Thread.currentThread().interrupt();
+                } catch (Exception ex){}
+            }
+        }).start();
+
+        TaskSchedule.getInstance().shutDown(10);
+    }
+}

+ 188 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TcpClient.java

@@ -0,0 +1,188 @@
+package com.wdkl.ncs.android.middleware.tcp;
+
+import com.alibaba.fastjson.JSONObject;
+import com.wdkl.ncs.android.lib.vo.MessageEvent;
+import com.wdkl.ncs.android.middleware.common.Constants;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpSendModel;
+import com.wdkl.ncs.android.middleware.tcp.util.DateUtil;
+
+import org.greenrobot.eventbus.EventBus;
+
+import java.util.concurrent.TimeUnit;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelFutureListener;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.SocketChannel;
+import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
+import io.netty.handler.codec.LengthFieldPrepender;
+import io.netty.handler.codec.string.StringDecoder;
+import io.netty.handler.codec.string.StringEncoder;
+import io.netty.handler.timeout.IdleStateHandler;
+import io.netty.util.CharsetUtil;
+
+/**
+ * 描述
+ *
+ * @author allen
+ * 2022-11-01 15:51
+ */
+public class TcpClient {
+    private NioEventLoopGroup workGroup;
+    public Channel channel;
+    private Bootstrap bootstrap;
+
+    //数据处理
+    private TcpClientHandler tcpClientHandler = new TcpClientHandler();
+
+    //tcp是否完成初始化
+    private boolean inited = false;
+
+    //重试计数
+    private Integer retryTimes = 1;
+    private Integer reconnetTimes = 0;
+    private boolean connecting = false;
+
+
+    //单例
+    private static class TcpClientHolder {
+        private static TcpClient instance = new TcpClient();
+    }
+
+    public static TcpClient getInstance() {
+        return TcpClientHolder.instance;
+    }
+
+    //初始化Netty Tcp Client 并连接
+    public void init(String serverIP, Integer serverPort, Integer heartBeatSeconds) {
+
+        final Integer hbSeconds = heartBeatSeconds;
+        workGroup = new NioEventLoopGroup(2);
+        bootstrap = new Bootstrap();
+        bootstrap.group(workGroup)
+                .channel(NioSocketChannel.class)
+                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 15 * 1000)
+                .option(ChannelOption.SO_KEEPALIVE, true)
+                .handler(new ChannelInitializer<SocketChannel>() {
+                    @Override
+                    protected void initChannel(SocketChannel socketChannel) throws Exception {
+                        // 这里将LengthFieldBasedFrameDecoder添加到pipeline的首位,因为其需要对接收到的数据
+                        // 进行长度字段解码,这里也会对数据进行粘包和拆包处理
+                        socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(2048, 0, 2, 0, 2));
+                        // LengthFieldPrepender是一个编码器,主要是在响应字节数据前面添加字节长度字段
+                        socketChannel.pipeline().addLast(new LengthFieldPrepender(2));
+                        //心跳包应当小于服务器间隔
+                        socketChannel.pipeline().addLast(new IdleStateHandler(hbSeconds*2, hbSeconds, 0, TimeUnit.SECONDS));
+                        socketChannel.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
+                        socketChannel.pipeline().addLast(new StringEncoder(CharsetUtil.UTF_8));
+                        socketChannel.pipeline().addLast(tcpClientHandler);
+                    }
+                }).remoteAddress(serverIP, serverPort);
+        inited = true;
+        doConnect();
+    }
+
+    //独立连接方法,用于重新连接
+    public synchronized void doConnect() {
+        if (!inited) {
+            System.out.println("tcp is not initialized");
+            return;
+        }
+
+        if (channel != null && (channel.isActive() || channel.isOpen())) {
+            System.out.println("TcpClient connecting");
+            return;
+        }
+
+        //正在连接
+        if (connecting || TcpClientHandler.getConnected()) {
+            System.out.println("tcp is connecting or connected");
+            return;
+        }
+        connecting = true;
+
+        System.out.println("TcpClient connect start1");
+        ChannelFuture future = bootstrap.connect().addListener(new ChannelFutureListener() {
+            @Override
+            public void operationComplete(ChannelFuture channelFuture) throws Exception {
+                connecting = false;
+                if (channelFuture.isSuccess()) {
+                    channel = channelFuture.channel();
+                    retryTimes = 1;
+                    System.out.println("TcpClient connect success");
+                } else {
+                    //连接失败时的处理
+                    System.out.println("TcpClient connect retry : " + retryTimes);
+                    channelFuture.channel().eventLoop().schedule(new Runnable() {
+                        @Override
+                        public void run() {
+                            retryTimes++;
+                            if (retryTimes > 30) { //重试30次还没连成功,等10分钟后再试
+                                retryTimes=1;
+                                reconnetTimes++;
+                                channelFuture.channel().eventLoop().schedule(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        System.out.println("TcpClientHandler 重新连接,第" + retryTimes + "次" + ", 重试" + reconnetTimes + "次");
+                                        if (reconnetTimes > 2) {
+                                            EventBus.getDefault().post(new MessageEvent(0, Constants.EVENT_RESTART_APP));
+                                        } else {
+                                            doConnect();
+                                        }
+                                    }
+                                }, 60*2, TimeUnit.SECONDS);
+
+                            }else{
+                                doConnect();
+                            }
+
+                        }
+                    }, 5, TimeUnit.SECONDS);
+                }
+            }
+        });
+    }
+
+    //发送消息,线程安全
+    public void sendTcp(TcpModel tcpModel, Boolean reSend, TcpCallback transaction) {
+        String tcpString = JSONObject.toJSONString(tcpModel);
+
+        if (reSend){
+            TcpSendModel model = new TcpSendModel();
+            model.setMsg(tcpString);
+            model.setTid(tcpModel.getTid());
+            model.setTs(DateUtil.getDateline());
+            //启动定时任务
+            tcpClientHandler.handleReSend(model);
+        }
+        sendMsg(tcpString, transaction);
+    }
+
+    //发送消息,线程安全
+    public synchronized void sendMsg(String content, TcpCallback transaction) {
+        //System.out.println("send tcp msg = [" + content + "]");
+        if (tcpClientHandler != null) {
+            tcpClientHandler.sendMsg(content, transaction);
+        }
+    }
+
+    //发送消息,线程安全
+    public synchronized void sendMsg(String content) {
+        //System.out.println("send tcp msg = [" + content + "]");
+        if (tcpClientHandler != null) {
+            tcpClientHandler.sendMsg(content);
+        }
+    }
+
+
+    public Channel getChannel() {
+        return channel;
+    }
+}

+ 150 - 74
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/TcpClientHandler.java

@@ -1,53 +1,65 @@
 package com.wdkl.ncs.android.middleware.tcp;
 
-import android.annotation.SuppressLint;
 import android.util.Log;
 
-import com.wdkl.ncs.android.middleware.common.Constants;
+import com.alibaba.fastjson.JSONObject;
+import com.google.common.base.Strings;
 import com.wdkl.ncs.android.lib.vo.MessageEvent;
+import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceChannel;
 import com.wdkl.ncs.android.middleware.tcp.channel.DeviceUtil;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpCallback;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpSendModel;
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
+import com.wdkl.ncs.android.middleware.tcp.util.DateUtil;
 
 import org.greenrobot.eventbus.EventBus;
 
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ConcurrentHashMap;
 
+import io.netty.buffer.Unpooled;
 import io.netty.channel.ChannelHandler;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.handler.timeout.IdleState;
 import io.netty.handler.timeout.IdleStateEvent;
+import io.netty.util.CharsetUtil;
 import io.netty.util.ReferenceCountUtil;
 
+/**
+ * 描述
+ *
+ * @author allen
+ * 2022-11-01 15:52
+ */
 @ChannelHandler.Sharable
 public class TcpClientHandler extends SimpleChannelInboundHandler<String> {
     private String TAG = TcpClientHandler.class.getSimpleName();
 
     ChannelHandlerContext ctx;
-    //重连间隔
-    private static Integer retrySeconds = 3;
-    //重连计数
-    private static Integer retryTimes = 0;
-    private static Integer retrySendMsg = 0;
-    //总共总连接次数,总连接次数过多可能是网络不稳定
-    private static Integer totalRetryTimes = 0;
+
+    private Integer stopSendSeconds = 20;
+
     //是否连接成功
     private static Boolean connected = false;
     public static Boolean getConnected(){
         return connected;
     }
 
+    //存储回调 callback, key: tid
+    private static ConcurrentHashMap<String, TcpCallback> trantCache = new ConcurrentHashMap<>();
+    //key: tid。用于重发
+    static ConcurrentHashMap<String, TcpSendModel> tcpSendCache = new ConcurrentHashMap<>();
+
     //连接成功执行的方法
     @Override
     public void channelActive(ChannelHandlerContext ctx) throws Exception {
         super.channelActive(ctx);
         this.ctx = ctx;
-        connected = true;
-        retryTimes = 0;
-        retrySendMsg = 0;
 
-        EventBus.getDefault().post(new MessageEvent("net on",Constants.EVENT_TCP_CONNECTED));
+        connected = true;
+        EventBus.getDefault().post(new MessageEvent("net on", Constants.EVENT_TCP_CONNECTED));
 
         TcpModel tcpModel = DeviceUtil.deviceConnect(Constants.Companion.getImei());
         Log.e(TAG, "tcp连接成功: " + tcpModel.toJson());
@@ -58,56 +70,92 @@ public class TcpClientHandler extends SimpleChannelInboundHandler<String> {
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
         super.channelInactive(ctx);
-        connected = false;
         this.ctx = null;
+        connected = false;
         Log.i(TAG, "TcpClientHandler 失去连接");
         EventBus.getDefault().post(new MessageEvent("net off",Constants.EVENT_TCP_BREAK));
 
-        ctx.channel().eventLoop().schedule(new Runnable() {
-            @SuppressLint("CheckResult")
-            @Override
-            public void run() {
-                NettyClient.Companion.getInstance().reConnect().subscribe(it->{
-                    if (it){
-                        Log.d(TAG, "TCP.重连成功");
-                    } else {
-                        Log.e(TAG, "TCP.重连失败");
-                    }
-                });
-            }
-        },retrySeconds,TimeUnit.SECONDS);
+        TcpClient.getInstance().doConnect();
     }
 
-    //读取String消息
     @Override
     protected void channelRead0(ChannelHandlerContext ctx, String source) throws Exception {
-        Log.i(TAG, "TcpClientHandler "+ Thread.currentThread().getId() +" from server ===> " + source);
-        if(source.equals("1")){
-            Log.i(TAG,"收到服务器返回的心跳 "+source);
-        }else {
-            TcpModel tcpModel = TcpModel.getModelByJson(source);
-
-            TcpModel responseTcpModel = DeviceChannel.handleTcpReceived(tcpModel);
-            if (responseTcpModel!=null){
-                String msg = responseTcpModel.toJson();
-                Log.i(TAG, "TcpClientHandler send msg ===> " + msg);
-                ctx.writeAndFlush(msg);
+        try {
+            //System.out.println("tcp msg = [" + source + "]");
+
+            if (source.equals("1")) {
+                Log.e(TAG, "收到服务器返回的心跳" + "source " + source);
             } else {
-                ReferenceCountUtil.release(source);
+                Log.i(TAG, "received msg: " + source);
+                TcpModel tcpModel = TcpModel.getModelByJson(source);
+                if (tcpModel != null) {
+                    //Log.i(TAG, "received type==" + tcpModel.getType() + ", action==" + tcpModel.getAction() + ", tid===" + tcpModel.getTid());
+                    switch (tcpModel.getType()) {
+                        case CALLBACK:
+                            //收到ack说明消息已到达服务器,可以取消重发,收到success说明消息正常处理
+                            if (tcpModel.getAction() == TcpAction.CallbackAction.ACK) {
+                                //服务器已收到tcp消息
+                                if (!Strings.isNullOrEmpty(tcpModel.getTid())) {
+                                    // 取消定时任务
+                                    tcpSendCache.remove(tcpModel.getTid());
+                                }
+                            } else if (tcpModel.getAction() == TcpAction.CallbackAction.SUCCESS) {
+                                //回调成功
+                                if (!Strings.isNullOrEmpty(tcpModel.getTid())) {
+                                    TcpCallback transaction = trantCache.get(tcpModel.getTid());
+                                    if (transaction != null) {
+                                        JSONObject jsonObject = new JSONObject();
+                                        jsonObject.put(TcpCallback.CALLBACK, TcpCallback.CALLBACK_SUCCESS);
+                                        transaction.onSuccess(jsonObject);
+                                        trantCache.remove(tcpModel.getTid());
+                                    }
+                                }
+                            } else if (tcpModel.getAction() == TcpAction.CallbackAction.FAILED) {
+                                //回调失败
+                                if (!Strings.isNullOrEmpty(tcpModel.getTid())) {
+                                    TcpCallback transaction = trantCache.get(tcpModel.getTid());
+                                    if (transaction != null) {
+                                        JSONObject jsonObject = new JSONObject();
+                                        if (tcpModel.getData() != null) {
+                                            jsonObject.put(TcpCallback.CALLBACK, tcpModel.getData().toString());
+                                        } else {
+                                            jsonObject.put(TcpCallback.CALLBACK, TcpCallback.CALLBACK_FAIL);
+                                        }
+                                        transaction.onFailed(jsonObject);
+                                        trantCache.remove(tcpModel.getTid());
+                                    }
+                                }
+                            }
+                            break;
+
+                        default:
+                            //原来的方式处理
+                            TcpModel responseTcpModel = DeviceChannel.handleTcpReceived(tcpModel);
+                            if (responseTcpModel != null) {
+                                ctx.writeAndFlush(responseTcpModel.toJson());
+                            } else {
+                                ReferenceCountUtil.release(source);
+                            }
+                    }
+                }
             }
+        } catch (Exception ex) {
+            ex.printStackTrace();
         }
     }
 
     //写心跳包。没有消息发送时,每间隔一定时间会由此方法向服务端发送心跳
     @Override
     public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
-        if (evt instanceof IdleStateEvent){
-            IdleStateEvent event = (IdleStateEvent)evt;
-            if (event.state()== IdleState.WRITER_IDLE){
-                ctx.writeAndFlush("0");
-            }else if (event.state() == IdleState.READER_IDLE){
-                Log.i(TAG,"TcpClientHandler ===> pong from server failed");
+        if (evt instanceof IdleStateEvent) {
+            IdleStateEvent event = (IdleStateEvent) evt;
+            if (event.state() == IdleState.WRITER_IDLE) { //超时未执行写操作,在指定的超时时间内未有写操作,要发送心跳包,告诉服务器连接还存活。服务器收到心跳立马回应,正常客户端收到后执行读操作,
+                ctx.writeAndFlush("0");                //这种情况下不会引发READER_IDLE事件。如果服务器因为网络或其他原因导致回应的心跳,客户端没有收到,在超过写超时时间2个周期后依然没有收到,
+            } else if (event.state() == IdleState.READER_IDLE) { //认为服务不可用,主动断开连接
+                Log.i(TAG, "TcpClientHandler ===> READER_IDLE");
                 ctx.close();
+            } else if (event.state() == IdleState.ALL_IDLE) {
+                Log.i(TAG, "TcpClientHandler ===> ALL_IDLE");
             }
         }
     }
@@ -119,39 +167,67 @@ public class TcpClientHandler extends SimpleChannelInboundHandler<String> {
         Log.i(TAG,"TcpClientHandler 失去连接,错误引起 " + cause.getMessage());
     }
 
-    //已经连接上,中途失去连接时的处理
-    private void reConnect(final ChannelHandlerContext ctx){
-        if (totalRetryTimes>100){
-            //todo: 存储数据库,并告警
-        }
-        if (NettyClient.Companion.getInstance().isConnect()){
+    //使用原来的方式发送消息
+    public void sendMsg(String msg) {
+        if (ctx == null) {
+            System.out.println("ctx is null");
             return;
         }
-        totalRetryTimes++;
-        Log.i(TAG,"TcpClientHandler 总计连接次数:"+totalRetryTimes);
-        retryTimes++;
-        if (retryTimes>30){
-            //超时3次,其它处理
-            Log.i(TAG,"TcpClientHandler 重新连接"+(retryTimes-1)+"次,结束");
-            retryTimes = 0;
-
-            //10分钟后重连
-            ctx.channel().eventLoop().schedule(new Runnable() {
-                @Override
-                public void run() {
-                    System.out.println("TcpClientHandler 重新连接,第"+retryTimes+"次");
-                    NettyClient.Companion.getInstance().reConnect();
-                }
-            },10, TimeUnit.MINUTES);
-            return;
+
+        Log.i(TAG, "sendMsg ==> " + msg);
+        ctx.writeAndFlush(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
+    }
+
+    //使用带callback和tid方式发送消息
+    public synchronized boolean sendMsg(String msg, TcpCallback transaction){
+        if (ctx == null){
+            return false;
+        }
+
+        Log.i(TAG, "sendMsg ==> " + msg + ", transaction ==> " + transaction);
+        //ctx.writeAndFlush(msg);
+        ctx.writeAndFlush(Unpooled.copiedBuffer(msg, CharsetUtil.UTF_8));
+        if (transaction!=null) {
+            trantCache.put(transaction.getTid(), transaction);
         }
+        return true;
+    }
 
-        ctx.channel().eventLoop().schedule(new Runnable() {
+    //发送消息时缓存定时任务
+    public void handleReSend(TcpSendModel model){
+        tcpSendCache.put(model.getTid(), model);
+        TaskSchedule.getInstance().scheduleTask("TCP_MESSAGE_REPEAT" + model.getTid(), new Runnable() {
             @Override
             public void run() {
-                System.out.println("TcpClientHandler 重新连接,第"+retryTimes+"次");
-                NettyClient.Companion.getInstance().reConnect();
+                TcpSendModel m = tcpSendCache.get(model.getTid());
+                if (m != null){
+                    System.out.println("定时任务:" + m.getTid() + "...........");
+                    long time = DateUtil.getDateline() - m.getTs();
+                    //比对时间
+                    if (time < stopSendSeconds){
+                        //因为是重发,所以不需要再缓存 callback
+                        System.out.println("重发消息");
+                        sendMsg(model.getMsg(), null);
+                    } else { //超时处理
+                        //关闭定时任务,提示掉线?
+                        System.out.println("取消定时任务,提示掉线");
+                        TaskSchedule.getInstance().cancelTask("TCP_MESSAGE_REPEAT" + model.getTid());
+                        //这里可以执行失败的方法
+                        TcpCallback transaction = trantCache.get(model.getTid());
+                        if (transaction!=null){
+                            JSONObject jsonObject = new JSONObject();
+                            jsonObject.put(TcpCallback.CALLBACK, TcpCallback.CALLBACK_FAIL);
+                            transaction.onFailed(jsonObject);
+                        }
+                        trantCache.remove(model.getTid());
+                        tcpSendCache.remove(model.getTid());
+                    }
+                } else {    //缓存不存在,取消定时
+                    System.out.println("缓存不存在,取消定时");
+                    TaskSchedule.getInstance().cancelTask("TCP_MESSAGE_REPEAT" + model.getTid());
+                }
             }
-        },retrySeconds*retryTimes, TimeUnit.SECONDS);
+        },5000L, 5000L);
+
     }
 }

+ 8 - 3
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/ChannelImUtil.java

@@ -1,5 +1,6 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
+import com.google.common.base.Strings;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.model.dos.ChannelImDO;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
@@ -7,9 +8,9 @@ import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 
 public class ChannelImUtil {
-
+    //tid1,fromId,data
     public static TcpModel channelImMsg(Integer fromId, ChannelImDO channelImDO){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.CHANNELIM);
         tcpModel.setAction(TcpAction.CHANNELIMAction.MSG);
         tcpModel.setFromId(fromId);
@@ -18,7 +19,11 @@ public class ChannelImUtil {
     }
 
     public static TcpModel channelImReceived(TcpModel model){
+        //回复收到需要使用同一个tid
         TcpModel tcpModel = new TcpModel();
+        if (!Strings.isNullOrEmpty(model.getTid())) {
+            tcpModel.setTid(model.getTid());
+        }
         tcpModel.setType(TcpType.CHANNELIM);
         tcpModel.setAction(TcpAction.CHANNELIMAction.RECEIVED);
         tcpModel.setFromId(Constants.Companion.getDeviceId());
@@ -28,7 +33,7 @@ public class ChannelImUtil {
     }
 
     public static TcpModel channelImRead(Integer fromId, ChannelImDO channelImDO){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.CHANNELIM);
         tcpModel.setAction(TcpAction.CHANNELIMAction.MSG_READ);
         tcpModel.setFromId(fromId);

+ 12 - 41
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceChannel.java

@@ -1,56 +1,35 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
-import android.content.Intent;
 import android.util.Log;
 
 import com.google.gson.Gson;
-import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.vo.MessageEvent;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
-import com.wdkl.ncs.android.lib.vo.MessageEvent;
 
 import org.greenrobot.eventbus.EventBus;
 
-import java.util.HashMap;
-import java.util.Map;
-
 /**
  * 前提:所有安卓设备可以互相通话。
  * 在此前提下,所有安卓设备接收TCP信号的逻辑一致
  */
 public class DeviceChannel {
     private static String TAG = DeviceChannel.class.getSimpleName();
-    private static Map<String,Long> lastTcp = new HashMap<>();
 
     //通话中模拟
     public static boolean calling = false;
     public static int callId = 0;
 
     public static TcpModel handleTcpReceived(TcpModel tcpModel){
-        /*TcpModel responseTcpModel = new TcpModel();
-        responseTcpModel.setType(TcpType.CALLBACK);
-        responseTcpModel.setAction(TcpAction.CallbackAction.SUCCESS);
-        responseTcpModel.setFromId(Constants.Companion.getDeviceId());
-        responseTcpModel.setToId(tcpModel.getFromId());
-
-        //处理重复
-        String tcpJsonStr = tcpModel.toJson();
-        Long currentTime = System.currentTimeMillis();
-        if (lastTcp.get(tcpJsonStr)!=null && currentTime/1000 - lastTcp.get(tcpJsonStr)/1000 <1){
-            return responseTcpModel;
-        }
-        lastTcp.clear();
-        lastTcp.put(tcpModel.toJson(), System.currentTimeMillis());*/
-
         TcpModel responseTcpModel = null;
 
-//        Log.e(TAG,"收到tcp消息 DeviceChannel "+tcpJsonStr);
-
+        //Log.d("DeviceChannel", "received tcp model: " + tcpModel.toJson());
         switch (tcpModel.getType()){
             case VOICE:
                 if (tcpModel.getAction()==TcpAction.VoiceAction.SUCCESS) {
+                    Log.e(TAG, "call success 1111111");
                     EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_NEW_TCP));
                     //EventBus.getDefault().post(new MessageEvent(tcpModel, 1));
                 } else if(tcpModel.getAction() == TcpAction.VoiceAction.CALL){
@@ -62,20 +41,23 @@ public class DeviceChannel {
                             //EventBus.getDefault().post(new MessageEvent(tcpModel, 11));
                         } else {
                             InteractionVO interactionVO = new Gson().fromJson(tcpModel.getData().toString(), InteractionVO.class);
-                            responseTcpModel = VoiceUtil.voiceCalling(Constants.Companion.getDeviceId(), tcpModel.getFromId(), interactionVO.getId());
+                            responseTcpModel = VoiceUtil.voiceCalling(tcpModel.getTid(), Constants.Companion.getDeviceId(), tcpModel.getFromId(), interactionVO.getId());
                             //给服务器发送正在通话中 tcp
                             return responseTcpModel;
                         }
                     } else { //得到通话
                         EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_NEW_TCP));
                         //EventBus.getDefault().post(new MessageEvent(tcpModel, 1));
+                        responseTcpModel = VoiceUtil.voiceSuccess(tcpModel.getTid(), tcpModel.getToId(), tcpModel.getFromId());
+                        return responseTcpModel;
                     }
                 } else if ((tcpModel.getAction() == TcpAction.VoiceAction.ACCEPT)  //我方呼出,对方接受
                         || (tcpModel.getAction() == TcpAction.VoiceAction.REJECT) //我方呼出,对方拒绝
                         || (tcpModel.getAction() == TcpAction.VoiceAction.CALLING) //我方呼出,对方通话中
                         || (tcpModel.getAction() == TcpAction.VoiceAction.HANDOFF)
                         || (tcpModel.getAction() == TcpAction.VoiceAction.FAILED) //我方呼出,对方不在线,设备离线或其它错误
-                        || (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL)) { //对方取消
+                        || (tcpModel.getAction() == TcpAction.VoiceAction.CANCEL)
+                        || (tcpModel.getAction() == TcpAction.VoiceAction.VOICE_OFF)) { //对方取消
                     if (tcpModel.getAction() == TcpAction.VoiceAction.CALLING){
                         final TcpModel tm = tcpModel;
                         new Thread(new Runnable() {
@@ -119,9 +101,11 @@ public class DeviceChannel {
                 EventBus.getDefault().post(new MessageEvent(tcpModel, 3));
                 break;
             case DATA:
-//                if (tcpModel.getAction() == TcpAction.DataAction.REFRESH){
+                if (tcpModel.getAction() == TcpAction.DataAction.REFRESH){
+                    EventBus.getDefault().post(new MessageEvent(tcpModel, Constants.EVENT_DATA_REFRESH));
+                } else if (tcpModel.getAction() == TcpAction.DataAction.INTERACTION) {
                     EventBus.getDefault().post(new MessageEvent(tcpModel, 4));
-//                }
+                }
                 break;
             case SOS:
                 //紧急呼叫
@@ -156,17 +140,4 @@ public class DeviceChannel {
 
         return responseTcpModel;
     }
-
-
-    private static void sendCallBroadcast(TcpModel tcpModel) {
-        Intent intent = new Intent();
-        intent.setAction(Constants.call_action);
-        intent.putExtra(Constants.action_name, tcpModel.getAction().getName());
-        if (tcpModel.getData() != null) {
-            InteractionVO interactionVO = new Gson().fromJson(tcpModel.getData().toString(), InteractionVO.class);
-            intent.putExtra(Constants.interaction_id, interactionVO.getId());
-        }
-
-        BaseApplication.appContext.sendBroadcast(intent);
-    }
 }

+ 5 - 5
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/DeviceUtil.java

@@ -21,7 +21,7 @@ public class DeviceUtil {
         deviceConnectDTO.setHardware_version(Build.HARDWARE);
         deviceConnectDTO.setCode(Constants.Companion.getImei());
         deviceConnectDTO.setPhoneNumber(ContactHelper.getPhoneNumber());
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.DEVICE);
         tcpModel.setAction(TcpAction.DeviceAction.CONNECT);
         tcpModel.setData(deviceConnectDTO);
@@ -32,11 +32,11 @@ public class DeviceUtil {
         DeviceConnectDTO deviceConnectDTO = new DeviceConnectDTO();
         deviceConnectDTO.setIdentification(mac);
         deviceConnectDTO.setModel(Build.MODEL);
-        deviceConnectDTO.setSoftware_version("V"+CommonUtils.getAppVersionName(BaseApplication.appContext));
+        deviceConnectDTO.setSoftware_version("V" + CommonUtils.getAppVersionName(BaseApplication.appContext));
         deviceConnectDTO.setHardware_version(Build.HARDWARE);
         deviceConnectDTO.setCode(Constants.Companion.getImei());
         deviceConnectDTO.setPhoneNumber(phoneNumber);
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.DEVICE);
         tcpModel.setAction(TcpAction.DeviceAction.CONNECT);
         tcpModel.setData(deviceConnectDTO);
@@ -44,7 +44,7 @@ public class DeviceUtil {
     }
 
     public static TcpModel userChange(Integer fromId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.DEVICE);
         tcpModel.setAction(TcpAction.DeviceAction.USER_CHANGE);
         tcpModel.setFromId(fromId);
@@ -52,7 +52,7 @@ public class DeviceUtil {
     }
 
     public static TcpModel deviceChange(Integer fromId, Integer toId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.DEVICE);
         tcpModel.setAction(TcpAction.DeviceAction.DEVICE_CHANGE);
         tcpModel.setFromId(fromId);

+ 43 - 7
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/EventUtil.java

@@ -1,33 +1,45 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
+import com.google.common.base.Strings;
 import com.wdkl.ncs.android.middleware.common.Constants;
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class EventUtil {
-    public static TcpModel eventKeyClick(Integer fromId, Integer toId, Integer ineractionId){
-        TcpModel tcpModel = new TcpModel();
+    //分机发送按键事件无需toId
+    public static TcpModel eventKeyClick(Integer fromId, Integer toId, Integer keyId){
+        Map map = new HashMap();
+        map.put("id", keyId);
+
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.EVENT);
         tcpModel.setAction(TcpAction.EventAction.KEY_CLICK);
         tcpModel.setFromId(fromId);
-        tcpModel.setToId(toId);
-        tcpModel.setData(ineractionId);
+        tcpModel.setData(map);
         return tcpModel;
     }
 
-    public static TcpModel eventResponse(Integer fromId, Integer toId, Integer ineractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel eventResponse(Integer fromId, Integer toId, Integer eventId){
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.EVENT);
         tcpModel.setAction(TcpAction.EventAction.RESPONSE);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(ineractionId);
+        tcpModel.setData(eventId);
         return tcpModel;
     }
 
     public static TcpModel eventReceived(TcpModel model){
+        //回复收到需要使用同一个tid
         TcpModel tcpModel = new TcpModel();
+        if (!Strings.isNullOrEmpty(model.getTid())) {
+            tcpModel.setTid(model.getTid());
+        }
         tcpModel.setType(TcpType.EVENT);
         tcpModel.setAction(TcpAction.EventAction.RECEIVED);
         tcpModel.setFromId(Constants.Companion.getDeviceId());
@@ -37,8 +49,32 @@ public class EventUtil {
     }
 
 
+    public static TcpModel cancelEvent(InteractionVO interactionVO){
+        TcpModel tcpModel = new TcpModel(null);
+        tcpModel.setType(TcpType.EVENT);
+        tcpModel.setAction(TcpAction.EventAction.CANCEL);
+        tcpModel.setFromId(interactionVO.getFromDeviceId());
+        //tcpModel.setToId(model.getToId());
+        tcpModel.setData(interactionVO);
+        return tcpModel;
+    }
+
+    public static TcpModel eventCompleted(InteractionVO interactionVO){
+        TcpModel tcpModel = new TcpModel(null);
+        tcpModel.setType(TcpType.EVENT);
+        tcpModel.setAction(TcpAction.EventAction.COMPLETED);
+        tcpModel.setFromId(interactionVO.getFromDeviceId());
+        tcpModel.setToId(interactionVO.getToDeviceId());
+        tcpModel.setData(interactionVO);
+        return tcpModel;
+    }
+
     public static TcpModel eventCancelReceived(TcpModel model) {
+        //回复收到需要使用同一个tid
         TcpModel tcpModel = new TcpModel();
+        if (!Strings.isNullOrEmpty(model.getTid())) {
+            tcpModel.setTid(model.getTid());
+        }
         tcpModel.setType(TcpType.EVENT);
         tcpModel.setAction(TcpAction.EventAction.CANCEL_CONFIRM);
         tcpModel.setFromId(Constants.Companion.getDeviceId());

+ 17 - 4
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/ImUtil.java

@@ -1,23 +1,32 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
+import com.google.common.base.Strings;
 import com.wdkl.ncs.android.middleware.common.Constants;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 
+import java.util.HashMap;
+import java.util.Map;
+
 public class ImUtil {
-    public static TcpModel imMsg(Integer fromId, Integer toId, String msg){
-        TcpModel tcpModel = new TcpModel();
+    //tid1,fromId,data:{roleType:NURSE,filePath:pathUrl}
+    //带toId指定了目标设备的不用传roleType
+    public static TcpModel imMsg(Integer fromId, Integer toId, String filePath){
+        Map map = new HashMap();
+        map.put("filePath", filePath);
+
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.IM);
         tcpModel.setAction(TcpAction.IMAction.MSG);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(msg);
+        tcpModel.setData(map);
         return tcpModel;
     }
 
     public static TcpModel imRead(Integer fromId, Integer toId, Integer msgId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.IM);
         tcpModel.setAction(TcpAction.IMAction.MSG_READ);
         tcpModel.setFromId(fromId);
@@ -27,7 +36,11 @@ public class ImUtil {
     }
 
     public static TcpModel imReceived(TcpModel model){
+        //回复收到需要使用同一个tid
         TcpModel tcpModel = new TcpModel();
+        if (!Strings.isNullOrEmpty(model.getTid())) {
+            tcpModel.setTid(model.getTid());
+        }
         tcpModel.setType(TcpType.IM);
         tcpModel.setAction(TcpAction.IMAction.RECEIVED);
         tcpModel.setFromId(Constants.Companion.getDeviceId());

+ 2 - 2
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/OtherUtil.java

@@ -6,7 +6,7 @@ import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 
 public class OtherUtil {
     public static TcpModel SOSCall(Integer fromId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.SOS);
         tcpModel.setAction(TcpAction.SOSAction.CALL);
         tcpModel.setFromId(fromId);
@@ -14,7 +14,7 @@ public class OtherUtil {
     }
 
     public static TcpModel SOSCancel(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.SOS);
         tcpModel.setAction(TcpAction.SOSAction.CANCEL);
         tcpModel.setFromId(fromId);

+ 5 - 5
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/PhoneUtil.java

@@ -9,7 +9,7 @@ public class PhoneUtil {
 
     //电话呼出
     public static TcpModel phoneCall(Integer fromId, Integer toId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.PHONE);
         tcpModel.setAction(TcpAction.PhoneAction.CALL);
         tcpModel.setFromId(fromId);
@@ -19,7 +19,7 @@ public class PhoneUtil {
 
     //电话取消
     public static TcpModel phoneCancel(Integer fromId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.PHONE);
         tcpModel.setAction(TcpAction.PhoneAction.CANCEL);
         tcpModel.setFromId(fromId);
@@ -28,7 +28,7 @@ public class PhoneUtil {
 
     //电话接听
     public static TcpModel phoneAccept(Integer fromId, InteractionVO interactionVO){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.PHONE);
         tcpModel.setAction(TcpAction.PhoneAction.ACCEPT);
         tcpModel.setFromId(fromId);
@@ -38,7 +38,7 @@ public class PhoneUtil {
 
     //电话拒接
     public static TcpModel phoneReject(Integer fromId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.PHONE);
         tcpModel.setAction(TcpAction.PhoneAction.REJECT);
         tcpModel.setFromId(fromId);
@@ -47,7 +47,7 @@ public class PhoneUtil {
 
     //电话挂断
     public static TcpModel phoneHandoff(Integer fromId, InteractionVO interactionVO){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.PHONE);
         tcpModel.setAction(TcpAction.PhoneAction.HANDOFF);
         tcpModel.setFromId(fromId);

+ 33 - 29
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/channel/VoiceUtil.java

@@ -1,6 +1,5 @@
 package com.wdkl.ncs.android.middleware.tcp.channel;
 
-import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
 import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
@@ -9,9 +8,10 @@ import java.util.HashMap;
 import java.util.Map;
 
 public class VoiceUtil {
-    //护士呼叫 不要toId
+    //tid1,fromId,data:{roleType:NURSE}
+    //带toId指定了目标设备的不用传roleType
     public static TcpModel voiceCall(Integer fromId, Integer toId){
-        TcpModel tcpModel = new TcpModel();
+        TcpModel tcpModel = new TcpModel(null);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.CALL);
         tcpModel.setFromId(fromId);
@@ -29,84 +29,88 @@ public class VoiceUtil {
 //        return tcpModel;
 //    }
 
-    public static TcpModel voiceAccept(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+
+    public static TcpModel voiceAccept(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.ACCEPT);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
+        tcpModel.setData(interactionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceReject(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceReject(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.REJECT);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
+        tcpModel.setData(interactionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceCalling(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceCalling(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.CALLING);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
+        tcpModel.setData(interactionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceCancel(Integer fromId, Integer toId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceCancel(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.CANCEL);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
+        if (interactionId != null) {
+            tcpModel.setData(interactionId);
+        }
         return tcpModel;
     }
 
-    public static TcpModel voiceHandoff(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceHandoff(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.HANDOFF);
         tcpModel.setFromId(fromId);
-        tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
+        if (toId != -1) {
+            tcpModel.setToId(toId);
+        }
+        tcpModel.setData(interactionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceSuccess(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceSuccess(String tid, Integer fromId, Integer toId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.SUCCESS);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceFailed(Integer fromId, Integer toId,Integer InteractionId){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceFailed(String tid, Integer fromId, Integer toId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.FAILED);
         tcpModel.setFromId(fromId);
         tcpModel.setToId(toId);
-        tcpModel.setData(InteractionId);
+        tcpModel.setData(interactionId);
         return tcpModel;
     }
 
-    public static TcpModel voiceTransfer(Integer fromId, Integer toId, Object interactionVO){
-        TcpModel tcpModel = new TcpModel();
+    public static TcpModel voiceTransfer(String tid, Integer fromId, Integer deviceId, Integer interactionId){
+        TcpModel tcpModel = new TcpModel(tid);
         tcpModel.setType(TcpType.VOICE);
         tcpModel.setAction(TcpAction.VoiceAction.TRANSFER);
         tcpModel.setFromId(fromId);
-        tcpModel.setToId(toId);
         Map map = new HashMap<String,String>();
-        map.put("deviceId",toId);
-        map.put("interactionVo",interactionVO);
+        map.put("deviceId",deviceId);
+        map.put("itId",interactionId);
         tcpModel.setData(map);
         return tcpModel;
     }

+ 33 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpCallback.java

@@ -0,0 +1,33 @@
+package com.wdkl.ncs.android.middleware.tcp.dto;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * 描述
+ *
+ * @author allen
+ * 2022-11-01 12:10
+ */
+public class TcpCallback {
+    public static final String CALLBACK = "CALLBACK";
+    public static final String CALLBACK_SUCCESS = "send success";
+    public static final String CALLBACK_FAIL = "send fail";
+
+    private String tid;
+
+    public TcpCallback(String tid){
+        this.tid = tid;
+    }
+
+    public void onSuccess(JSONObject jsonObject){
+
+    }
+
+    public void onFailed(JSONObject jsonObject){
+
+    }
+
+    public String getTid() {
+        return tid;
+    }
+}

+ 39 - 77
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpModel.java

@@ -3,14 +3,12 @@ package com.wdkl.ncs.android.middleware.tcp.dto;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.google.common.base.Strings;
-import com.wdkl.ncs.android.middleware.model.dos.DeviceDO;
-import com.wdkl.ncs.android.middleware.model.dos.FrameDO;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction;
 import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
 
+import org.bson.types.ObjectId;
+
 import java.io.Serializable;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * tcp传输对象
@@ -19,6 +17,7 @@ import java.util.Map;
  * 2021-03-30 11:49
  */
 public class TcpModel implements Serializable {
+    private String tid;
     /**
      * TCP传输对象的类型
      */
@@ -42,6 +41,26 @@ public class TcpModel implements Serializable {
      */
     private Object data;
 
+    public TcpModel(){
+        //this.tid = new ObjectId().toString();
+    }
+
+    public TcpModel(String tid){
+        if (Strings.isNullOrEmpty(tid)) {
+            this.tid = new ObjectId().toString();
+        } else {
+            this.tid = tid;
+        }
+    }
+
+    public String getTid() {
+        return tid;
+    }
+
+    public void setTid(String tid) {
+        this.tid = tid;
+    }
+
     public TcpType getType() {
         return type;
     }
@@ -74,7 +93,7 @@ public class TcpModel implements Serializable {
         this.toId = toId;
     }
 
-    public Object  getData() {
+    public Object getData() {
         return data;
     }
 
@@ -82,17 +101,18 @@ public class TcpModel implements Serializable {
         this.data = data;
     }
 
-    public String toJson(){
+    public String toJson() {
         return JSON.toJSONString(this);
     }
 
-    public static TcpModel getModelByJson(String tcpModelJsonString){
-        if (Strings.isNullOrEmpty(tcpModelJsonString)){
+    public static TcpModel getModelByJson(String tcpModelJsonString) {
+        if (Strings.isNullOrEmpty(tcpModelJsonString)) {
             return null;
         }
         TcpModel tcpModel = new TcpModel();
 
         JSONObject jsonObject = JSON.parseObject(tcpModelJsonString);
+        String tid = jsonObject.getString("tid");
         String type = jsonObject.getString("type");
         String action = jsonObject.getString("action");
         Integer fromId = jsonObject.getInteger("fromId");
@@ -101,7 +121,7 @@ public class TcpModel implements Serializable {
 
         TcpType tcpType = TcpType.fromString(type);
         TcpAction tcpAction = null;
-        switch (tcpType){
+        switch (tcpType) {
             case CALLBACK:
                 tcpAction = TcpAction.CallbackAction.fromString(action);
                 break;
@@ -138,8 +158,18 @@ public class TcpModel implements Serializable {
             case PHONE:
                 tcpAction = TcpAction.PhoneAction.fromString(action);
                 break;
+            case SIDE:
+                tcpAction = TcpAction.SideAction.fromString(action);
+                break;
+            case REINFORCE:
+                tcpAction = TcpAction.ReinforceAction.fromString(action);
+                break;
+            case ENTRACEGUARD:
+                tcpAction = TcpAction.EntraceGuardAction.fromString(action);
+                break;
         }
 
+        tcpModel.setTid(tid);
         tcpModel.setType(tcpType);
         tcpModel.setAction(tcpAction);
         tcpModel.setToId(toId);
@@ -148,72 +178,4 @@ public class TcpModel implements Serializable {
 
         return tcpModel;
     }
-
-    public static String callbackSuccess(){
-        TcpModel tcpModel = new TcpModel();
-        tcpModel.setType(TcpType.CALLBACK);
-        tcpModel.setAction(TcpAction.CallbackAction.SUCCESS);
-        return tcpModel.toJson();
-    }
-
-    public static String callbackFailed(){
-        TcpModel tcpModel = new TcpModel();
-        tcpModel.setType(TcpType.CALLBACK);
-        tcpModel.setAction(TcpAction.CallbackAction.FAILED);
-        return tcpModel.toJson();
-    }
-
-    public static String refresh() {
-        TcpModel tcpModel = new TcpModel();
-        tcpModel.setType(TcpType.DATA);
-        tcpModel.setAction(TcpAction.DataAction.REFRESH);
-        return tcpModel.toJson();
-    }
-
-
-    public static String interaction() {
-        TcpModel tcpModel = new TcpModel();
-        tcpModel.setType(TcpType.DATA);
-        tcpModel.setAction(TcpAction.DataAction.INTERACTION);
-        return tcpModel.toJson();
-    }
-
-    /**
-     * 示例
-     * @param args
-     */
-    public static void main(String[] args) {
-        //创建对象示例
-        TcpModel tcpModel = new TcpModel();
-        tcpModel.type = TcpType.VOICE;
-        tcpModel.action = TcpAction.VoiceAction.CALL;
-
-        Map map = new HashMap();
-
-        DeviceDO deviceDO = new DeviceDO();
-        deviceDO.setCode("123");
-        deviceDO.setEthMac("abcd");
-        map.put("device",deviceDO);
-
-        FrameDO frameDO = new FrameDO();
-        frameDO.setName("ok");
-        map.put("frame",frameDO);
-
-        tcpModel.setData(map);
-
-        System.out.println("enum show === " + tcpModel.action.getDescription() + " -- " + tcpModel.action.getName());
-
-        //要传输的json字符串
-        String jsonStr = tcpModel.toJson();
-        System.out.println("json show === " + jsonStr);
-
-        //获利传输的JSON字符串,转换为对象
-        TcpModel dTcpModel = TcpModel.getModelByJson(jsonStr);
-        //数据反转
-        String dataString = dTcpModel.getData().toString();
-        JSONObject dataJSON = JSON.parseObject(dataString);
-        DeviceDO dDeviceDO = JSON.parseObject(dataJSON.getString("device"),DeviceDO.class);
-
-        System.out.println("json de show === " + dTcpModel.action + " -- " + dDeviceDO.getEthMac());
-    }
 }

+ 49 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/dto/TcpSendModel.java

@@ -0,0 +1,49 @@
+package com.wdkl.ncs.android.middleware.tcp.dto;
+
+import java.io.Serializable;
+
+/**
+ * 描述
+ *
+ * @author allen
+ * 2022-11-28 11:23
+ */
+public class TcpSendModel implements Serializable {
+    private String tid;
+    private String msg;
+    //第一次发出的时间戳,比对一定时间后清除缓存
+    private Long ts;
+
+    @Override
+    public String toString() {
+        return "TcpSendModel{" +
+                "tid='" + tid + '\'' +
+                ", msg='" + msg + '\'' +
+                ", ts=" + ts +
+                '}';
+    }
+
+    public String getTid() {
+        return tid;
+    }
+
+    public void setTid(String tid) {
+        this.tid = tid;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public Long getTs() {
+        return ts;
+    }
+
+    public void setTs(Long ts) {
+        this.ts = ts;
+    }
+}

+ 106 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/RoleTypeEnum.java

@@ -0,0 +1,106 @@
+package com.wdkl.ncs.android.middleware.tcp.enums;
+
+import com.alibaba.fastjson.JSONObject;
+import com.wdkl.ncs.android.middleware.model.dos.RoleDO;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * @author
+ * @title: Vothin
+ * @projectName nc
+ * @date 2021/5/1910:29
+ */
+public enum RoleTypeEnum {
+    ADMINISTRATORS(1, "管理员"),
+    DOCTOR(2, "医生"),
+    NURSE(3, "护士"),
+    WORKER(4, "护工"),
+    NURSE_SUPERVISOR(5, "护士主管"),
+    DIETITIAN(6, "营养师"),
+    HOUSEKEEPER(7, "管家"),
+    NURSE_HEAD(8, "护士组长"),
+    LIFE_ASSISTANT(9, "生活助理");
+    private final int value;
+    private final String typeName;
+
+
+    RoleTypeEnum(int value, String typeName) {
+        this.value = value;
+        this.typeName = typeName;
+    }
+
+    public int value() {
+        return this.value;
+    }
+
+    public String typeName() {
+        return this.typeName;
+    }
+
+    /**
+     * 通过typeName 转换成枚举
+     *
+     * @param typeName
+     * @return
+     */
+    public static RoleTypeEnum parse(String typeName) {
+        RoleTypeEnum[] values = RoleTypeEnum.values();
+        for (RoleTypeEnum value : values) {
+            if (value.typeName().equals(typeName)) {
+                return value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 通过value值转换成枚举
+     *
+     * @param value
+     * @return
+     */
+    public static RoleTypeEnum parse(int value) {
+        RoleTypeEnum[] values = RoleTypeEnum.values();
+        for (RoleTypeEnum roleTypeEnum : values) {
+            if (roleTypeEnum.value() == value) {
+                return roleTypeEnum;
+            }
+        }
+        return null;
+    }
+
+
+    /**
+     * 把角色DO转换为 RoleTypeEnum
+     * @param roleDO
+     * @return
+     */
+
+    public static RoleTypeEnum parse(RoleDO roleDO) {
+        RoleTypeEnum[] values = RoleTypeEnum.values();
+        for (RoleTypeEnum roleTypeEnum : values) {
+            if (roleTypeEnum.name().equals(roleDO.getRoleType())) {
+                return roleTypeEnum;
+            }
+        }
+        return null;
+    }
+
+
+    public static List getNames(){
+        RoleTypeEnum[] values = RoleTypeEnum.values();
+
+        return Arrays.stream(values).map(p-> {
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("key",p.name());
+            jsonObject.put("typeName",p.typeName());
+            return jsonObject;
+        }).collect(Collectors.toList());
+    }
+
+
+
+}

+ 13 - 6
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/TcpAction.java

@@ -15,7 +15,7 @@ public interface TcpAction {
 
     enum CallbackAction implements TcpAction {
         ACK("反馈"),
-        SUCCESS("成功"),
+        SUCCESS("同步"),
         FAILED("失败"),
         NO_MATCH("没有匹配");
         private final String description;
@@ -89,7 +89,7 @@ public interface TcpAction {
         HANDOFF("挂断"),
         CANCEL("取消"),
         PCALLING("已经通话中"),
-        VOICE_OFF("通话被接听"),
+        VOICE_OFF("通话被其他设备处理"),
         RS485CALL("485界面发起呼叫"),
         RS485CANCEL("485界面呼叫取消"),
         RS485CANCEL_BY_DOOR("485门口机取消房间内的呼叫"),
@@ -176,9 +176,9 @@ public interface TcpAction {
 
 
     enum SOSAction implements TcpAction {
-        CALL("紧急呼叫"),
-        CANCEL("取消"),
-        CANCELED("已取消"),
+        CALL("紧急呼叫"),   //1
+        CANCEL("取消"),   //1
+        CANCELED("已取消"),    //1
         TRANSFER("转接"),
         ALARM_TEST("测试报警"),
         ALARM_INTRUSION("侵入报警"),
@@ -200,7 +200,11 @@ public interface TcpAction {
         AlARM_BUTTON("紧急按钮"),
         ALARM_FALL_RADAR("跌到报警"),
         ALARM_INFUSION_RADAR("输液报警"),
-        ROOM_CALL("房间紧急呼叫"),
+        ROOM_CALL("房间紧急呼叫"),    //1
+        OTHER_CALL("其他紧急呼叫"),   //1
+        RECEIVED("客户端收到确认"),
+        // 当设备在科室级时用这个PART_USER_CALL,比如:用户手环
+        PART_USER_CALL("用户紧急呼叫"),   //
         NO_MATCH("没有匹配");
 
         private final String description;
@@ -325,6 +329,8 @@ public interface TcpAction {
 
     enum DeviceAction implements TcpAction {
         RESTART("重启"),
+        REBOOT("重启机器"),
+        OPEN_DEBUG("打开网络调试"),
         CONNECT("连接"),
         APP_UPDATE("APP更新"),
         DEVICE_REFRESH("设备刷新"),
@@ -365,6 +371,7 @@ public interface TcpAction {
         RECEIVED("接收端收到确认"),
         CANCEL("取消"),
         CANCEL_CONFIRM("接收端确认收到取消"),
+        NO_TARGET("没有目标设备"),
         COMPLETED("完成"),
         NO_MATCH("没有匹配");
         private final String description;

+ 6 - 3
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/enums/TcpType.java

@@ -8,16 +8,19 @@ import java.util.Map;
  */
 public enum TcpType {
     CALLBACK("TCP反馈"),
-    VOICE("语音"),
     PHONE("普通电话"),
+    VOICE("语音"),
     VIDEO("视频"),
     SOS("紧急呼叫"),
+    REINFORCE("增援"),
     IM("留言"),
-    CHANNELIM("频道对讲留言"),
+    EVENT("事件"),
+    SIDE("边外信息"),
     DEVICE("设备"),
     DATA("数据"),
-    EVENT("事件"),
     BROADCAST("广播"),
+    ENTRACEGUARD("门禁"),
+    CHANNELIM("频道留言"),
     TIME("时间");
 
     private String description;

+ 483 - 0
middleware/src/main/code/com/wdkl/ncs/android/middleware/tcp/util/DateUtil.java

@@ -0,0 +1,483 @@
+package com.wdkl.ncs.android.middleware.tcp.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * 日期相关的操作
+ *
+ * @author Dawei
+ */
+
+@SuppressWarnings({"AlibabaCollectionInitShouldAssignCapacity", "AlibabaUndefineMagicConstant"})
+public class DateUtil {
+    /**
+     * 一天的秒数
+     */
+    public static final long ONE_DAY = 86400;
+
+    /**
+     * 获取当前格式化后的时间
+     * @return
+     */
+    public static String formatNow() {
+        return DateUtil.toString(new Date(), "yyyy-MM-dd HH:mm:ss");
+    }
+    /**
+     * 当天的开始时间
+     *
+     * @return
+     */
+    public static long startOfTodDay() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 将 Sun Apr 15 04:12:39 CST 2018 格式的时间转换为时间戳
+     *
+     * @param dateFormat Sun Apr 15 04:12:39 CST 2018 格式的时间
+     * @return 时间戳
+     */
+    public static long getFormatDate(String dateFormat) {
+        try {
+            SimpleDateFormat sdf1 = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
+
+            return sdf1.parse(dateFormat).getTime() / 1000;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return 0;
+    }
+
+    public static long startOfDay(String s) {
+        Date date = null;
+        Calendar calendar= Calendar.getInstance();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            date = simpleDateFormat.parse(s);
+            calendar.setTime(date);
+        } catch (Exception e) {
+        }
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        long start = calendar.getTime().getTime()/1000;
+        return start;
+    }
+
+    public static long endOfDay(String s) {
+        Date date = null;
+        Calendar calendar= Calendar.getInstance();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+        try {
+            date = simpleDateFormat.parse(s);
+            calendar.setTime(date);
+        } catch (Exception e) {
+        }
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        long start = calendar.getTime().getTime()/1000;
+        return start;
+    }
+
+
+
+    /**
+     * 当天的结束时间
+     *
+     * @return
+     */
+    public static long endOfTodDay() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 昨天的开始时间
+     *
+     * @return
+     */
+    public static long startOfyesterday() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.add(Calendar.DATE, -1);
+        calendar.set(Calendar.MILLISECOND, 0);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 昨天的结束时间
+     *
+     * @return
+     */
+    public static long endOfyesterday() {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 23);
+        calendar.set(Calendar.MINUTE, 59);
+        calendar.set(Calendar.SECOND, 59);
+        calendar.set(Calendar.MILLISECOND, 999);
+        calendar.add(Calendar.DATE, -1);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 某天的开始时间
+     *
+     * @param dayUntilNow 距今多少天以前
+     * @return 时间戳
+     */
+    public static long startOfSomeDay(int dayUntilNow) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.add(Calendar.DATE, -dayUntilNow);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 某天的开始时间
+     *
+     * @param dayUntilNow 距今多少天以后
+     * @return 时间戳
+     */
+    public static long endOfSomeDay(int dayUntilNow) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.add(Calendar.DATE, +dayUntilNow);
+        Date date = calendar.getTime();
+        return date.getTime() / 1000;
+    }
+
+    /**
+     * 某天的年月日
+     *
+     * @param dayUntilNow 距今多少天以前
+     * @return 年月日map key为 year month day
+     */
+    public static Map<String, Object> getYearMonthAndDay(int dayUntilNow) {
+
+        Map<String, Object> map = new HashMap<String, Object>(3);
+        Calendar calendar = Calendar.getInstance();
+        calendar.set(Calendar.HOUR_OF_DAY, 0);
+        calendar.set(Calendar.MINUTE, 0);
+        calendar.set(Calendar.SECOND, 0);
+        calendar.set(Calendar.MILLISECOND, 0);
+        calendar.add(Calendar.DATE, -dayUntilNow);
+        map.put("year", calendar.get(Calendar.YEAR));
+        map.put("month", calendar.get(Calendar.MONTH) + 1);
+        map.put("day", calendar.get(Calendar.DAY_OF_MONTH));
+        return map;
+    }
+
+    /**
+     * 将一个字符串转换成日期格式
+     *
+     * @param date
+     * @param pattern
+     * @return
+     */
+    public static Date toDate(String date, String pattern) {
+        if ("".equals("" + date)) {
+            return null;
+        }
+        if (pattern == null) {
+            pattern = "yyyy-MM-dd";
+        }
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        Date newDate = new Date();
+        try {
+            newDate = sdf.parse(date);
+
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return newDate;
+    }
+
+    /**
+     * 获取上个月的开始结束时间
+     *
+     * @return
+     */
+    public static Long[] getLastMonth() {
+        // 取得系统当前时间
+        Calendar cal = Calendar.getInstance();
+        int year = cal.get(Calendar.YEAR);
+        int month = cal.get(Calendar.MONTH) + 1;
+
+        // 取得系统当前时间所在月第一天时间对象
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+
+        // 日期减一,取得上月最后一天时间对象
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+
+        // 输出上月最后一天日期
+        int day = cal.get(Calendar.DAY_OF_MONTH);
+
+        String months = "";
+        String days = "";
+
+        if (month > 1) {
+            month--;
+        } else {
+            year--;
+            month = 12;
+        }
+        if (!(String.valueOf(month).length() > 1)) {
+            months = "0" + month;
+        } else {
+            months = String.valueOf(month);
+        }
+        if (!(String.valueOf(day).length() > 1)) {
+            days = "0" + day;
+        } else {
+            days = String.valueOf(day);
+        }
+        String firstDay = "" + year + "-" + months + "-01";
+        String lastDay = "" + year + "-" + months + "-" + days + " 23:59:59";
+
+        Long[] lastMonth = new Long[2];
+        lastMonth[0] = DateUtil.getDateline(firstDay);
+        lastMonth[1] = DateUtil.getDateline(lastDay, "yyyy-MM-dd HH:mm:ss");
+
+        return lastMonth;
+    }
+
+    public static Long[] getMonthStartEnd(String year, String month){
+        Integer monthInt = Integer.parseInt(month);
+        if (monthInt<0 || monthInt>12){
+            return null;
+        }
+
+        Date date = null;
+        Calendar cal= Calendar.getInstance();
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM");
+        try {
+            date = simpleDateFormat.parse(year+'-'+month);
+            cal.setTime(date);
+        } catch (Exception e) {
+        }
+
+        // 输出下月第一天日期
+        int notMonth = monthInt + 1;
+        // 取得系统当前时间所在月第一天时间对象
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+
+        // 日期减一,取得上月最后一天时间对象
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+        cal.set(Calendar.MILLISECOND, 0);
+
+        //long start = cal.getTime().getTime()/1000;
+
+        String months = "";
+        String nextMonths = "";
+
+        if (!(String.valueOf(monthInt).length() > 1)) {
+            months = "0" + monthInt;
+        } else {
+            months = String.valueOf(monthInt);
+        }
+        if (!(String.valueOf(notMonth).length() > 1)) {
+            nextMonths = "0" + notMonth;
+        } else {
+            nextMonths = String.valueOf(notMonth);
+        }
+        String firstDay = "" + year + "-" + months + "-01 00:00:00";
+        String lastDay = "" + year + "-" + nextMonths + "-01 00:00:00";
+        Long[] currentMonth = new Long[2];
+        currentMonth[0] = DateUtil.getDateline(firstDay,"yyyy-MM-dd HH:mm:ss");
+        currentMonth[1] = DateUtil.getDateline(lastDay,"yyyy-MM-dd HH:mm:ss");
+
+        return currentMonth;
+    }
+
+    /**
+     * 获取当月的开始结束时间
+     *
+     * @return
+     */
+    public static Long[] getCurrentMonth() {
+        // 取得系统当前时间
+        Calendar cal = Calendar.getInstance();
+        int year = cal.get(Calendar.YEAR);
+        int month = cal.get(Calendar.MONTH) + 1;
+        // 输出下月第一天日期
+        int notMonth = cal.get(Calendar.MONTH) + 2;
+        // 取得系统当前时间所在月第一天时间对象
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+
+        // 日期减一,取得上月最后一天时间对象
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+
+        String months = "";
+        String nextMonths = "";
+
+        if (!(String.valueOf(month).length() > 1)) {
+            months = "0" + month;
+        } else {
+            months = String.valueOf(month);
+        }
+        if (!(String.valueOf(notMonth).length() > 1)) {
+            nextMonths = "0" + notMonth;
+        } else {
+            nextMonths = String.valueOf(notMonth);
+        }
+        String firstDay = "" + year + "-" + months + "-01";
+        String lastDay = "" + year + "-" + nextMonths + "-01";
+        Long[] currentMonth = new Long[2];
+        currentMonth[0] = DateUtil.getDateline(firstDay);
+        currentMonth[1] = DateUtil.getDateline(lastDay);
+
+        return currentMonth;
+    }
+
+    /**
+     * 获取某年开始结束时间
+     *
+     * @return
+     */
+    public static Long[] getYearTime(Integer year) {
+
+
+        Calendar firstCal = Calendar.getInstance();
+        firstCal.set(Calendar.YEAR, year - 1);
+        firstCal.set(Calendar.MONTH, Calendar.DECEMBER);
+        firstCal.set(Calendar.DATE, 31);
+
+        Calendar lastCal = Calendar.getInstance();
+        lastCal.set(Calendar.YEAR, year);
+        lastCal.set(Calendar.MONTH, Calendar.DECEMBER);
+        lastCal.set(Calendar.DATE, 31);
+
+        Long[] yearTime = new Long[2];
+        yearTime[0] = firstCal.getTime().getTime() / 1000;
+        yearTime[1] = lastCal.getTime().getTime() / 1000;
+
+        return yearTime;
+    }
+
+    /**
+     * 把日期转换成字符串型
+     *
+     * @param date
+     * @param pattern
+     * @return
+     */
+    public static String toString(Date date, String pattern) {
+        if (date == null) {
+            return "";
+        }
+        if (pattern == null) {
+            pattern = "yyyy-MM-dd";
+        }
+        String dateString = "";
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        try {
+            dateString = sdf.format(date);
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return dateString;
+    }
+
+    public static String toString(Long time, String pattern) {
+        if (time > 0) {
+            if (time.toString().length() == 10) {
+                time = time * 1000;
+            }
+            Date date = new Date(time);
+            String str = DateUtil.toString(date, pattern);
+            return str;
+        }
+        return "";
+    }
+
+    /**
+     * 为了方便mock 设置此属性
+     * 如果设置了此属性,则回直接返回设置的值
+     */
+    public static Long mockDate;
+
+    public static long getDateline() {
+        if (mockDate != null) {
+            return mockDate;
+        }
+        return System.currentTimeMillis() / 1000;
+    }
+
+    /**
+     * 判断当前时间是否在某个时间范围
+     *
+     * @param start 开始时间,以秒为单位的时间戳
+     * @param end   结束时间,以秒为单位的时间戳
+     * @return 是否在范围内
+     */
+    public static boolean inRangeOf(long start, long end) {
+        long now = getDateline();
+        return start <= now && end >= now;
+    }
+
+    public static long getDateline(String date) {
+        return toDate(date, "yyyy-MM-dd").getTime() / 1000;
+    }
+
+    public static long getDateHaveHour(String date) {
+        return toDate(date, "yyyy-MM-dd HH").getTime() / 1000;
+    }
+
+    public static long getDateline(String date, String pattern) {
+        return toDate(date, pattern).getTime() / 1000;
+    }
+
+    /**
+     * 查当前日期是一周中的星期几
+     * @return 1=Sunday,,,7=Saturday
+     */
+    public static long getDayOfWeek(Date date){
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        return cal.get(Calendar.DAY_OF_WEEK);// 1=Sunday,,,7=Saturday
+    }
+
+    public static long getDayOfWeekForMonBegin(Date date){
+        long week=getDayOfWeek(date);
+         if(week== Calendar.SUNDAY)return 7;
+         else return week-1;
+    }
+
+    public static String getNowStrForRs485(){
+        Date date = new Date();
+        String nowString = DateUtil.toString(date, "yyyy-MM-dd HH:mm:ss");
+        nowString += " " + getDayOfWeekForMonBegin(date);
+        return nowString;
+    }
+
+}

+ 1 - 1
resource/src/main/res/values-es/strings.xml

@@ -84,7 +84,7 @@
     <string name="call_error">Error de conexión</string>
     <string name="call_reject">Rechazar</string>
     <string name="call_busy">Ocupado</string>
-    <string name="call_incoming">Nueva llamada…</string>
+    <string name="call_incoming">llamada.</string>
     <string name="call_failed">Error de llamada</string>
     <string name="call_end">Fin de llamada</string>
     <string name="str_call_mute">Silencio</string>

+ 1 - 1
resource/src/main/res/values-ru/strings.xml

@@ -83,7 +83,7 @@
     <string name="call_error">Ошибка подключения</string>
     <string name="call_reject">Отклонить</string>
     <string name="call_busy">Занят</string>
-    <string name="call_incoming">Новый звонок…</string>
+    <string name="call_incoming">звонок.</string>
     <string name="call_failed">Ошибка вызова</string>
     <string name="call_end">Завершение вызова</string>
     <string name="str_call_mute">Отключить звук</string>

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

@@ -84,7 +84,7 @@
     <string name="call_error">通话错误</string>
     <string name="call_reject">对方拒绝</string>
     <string name="call_busy">对方忙线中</string>
-    <string name="call_incoming">新来电…</string>
+    <string name="call_incoming">来电.</string>
     <string name="call_failed">对方离线或不存在,呼叫失败</string>
     <string name="call_end">通话结束</string>
     <string name="str_call_mute">静音</string>

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

@@ -84,7 +84,7 @@
     <string name="call_error">Connect error</string>
     <string name="call_reject">Reject</string>
     <string name="call_busy">Busy</string>
-    <string name="call_incoming">New call…</string>
+    <string name="call_incoming">Incoming call.</string>
     <string name="call_failed">Call error</string>
     <string name="call_end">Call end</string>
     <string name="str_call_mute">Mute</string>