فهرست منبع

1.加入护士主机模块
2。增加门口机竖屏ui
3。解决了一些适配

xunchuanzhi 1 سال پیش
والد
کامیت
260b36ad12
100فایلهای تغییر یافته به همراه18470 افزوده شده و 4 حذف شده
  1. 0 2
      android_bed/build.gradle
  2. 3 0
      android_bed/src/main/java/com/wdkl/app/ncs/callingbed/fragment/SkyCallFragment.kt
  3. BIN
      android_bed/src/main/res/mipmap-mdpi/bg.png
  4. 205 0
      android_bed/src/main/res/values-es/strings.xml
  5. 206 0
      android_bed/src/main/res/values-ru/strings.xml
  6. 207 2
      android_bed/src/main/res/values-zh/strings.xml
  7. 1 0
      android_host/.gitignore
  8. 129 0
      android_host/build.gradle
  9. 21 0
      android_host/proguard-rules.pro
  10. 101 0
      android_host/src/main/AndroidManifest.xml
  11. BIN
      android_host/src/main/assets/launch.apk
  12. BIN
      android_host/src/main/assets/wd_update_plugin.apk
  13. 16 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/SipUtil/SipCallBack.java
  14. 661 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/SipUtil/SipHelperUtil.java.bak
  15. 149 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/AppUpdateActivity.kt
  16. 202 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/CallActivity.java
  17. 382 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/CallingHostActivationActivity.kt
  18. 2143 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/NurseHomeActivity.kt
  19. 428 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/RegisterActivity.kt
  20. 103 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/TestActivity.kt
  21. 76 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/BedItemAdapter.java
  22. 93 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/BroadcastAdapter.kt
  23. 366 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CallRecordsItemAdapter.kt
  24. 171 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CallingItemAdapter.kt
  25. 103 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CostItemAdapter.kt
  26. 76 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/DoctorHostAdapter.kt
  27. 103 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/ExamAdapter.kt
  28. 121 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedAdapter.kt
  29. 60 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosAdapter.kt
  30. 148 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosConfinementAdapter.kt
  31. 108 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FramePartItemAdapter.kt
  32. 44 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/InpatientWardAdapter.kt
  33. 65 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/LedItemAdapter.kt
  34. 56 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/NumAdapter.java
  35. 70 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/NurseMoveAdapter.kt
  36. 74 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/OtherHostAdapter.kt
  37. 71 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/ResponsibilityBedAdapter.kt
  38. 58 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/SickbedAdapter.kt
  39. 69 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/VisitManagementAdapter.kt
  40. 104 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/agreement/FloorActionAgreement.kt
  41. 35 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/di/NurseHomeComponent.kt
  42. 42 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/RebootDialogHelper.java
  43. 76 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/ServicesDialogHelper.java
  44. 70 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/SystemDialogHelper.java
  45. 98 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BaseCallFragment.kt
  46. 128 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BedsInTheWardFragment.kt
  47. 336 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BroadcastFragment.kt
  48. 436 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/CallRecordsFragment.kt
  49. 177 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/DoctorHostFragment.kt
  50. 246 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/EntraceGuardVideoFragment.kt
  51. 273 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/EntraceGuardVideoFragment.kt.bak
  52. 495 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/FramePartFragment.kt
  53. 143 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/InpatientWardFragment.kt
  54. 277 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/LedSettingsFragment.kt
  55. 198 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/NurseMoveFragment.kt
  56. 185 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/OtherHostFragment.kt
  57. 112 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SickbedFragment.kt
  58. 304 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SipCallFragment.kt
  59. 432 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SkyCallFragment.kt
  60. 787 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SystemSettingsFragment.kt
  61. 202 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/TestFragment.kt
  62. 85 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/TrustManagementFragment.kt
  63. 173 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/VisitManagementFragment.kt
  64. 58 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/HardTools.java
  65. 27 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/HardWareFactroy.java
  66. 158 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/imp/Z3128HardTools.java
  67. 126 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/helper/RecordHelper.java
  68. 83 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/helper/SoundPoolManager.java
  69. 24 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/launch/NurseHomeLaunch.kt
  70. 576 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedC2MManager.java
  71. 59 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedItem.java
  72. 52 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedManager.java
  73. 104 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedManagerUtils.java
  74. 28 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedProgram.java
  75. 100 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/AppService.kt
  76. 215 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/RTCKeepLiveService.java.bak
  77. 330 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/WdklSipService.java
  78. 839 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/settingconfig/SettingConfig.java
  79. 265 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AppUpdateHelper.java
  80. 149 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AppUtil.java
  81. 199 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AsyncPlayer.java
  82. 92 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/CallDialogHelper.java
  83. 14 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/EthernetWifiCallBack.java
  84. 190 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/HttpHelper.java
  85. 139 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LanguageSetDialogHelper.java
  86. 120 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LedHelper.java
  87. 79 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LocaleMangerUtils.java
  88. 225 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/MediaPlayHelper.java
  89. 571 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/NetHelper.java
  90. 122 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/PasswordDialogHelper.java
  91. 39 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/RingPlayHelper.java
  92. 233 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/SPUtils.java
  93. 81 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/ScreenManagerUtil.kt
  94. 159 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/ServerConfigDialogHelper.java
  95. 255 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/SpeechUtil.java
  96. 87 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/TimeTransition.kt
  97. 102 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/UpdateTipsDialogHelper.java
  98. 73 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/Util.kt
  99. 194 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/VoiceManagerUtil.java
  100. 0 0
      android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/WarningDialogHelper.java

+ 0 - 2
android_bed/build.gradle

@@ -17,8 +17,6 @@ kapt {
 android {
     compileSdkVersion target_sdk_version
     buildToolsVersion build_tools_version
-
-
     defaultConfig {
         minSdkVersion min_sdk_version
         targetSdkVersion target_sdk_version

+ 3 - 0
android_bed/src/main/java/com/wdkl/app/ncs/callingbed/fragment/SkyCallFragment.kt

@@ -539,6 +539,9 @@ class SkyCallFragment: BaseCallFragment(), CallSessionCallback {
         }
     }
 
+    override fun didRoomCreated() {
+    }
+
     //处理本地视频画面
     override fun didCreateLocalVideoTrack() {
         Log.e(TAG, "didCreateLocalVideoTrack")

BIN
android_bed/src/main/res/mipmap-mdpi/bg.png


+ 205 - 0
android_bed/src/main/res/values-es/strings.xml

@@ -0,0 +1,205 @@
+<resources>
+    <string name="app_name">NCS-Host_device_rk</string>
+
+    <string name="download_error">Error de descarga!</string>
+    <string name="download_cancel">Cancelar descarga</string>
+    <string name="update_success">Actualización exitosa</string>
+    <string name="update_fail">Actualización fallida</string>
+    <string name="downloading">Descargar…</string>
+    <string name="updating">Actualizando, espere</string>
+    <string name="update_no_required">Actualmente es la última versión</string>
+    <string name="detect_new_version">Nueva versión detectada, ?actualizar ahora?</string>
+    <string name="plugin_update_tips">plugin service updating, please restart app later</string>
+    <string name="plugin_start_failed">start plugin service failed:</string>
+    <string name="plugin_start_success">plugin service started</string>
+    <string name="plugin_start_error">plugin service start failed, please restart app</string>
+    <string name="enable_debug">Enable debug</string>
+
+    <string name="permission_grant_tips">Otorgue todos los permisos</string>
+    <string name="device_init_fail">Error de datos de inicialización, ?verifíquelo!</string>
+    <string name="device_disabled">Dispositivo desactivado</string>
+    <string name="tts_invalid">TTS no válido</string>
+    <string name="tts_enabled">TTS habilitado</string>
+    <string name="tts_disabled">Inicio de TTS falló, cambie al modo de timbre</string>
+    <string name="call_sos_forwarding">Reenvío de llamadas SOS</string>
+    <string name="call_voice_forwarding">Reenvío de llamadas de voz</string>
+    <string name="call_init_error">Error de red o error de SIPID</string>
+    <string name="call_failed">Llamada fallida</string>
+    <string name="net_error">Error de red</string>
+    <string name="voice_call_speech">%s llamando</string>
+    <string name="sos_call_speech">%s llamada de emergencia</string>
+    <string name="reinforce_call_speech">%s llamada de refuerzo</string>
+    <string name="emergency_call">llamada de emergencia</string>
+    <string name="event_todo">necesita manejar</string>
+    <string name="event_done">Terminado</string>
+    <string name="event_todo_tips">Llamada entrante, primera tarea</string>
+    <string name="voice_message">Mensaje de voz</string>
+
+    <string name="call_video">%s Videollamada</string>
+    <string name="call_visiting">Solicitud de visita</string>
+    <string name="call_entrance_guard">Solicitud de guardia de entrada</string>
+    <string name="call_sos">Llamada de emergencia</string>
+    <string name="call_reinforce">Reforzar llamada</string>
+    <string name="call_door">Máquina de puerta</string>
+    <string name="call_in_list">El dispositivo está en la lista de llamadas</string>
+    <string name="call_no_device">sin ID de dispositivo</string>
+    <string name="extension_connect_fail">extension connect fail</string>
+    <string name="extension_call_busy">extension busy</string>
+    <string name="extension_call_error">extension error</string>
+
+    <string name="cost_subtotal">Subtotal: %f</string>
+    <string name="exam_desc">Descripción: %s</string>
+    <string name="exam_time">Hora: %s</string>
+    <string name="empty_bed">Cama vacía</string>
+    <string name="empty">nulo</string>
+    <string name="call_wait">Por favor espere</string>
+    <string name="no_custom">Cama vacía o sin dispositivo, llamada fallida</string>
+    <string name="no_device">No device</string>
+    <string name="not_support_video_call">Not support video call</string>
+    <string name="led_resolution">Resolución LED: %s</string>
+    <string name="led_voice_on">Voz LED: Encendido</string>
+    <string name="led_voice_off">Voz LED: Apagado</string>
+    <string name="led_font_size">Tama?o de fuente LED: %d</string>
+    <string name="led_info_duration">Duración de información de llamada de LED: %d</string>
+    <string name="led_voice_volume">Volumen de llamada LED: %d</string>
+    <string name="led_voice_times">Tiempos de llamada de LED: %d</string>
+    <string name="less_then">No puede ser menor que: %d</string>
+    <string name="led_no_font">Sin archivo de fuente</string>
+    <string name="led_font_file_size">Tama?o del archivo de fuente: %d</string>
+    <string name="led_null">Sin dispositivo LED</string>
+    <string name="led_sync_time">Tiempo de sincronización de LED</string>
+    <string name="led_reset">Restablecer LED</string>
+    <string name="led_on_off">Encender/apagar</string>
+    <string name="led_check_font">Verificar fuente</string>
+    <string name="led_copy_font">Actualizar fuente</string>
+    <string name="led_default_info">Información predeterminada:</string>
+    <string name="led_show_date">Solo fecha hora</string>
+    <string name="led_add_info">A?adir información personalizada</string>
+
+    <string name="no_response">Sin respuesta</string>
+    <string name="call_video_call">Videollamada</string>
+    <string name="call_in_calling">Llamando</string>
+    <string name="call_connecting">Conectando…</string>
+    <string name="call_in_call">En llamada…</string>
+    <string name="call_disconnect">Desconectar</string>
+    <string name="call_error">Error de llamada</string>
+    <string name="call_reject">Rechazo de llamada</string>
+    <string name="call_busy">Llamada ocupada</string>
+    <string name="call_incoming">Llamada entrante…</string>
+    <string name="settings_success">Configuración exitosa</string>
+    <string name="settings_failed">Configuración fallida</string>
+    <string name="led_show_reinforce">%s Reforzar</string>
+    <string name="led_show_emergency_call">%s SOS</string>
+    <string name="led_show_voice_call">%s llamando</string>
+    <string name="input_password">Por favor ingrese la contrase?a</string>
+    <string name="data_invalid">empty data</string>
+    <string name="invalid_password">contrase?a no válida</string>
+    <string name="confirm_down_time">Confirmar(%d)</string>
+    <string name="visiting_call">%s visitando…</string>
+    <string name="str_home">Inicio</string>
+    <string name="str_broadcast">Transmitir</string>
+    <string name="str_visiting">Visitando</string>
+    <string name="str_doctor">Médico</string>
+    <string name="str_ward">Guardia</string>
+    <string name="str_sick_bed">Cama</string>
+    <string name="str_mobile">Móvil</string>
+    <string name="str_other_host">Otro host</string>
+    <string name="str_manage_host">Administrar host</string>
+    <string name="str_trusteeship">Custodia</string>
+    <string name="str_led">LED</string>
+    <string name="str_settings">Configuración</string>
+    <string name="str_delete">Eliminar</string>
+    <string name="str_save">Guardar</string>
+    <string name="setting_day_night_time">Configuración de horario de día y noche</string>
+    <string name="setting_call_type">Tipo de llamada:</string>
+    <string name="setting_call_type_tts">TTS</string>
+    <string name="setting_call_type_ringtone">tono de llamada</string>
+    <string name="setting_call_type_music">música</string>
+    <string name="setting_call_forwarding">Reenvío de llamadas:</string>
+    <string name="setting_call_forwarding_enable">habilitar</string>
+    <string name="setting_call_forwarding_disable">deshabilitar</string>
+    <string name="setting_sos_call_name">SOS name:</string>
+    <string name="setting_loop_call">Loop calling:</string>
+    <string name="setting_call_dismiss_time">Calls auto dismiss time:</string>
+    <string name="setting_call_times">Horarios de llamadas:</string>
+    <string name="setting_sip_enable">SIP enable:</string>
+    <string name="setting_host_device">Dispositivo host</string>
+    <string name="setting_host_device_day_brightness">Host: brillo diurno</string>
+    <string name="setting_host_device_night_brightness">Host: brillo nocturno</string>
+    <string name="setting_host_device_day_volume">Host: volumen diurno</string>
+    <string name="setting_host_device_night_volume">Host: volumen nocturno</string>
+    <string name="setting_host_device_hands_free_volume">Host: volumen de manos libres</string>
+    <string name="setting_host_device_earpiece_volume">Host: volumen del auricular</string>
+    <string name="setting_host_device_call_volume">Host: call volume</string>
+    <string name="setting_bed_device">extensión de cama</string>
+    <string name="setting_bed_device_day_brightness">Extensión: brillo diurno</string>
+    <string name="setting_bed_device_night_brightness">Extensión: brillo nocturno</string>
+    <string name="setting_bed_device_day_led_brightness">Extensión: brillo de día LED</string>
+    <string name="setting_bed_device_night_led_brightness">Extensión: brillo nocturno LED</string>
+    <string name="setting_bed_device_day_volume">Extensión: volumen diurno</string>
+    <string name="setting_bed_device_night_volume">Extensión: volumen nocturno</string>
+    <string name="setting_bed_device_call_volume">Extensión: volumen de llamada</string>
+    <string name="setting_conversion_box_volume">Volumen de dispositivo de conversión</string>
+    <string name="language_settings">Configuración de idioma</string>
+    <string name="system_settings">Configuración del sistema</string>
+    <string name="save_settings">Guardar configuración</string>
+    <string name="language_set_title">Idioma:</string>
+    <string name="language_set_mode">Sync language from server:</string>
+    <string name="str_yes">Yes</string>
+    <string name="str_no">No</string>
+    <string name="str_confirm">Confirmar</string>
+    <string name="str_cancel">Cancelar</string>
+    <string name="register_auto_config">Configuración automática</string>
+    <string name="register_manual_config">Configuración manual</string>
+    <string name="register_reboot">Reiniciar</string>
+    <string name="register_test">Test</string>
+    <string name="register_reload">Recargar</string>
+    <string name="call_record_unhandled">No manejado</string>
+    <string name="call_record_entrance">Entrada</string>
+    <string name="call_record_replay">Reproducción</string>
+    <string name="str_invite">Invitar</string>
+    <string name="str_call">Llamar</string>
+    <string name="str_missed_call">Perdida</string>
+    <string name="str_all_call">Todos</string>
+    <string name="str_other_call">Otros</string>
+    <string name="entrance_call">Llamada de entrada</string>
+    <string name="door_open">Abrir</string>
+    <string name="call_volume_control">activar/desactivar volumen</string>
+    <string name="call_end">Finalizar llamada</string>
+    <string name="voice_call">Voz</string>
+    <string name="video_call">Vídeo</string>
+    <string name="basic_info">Información básica</string>
+    <string name="fees_info">Tarifas</string>
+    <string name="inspection_info">Inspección</string>
+    <string name="indate">Fecha de entrada:</string>
+    <string name="mobile">Móvil:</string>
+    <string name="duty_doctor">Doctor:</string>
+    <string name="duty_nurse">Enfermera:</string>
+    <string name="nursing_configs">Proyectos de enfermería:</string>
+    <string name="orders">Pedidos:</string>
+    <string name="illness">Información de la enfermedad:</string>
+    <string name="reboot_conform">configuración exitosa, ?reiniciar ahora?</string>
+    <string name="new_event_title">Nuevo evento</string>
+    <string name="responsible_bed">responsible bed</string>
+    <string name="str_manager_host">Manager host</string>
+    <string name="server_config">Configuración del servidor</string>
+
+    <string name="broadcast_init_error">Broadcast init error</string>
+    <string name="broadcast_init_success">Broadcast init success</string>
+    <string name="broadcast_start_warning">Please start broadcast</string>
+    <string name="broadcast_start">Start</string>
+    <string name="broadcast_record_start">Start record</string>
+    <string name="broadcast_record_stop">Stop record</string>
+    <string name="broadcast_playing">Broadcast playing…</string>
+    <string name="broadcast_stop">Broadcast stop</string>
+
+    <string name="str_warning">alerta</string>
+    <string name="str_fall_alarm">fall alarm</string>
+    <string name="none_warning">Nadie alerta</string>
+
+    <string name="call_stay_time">Incoming Call timeout</string>
+    <string name="device_managed">El dispositivo está gestionado</string>
+    <string name="cancel_managed">Sin custodia…</string>
+    <string name="trusteeship_confirm">Se administrará el dispositivo y las llamadas se transferirán al dispositivo administrado.</string>
+    <string name="cancel_managed_btn">Mantenga presionada cancelar</string>
+</resources>

+ 206 - 0
android_bed/src/main/res/values-ru/strings.xml

@@ -0,0 +1,206 @@
+<resources>
+    <string name="app_name">NCS-Host_device_rk</string>
+
+
+
+    <string name="download_error">Ошибка загрузки!</string>
+    <string name="download_cancel">Отмена загрузки</string>
+    <string name="update_success">Обновление выполнено</string>
+    <string name="update_fail">Не удалось обновить</string>
+    <string name="downloading">Загрузка…</string>
+    <string name="updating">Обновление, пожалуйста подождите</string>
+    <string name="update_no_required">Установлена последняя версия</string>
+    <string name="detect_new_version">Обнаружена новая версия, обновить сейчас?</string>
+    <string name="plugin_update_tips">plugin service updating, please restart app later</string>
+    <string name="plugin_start_failed">start plugin service failed:</string>
+    <string name="plugin_start_success">plugin service started</string>
+    <string name="plugin_start_error">plugin service start failed, please restart app</string>
+    <string name="enable_debug">Enable debug</string>
+
+    <string name="permission_grant_tips">Предоставьте все разрешения</string>
+    <string name="device_init_fail">Ошибка инициализации данных, проверьте!</string>
+    <string name="device_disabled">Отключить устройство</string>
+    <string name="tts_invalid">Неверный TTS</string>
+    <string name="tts_enabled">TTS включен</string>
+    <string name="tts_disabled">Ошибка инициализации TTS, переключитесь в режим звонка</string>
+    <string name="call_sos_forwarding">Переадресация вызова SOS</string>
+    <string name="call_voice_forwarding">Переадресация голосовых вызовов</string>
+    <string name="call_init_error">Ошибка сети или ошибка sipId</string>
+    <string name="net_error">Сетевая ошибка</string>
+    <string name="call_failed">Вызов не удался</string>
+    <string name="voice_call_speech">%s вызывает</string>
+    <string name="sos_call_speech">экстренный вызов %s</string>
+    <string name="reinforce_call_speech">%s просит помощи</string>
+    <string name="emergency_call">экстренный вызов</string>
+    <string name="event_todo">Задачи</string>
+    <string name="event_done">Готово</string>
+    <string name="event_todo_tips">Сначала входящий вызов</string>
+    <string name="voice_message">Голосовое сообщение</string>
+
+    <string name="call_video">%s video call</string>
+    <string name="call_visiting">Запрос на посещение</string>
+    <string name="call_entrance_guard">Охранник на входе</string>
+    <string name="call_sos">Экстренный вызов</string>
+    <string name="call_reinforce">Вызов усиления</string>
+    <string name="call_door">Дверной звонок</string>
+    <string name="call_in_list">Устройство находится в списке вызовов</string>
+    <string name="call_no_device">Идентификатор устройства равен нулю</string>
+    <string name="extension_connect_fail">extension connect fail</string>
+    <string name="extension_call_busy">extension busy</string>
+    <string name="extension_call_error">extension error</string>
+
+    <string name="cost_subtotal">Итого: %f</string>
+    <string name="exam_desc">Описание: %s</string>
+    <string name="exam_time">Время: %s</string>
+    <string name="empty_bed">Нет</string>
+    <string name="empty">ноль</string>
+    <string name="call_wait">Пожалуйста, подождите</string>
+    <string name="no_custom">Нет пользовательских настроек или устройств, ошибка вызова</string>
+    <string name="no_device">Нет устройства</string>
+    <string name="not_support_video_call">Not support video call</string>
+    <string name="led_resolution">Разрешение экрана: %s</string>
+    <string name="led_voice_on">Голосовая трансляция: вкл.</string>
+    <string name="led_voice_off">Голосовая трансляция: выкл.</string>
+    <string name="led_font_size">Размер шрифта на экране: %d</string>
+    <string name="led_info_duration">Продолжительность показа информации о звонке: %d</string>
+    <string name="led_voice_volume">Громкость звонка: %d</string>
+    <string name="led_voice_times">время вызова экрана: %d</string>
+    <string name="less_then">Не может быть меньше: %d</string>
+    <string name="led_no_font">Нет файла шрифта</string>
+    <string name="led_font_file_size">размер файла шрифта: %d</string>
+    <string name="led_null">Нет устройств с экраном</string>
+    <string name="led_sync_time">время синхронизации экранов</string>
+    <string name="led_reset">Сбросить индикатор</string>
+    <string name="led_on_off">Включить/выключить</string>
+    <string name="led_check_font">Проверить шрифт</string>
+    <string name="led_copy_font">Обновить шрифт</string>
+    <string name="led_default_info">Информация по умолчанию:</string>
+    <string name="led_show_date">Только дата и время</string>
+    <string name="led_add_info">Добавить пользовательскую информацию</string>
+
+    <string name="no_response">Нет ответа</string>
+    <string name="call_video_call">Video call</string>
+    <string name="call_in_calling">Звонок</string>
+    <string name="call_connecting">Подключение…</string>
+    <string name="call_in_call">Разговаривает…</string>
+    <string name="call_disconnect">Отключить</string>
+    <string name="call_error">Ошибка вызова</string>
+    <string name="call_reject">Отклонить вызов</string>
+    <string name="call_busy">Занято</string>
+    <string name="call_incoming">Входящий звонок…</string>
+    <string name="settings_success">Успешно настроено</string>
+    <string name="settings_failed">Не удалось установить</string>
+    <string name="led_show_reinforce">%s Усилить</string>
+    <string name="led_show_emergency_call">%s SOS</string>
+    <string name="led_show_voice_call">%s звонит</string>
+    <string name="input_password">Пожалуйста, введите пароль</string>
+    <string name="data_invalid">empty data</string>
+    <string name="invalid_password">неверный пароль</string>
+    <string name="confirm_down_time">Подтвердить(%d)</string>
+    <string name="visiting_call">%s посещение…</string>
+    <string name="str_home">Главная</string>
+    <string name="str_broadcast">Трансляция</string>
+    <string name="str_visiting">Посещение</string>
+    <string name="str_doctor">Врач</string>
+    <string name="str_ward">Палата</string>
+    <string name="str_sick_bed">Кровать</string>
+    <string name="str_mobile">Мобильный</string>
+    <string name="str_other_host">Другой хост</string>
+    <string name="str_manage_host">Пульт медсестры</string>
+    <string name="str_trusteeship">Доверительное управление</string>
+    <string name="str_led">светодиод</string>
+    <string name="str_settings">Настройки</string>
+    <string name="str_delete">Удалить</string>
+    <string name="str_save">Сохранить</string>
+    <string name="setting_day_night_time">Установка дневного и ночного времени</string>
+    <string name="setting_call_type">Тип звонка:</string>
+    <string name="setting_call_type_tts">ТТС</string>
+    <string name="setting_call_type_ringtone">рингтон</string>
+    <string name="setting_call_type_music">музыка</string>
+    <string name="setting_call_forwarding">Переадресация:</string>
+    <string name="setting_call_forwarding_enable">включить</string>
+    <string name="setting_call_forwarding_disable">отключить</string>
+    <string name="setting_sos_call_name">Название SOS:</string>
+    <string name="setting_loop_call">Loop calling:</string>
+    <string name="setting_call_dismiss_time">Calls auto dismiss time:</string>
+    <string name="setting_call_times">Время звонка:</string>
+    <string name="setting_sip_enable">SIP enable:</string>
+    <string name="setting_host_device">Главный хост</string>
+    <string name="setting_host_device_day_brightness">Хост: дневная яркость</string>
+    <string name="setting_host_device_night_brightness">Хост: ночная яркость</string>
+    <string name="setting_host_device_day_volume">Хост: дневная громкость</string>
+    <string name="setting_host_device_night_volume">Хост: ночная громкость</string>
+    <string name="setting_host_device_hands_free_volume">Хост: громкая связь</string>
+    <string name="setting_host_device_earpiece_volume">Хост: громкость динамика</string>
+    <string name="setting_host_device_call_volume">Host: call volume</string>
+    <string name="setting_bed_device">Дополнительное устройство</string>
+    <string name="setting_bed_device_day_brightness">Расширение: дневная яркость</string>
+    <string name="setting_bed_device_night_brightness">Расширение: ночная яркость</string>
+    <string name="setting_bed_device_day_led_brightness">Расширение: Дневная яркость светодиодов</string>
+    <string name="setting_bed_device_night_led_brightness">Расширение: Ночная яркость светодиодов</string>
+    <string name="setting_bed_device_day_volume">Расширение: дневной объем</string>
+    <string name="setting_bed_device_night_volume">Расширение: ночная громкость</string>
+    <string name="setting_bed_device_call_volume">Расширение: громкость звонков</string>
+    <string name="setting_conversion_box_volume">Объем коробки конвертации</string>
+    <string name="language_settings">Языковые настройки</string>
+    <string name="system_settings">Системные настройки</string>
+    <string name="save_settings">Сохранить настройки</string>
+    <string name="language_set_title">Язык:</string>
+    <string name="language_set_mode">Синхронизировать язык с сервером:</string>
+    <string name="str_yes">Да</string>
+    <string name="str_no">Нет</string>
+    <string name="str_confirm">Подтвердить</string>
+    <string name="str_cancel">Отменить</string>
+    <string name="register_auto_config">Автоматическая настройка</string>
+    <string name="register_manual_config">Ручная настройка</string>
+    <string name="register_reboot">Перезагрузить</string>
+    <string name="register_test">Тест</string>
+    <string name="register_reload">Перезагрузить</string>
+    <string name="call_record_unhandled">Не обработано</string>
+    <string name="call_record_entrance">Вход</string>
+    <string name="call_record_replay">Ответить</string>
+    <string name="str_invite">Пригласить</string>
+    <string name="str_call">Позвонить</string>
+    <string name="str_missed_call">Пропущено</string>
+    <string name="str_all_call">Все</string>
+    <string name="str_other_call">Другие</string>
+    <string name="entrance_call">Дверной звонок</string>
+    <string name="door_open">Открыть</string>
+    <string name="call_volume_control">Отключить/включить звук</string>
+    <string name="call_end">Завершить вызов</string>
+    <string name="voice_call">Голос</string>
+    <string name="video_call">Видео</string>
+    <string name="basic_info">Базовый</string>
+    <string name="fees_info">Оплата</string>
+    <string name="inspection_info">Осмотр</string>
+    <string name="indate">Дата:</string>
+    <string name="mobile">Мобильный:</string>
+    <string name="duty_doctor">Доктор:</string>
+    <string name="duty_nurse">Медсестра:</string>
+    <string name="nursing_configs">Тип ухода:</string>
+    <string name="orders">Заказы:</string>
+    <string name="illness">Болезнь:</string>
+    <string name="responsible_bed">основная кровать</string>
+    <string name="reboot_conform">установка завершена, перезагрузить сейчас?</string>
+    <string name="new_event_title">Новое мероприятие</string>
+    <string name="call_stay_time">Время ожидания входящего вызова</string>
+    <string name="str_manager_host">Manager host</string>
+    <string name="server_config">Конфигурация сервера</string>
+
+    <string name="broadcast_init_error">Broadcast init error</string>
+    <string name="broadcast_init_success">Broadcast init success</string>
+    <string name="broadcast_start_warning">Please start broadcast</string>
+    <string name="broadcast_start">Start</string>
+    <string name="broadcast_record_start">Start record</string>
+    <string name="broadcast_record_stop">Stop record</string>
+    <string name="broadcast_playing">Broadcast playing…</string>
+    <string name="broadcast_stop">Broadcast stop</string>
+
+    <string name="str_warning">тревога</string>
+    <string name="str_fall_alarm">fall alarm</string>
+    <string name="none_warning">Никто не предупреждает</string>
+    <string name="device_managed">The device is managed</string>
+    <string name="cancel_managed">Unescrowed…</string>
+    <string name="trusteeship_confirm">The device will be managed, and the calls will be transferred to the managed device.</string>
+    <string name="cancel_managed_btn">Long press cancel</string>
+</resources>

+ 207 - 2
android_bed/src/main/res/values-zh/strings.xml

@@ -1,4 +1,209 @@
 <resources>
-    <string name="app_name">NCS-床头分机</string>
-    <string name="wdkl_app_name">分机</string>
+    <string name="app_name">NCS-护士主机RK版</string>
+    <string name="download_error">下载路径异常</string>
+    <string name="download_cancel">取消下载</string>
+    <string name="update_success">升级成功</string>
+    <string name="update_fail">升级失败</string>
+    <string name="downloading">正在下载中…</string>
+    <string name="updating">正在升级中,请稍后</string>
+    <string name="update_no_required">当前已是最新版本</string>
+    <string name="detect_new_version">检测到新版本,是否升级?</string>
+    <string name="plugin_update_tips">app升级服务正在安装,请稍后重启设备以完成升级服务启动</string>
+    <string name="plugin_start_failed">启动升级插件服务失败:</string>
+    <string name="plugin_start_success">升级服务插件已启动</string>
+    <string name="plugin_start_error">升级服务插件启动失败,需要重启应用</string>
+    <string name="enable_debug">打开调试</string>
+
+    <string name="permission_grant_tips">请重新授权</string>
+    <string name="device_init_fail">初始化数据不全,请联系管理员</string>
+    <string name="device_disabled">设备未启用</string>
+    <string name="tts_invalid">TTS不可用,请检查是否安装TTS服务</string>
+    <string name="tts_enabled">TTS启用成功</string>
+    <string name="tts_disabled">当前TTS不可用,语音播报已切换至铃声模式</string>
+    <string name="call_sos_forwarding">紧急呼叫已转接</string>
+    <string name="call_voice_forwarding">语音呼叫已转接</string>
+    <string name="call_init_error">网络异常或sipId异常,请稍后</string>
+    <string name="call_failed">对方离线或不存在,呼叫失败</string>
+    <string name="net_error">网络错误</string>
+    <string name="voice_call_speech">%s呼叫</string>
+    <string name="sos_call_speech">%s紧急呼叫</string>
+    <string name="reinforce_call_speech">%s请求增援</string>
+    <string name="emergency_call">紧急报警</string>
+    <string name="event_todo">未处理</string>
+    <string name="event_done">已处理</string>
+    <string name="event_todo_tips">请先处理未接来电</string>
+    <string name="voice_message">语音留言</string>
+
+    <string name="call_video">%s请求视频</string>
+    <string name="call_visiting">探视请求</string>
+    <string name="call_entrance_guard">门禁请求</string>
+    <string name="call_sos">紧急呼叫</string>
+    <string name="call_reinforce">增援请求</string>
+    <string name="call_door">门口机</string>
+    <string name="call_in_list">已在呼叫列表中,请先处理</string>
+    <string name="call_no_device">没有设备id</string>
+    <string name="extension_connect_fail">分机连线失败</string>
+    <string name="extension_call_busy">分机正在通话中</string>
+    <string name="extension_call_error">分机通话异常</string>
+
+    <string name="cost_subtotal">小计: %f</string>
+    <string name="exam_desc">描述: %s</string>
+    <string name="exam_time">检验时间: %s</string>
+    <string name="empty_bed">空床位</string>
+    <string name="empty">无</string>
+    <string name="call_wait">请稍后</string>
+    <string name="no_custom">床位未入住或未绑定设备,无法呼叫</string>
+    <string name="no_device">没有设备,无法呼叫</string>
+    <string name="not_support_video_call">不支持视频通话</string>
+
+    <string name="led_resolution">点阵屏规格: %s</string>
+    <string name="led_voice_on">点阵屏语音播报: 开启</string>
+    <string name="led_voice_off">点阵屏语音播报: 关闭</string>
+    <string name="led_font_size">点阵屏字体大小: %d</string>
+    <string name="led_info_duration">点阵屏呼叫信息显示时长: %d</string>
+    <string name="led_voice_volume">点阵屏语音呼叫音量: %d</string>
+    <string name="led_voice_times">点阵屏语音呼叫次数: %d</string>
+    <string name="less_then">不能小于: %d</string>
+    <string name="led_no_font">字库文件不存在</string>
+    <string name="led_font_file_size">字库文件大小: %d</string>
+    <string name="led_null">没有点阵屏设备</string>
+    <string name="led_sync_time">校正点阵屏时间</string>
+    <string name="led_reset">重置点阵屏</string>
+    <string name="led_on_off">开/关点阵屏</string>
+    <string name="led_check_font">检查字库文件</string>
+    <string name="led_copy_font">更新字库文件</string>
+    <string name="led_default_info">默认显示内容:</string>
+    <string name="led_show_date">仅日期时间</string>
+    <string name="led_add_info">添加自定义</string>
+
+    <string name="no_response">无人接听</string>
+    <string name="call_video_call">视频通话请求</string>
+    <string name="call_in_calling">正在呼叫</string>
+    <string name="call_connecting">连接中…</string>
+    <string name="call_in_call">通话中…</string>
+    <string name="call_disconnect">断开连接</string>
+    <string name="call_error">通话错误</string>
+    <string name="call_reject">对方拒绝</string>
+    <string name="call_busy">对方忙线中</string>
+    <string name="call_incoming">新来电…</string>
+
+    <string name="settings_success">设置成功</string>
+    <string name="settings_failed">设置失败</string>
+    <string name="led_show_reinforce">%s请求增援</string>
+    <string name="led_show_emergency_call">%s紧急呼叫</string>
+    <string name="led_show_voice_call">%s呼叫</string>
+    <string name="input_password">请输入密码</string>
+    <string name="invalid_password">密码错误</string>
+    <string name="data_invalid">参数不能为空</string>
+    <string name="confirm_down_time">确定(%d)</string>
+    <string name="visiting_call">%s 正在探视中…</string>
+
+    <string name="str_home">首页</string>
+    <string name="str_broadcast">广播</string>
+    <string name="str_visiting">探视</string>
+    <string name="str_doctor">医生机</string>
+    <string name="str_ward">病区</string>
+    <string name="str_sick_bed">病床</string>
+    <string name="str_mobile">移动设备</string>
+    <string name="str_other_host">其他主机</string>
+    <string name="str_manage_host">总控主机</string>
+    <string name="str_trusteeship">托管</string>
+    <string name="str_led">点阵屏</string>
+    <string name="str_settings">设置</string>
+    <string name="str_delete">删除</string>
+    <string name="str_save">保存</string>
+    <string name="str_manager_host">总控主机</string>
+    <string name="server_config">服务器配置</string>
+
+    <string name="broadcast_init_error">广播初始化异常</string>
+    <string name="broadcast_init_success">广播初始化完成</string>
+    <string name="broadcast_start_warning">请先启动广播</string>
+    <string name="broadcast_start">启动广播</string>
+    <string name="broadcast_record_start">开始说话</string>
+    <string name="broadcast_record_stop">停止说话</string>
+    <string name="broadcast_playing">正在广播…</string>
+    <string name="broadcast_stop">广播停止</string>
+
+    <string name="setting_day_night_time">白天-晚上时间设置</string>
+    <string name="setting_call_type">播报模式:</string>
+    <string name="setting_call_type_tts">TTS</string>
+    <string name="setting_call_type_ringtone">铃声</string>
+    <string name="setting_call_type_music">音乐</string>
+    <string name="setting_call_forwarding">呼叫转移:</string>
+    <string name="setting_call_forwarding_enable">开启</string>
+    <string name="setting_call_forwarding_disable">关闭</string>
+    <string name="setting_sos_call_name">紧急呼叫名称:</string>
+    <string name="setting_call_dismiss_time">来电自动消除时间:</string>
+    <string name="setting_loop_call">循环播报:</string>
+    <string name="setting_call_times">播报次数:</string>
+    <string name="setting_sip_enable">启用SIP:</string>
+    <string name="setting_host_device">主机</string>
+    <string name="setting_host_device_day_brightness">主机白天亮度</string>
+    <string name="setting_host_device_night_brightness">主机夜晚亮度</string>
+    <string name="setting_host_device_day_volume">主机白天音量</string>
+    <string name="setting_host_device_night_volume">主机夜晚音量</string>
+    <string name="setting_host_device_hands_free_volume">主机免提模式音量</string>
+    <string name="setting_host_device_earpiece_volume">主机听筒模式音量</string>
+    <string name="setting_host_device_call_volume">主机通话音量</string>
+    <string name="setting_bed_device">分机</string>
+    <string name="setting_bed_device_day_brightness">分机白天亮度</string>
+    <string name="setting_bed_device_night_brightness">分机夜晚亮度</string>
+    <string name="setting_bed_device_day_led_brightness">分机白天护理灯亮度</string>
+    <string name="setting_bed_device_night_led_brightness">分机夜晚护理灯亮度</string>
+    <string name="setting_bed_device_day_volume">分机白天音量</string>
+    <string name="setting_bed_device_night_volume">分机夜晚音量</string>
+    <string name="setting_bed_device_call_volume">分机通话音量</string>
+    <string name="setting_conversion_box_volume">转换盒系统音量</string>
+    <string name="language_settings">语言设置</string>
+    <string name="system_settings">系统设置</string>
+    <string name="save_settings">保存设置</string>
+
+    <string name="language_set_title">语言:</string>
+    <string name="language_set_mode">同步语言设置:</string>
+    <string name="str_yes">是</string>
+    <string name="str_no">否</string>
+    <string name="str_confirm">确定</string>
+    <string name="str_cancel">取消</string>
+    <string name="register_auto_config">自动配置</string>
+    <string name="register_manual_config">手动配置</string>
+    <string name="register_reboot">重新启动</string>
+    <string name="register_test">测试</string>
+    <string name="register_reload">重新加载</string>
+    <string name="call_record_unhandled">未处理</string>
+    <string name="call_record_entrance">开门</string>
+    <string name="call_record_replay">回拨</string>
+    <string name="str_invite">邀请</string>
+    <string name="str_call">呼叫</string>
+    <string name="str_missed_call">未接</string>
+    <string name="str_all_call">全部</string>
+    <string name="str_other_call">其他</string>
+    <string name="entrance_call">请求开门</string>
+    <string name="door_open">开锁</string>
+    <string name="call_volume_control">打开/关闭声音</string>
+    <string name="call_end">结束通话</string>
+    <string name="voice_call">语音</string>
+    <string name="video_call">视频</string>
+    <string name="basic_info">基本信息</string>
+    <string name="fees_info">费用</string>
+    <string name="inspection_info">检验</string>
+    <string name="indate">入住日期:</string>
+    <string name="mobile">手机号:</string>
+    <string name="duty_doctor">责任医生:</string>
+    <string name="duty_nurse">责任护士:</string>
+    <string name="nursing_configs">护理项:</string>
+    <string name="orders">医嘱:</string>
+    <string name="illness">病情描述:</string>
+    <string name="responsible_bed">管理床位</string>
+
+    <string name="str_warning">紧急报警</string>
+    <string name="str_fall_alarm">跌倒报警</string>
+    <string name="none_warning">无人警报</string>
+
+    <string name="reboot_conform">设置成功,重启生效</string>
+    <string name="new_event_title">事件待处理</string>
+    <string name="call_stay_time">来电超时时间</string>
+    <string name="device_managed">设备已被托管</string>
+    <string name="cancel_managed">取消托管…</string>
+    <string name="trusteeship_confirm">该设备将会被托管,托管成功后呼叫信息将会被转移到托管的设备.</string>
+    <string name="cancel_managed_btn">长按取消</string>
 </resources>

+ 1 - 0
android_host/.gitignore

@@ -0,0 +1 @@
+/build

+ 129 - 0
android_host/build.gradle

@@ -0,0 +1,129 @@
+if (rootProject.ext.android_host.toBoolean()) {
+    apply plugin: 'com.android.library'
+} else {
+    return
+}
+
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+
+kapt {
+    arguments {
+        arg("moduleName", project.getName())
+    }
+}
+
+android {
+    compileSdkVersion target_sdk_version
+    buildToolsVersion build_tools_version
+
+    defaultConfig {
+        minSdkVersion min_sdk_version
+        targetSdkVersion target_sdk_version
+        versionCode app_version_code
+        versionName app_version
+        multiDexEnabled true
+        flavorDimensions "app"
+        buildFeatures {
+            dataBinding = true
+        }
+        buildConfigField "String", "BUILD_TIME", getDate()
+        buildConfigField 'String', 'VERSION_NAME', "\"${project.rootProject.ext.app_version}\""
+        buildConfigField 'String', 'VERSION_CODE', "\"${project.rootProject.ext.app_version_code}\""
+        buildConfigField "String", "BUILD_TIME", getDate()
+    }
+
+    productFlavors {
+        //自研3128 10寸 医院护士主机
+        rk3128{
+            dimension "app"
+            buildConfigField 'String', 'flag', '"1"'
+        }
+        //自研3128 10寸 医院护士主机-智利项目
+        //自研3128_2h 10寸 月子中心
+    }
+
+
+    lintOptions {
+        abortOnError false
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
+        }
+    }
+}
+
+//获取编译日期
+static String getDate() {
+    Date date = new Date()
+    String dates = "\""+date.format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))+"\""
+    return dates
+}
+
+dependencies {
+
+    /**
+     * 单元测试
+     */
+    testImplementation 'junit:junit:4.12'
+
+
+    /**
+     * 公共库依赖
+     */
+    implementation project(':middleware')
+
+
+    /**
+     * Dagger编译依赖
+     */
+    kapt 'com.google.dagger:dagger-compiler:2.7'
+
+    /**
+     * Kotlin依赖
+     */
+    kapt 'com.android.databinding:compiler:2.3.3'
+
+    /**
+     * 路由注解处理器
+     */
+    kapt "com.enation.geamtear:jrouter-compiler:$router_version"
+
+    /**
+     *  constraint-layout布局依赖
+     */
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
+    //compile 'com.github.anrwatchdog:anrwatchdog:1.3.0'
+
+    //使用xCrash捕获异常
+    implementation 'com.iqiyi.xcrash:xcrash-android-lib:3.0.0'
+
+    //janus信令
+    compile project(':janus')
+
+    //串口
+    compile project(':bedlib')
+
+    compile project(':listenvision')
+
+//
+//    //广播喊话组件
+    compile project(':gstream')
+
+}
+
+/**
+ * kawo组件化框架配置
+ */
+if(componentTag){
+    kawo {
+        /**
+         * Aop注解排除Jar
+         */
+        aspectExcludeJarFilter 'com.enation.geamtear.pay','AlipaySdk'
+    }
+}

+ 21 - 0
android_host/proguard-rules.pro

@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile

+ 101 - 0
android_host/src/main/AndroidManifest.xml

@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    package="com.wdkl.ncs.android.component.nursehome">
+
+
+    <!-- Android8.0未知来源权限 -->
+    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
+    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
+    <!-- silentUpdate -->
+    <uses-permission
+        android:name="android.permission."
+        tools:ignore="ProtectedPermissions" />
+
+    <!-- for sip mCall -->
+    <uses-permission android:name="android.permission.USE_SIP" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission
+        android:name="android.permission.WRITE_SECURE_SETTINGS"
+        tools:ignore="ProtectedPermissions" />
+
+    <uses-feature
+        android:name="android.hardware.sip.voip"
+        android:required="true" />
+    <uses-feature
+        android:name="android.hardware.wifi"
+        android:required="true" />
+    <uses-feature
+        android:name="android.hardware.microphone"
+        android:required="true" />
+
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission
+        android:name="android.permission.DEVICE_POWER"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
+
+    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"></uses-permission>
+    <uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
+    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
+    <uses-permission android:name="android.permission.BLUETOOTH"></uses-permission>
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD"></uses-permission>
+    <uses-permission android:name="android.permission.BROADCAST_STICKY"></uses-permission>
+    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"></uses-permission>
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+    <uses-permission android:name= "android.manifest.permission.INTERNAL_SYSTEM_WINDOW"/>
+    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+    <!--     设置屏幕亮度-->
+    <uses-permission android:name="android.permission.CHANGE_CONFIGURATION"
+        tools:ignore="ProtectedPermissions" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS"
+        tools:ignore="ProtectedPermissions" />
+    <!--    音量权限-->
+    <uses-permission android:name="android.permission.ACCESS_NOTIFICATION_POLICY"/>
+
+    <application
+        android:allowBackup="true"
+        android:label="@string/app_name"
+        android:supportsRtl="true">
+        <activity android:name="com.wdkl.ncs.android.component.nursehome.activity.RegisterActivity"
+            android:launchMode="singleInstance">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+
+        <activity android:name=".activity.NurseHomeActivity"
+            android:screenOrientation="landscape"
+            android:launchMode="singleInstance">
+        </activity>
+
+        <activity android:name=".activity.AppUpdateActivity"
+            android:screenOrientation="landscape"
+            android:launchMode="singleTask"/>
+
+        <activity android:name=".activity.TestActivity"
+            android:screenOrientation="landscape"
+            android:launchMode="singleInstance"/>
+
+        <activity android:name="com.wdkl.ncs.host.activity.SipTestActivity" />
+        <activity android:name="com.wdkl.ncs.host.activity.CallActivity" />
+
+        <service
+            android:name="com.wdkl.ncs.host.service.WdklSipService"
+            android:label="@string/app_name" />
+
+    </application>
+
+
+</manifest>

BIN
android_host/src/main/assets/launch.apk


BIN
android_host/src/main/assets/wd_update_plugin.apk


+ 16 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/SipUtil/SipCallBack.java

@@ -0,0 +1,16 @@
+package com.wdkl.ncs.android.component.nursehome.SipUtil;
+
+/**
+ * ======================Sip回调接口=====================
+ * Created by dengzhe on 2018/2/7.
+ */
+
+public interface SipCallBack {
+    void startCall(String sipAddress);//开始拨打
+
+    void autoTalking();//自动接听
+
+    void endCall();//结束通话
+
+
+}

+ 661 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/SipUtil/SipHelperUtil.java.bak

@@ -0,0 +1,661 @@
+package com.wdkl.ncs.android.component.nursehome.SipUtil;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.os.Build;
+import android.os.CountDownTimer;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.util.Log;
+import android.view.WindowManager;
+
+import com.vvsip.ansip.IVvsipService;
+import com.vvsip.ansip.IVvsipServiceListener;
+import com.vvsip.ansip.VvsipCall;
+import com.vvsip.ansip.VvsipService;
+import com.vvsip.ansip.VvsipServiceBinder;
+import com.vvsip.ansip.VvsipTask;
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity;
+import com.wdkl.ncs.android.component.nursehome.util.EthernetWifiCallBack;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by dengzhe on 2017/12/18.
+ */
+public class SipHelperUtil implements EthernetWifiCallBack {
+
+    private String TAG = SipHelperUtil.class.getSimpleName();
+
+    //挂断状态  21
+    public static int CALLING_ENDING = 21;
+
+    /**
+     * 注册中
+     */
+    public static final String REGISTERING = "register_ing";
+    /**
+     * 注册失败.
+     */
+    public static final String REGISTERFAIL = "register_fail";
+    /**
+     * 注册完成
+     */
+    public static final String REGISTERCOM = "register_com";
+
+
+    private static String SIP_IP = "192.168.101.1";
+    private static String SIP_IP_PORT = ":5060";
+    private static String SIP_PASS_WORD = "4000361820";
+    private static String SIP_ID = "4000361820";
+
+    /**
+     * Sip启动注册.
+     */
+    protected int mSipRegisterTime = 3000;
+    private Handler sipRegisterHandler = null;
+    private Runnable sipRegisterRunnable = null;
+
+    /**
+     * SIP信息
+     */
+    public static final String SipInfoTag = "SipInfo";
+    /**
+     * 电话呼叫对象
+     */
+    private List<VvsipCall> mVvsipCalls = null;
+
+
+    private static SipHelperUtil mSipRegisterUtil;
+
+    public Handler getSipRegisterHandler() {
+        return sipRegisterHandler;
+    }
+
+    public Runnable getSipRegisterRunnable() {
+        return sipRegisterRunnable;
+    }
+
+    public List<VvsipCall> getmVvsipCalls() {
+        return mVvsipCalls;
+    }
+
+    /**
+     * Gets instance.
+     *
+     * @param context the context
+     * @return the instance
+     */
+    private static Context contexts;
+
+    public static SipHelperUtil getInstance(Context context) {
+
+        if (mSipRegisterUtil == null) {
+            synchronized (SipHelperUtil.class) {
+                if (mSipRegisterUtil == null) {
+                    mSipRegisterUtil = new SipHelperUtil();
+                    contexts = context;
+                }
+            }
+        }
+        return mSipRegisterUtil;
+    }
+
+    /**
+     * Instantiates a new Sip register util.
+     */
+    private SipHelperUtil() {
+        setEthernetWifiCallBack(this);
+        if (mVvsipCalls == null) {
+            mVvsipCalls = new ArrayList<VvsipCall>();
+        }
+
+        // Runnable exiting the splash screen and launching the menu
+        sipRegisterRunnable = new Runnable() {
+            public void run() {
+                isSuccessRegisterSip();
+            }
+        };
+
+        // Run the exitRunnable in in mSipRegisterTime ms
+        sipRegisterHandler = new Handler();
+
+        IVvsipService sipservice = VvsipService.getService();
+        if (sipservice != null) {
+            sipRegisterHandler.postDelayed(sipRegisterRunnable, 0);
+            return;
+        }
+        sipRegisterHandler.postDelayed(sipRegisterRunnable, mSipRegisterTime);
+
+
+    }
+
+    /**
+     * 检测Sip服务是否注册成功
+     */
+    public void isSuccessRegisterSip() {
+        VvsipTask vvsipTask = VvsipTask.getVvsipTask();
+        if (vvsipTask != null && VvsipTask.global_failure != 0) {
+            /**
+             * ==================================sip服务启动失败 ================================
+             */
+            Intent intent = new Intent(Intent.ACTION_MAIN);
+            intent.setClass(contexts.getApplicationContext(), VvsipService.class);
+            contexts.stopService(intent);
+//            LogUtil.i(SipInfoTag, "注册失败:lifecycle // isSuccessStartSipService");
+        } else {
+//            finish();
+            /**
+             * ==================================sip服务启动成功 ================================
+             */
+//            LogUtil.i(SipInfoTag, "sip服务启动:lifecycle // isSuccessStartSipService");
+
+        }
+    }
+
+    /**
+     * 注销Sip服务
+     */
+    public void unRegisterSip() {
+//        LogUtil.i(SipInfoTag, "lifecycle // onDestroy");
+
+        IVvsipService sipservice = VvsipService.getService();
+        if (contexts instanceof IVvsipServiceListener && sipservice != null) {
+            sipservice.removeListener((IVvsipServiceListener) contexts);
+        }
+        getSipServiceStartHandler().removeCallbacks(getSipServiceStartRunnable());
+        sipRegisterHandler.removeCallbacks(sipRegisterRunnable);
+        if (getSipServiceConnection() != null && isRegister) {
+            try {
+                contexts.unbindService(getSipServiceConnection());
+                setSipServiceConnection(null);
+            } catch (IllegalArgumentException e) {
+                e.printStackTrace();
+            }
+        }
+        if (mVvsipCalls != null) {
+            mVvsipCalls.clear();
+            mVvsipCalls = null;
+        }
+
+//        Log.i(SipInfoTag, "lifecycle // onDestroy");
+    }
+
+    private boolean isFirstRegister = true;
+    public static String sipMessageCounts = "";
+
+    /**
+     * Sip信息获取
+     */
+    public void obtainSipInfo() {
+        if (sipMessageCounts.equals(REGISTERCOM) && ethernetS) {//sip注册成功并且以太网连上
+            return;
+        }
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService != null) {
+            sipService.addListener((IVvsipServiceListener) contexts);
+            sipService.setMessageHandler(messageHandler);
+        } else {
+//            LogUtil.i(SipInfoTag, "lifecycle // _service==null");
+        }
+        sipRegister();
+        failUiRefreshSip();
+    }
+
+    /**
+     * Sip信息
+     */
+    private String sipinfo = "";
+    private static int handleCount = 0;
+    //Sip註冊次數
+    private CountDownTimer mCountDownAutoTimer;
+    @SuppressLint("HandlerLeak")
+    private Handler messageHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+//            LogUtil.i(SipInfoTag, "VvsipEvent received (?" + msg.what + " " + msg.arg1
+//                    + " " + msg.arg2 + ")\n");
+//            LogUtil.i(SipInfoTag, "#" + msg.obj);
+            sipinfo = "" + msg.obj + sipinfo;
+//            LogUtil.i(SipInfoTag, "Sip信息" + sipinfo);
+
+            if (msg.what == 22) {//释放资源
+//                EventBus.getDefault().post(new MessageEvent(msg.what, EVENT_SIP_REGISTER_STATUS));
+            }
+
+            if (sipinfo.contains("200 OK")) {//注册成功
+                Log.e(TAG,"SIP注册成功");
+//                sipMessageCounts = CallingDoorActivity.REGISTERCOM;
+//                EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERCOM, EVENT_SIP_REGISTER_STATUS));
+                if (mSipThread != null) {
+                    mSipThread.interrupt();
+                    mSipThread = null;
+                }
+                if (msg.obj.toString().contains("408")) {//超时
+                    Log.e(TAG,"SIP注册超时");
+//                    sipMessageCounts = CallingDoorActivity.REGISTERFAIL;
+//                    EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+                    sipRegister();
+                }
+            } else {//注册失败
+
+                Log.e(TAG,"SIP注册失败");
+//                sipMessageCounts = CallingDoorActivity.REGISTERFAIL;
+//                EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+                if (mSipThread != null) {
+                    mSipThread.interrupt();
+                    mSipThread = null;
+                }
+                sipRegister();
+            }
+            failUiRefreshSip();
+
+            if (msg.obj.toString().contains("autocall")) {
+                VvsipCall pCall = null;
+//                LogUtil.e(SipInfoTag, "onClick1");
+                for (VvsipCall _pCall : mVvsipCalls) {
+                    if (_pCall.cid > 0)
+//                        LogUtil.e(SipInfoTag, "state#" + _pCall.mState);
+                        if (_pCall.cid > 0 && _pCall.mState <= 2) {
+                            pCall = _pCall;
+                            break;
+                        }
+                }
+//                LogUtil.e(SipInfoTag, "onClick2");
+                if (pCall == null)
+                    return;
+//                LogUtil.e(SipInfoTag, "onClick3#" + pCall.mState);
+                IVvsipService _service = VvsipService.getService();
+                if (_service == null)
+                    return;
+                VvsipTask _vvsipTask = _service.getVvsipTask();
+                if (_vvsipTask == null)
+                    return;
+                pCall.stop();
+                _service.setSpeakerModeOff();
+            }
+        }
+    };
+
+    /**
+     * UI刷新:SIP失败
+     */
+    private void failUiRefreshSip() {
+        if (!ethernetS) {
+//            sipMessageCounts = CallingDoorActivity.REGISTERFAIL;
+//            EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERFAIL, EVENT_SIP_REGISTER_STATUS));
+            if (mSipThread != null) {
+                mSipThread.interrupt();
+                mSipThread = null;
+            }
+//            LogUtil.e(SipInfoTag, "以太网断开,SIP UI状态刷新为失败");
+        }
+    }
+
+    /**
+     * ====================Sip注册======================
+     */
+    private Thread mSipThread;
+
+    private static class SipThread extends Thread {
+        WeakReference<NurseHomeActivity> mThreadCallingDoorActivity;
+
+        public SipThread(NurseHomeActivity activity) {
+            mThreadCallingDoorActivity = new WeakReference<NurseHomeActivity>(
+                    activity);
+        }
+
+        @Override
+        public void run() {
+            super.run();
+            if (mThreadCallingDoorActivity == null)
+                return;
+            if (mThreadCallingDoorActivity.get() != null) {
+                VvsipService sipService = VvsipService.getService();
+                try {
+                    if (sipService != null && !SipHelperUtil.getInstance(contexts).sipinfo.contains("200 OK") && ethernetS) {//注册正在进行中
+//                        sipMessageCounts = CallingDoorActivity.REGISTERING;
+//                        EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERING, EVENT_SIP_REGISTER_STATUS));
+                        sipService.register(SIP_IP +SIP_IP_PORT ,
+                                SIP_ID, SIP_PASS_WORD);
+                    //                        LogUtil.i(SipInfoTag, "Sip地址" + Constants.SIP_IP + SIP_IP_END + "\nSip账号" + Constants.SIP_ID + "\nSip密码" + Constants.SIP_PASS_WORD);
+                        handleCount++;
+                    //                        LogUtil.d(SipInfoTag, "Sip第-----" + (handleCount + 1) + "-------次註冊");
+//                        LogUtil.e(SipInfoTag, "以太网连接,SIP UI状态刷新为注册中");
+                    } else if (sipService != null && SipHelperUtil.getInstance(contexts).sipinfo.contains("200 OK")) {
+//                        sipMessageCounts = CallingDoorActivity.REGISTERCOM;
+//                        EventBus.getDefault().post(new MessageEvent(CallingDoorActivity.REGISTERCOM, EVENT_SIP_REGISTER_STATUS));
+                    }
+                } catch (NullPointerException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+    private void sipRegister() {
+        synchronized (this) {
+            mSipThread = new SipThread((NurseHomeActivity) contexts);
+            if (handleCount < 3) {
+                if (mCountDownAutoTimer == null) {
+                    mCountDownAutoTimer = new CountDownTimer(10000, 1000) {
+                        @Override
+                        public void onTick(long l) {
+//                            LogUtil.d(SipInfoTag, "已經註冊第" + (handleCount + 1) + "次:" + l / 1000 + "秒后重啟註冊");
+                        }
+
+                        @Override
+                        public void onFinish() {
+                            handleCount = 0;
+                            if (mSipThread != null) {
+                                mSipThread.start();
+                            }
+                            if (mCountDownAutoTimer != null) {
+                                mCountDownAutoTimer.cancel();
+                                mCountDownAutoTimer = null;
+                            }
+                        }
+
+                    };
+                    mCountDownAutoTimer.start();
+                }
+                return;
+            } else {
+                if (mCountDownAutoTimer != null) {
+                    mCountDownAutoTimer.cancel();
+                    mCountDownAutoTimer = null;
+                }
+            }
+            if (handleCount == 0) {
+                mSipThread.start();
+            }
+        }
+    }
+
+    public void setmSipThread(Thread mSipThread) {
+        this.mSipThread = mSipThread;
+    }
+
+    public Thread getmSipThread() {
+        return mSipThread;
+    }
+
+    /**
+     * 开始通话
+     */
+    public void startCall(String sipUseName) {
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService == null) return;
+        //----------------------------------------------携带Mac地址(暂时无用)--------------------------------------------------//
+        sipService.initiateOutgoingCall(sipUseName, "");
+    }
+
+    /**
+     * 结束通话
+     */
+    public void endCall() {
+        VvsipCall call = null;
+        for (VvsipCall pCall : mVvsipCalls) {
+            if (pCall.cid > 0 && pCall.mState <= 2) {
+                call = pCall;
+                break;
+            }
+        }
+        if (call == null) return;
+        IVvsipService sipService = VvsipService.getService();
+        if (sipService == null) return;
+        VvsipTask sipTask = sipService.getVvsipTask();
+        if (sipTask == null) return;
+        VvsipService.getService().mainEndCall(CALLING_ENDING);
+        call.stop();
+        sipService.setSpeakerModeOff();
+        sipService.stopPlayer();
+        sipService.setAudioNormalMode();
+
+    }
+
+    /**
+     * 添加一个电话呼叫对象
+     *
+     * @param call
+     */
+    public void addCallObject(final VvsipCall call) {
+        ((Activity) contexts).runOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    if (call == null) {
+                        return;
+                    }
+
+                    if (mVvsipCalls == null)
+                        return;
+                    mVvsipCalls.add(call);
+
+                    if (Build.VERSION.SDK_INT >= 5) {
+                        ((Activity) contexts).getWindow().addFlags( // WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                                // |
+                                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                    }
+
+                } catch (Exception e) {
+//                    LogUtil.e(SipInfoTag, "onNewVvsipCallEvent: " + e);
+                }
+            }
+        });
+    }
+
+    /**
+     * 移除一个电话呼叫对象
+     *
+     * @param call
+     */
+    public void removeCallObject(final VvsipCall call) {
+        ((Activity) contexts).runOnUiThread(new Runnable() {
+            public void run() {
+                try {
+                    if (call == null) {
+                        return;
+                    }
+
+                    // 4 crash detected here for 4.0.9 with mVvsipCalls=NULL
+                    if (mVvsipCalls == null)
+                        return;
+                    mVvsipCalls.remove(call);
+
+                    if (mVvsipCalls.size() == 0) {
+                        if (Build.VERSION.SDK_INT >= 5) {
+                            ((Activity) contexts).getWindow()
+                                    .clearFlags( // WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
+                                            // |
+                                            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
+                                                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+                                                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+                        }
+                    }
+                } catch (Exception e) {
+//                    Log.e(SipInfoTag, "onRemoveVvsipCallEvent: " + e);
+                }
+            }
+        });
+    }
+
+    /**
+     * 自动接电话
+     */
+    public void autoTalking() {
+        if (mVvsipCalls == null) {
+            mVvsipCalls = new ArrayList<VvsipCall>();
+        }
+        for (VvsipCall _pCall : mVvsipCalls) {
+            if (_pCall.cid > 0 && _pCall.mState < 2 && _pCall.mIncomingCall) {
+                // ANSWER EXISTING CALL
+                int i = _pCall.answer(200, 1);
+//                LogUtil.d(SipInfoTag, "ANSWER EXISTING CALL");
+                IVvsipService _service = VvsipService.getService();
+                if (_service != null) {
+                    if (i >= 0) {
+                        _service.stopPlayer();
+                        _service.setSpeakerModeOff();
+                        _service.setAudioInCallMode();
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    public static boolean isServiceRunning(Context mContext, String className) {
+
+        boolean isRunning = false;
+        ActivityManager activityManager = (ActivityManager) mContext
+                .getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningServiceInfo> serviceList = activityManager
+                .getRunningServices(30);
+
+        if (!(serviceList.size() > 0)) {
+            return false;
+        }
+
+        for (int i = 0; i < serviceList.size(); i++) {
+            if (serviceList.get(i).service.getClassName().equals(className) == true) {
+                isRunning = true;
+                break;
+            }
+        }
+        return isRunning;
+    }
+
+    /**
+     * #############################
+     * <p>
+     * Sip启动服务.
+     * <p>
+     * #############################
+     */
+    private static Handler sipServiceStartHandler = null;
+    private static Runnable sipServiceStartRunnable = null;
+    private static ServiceConnection sipServiceConnection;
+
+    public static Runnable getSipServiceStartRunnable() {
+        return sipServiceStartRunnable;
+    }
+
+    public static Handler getSipServiceStartHandler() {
+        return sipServiceStartHandler;
+    }
+
+    public static ServiceConnection getSipServiceConnection() {
+        return sipServiceConnection;
+    }
+
+    public static void setSipServiceConnection(ServiceConnection sipServiceConnections) {
+        sipServiceConnection = sipServiceConnections;
+    }
+
+    /**
+     * 启动服务
+     */
+    public static Boolean isRegister = false;//是否注册
+
+    public void sipStartService() {
+        sipServiceStartHandler = new Handler();
+
+        sipServiceStartRunnable = new Runnable() {
+            public void run() {
+
+                Intent intent = new Intent(contexts.getApplicationContext(), VvsipService.class);
+                contexts.startService(intent);
+
+                sipServiceConnection = new ServiceConnection() {
+                    public void onServiceConnected(ComponentName name, IBinder service) {
+                        IVvsipService sipservice = ((VvsipServiceBinder) service).getService();
+                        if (contexts instanceof IVvsipServiceListener) {
+                            sipservice.addListener((IVvsipServiceListener) contexts);
+//                            LogUtil.i(SipInfoTag, "Connected!");
+                            SipHelperUtil.getInstance(contexts).obtainSipInfo();//Sip信息获取
+                        }
+                    }
+
+                    public void onServiceDisconnected(ComponentName name) {
+//                        LogUtil.i(SipInfoTag, "Disconnected!");
+                    }
+                };
+                if (!SipHelperUtil.isServiceRunning(contexts, "com.vvsip.ansip.VvsipService")) {
+                    isRegister = contexts.bindService(intent, sipServiceConnection, Context.BIND_AUTO_CREATE);
+                }
+            }
+        };
+
+        sipServiceStartHandler.postDelayed(sipServiceStartRunnable, 0);
+    }
+
+    /**
+     * 用来解析错误代码
+     */
+    public static String analyseErrorCode(String errorCode) {
+        switch (errorCode) {
+            case "200":
+                return "成功";
+            case "408":
+                return "请求超时";
+            case "400":
+                return "服务器不支持请求的语法";
+            case "401":
+                return "未授权";
+            case "403":
+                return "服务器禁止请求";
+            case "404":
+                return "服务器找不到";
+            default:
+                return "未知错误";
+        }
+    }
+
+    //======================Sip回调接口=====================
+    private SipCallBack mSipCallBack;
+
+    public void setSipCallBack(SipCallBack mSipCallBack) {
+        this.mSipCallBack = mSipCallBack;
+    }
+
+    public SipCallBack getmSipCallBack() {
+        return mSipCallBack;
+    }
+
+    //======================以太网和wifi状态接口=====================
+    private EthernetWifiCallBack mEthernetWifiCallBack;
+
+    public void setEthernetWifiCallBack(EthernetWifiCallBack mEthernetWifiCallBack) {
+        this.mEthernetWifiCallBack = mEthernetWifiCallBack;
+    }
+
+    public EthernetWifiCallBack getmEthernetWifiCallBack() {
+        return mEthernetWifiCallBack;
+    }
+
+    private static boolean ethernetS = true;//获取以太网状态
+    private static boolean wifiS = false;//获取wifi状态
+
+    @Override
+    public boolean ethernetStatus(boolean status) {
+        ethernetS = status;
+        return status;
+    }
+
+    @Override
+    public boolean wifiStatus(boolean status) {
+        wifiS = status;
+        return status;
+    }
+}

+ 149 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/AppUpdateActivity.kt

@@ -0,0 +1,149 @@
+package com.wdkl.ncs.android.component.nursehome.activity
+
+import android.text.TextUtils
+import android.util.Log
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.HostAppUpdatePresenter
+import com.wdkl.ncs.android.component.nursehome.databinding.UpdateLayBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.AppUpdateHelper
+import com.wdkl.ncs.android.component.nursehome.util.HttpHelper
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.AppUpdateContract
+import kotlinx.android.synthetic.main.update_lay.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+@Router(path = "/nursehome/update")
+class AppUpdateActivity :BaseActivity<HostAppUpdatePresenter, UpdateLayBinding>(), AppUpdateContract.View {
+    private val TAG = "AppUpdateActivity"
+
+    private val urlManager = UrlManager.build()
+
+    override fun getLayId(): Int {
+        return R.layout.update_lay
+    }
+
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        Constant.APP_UPDATING = true
+        if (!TextUtils.isEmpty(Constant.APP_PATH)) {
+            downLoadAPK(urlManager.buyer + "/" + Constant.APP_PATH)
+        } else {
+            showMessage(R.string.download_error)
+            finish()
+        }
+    }
+
+    /**
+     * 下载APK包
+     */
+    fun downLoadAPK(url: String) {
+        Log.d(TAG, "downLoadAPK  url==$url")
+        activity_appupdate_dialog_progressview.setCurProgress(0)
+        activity_update_version.setText(Constant.APP_PATH.substringAfterLast("/"))
+        activity_update_version.setOnLongClickListener {
+            Log.d(TAG, "downLoadAPK cancel...")
+            showMessage(R.string.download_cancel)
+            HttpHelper.cancelRequestByTag(TAG)
+            activity.finish()
+
+            return@setOnLongClickListener true
+        }
+
+        HttpHelper.download(url, TAG, object : HttpHelper.DownloadListener {
+            override fun onDownloadSuccess() {
+                Log.d("download", "onDownloadSuccess====")
+                runOnUiThread {
+                    activity_update_text_download.setText(R.string.updating)
+                }
+                startInstallApk()
+            }
+
+            override fun onDownloading(progress: Int) {
+                runOnUiThread {
+                    activity_appupdate_dialog_progressview.setCurProgress(progress)
+                }
+            }
+
+            override fun onDownloadFailed() {
+                Log.d("download", "onDownloadFailed====")
+                finish()
+            }
+        })
+    }
+
+    fun startInstallApk() {
+        //AppUpdateHelper.installAPK(this);
+        //finish()
+
+        Thread{
+            AppUpdateHelper.updateApp(this, object : AppUpdateHelper.UpdateCallBack {
+                override fun onFailed() {
+                    runOnUiThread {
+                        showMessage(R.string.update_fail)
+                        finish()
+                    }
+                }
+
+                override fun onSuccess() {
+                    runOnUiThread {
+                        showMessage(R.string.update_success)
+                        //finish()
+                        android.os.Process.killProcess(android.os.Process.myPid())
+                        System.exit(0)
+                    }
+                }
+            })
+        }.start()
+    }
+
+    override fun bindEvent() {
+        //
+    }
+
+    override fun destory() {
+        Constant.APP_UPDATING = false
+    }
+
+    //数据加载错误
+    override fun onError(message: String, type: Int) {
+        //
+    }
+
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+        //
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        },onWifi = {
+
+        },offline = {
+
+        })
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        //
+    }
+}

+ 202 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/CallActivity.java

@@ -0,0 +1,202 @@
+package com.wdkl.ncs.android.component.nursehome.activity;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.res.Configuration;
+import android.media.AudioManager;
+import android.os.Bundle;
+
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.View;
+import android.widget.RelativeLayout;
+
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.service.WdklSipService;
+import com.wdkl.ncs.android.middleware.utils.AudioRouteUtils;
+
+
+import org.linphone.core.Call;
+import org.linphone.core.Core;
+import org.linphone.core.CoreListenerStub;
+import org.linphone.core.VideoDefinition;
+import org.linphone.mediastream.Version;
+
+
+
+public class CallActivity extends Activity {
+    private static final String TAG = "CallActivity";
+    // 远程视频
+    private TextureView mVideoView;
+    // 本地视频
+    private TextureView mCaptureView;
+
+    private CoreListenerStub mCoreListener;
+
+    private AudioManager audioManager;
+    private Core core;
+
+    @Override
+    protected void onCreate( Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.call);
+
+        mVideoView = findViewById(R.id.videoSurface);
+        mCaptureView = findViewById(R.id.videoCaptureSurface);
+
+        core = WdklSipService.getCore();
+        // 配置核心视频层渲染
+        core.setNativeVideoWindowId(mVideoView);
+        core.setNativePreviewWindowId(mCaptureView);
+
+        audioManager = (AudioManager) getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
+
+        // 配置通话状态结束监听
+        mCoreListener = new CoreListenerStub() {
+            @Override
+            public void onCallStateChanged(Core core, Call call, Call.State state, String message) {
+                if (state == Call.State.End || state == Call.State.Released) {
+                    finish();
+                }
+            }
+        };
+
+        findViewById(R.id.toggle_speaker).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                speakerOn();
+            }
+        });
+
+        findViewById(R.id.terminate_call).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Core core = WdklSipService.getCore();
+                if (core.getCallsNb() > 0) {
+                    Call call = core.getCurrentCall();
+                    if (call == null) {
+                        call = core.getCalls()[0];
+                    }
+                    call.terminate();
+                }
+            }
+        });
+    }
+
+    private void speakerOn(){
+        Log.i(TAG,">>>>>>>>>>>>>>"+audioManager.isSpeakerphoneOn());
+        //5.0以上
+        audioManager.setMode(AudioManager.MODE_IN_CALL);
+        //设置音量,解决有些机型切换后没声音或者声音突然变大的问题
+        audioManager.setStreamVolume(
+                AudioManager.STREAM_MUSIC,
+                audioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
+                AudioManager.FX_KEY_CLICK
+        );
+        audioManager.setSpeakerphoneOn(true);
+        Log.i(TAG,">>>>>>>>>>>>>>"+audioManager.isSpeakerphoneOn());
+
+        if (core != null) {
+            AudioRouteUtils.Companion.routeAudioToSpeaker(core, null, false);
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+    }
+
+    @Override
+    protected void onResume() {
+        super.onResume();
+
+        WdklSipService.getCore().addListener(mCoreListener);
+        resizePreview();
+    }
+
+    @Override
+    protected void onPause() {
+        WdklSipService.getCore().removeListener(mCoreListener);
+
+        super.onPause();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+    }
+
+    @TargetApi(24)
+    @Override
+    public void onUserLeaveHint() {
+        // 判断设备是否支持画中画
+        boolean supportsPip =
+                getPackageManager()
+                        .hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE);
+        Log.i(TAG,"[Call] Is picture in picture supported: " + supportsPip);
+        if (supportsPip && Version.sdkAboveOrEqual(24)) {
+            enterPictureInPictureMode();
+        }
+    }
+
+    @Override
+    public void onPictureInPictureModeChanged(
+            boolean isInPictureInPictureMode, Configuration newConfig) {
+        if (isInPictureInPictureMode) {
+            // Currently nothing to do has we only display video
+            // But if we had controls or other UI elements we should hide them
+        } else {
+            // If we did hide something, let's make them visible again
+        }
+    }
+
+    private void resizePreview() {
+        Core core = WdklSipService.getCore();
+        if (core.getCallsNb() > 0) {
+            Call call = core.getCurrentCall();
+            if (call == null) {
+                call = core.getCalls()[0];
+            }
+            if (call == null) return;
+
+            DisplayMetrics metrics = new DisplayMetrics();
+            getWindowManager().getDefaultDisplay().getMetrics(metrics);
+            int screenHeight = metrics.heightPixels;
+            int maxHeight =
+                    screenHeight / 4; // 本地1/4高
+
+            VideoDefinition videoSize =
+                    call.getCurrentParams()
+                            .getSentVideoDefinition();
+            if (videoSize.getWidth() == 0 || videoSize.getHeight() == 0) {
+                Log.w(TAG,
+                        "[Video] 无法使用发送端视频定义, 使用默认");
+                videoSize = core.getPreferredVideoDefinition();
+            }
+            int width = videoSize.getWidth();
+            int height = videoSize.getHeight();
+
+            Log.d(TAG,"[Video] Video height is " + height + ", width is " + width);
+            width = width * maxHeight / height;
+            height = maxHeight;
+
+            if (mCaptureView == null) {
+                Log.e(TAG,"[Video] 本地视频流 is null !");
+                return;
+            }
+
+            RelativeLayout.LayoutParams newLp = new RelativeLayout.LayoutParams(width, height);
+            newLp.addRule(
+                    RelativeLayout.ALIGN_PARENT_BOTTOM,
+                    1); // Clears the rule, as there is no removeRule until API 17.
+            newLp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 1);
+            mCaptureView.setLayoutParams(newLp);
+            Log.d(TAG,"[Video] 远程视频 size set to " + width + "x" + height);
+        }
+    }
+}

+ 382 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/CallingHostActivationActivity.kt

@@ -0,0 +1,382 @@
+ package com.wdkl.ncs.android.component.nursehome.activity
+
+import android.content.Context
+import android.content.Intent
+
+import android.content.res.Configuration
+import android.os.Build
+import android.os.Handler
+import android.os.Looper
+import android.text.TextUtils
+import android.util.Log
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.config.NetEngineConfig
+import com.enation.javashop.net.engine.model.NetState
+import com.enation.javashop.net.engine.plugin.exception.RestfulExceptionInterceptor
+import com.enation.javashop.utils.base.config.BaseConfig
+import com.wdkl.ncs.android.component.nursehome.BuildConfig
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.CallinghostActivationBinding
+import com.wdkl.ncs.android.component.nursehome.dialog.RebootDialogHelper
+import com.wdkl.ncs.android.component.nursehome.dialog.ServicesDialogHelper
+import com.wdkl.ncs.android.component.nursehome.dialog.SystemDialogHelper
+import com.wdkl.ncs.android.component.nursehome.hardware.HardWareFactroy
+import com.wdkl.ncs.android.component.nursehome.helper.SoundPoolManager
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.nursehome.util.*
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.EcodeHelper
+import com.wdkl.ncs.android.lib.utils.push
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DeviceContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DevicePresenter
+import com.wdkl.ncs.android.middleware.model.ThirdServerInfo
+import com.wdkl.ncs.android.middleware.model.vo.NurseDeviceInfoVO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import com.wdkl.ncs.android.middleware.udp.ServerInfoUtil
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import kotlinx.android.synthetic.main.activity_register.*
+import kotlinx.android.synthetic.main.callinghost_activation.*
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import java.util.concurrent.TimeUnit
+
+ /**
+  * 激活页面
+  * */
+ @Router(path = "/nursehome/activation")
+class CallingHostActivationActivity  : BaseActivity<DevicePresenter, CallinghostActivationBinding>(), DeviceContract.View {
+
+    private val TAG = "CallingHostActivationActivity"
+    val QR_CODE_PATH = "http://m.wdklian.com/care/apk/care.user?type=NCS_DEVICE"
+
+    private val handler by lazy { Handler(Looper.getMainLooper()) }
+    //服务器是否请求成功
+    private var serverSuccess = false
+    //是否重启
+    private var cancelRestart = false
+
+
+
+    override fun getLayId(): Int {
+       return R.layout.callinghost_activation
+    }
+
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        BaseConfig.getInstance().addActivity("WelcomeActivity", "AppUpdateActivity", "CallingbedActivity" +
+                "CallingbedActivationActivity", "SystemActivity", "TextActivity",
+                "WebviewActivity", "HospitalInfoActivity", "DepartmentInfoActivity",
+                "CostActivity", "SignActivity", "DoctorsAdviceActivity", "SipTestActivity", "CallActivity",
+                "CountdownActivity")
+        NetEngineConfig.init(baseContext)
+                .openLogger()
+                .addNetInterceptor(RestfulExceptionInterceptor())
+        LedManagerUtils.getInstance().ledInit(this)
+        //init
+        NetHelper.getInstance().init()
+
+        SoundPoolManager.getInstance().init()
+        //初始化串口
+//        HardWareFactroy.getHardTools().init()
+        //是否卸载旧版本apk
+//        HardWareFactroy.getHardTools().uninstallApp(this, uninstallApk, APP_NAME)
+        //xCrash catcher
+        XCrashUtils().init(application)
+
+        AppUtil.checkCameraSupport()
+
+        checkServer()
+    }
+
+    override fun bindEvent() {
+        //设备重启
+        activation_settings_button.setOnClickListener {
+            RebootDialogHelper.showDialog(activity)
+        }
+        //系统设置
+        activation_system_button.setOnClickListener {
+            SystemDialogHelper.showDialog(activity)
+        }
+        //服务器设置
+        activation_services_button.setOnClickListener {
+            ServicesDialogHelper.showDialog(activity, object : ServicesDialogHelper.ClickListener {
+                override fun onClick(bedVO: String?) {
+                    setfuq()
+                }
+            })
+        }
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        showUI()
+    }
+
+    override fun destory() {
+
+    }
+
+    private fun showUI(){
+        //设置二维码
+        setQrcode()
+        val isActivation = SPUtils.get(this, Constant.APP_ACTIVATION, "");
+        if (isActivation.equals("已激活")){
+            activation_title.setText("系统连接失败")
+            activation_title.setTextColor(resources.getColor(R.color.red_color))
+            activation_title_msg.setText("请检查网络与服务器地址")
+            activation_title.setTextColor(resources.getColor(R.color.red_color))
+        }else{
+            activation_title.setText("请先激活设备")
+            activation_title.setTextColor(resources.getColor(R.color.white))
+            activation_title_msg.setText("设置右侧参数后激活")
+            activation_title.setTextColor(resources.getColor(R.color.white))
+        }
+        //注册方式
+        HardWareFactroy.getHardTools().Registration(this)
+
+        val netInfo = NetHelper.getNetInfo(activity)
+        activation_v.text =  BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL
+        activation_ip.text = NetHelper.getInstance().localIP
+        if (netInfo != null) {
+            activation_wg.text = netInfo.gateway
+            activation_ym.text = netInfo.netMask
+        }
+        activation_zcm.text=  Constant.DEVICE_REGISTER_ID
+        val buildUrl = UrlManager.build()
+        activation_fuq.text=   buildUrl.buyer.substringAfterLast("//").substringBefore(":")
+    }
+
+     fun setfuq(){
+         activation_fuq.text=CommonUtils.getUrl(this)
+         showMessage("请重启设备,重新激活设备")
+    }
+
+    //设置二维码
+    private fun setQrcode(){
+        Thread{
+            //val logoBitmap = BitmapFactory.decodeResource(resources, R.mipmap.erlogo)
+            var builder = StringBuilder()
+            builder.append(QR_CODE_PATH)
+            builder.append("&code=")
+            builder.append(Constant.DEVICE_CODE)
+            builder.append("&mac=")
+            builder.append(Constant.DEVICE_REGISTER_ID)
+            builder.append("&model=")
+            builder.append(Constant.DEVICE_MODEL)
+            builder.append("&hard_ver=")
+            builder.append(Constant.DEVICE_HARD_VER)
+            builder.append("&soft_ver=")
+            builder.append(Constant.DEVICE_SOFT_VER)
+            builder.append("&device_type=")
+            builder.append(DeviceTypeEnum.DIGIT_BED_DEVICE.value())
+            builder.append("&device_name=")
+            builder.append(DeviceTypeEnum.DIGIT_BED_DEVICE.typeName())
+            val code = EcodeHelper().createQRImage(builder.toString(), 250, null)
+            activity.runOnUiThread {
+                activation_qr_code?.setImageBitmap(code)
+            }
+        }.start()
+    }
+
+
+
+    private fun checkServer() {
+        Thread {
+            while (!serverSuccess) {
+                val okHttpClient = OkHttpClient().newBuilder()
+                        .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .build()
+                val url: String = CommonUtils.getUrl(BaseApplication.appContext)
+                val port: String = CommonUtils.getUrlPort(BaseApplication.appContext)
+                val request = Request.Builder()
+                        .url("http://$url:$port/ncs_url/server_info")
+                        .get()
+                        .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,进入下一步获取设备信息
+                        serverSuccess = true
+                        presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+
+                    } else {
+                        //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                        val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                        checkServerInfo(info)
+                    }
+                } catch (e: Exception) {
+                    //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                    val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                    checkServerInfo(info)
+                    //e.printStackTrace()
+                }
+
+                try {
+                    Thread.sleep(30000)
+                } catch (ex: Exception) {
+                    ex.printStackTrace()
+                }
+            }
+        }.start()
+    }
+
+
+    private fun checkServerInfo(info: ThirdServerInfo?) {
+        //检查获取到的服务器ip是否可用,可用则重启app重新初始化,不可用则什么都不做,等待下次重新获取服务器ip
+        if (info != null) {
+            if (info.thirdServer == null || info.thirdServerPort == null) {
+                Log.d(TAG, "server info data null")
+                showMsgMain("get server data null")
+            } else {
+                val okHttpClient = OkHttpClient().newBuilder()
+                        .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                        .build()
+                val request = Request.Builder()
+                        .url("http://${info.thirdServer}:${info.thirdServerPort}/ncs_url/server_info")
+                        .get()
+                        .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,稍后重启app
+                        serverSuccess = true
+                        CommonUtils.setUrl(activity, info.thirdServer)
+                        CommonUtils.setUrlPort(activity, info.thirdServerPort.toString())
+                        showMsgMain("restart...")
+                        handler.postDelayed({
+                            if (!cancelRestart) {
+                                AppUpdateHelper.restartApp(activity)
+                            }
+                        }, 10000)
+                    }
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    showMsgMain("server error or net error")
+                }
+            }
+        } else {
+            Log.d(TAG, "server info null")
+            showMsgMain("get server null")
+        }
+    }
+
+    private fun showMsgMain(msg: String) {
+        runOnUiThread {
+            showMessage(msg)
+        }
+    }
+    override fun attachBaseContext(base: Context) {
+        val languageId: Int = SettingConfig.getLanguageId(base)
+        LocaleMangerUtils.setApplicationLanguageByIndex(base, languageId)
+        super.attachBaseContext(base)
+    }
+
+    override fun onConfigurationChanged(newConfig: Configuration) {
+        super.onConfigurationChanged(newConfig)
+        val languageId: Int = SettingConfig.getLanguageId(baseContext)
+        LocaleMangerUtils.setApplicationLanguageByIndex(baseContext, languageId)
+    }
+
+     override fun showData(data: NurseDeviceInfoVO) {
+         Log.e(TAG,"收到返回的设备信息 "+data.hospitalName)
+         Log.e(TAG,"收到返回的设备信息 "+data.partName)
+         Log.e(TAG,"收到返回的设备信息 "+data.partId)
+         Log.e(TAG,"收到返回的设备信息 "+data.id)
+         Log.e(TAG,"收到返回的设备信息 "+data.sipId)
+         Log.e(TAG,"收到返回的设备信息 "+data.toString())
+
+         Constant.hospital_name = data.hospitalName
+         Constant.part_name = data.partName
+         Constant.partDisplay = data.partDisplay
+         Constant.part_id = data.partId
+         Constant.DEVICE_ID = data.id
+         Constant.SIP_ID = data.sipId
+         Constant.eth_ip = data.ethIp
+         if (data.hospitalId != null) {
+             Constant.hospital_id = data.hospitalId
+         }
+         if (data.sipIp != null) {
+             Constant.sip_ip = data.sipIp
+         }
+
+         Constant.DEVICE_CODE = data.code
+         Constant.DEVICE_MODEL =  data.model
+         Constant.DEVICE_HARD_VER =  data.hardVer
+         Constant.DEVICE_SOFT_VER = data.softVer
+         if (data.deviceType != null) {
+             Constant.DEVICE_TYPE = data.deviceType
+         }
+         if (data.name != null) {
+             Constant.DEVICE_NAME = data.name
+         }
+         if (data.backupId != null) {
+             Constant.back_id = data.backupId
+         }
+
+         if(TextUtils.isEmpty(data.partId.toString())|| TextUtils.isEmpty(data.id.toString())
+                 || TextUtils.isEmpty(data.sipId)){
+//             feedback_device_info_tv.setText(R.string.device_init_fail)
+             showMessage(R.string.device_init_fail)
+             presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+             return
+         } else if (data.status != null && data.status == 0) {
+//             feedback_device_info_tv.setText(R.string.device_disabled)
+             showMessage(R.string.device_disabled)
+             presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+             return
+         }
+
+         handler.removeCallbacksAndMessages(null)
+         val intent = Intent()
+         intent.setClass(activity, NurseHomeActivity::class.java)
+         activity.startActivity(intent)
+         finish()
+     }
+
+     override fun onNoneNet() {
+         presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+     }
+
+     //数据加载错误
+    override fun onError(message: String, type: Int) {
+         presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+    }
+    //数据加载完成
+    override fun complete(message: String, type: Int) {
+
+    }
+
+    //开始获取数据
+    override fun start() {
+        //
+    }
+
+    //网络监听
+    override fun networkMonitor(state: NetState) {
+        state.filter(onMobile = {
+
+        }, onWifi = {
+
+        }, offline = {
+
+        })
+    }
+
+}

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2143 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/NurseHomeActivity.kt


+ 428 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/RegisterActivity.kt

@@ -0,0 +1,428 @@
+package com.wdkl.ncs.android.component.nursehome.activity
+
+import android.Manifest
+import android.graphics.Color
+import android.os.Build
+import android.os.Handler
+import android.provider.Settings.Global.DEVICE_NAME
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.model.NetState
+import com.enation.javashop.net.engine.plugin.permission.RxPermissions
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.ActivityRegisterBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import io.reactivex.Observable
+import com.wdkl.ncs.android.component.nursehome.BuildConfig
+import com.wdkl.ncs.android.component.nursehome.helper.SoundPoolManager
+import com.wdkl.ncs.android.component.nursehome.util.*
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.*
+import com.wdkl.ncs.android.middleware.api.UrlManager
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DeviceContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DevicePresenter
+import com.wdkl.ncs.android.middleware.model.ThirdServerInfo
+import com.wdkl.ncs.android.middleware.model.vo.NurseDeviceInfoVO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import com.wdkl.ncs.android.middleware.udp.ServerInfoUtil
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import kotlinx.android.synthetic.main.activity_register.*
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import serialporttest.utils.SerialPortUtil
+import java.lang.StringBuilder
+import java.util.concurrent.TimeUnit
+
+/**
+ *注册页Activity
+ */
+@Router(path = "/nursehome/register")
+class RegisterActivity : BaseActivity<DevicePresenter, ActivityRegisterBinding>(),  DeviceContract.View {
+    var TAG = RegisterActivity::class.java.getSimpleName()
+
+    val QR_CODE_PATH = "http://m.wdklian.com/care/apk/care.user?type=NCS_DEVICE"
+
+    private val handler by lazy { Handler() }
+
+    private var serverIp = ""
+    private var serverSuccess = false
+    private var cancelRestart = false
+    private var homeLaunch = false
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.activity_register
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+        AppTool.SystemUI.showNavigationBar(this,false)
+        AppTool.SystemUI.ImmersiveWithBottomBarColor(this, Color.BLACK)
+
+        //open serial port
+        SerialPortUtil.getInstance().openSerialPort()
+
+        requestPermissions()
+
+        SoundPoolManager.getInstance().init()
+
+        if ("rk3128" == Build.MODEL) {
+            btn_test.visibility = View.VISIBLE
+        } else {
+            btn_test.visibility = View.GONE
+        }
+    }
+
+    private fun reload() {
+        tv_local_ip.text = "IP: " + NetHelper.getInstance().localIP + ", server: " + serverIp
+
+        handler.postDelayed({
+            presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+        }, 30000)
+    }
+
+    private fun permissionGranted() {
+        Constant.DEVICE_REGISTER_ID = NetHelper.getInstance().macAddress
+        Log.e(TAG,"mac "+ Constant.DEVICE_REGISTER_ID)
+        tv_local_mac.text = "MAC:"+ Constant.DEVICE_REGISTER_ID
+
+        Thread{
+            //val logoBitmap = BitmapFactory.decodeResource(resources, R.mipmap.erlogo)
+            var builder = StringBuilder()
+            builder.append(QR_CODE_PATH)
+            builder.append("&code=")
+            builder.append(Constant.DEVICE_CODE)
+            builder.append("&mac=")
+            builder.append(Constant.DEVICE_REGISTER_ID)
+            builder.append("&model=")
+            builder.append(Constant.DEVICE_MODEL)
+            builder.append("&hard_ver=")
+            builder.append(Constant.DEVICE_HARD_VER)
+            builder.append("&soft_ver=")
+            builder.append(Constant.DEVICE_SOFT_VER)
+            builder.append("&device_type=")
+            builder.append(DeviceTypeEnum.NURSE_HOST.value())
+            builder.append("&device_name=")
+            builder.append(DeviceTypeEnum.NURSE_HOST.typeName())
+            val code = EcodeHelper().createQRImage(builder.toString(),320, null)
+            activity.runOnUiThread {
+                view_qr_code?.setImageBitmap(code)
+            }
+        }.start()
+        //val macAddr = NetHelper.getInstance().macAddress
+        val ipAddr = NetHelper.getInstance().localIP
+        val buildUrl = UrlManager.build()
+        serverIp =  buildUrl.buyer.substringAfterLast("//").substringBefore(":")
+
+        tv_local_ip.text = "IP: " + ipAddr + ", server: " + serverIp
+        tv_local_mac.text = "MAC: " + Constant.DEVICE_REGISTER_ID
+        val str = ("App name: " + getString(R.string.wdkl_app_name)
+                + "\r\nAPP version: V" + BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE + "_" + Build.MODEL
+                + "\r\nRelease:" + BuildConfig.BUILD_TIME
+                + "\r\nSDK: " + Build.VERSION.SDK_INT)
+
+        if (Constant.DEVICE_7INCH) {
+            tv_app_version.text = str + "\r\n--7inch"
+        } else {
+            tv_app_version.text = str
+        }
+        //tv_mcu_version.text = "MCU版本: " + Constants.MCU_VERSION_NUMBER
+
+        //检查服务器地址接口是否可用,可用则进入下一步获取设备信息,不可用则稍后再次尝试
+        checkServer()
+    }
+
+    private fun requestPermissions(){
+        Observable.just("").compose(
+            RxPermissions(this).ensure(
+                Manifest.permission.CAMERA,
+                Manifest.permission.READ_EXTERNAL_STORAGE,
+                Manifest.permission.WRITE_EXTERNAL_STORAGE,
+                Manifest.permission.ACCESS_WIFI_STATE,
+                Manifest.permission.RECORD_AUDIO,
+                Manifest.permission.READ_PHONE_STATE
+            )
+        ).subscribe {
+            if (it){
+                Log.e(TAG,"拿到APP所有权限")
+                permissionGranted()
+            }else{
+                showMessage(R.string.permission_grant_tips)
+                requestPermissions()
+            }
+        }.joinManager(disposableManager)
+    }
+
+    private fun checkServer() {
+        Thread {
+            while (!serverSuccess) {
+                val okHttpClient = OkHttpClient().newBuilder()
+                    .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .build()
+                val url: String = CommonUtils.getUrl(BaseApplication.appContext)
+                val port: String = CommonUtils.getUrlPort(BaseApplication.appContext)
+                val request = Request.Builder()
+                    .url("http://$url:$port/ncs_url/server_info")
+                    .get()
+                    .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,进入下一步获取设备信息
+                        serverSuccess = true
+                        presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+                    } else {
+                        //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                        val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                        checkServerInfo(info)
+                    }
+                } catch (e: Exception) {
+                    //接口数据获取失败,可能服务器ip不对,尝试重新获取服务器ip
+                    val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                    checkServerInfo(info)
+                    //e.printStackTrace()
+                }
+
+                try {
+                    Thread.sleep(30000)
+                } catch (ex: Exception) {
+                    ex.printStackTrace()
+                }
+            }
+        }.start()
+    }
+
+    private fun checkServerInfo(info: ThirdServerInfo?) {
+        //检查获取到的服务器ip是否可用,可用则重启app重新初始化,不可用则什么都不做,等待下次重新获取服务器ip
+        if (info != null) {
+            if (info.thirdServer == null || info.thirdServerPort == null) {
+                Log.d(TAG, "server info data null")
+                showMsgMain("get server data null")
+            } else {
+                val okHttpClient = OkHttpClient().newBuilder()
+                    .connectTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .readTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .writeTimeout(15 * 1000L, TimeUnit.MILLISECONDS)
+                    .build()
+                val request = Request.Builder()
+                    .url("http://${info.thirdServer}:${info.thirdServerPort}/ncs_url/server_info")
+                    .get()
+                    .build()
+
+                try {
+                    val response = okHttpClient.newCall(request).execute()
+                    if (response != null && response.isSuccessful) {
+                        //接口数据获取成功,稍后重启app
+                        serverSuccess = true
+                        CommonUtils.setUrl(activity, info.thirdServer)
+                        CommonUtils.setUrlPort(activity, info.thirdServerPort.toString())
+                        showMsgMain("restart...")
+                        handler.postDelayed({
+                            if (!cancelRestart) {
+                                AppUpdateHelper.restartApp(activity)
+                            }
+                        }, 10000)
+                    }
+                } catch (e: Exception) {
+                    e.printStackTrace()
+                    showMsgMain("server error or net error")
+                }
+            }
+        } else {
+            Log.d(TAG, "server info null")
+            showMsgMain("get server null")
+        }
+    }
+
+    private fun showMsgMain(msg: String) {
+        runOnUiThread {
+            showMessage(msg)
+        }
+    }
+
+    /**
+     *显示数据
+     */
+    override fun showData(data : NurseDeviceInfoVO) {
+        Log.e(TAG,"收到返回的设备信息 "+data.hospitalName)
+        Log.e(TAG,"收到返回的设备信息 "+data.partName)
+        Log.e(TAG,"收到返回的设备信息 "+data.partId)
+        Log.e(TAG,"收到返回的设备信息 "+data.id)
+        Log.e(TAG,"收到返回的设备信息 "+data.sipId)
+        Log.e(TAG,"收到返回的设备信息 "+data.toString())
+
+        Constant.hospital_name = data.hospitalName
+        Constant.part_name = data.partName
+        Constant.partDisplay = data.partDisplay
+        Constant.part_id = data.partId
+        Constant.DEVICE_ID = data.id
+        Constant.SIP_ID = data.sipId
+        Constant.eth_ip = data.ethIp
+        if (data.hospitalId != null) {
+            Constant.hospital_id = data.hospitalId
+        }
+        if (data.sipIp != null) {
+            Constant.sip_ip = data.sipIp
+        }
+
+        Constant.DEVICE_CODE = data.code
+        Constant.DEVICE_MODEL =  data.model
+        Constant.DEVICE_HARD_VER =  data.hardVer
+        Constant.DEVICE_SOFT_VER = data.softVer
+        if (data.deviceType != null) {
+            Constant.DEVICE_TYPE = data.deviceType
+        }
+        if (data.name != null) {
+            Constant.DEVICE_NAME = data.name
+        }
+        if (data.backupId != null) {
+            Constant.back_id = data.backupId
+        }
+
+        if(TextUtils.isEmpty(data.partId.toString())|| TextUtils.isEmpty(data.id.toString())
+                || TextUtils.isEmpty(data.sipId)){
+            feedback_device_info_tv.setText(R.string.device_init_fail)
+            showMessage(R.string.device_init_fail)
+            reload()
+            return
+        } else if (data.status != null && data.status == 0) {
+            feedback_device_info_tv.setText(R.string.device_disabled)
+            showMessage(R.string.device_disabled)
+            reload()
+            return
+        }
+
+        handler.removeCallbacksAndMessages(null)
+
+        AppTool.Time.delay(1000) {
+            if (!homeLaunch) {
+                homeLaunch = true
+                push("/nursehome/main")
+                finish()
+            }
+        }
+    }
+
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        btn_reload.isEnabled = false
+        btn_reload.setOnClickListener {
+            btn_reload.isEnabled = false
+            presenter.loadData(Constant.DEVICE_REGISTER_ID!!)
+        }
+
+        btn_get_server.setOnClickListener {
+            btn_get_server.isEnabled = false
+            Thread {
+                val info = ServerInfoUtil.get(Constant.DEVICE_REGISTER_ID!!)
+                runOnUiThread {
+                    btn_get_server.isEnabled = true
+                    if (info != null) {
+                        Log.d(TAG, "server info-" + info.thirdServer)
+                        showMessage("server info: ${info.thirdServer}")
+                        tv_local_ip.text = "IP: ${NetHelper.getInstance().localIP}, server: ${info.thirdServer}"
+                    } else {
+                        Log.d(TAG, "server info null")
+                        showMessage("server info null")
+                    }
+                }
+
+                if (info != null && info.thirdServer != null && info.thirdServerPort != null) {
+                    CommonUtils.setUrl(activity, info.thirdServer)
+                    CommonUtils.setUrlPort(activity, info.thirdServerPort.toString())
+                }
+            }.start()
+        }
+
+        btn_set_server.setOnClickListener {
+            cancelRestart = true
+            handler.removeCallbacksAndMessages(null)
+            ServerConfigDialogHelper.showPasswordDialog(activity)
+        }
+
+        btn_reboot.setOnClickListener {
+            cancelRestart = true
+            handler.removeCallbacksAndMessages(null)
+            AppUpdateHelper.restartApp(activity)
+        }
+
+        btn_set_language.setOnClickListener {
+            cancelRestart = true
+            handler.removeCallbacksAndMessages(null)
+            LanguageSetDialogHelper.showDialog(activity)
+        }
+
+        btn_test.setOnClickListener {
+            cancelRestart = true
+            handler.removeCallbacksAndMessages(null)
+            PasswordDialogHelper.showPasswordDialog(activity) {
+                push("/nursehome/test")
+            }
+        }
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+        handler.removeCallbacksAndMessages(null)
+        SoundPoolManager.getInstance().release()
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+        btn_reload.isEnabled = true
+        showMessage("Load error: $message")
+        reload()
+    }
+
+    override fun onNoneNet() {
+        //Log.e(TAG,"none net ")
+        btn_reload.isEnabled = true
+        showMessage("None net")
+        reload()
+    }
+
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+    }
+
+}

+ 103 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/activity/TestActivity.kt

@@ -0,0 +1,103 @@
+package com.wdkl.ncs.android.component.nursehome.activity
+
+
+import androidx.fragment.app.Fragment
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.TestActivityBinding
+import com.wdkl.ncs.android.component.nursehome.fragment.TestFragment
+import com.wdkl.ncs.android.component.nursehome.helper.RecordHelper
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseActivity
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DeviceContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DevicePresenter
+import com.wdkl.ncs.android.middleware.model.vo.NurseDeviceInfoVO
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import serialporttest.utils.SerialPortUtilHost
+
+@Router(path = "/nursehome/test")
+class TestActivity : BaseActivity<DevicePresenter, TestActivityBinding>(), DeviceContract.View,
+        SerialPortUtilHost.ISerialPortOnclickEvent, SerialPortUtilHost.IForkSpringSwiData{
+
+    override fun getLayId(): Int {
+        return R.layout.test_activity
+    }
+
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        SerialPortUtilHost.getInstance().setOnDataReceiveListener(this, this)
+
+        RecordHelper.getInstance().init()
+
+        switchFragment(R.id.test_frame, TestFragment(), "test_fragment")
+    }
+
+    override fun bindEvent() {
+        //
+    }
+
+    override fun destory() {
+    }
+
+
+
+    private fun switchFragment(id: Int, fragment: Fragment, tag: String) {
+        supportFragmentManager.beginTransaction()
+            .replace(id, fragment, tag)
+            .commitAllowingStateLoss()
+    }
+
+    override fun serialPortBedOnclick(buffer: ByteArray) {
+        //呼叫键按下
+        if (buffer[0].toInt() == 0) {
+            EventBus.getDefault().post(MessageEvent("call1", Constant.EVENT_SERIAL_TEST))
+        }
+    }
+
+    override fun forkSpringData(data: Int) {
+        if (data == 1) {
+            //放下手柄
+            EventBus.getDefault().post(MessageEvent("hook_on", Constant.EVENT_SERIAL_TEST))
+        } else if (data == 0) {
+            //拿起手柄
+            EventBus.getDefault().post(MessageEvent("hook_off", Constant.EVENT_SERIAL_TEST))
+        }
+    }
+
+    override fun showData(data: NurseDeviceInfoVO) {
+        //
+    }
+
+    override fun onNoneNet() {
+        //
+    }
+
+    override fun onError(message: String, type: Int) {
+        //
+    }
+
+    override fun complete(message: String, type: Int) {
+        //
+    }
+
+    override fun start() {
+        //
+    }
+
+    override fun networkMonitor(state: NetState) {
+        //
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+    }
+}

+ 76 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/BedItemAdapter.java

@@ -0,0 +1,76 @@
+package com.wdkl.ncs.android.component.nursehome.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.middleware.model.vo.FrameBedVO;
+
+import java.util.ArrayList;
+
+import androidx.recyclerview.widget.RecyclerView;
+
+public class BedItemAdapter extends RecyclerView.Adapter<BedItemAdapter.BedViewHolder> {
+
+    private Context context;
+    private ArrayList<FrameBedVO> data;
+    private InviteClickListener inviteClickListener;
+
+    public BedItemAdapter(Context context, ArrayList<FrameBedVO> data) {
+        this.context = context;
+        this.data = data;
+    }
+
+    @Override
+    public BedViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
+        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.adapter_visit_bed, viewGroup, false);
+        BedViewHolder viewHolder = new BedViewHolder(view);
+
+        return viewHolder;
+    }
+
+    @Override
+    public void onBindViewHolder(final BedViewHolder bedViewHolder, int i) {
+        bedViewHolder.visitBed.setText(data.get(i).getFrameBed().getFullName());
+        bedViewHolder.visitName.setText(data.get(i).getCustomerName());
+        bedViewHolder.visit.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (inviteClickListener != null) {
+                    inviteClickListener.onClick(data.get(bedViewHolder.getAdapterPosition()));
+                }
+            }
+        });
+    }
+
+    @Override
+    public int getItemCount() {
+        return data.size();
+    }
+
+    public void setInvitClickListener(InviteClickListener listener) {
+        inviteClickListener = listener;
+    }
+
+
+    class BedViewHolder extends RecyclerView.ViewHolder {
+        TextView visitBed;
+        TextView visitName;
+        Button visit;
+
+        BedViewHolder(View itemView) {
+            super(itemView);
+            visitBed = itemView.findViewById(R.id.tv_visit_bed);
+            visitName = itemView.findViewById(R.id.tv_visit_name);
+            visit = itemView.findViewById(R.id.btn_visit);
+        }
+    }
+
+    public interface InviteClickListener{
+        void onClick(FrameBedVO bedVO);
+    }
+}

+ 93 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/BroadcastAdapter.kt

@@ -0,0 +1,93 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterBroadcastBinding
+import com.wdkl.ncs.android.component.nursehome.fragment.BroadcastFragment
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+
+/**
+ * 广播列表适配器
+ */
+class BroadcastAdapter(var context: BroadcastFragment, val data: ArrayList<String>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterBroadcastBinding>, String>() {
+
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0, data.size)
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterBroadcastBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_broadcast)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterBroadcastBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.serialNumberTv.text = "" + (position + 1)
+
+            binding.deleteBt.setOnClickListener {
+
+
+            }
+            binding.auditionBt.setOnClickListener {
+
+            }
+            binding.playBt.setOnClickListener {
+
+            }
+            binding.suspendBt.setOnClickListener {
+
+            }
+            binding.setBt.setOnClickListener {
+//
+                context.addTheTiming(position)
+            }
+
+//            binding.addTheTimingTv.setOnClickListener{
+//                binding.setTheTimerRelalyout.addView(binding.suspendBt)
+//
+//            }
+
+
+
+
+        }
+    }
+
+
+}
+
+

+ 366 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CallRecordsItemAdapter.kt

@@ -0,0 +1,366 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.util.Log
+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.google.common.base.Strings
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterCallRecordsItemBinding
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.nursehome.util.*
+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.common.MessageEvent
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.TcpClient
+import com.wdkl.ncs.android.middleware.tcp.channel.OtherUtil
+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.DeviceTypeEnum
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+import org.greenrobot.eventbus.EventBus
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * 呼叫记录适配器
+ */
+class CallRecordsItemAdapter(val data:ArrayList<InteractionVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterCallRecordsItemBinding>,InteractionVO>(){
+     var TAG = CallRecordsItemAdapter::class.java.getSimpleName()
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        Log.i("abc",data.toString());
+        return LinearLayoutHelper(0,data.size)
+    }
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterCallRecordsItemBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_call_records_item)
+    }
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterCallRecordsItemBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+
+            if (itemData.createDate != null) {
+                binding.processingTimeTv.text = TimeTransition.stampToDateTime(itemData.createDate * 1000)
+            }
+            binding.stateText.visibility = View.GONE
+
+            //探视记录
+            if (TcpType.VIDEO.name == itemData.actionType) {
+                binding.sickbedTv.text = itemData.fromFrameFullName
+                binding.nameTv.setText(R.string.call_visiting)
+                binding.callStatusImagev.visibility = View.GONE
+                binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                binding.callListReply.visibility = View.GONE
+                binding.callSosReply.visibility = View.GONE
+                return
+            }
+
+            //访客开门
+            else if (TcpType.ENTRACEGUARD.name == itemData.actionType) {
+                binding.sickbedTv.text = itemData.fromDeviceName
+                binding.nameTv.setText(R.string.call_entrance_guard)
+                binding.callStatusImagev.visibility = View.GONE
+                binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                binding.callListReply.visibility = View.GONE
+                binding.callSosReply.visibility = View.GONE
+                binding.stateText.visibility = View.VISIBLE
+                binding.stateText.text=itemData.data?.toString()
+                return
+            }
+
+            //事件
+            else if (TcpType.EVENT.name == itemData.actionType){
+                binding.sickbedTv.text = itemData.fromFrameFullName
+                binding.nameTv.text = itemData.fromMemberName
+                binding.callStatusImagev.visibility = View.GONE
+                binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                binding.callListReply.visibility = View.GONE
+                binding.callSosReply.visibility = View.GONE
+                binding.stateText.visibility = View.VISIBLE
+                binding.stateText.text=itemData.data
+                return
+            }
+
+            //是否已处理
+            if (itemData.actionEnd != null) {
+                binding.processingTimeTv.text = TimeTransition.stampToDateTime(itemData.actionEnd * 1000)
+
+                if (TcpType.SOS.name == itemData.actionType) {
+                    //紧急呼叫已处理: 因为紧急按钮是连接在某个分机上,所以收到的紧急呼叫信息会携带该分机的信息,实际需要显示的是该房间的信息
+                    var roomNo: String? = ""
+                    if (itemData.fromFrameFullName != null) {
+                        roomNo = itemData.fromFrameFullName.substringBefore("-")
+                    }
+                    //如果分机绑定了紧急按钮则加上紧急按钮名称
+                    if (itemData.fromDeviceType == DeviceTypeEnum.EMERGENCY_BUTTON.value()
+                        || itemData.fromDeviceType == DeviceTypeEnum.SIMULATE_EMERGENCY_BUTTON.value()) {
+                        if (SettingConfig.getSosCallNameOn(BaseApplication.appContext)) {
+                            roomNo = itemData.fromDeviceName
+                        }
+                    }
+
+                    if (!Strings.isNullOrEmpty(itemData.data)) {
+                        binding.sickbedTv.text = itemData.fromFrameFullName
+                        binding.nameTv.text = itemData.data
+                    } else {
+                        binding.sickbedTv.text = roomNo
+                        binding.nameTv.setText(R.string.call_sos)
+                    }
+
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.ic_sos)
+                    binding.callListReply.visibility = View.GONE
+                    binding.callSosReply.visibility = View.GONE
+                } else if (TcpType.VOICE.name == itemData.actionType) {
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                    binding.callListReply.visibility = View.GONE
+                    binding.callSosReply.visibility = View.GONE
+                    binding.sickbedTv.text = ""
+                    binding.nameTv.text = ""
+
+                    if (itemData.fromDeviceId == Constant.DEVICE_ID) {
+                        //这是去电
+                        if (itemData.toDeviceType == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                            || itemData.toDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+                            binding.sickbedTv.text = itemData.toFrameFullName
+                            binding.nameTv.text = itemData.toMemberName
+                            binding.callStatusImagev.setImageResource(R.drawable.hu_chu_yi_jie)
+                            binding.callStatusImagev.visibility = View.VISIBLE
+                        } else {
+                            //护士主机,医生机,移动手机等交互记录
+                            binding.sickbedTv.text = itemData.toFrameFullName
+                            binding.nameTv.text = itemData.toDeviceName
+                            binding.callStatusImagev.visibility = View.GONE
+                            binding.callListReply.visibility = View.GONE
+                        }
+                    } else {
+                        //来电
+                        if (itemData.fromDeviceType == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                            || itemData.fromDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()
+                        ) {
+                            //分机呼叫主机
+                            binding.sickbedTv.text = itemData.fromFrameFullName
+                            binding.nameTv.text = itemData.fromMemberName
+                            binding.callStatusImagev.setImageResource(R.drawable.hu_ru_yi_jie)
+                            binding.callStatusImagev.visibility = View.VISIBLE
+                        } else if (itemData.fromDeviceType == DeviceTypeEnum.NURSE_HOST.value()
+                            || itemData.fromDeviceType == DeviceTypeEnum.NURSE_WATCH.value()
+                        ) {
+                            //护士主机,医生机,移动手机等交互记录
+                            binding.sickbedTv.text = itemData.fromFrameFullName
+                            binding.nameTv.text = itemData.fromDeviceName
+                            binding.callStatusImagev.visibility = View.GONE
+                            binding.callListReply.visibility = View.GONE
+                        }
+                    }
+                } else if (TcpType.REINFORCE.name == itemData.actionType) {
+                    //增援请求
+                    //val roomNo = itemData.fromFrameFullName.substringBefore("-")
+                    binding.sickbedTv.text = itemData.fromFrameFullName
+                    binding.nameTv.setText(R.string.call_reinforce)
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                    binding.callListReply.visibility = View.GONE
+                    binding.callSosReply.visibility = View.GONE
+                }
+            } else {
+                if (TcpType.SOS.name == itemData.actionType) {
+                    //紧急呼叫未处理
+                    var roomNo: String? = ""
+                    if (itemData.fromFrameFullName != null) {
+                        roomNo = itemData.fromFrameFullName.substringBefore("-")
+                    }
+                    //如果分机绑定了紧急按钮则加上紧急按钮名称
+                    if (itemData.fromDeviceType == DeviceTypeEnum.EMERGENCY_BUTTON.value()
+                        || itemData.fromDeviceType == DeviceTypeEnum.SIMULATE_EMERGENCY_BUTTON.value()) {
+                        if (SettingConfig.getSosCallNameOn(BaseApplication.appContext)) {
+                            roomNo = itemData.fromDeviceName
+                        }
+                    }
+
+                    if (!Strings.isNullOrEmpty(itemData.data)) {
+                        binding.sickbedTv.text = itemData.fromFrameFullName
+                        binding.nameTv.text = itemData.data
+                    } else {
+                        binding.sickbedTv.text = roomNo
+                        binding.nameTv.setText(R.string.call_sos)
+                    }
+
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.ic_sos)
+                    binding.callListReply.visibility = View.GONE
+                    binding.callSosReply.visibility = View.VISIBLE
+                } else if (TcpType.VOICE.name == itemData.actionType) {
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                    binding.callListReply.visibility = View.VISIBLE
+                    binding.callSosReply.visibility = View.GONE
+                    binding.sickbedTv.text = ""
+                    binding.nameTv.text = ""
+
+                    if (itemData.fromDeviceId == Constant.DEVICE_ID) {
+                        //这是去电
+                        if (itemData.toDeviceType == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                            || itemData.toDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+                            binding.sickbedTv.text = itemData.toFrameFullName
+                            binding.nameTv.text = itemData.toMemberName
+                            binding.callStatusImagev.setImageResource(R.drawable.hu_chu_wei_jie)
+                            binding.callStatusImagev.visibility = View.VISIBLE
+                        } else {
+                            //护士主机,医生机,移动手机等交互记录
+                            binding.sickbedTv.text = itemData.toFrameFullName
+                            binding.nameTv.text = itemData.toDeviceName
+                            binding.callStatusImagev.visibility = View.GONE
+                            binding.callListReply.visibility = View.GONE
+                        }
+                    } else {
+                        //来电
+                        if (itemData.fromDeviceType == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                            || itemData.fromDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()
+                        ) {
+                            //分机呼叫主机
+                            binding.sickbedTv.text = itemData.fromFrameFullName
+                            binding.nameTv.text = itemData.fromMemberName
+                            binding.callStatusImagev.setImageResource(R.drawable.hu_ru_wei_jie)
+                            binding.callStatusImagev.visibility = View.VISIBLE
+                        } else {
+                            //护士主机,医生机,移动手机等交互记录
+                            binding.sickbedTv.text = itemData.fromFrameFullName
+                            binding.nameTv.text = itemData.fromDeviceName
+                            binding.callStatusImagev.visibility = View.GONE
+                            binding.callListReply.visibility = View.GONE
+                        }
+                    }
+                } else if (TcpType.REINFORCE.name == itemData.actionType) {
+                    //增援请求
+                    //val roomNo = itemData.fromFrameFullName.substringBefore("-")
+                    binding.sickbedTv.text = itemData.fromFrameFullName
+                    binding.nameTv.setText(R.string.call_reinforce)
+                    binding.callStatusImagev.visibility = View.GONE
+                    binding.tabImagev.setImageResource(R.drawable.lai_dian_tou_xiang_bg)
+                    binding.callListReply.visibility = View.GONE
+                    binding.callSosReply.visibility = View.GONE
+                }
+            }
+
+            //门口机呼叫记录
+            if (itemData.fromDeviceType != null && itemData.fromDeviceType == 3 && TcpType.VOICE.name == itemData.actionType) {
+                binding.sickbedTv.text = itemData.fromFrameFullName
+                binding.nameTv.setText(R.string.call_door)
+                binding.callStatusImagev.visibility = View.GONE
+                binding.callListReply.visibility = View.GONE
+                binding.callSosReply.visibility = View.GONE
+            }
+
+            binding.callListReply.setOnClickListener {
+                if (Constant.DEVICE_ID != 0) {
+                    //呼出时停止语音播报及铃声
+                    SpeechUtil.getInstance().stopSpeak(true)
+                    RingPlayHelper.stopRingTone()
+
+                    if (itemData.fromDeviceId == Constant.DEVICE_ID) {
+                        //去电
+                        if (NurseHomeActivity.checkIncomingCall(itemData.toDeviceId)) {
+                            showMessage(R.string.call_in_list)
+                        } else {
+                            if (Constant.TCP_CONNECTED) {
+                                Constant.targetDeviceId = itemData.toDeviceId
+                                Constant.CALL_TYPE = 0
+                                val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, itemData.toDeviceId)
+                                val transaction = object : TcpCallback(callTcp.tid) {
+                                    override fun onSuccess(jsonObject: JSONObject) {
+                                        super.onSuccess(jsonObject)
+                                    }
+
+                                    override fun onFailed(jsonObject: JSONObject) {
+                                        // 这里写发送失败的方法
+                                        val callbackString = jsonObject.getString(CALLBACK)
+                                        showMessage("call fail: $callbackString")
+                                        super.onFailed(jsonObject)
+                                    }
+                                }
+                                TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+                            } else {
+                                showMessage(R.string.net_error)
+                            }
+                        }
+                    } else {
+                        //来电
+                        if (NurseHomeActivity.checkIncomingCall(itemData.fromDeviceId)) {
+                            showMessage(R.string.call_in_list)
+                        } else {
+                            if (Constant.TCP_CONNECTED) {
+                                Constant.targetDeviceId = itemData.toDeviceId
+                                Constant.CALL_TYPE = 0
+                                val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, itemData.fromDeviceId)
+                                val transaction = object : TcpCallback(callTcp.tid) {
+                                    override fun onSuccess(jsonObject: JSONObject) {
+                                        super.onSuccess(jsonObject)
+                                    }
+
+                                    override fun onFailed(jsonObject: JSONObject) {
+                                        // 这里写发送失败的方法
+                                        val callbackString = jsonObject.getString(CALLBACK)
+                                        showMessage("call fail: $callbackString")
+                                        super.onFailed(jsonObject)
+                                    }
+                                }
+                                TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+                            } else {
+                                showMessage(R.string.net_error)
+                            }
+                        }
+                    }
+                } else {
+                    showMessage(R.string.call_no_device)
+                }
+            }
+
+            binding.callSosReply.setOnClickListener {
+                if (Constant.DEVICE_ID != 0) {
+                    OtherUtil.cancelSosCallHost(Constant.DEVICE_ID, itemData.fromDeviceId, itemData.id)
+                    LedHelper.updateLedInfo(itemData, false, true)
+                    EventBus.getDefault().post(MessageEvent(0, Constant.EVENT_REFRESH_CALL_LIST))
+                } else {
+                    showMessage(R.string.call_no_device)
+                }
+            }
+        }
+    }
+
+}

+ 171 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CallingItemAdapter.kt

@@ -0,0 +1,171 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil
+import com.wdkl.ncs.android.component.nursehome.util.TimeTransition
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.entity.CallingItem
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum
+import org.greenrobot.eventbus.EventBus
+
+class CallingItemAdapter : RecyclerView.Adapter<CallingItemAdapter.ParentViewHolder> {
+    private var context: Context
+    private var callingData: ArrayList<CallingItem>
+    private var updateCallback: UpdateCallback? = null
+
+    constructor(context: Context, data: ArrayList<CallingItem>) {
+        this.context = context
+        this.callingData = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParentViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.adapter_calling_item, parent, false)
+        val viewHolder = ParentViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
+        try {
+            val callingItem = callingData.get(position)
+            val itemData = callingItem.interactionVO
+            var frameName: String? = ""
+            var memberName: String? = ""
+            if (DeviceTypeEnum.DOCTOR_HOST.value() == itemData.fromDeviceType
+                || DeviceTypeEnum.NURSE_HOST.value() == itemData.fromDeviceType
+                || DeviceTypeEnum.OTHER_HOST.value() == itemData.fromDeviceType) {
+                //医生机,护士主机,其他主机,总控主机等
+                frameName = itemData.fromDeviceName
+            } else if (DeviceTypeEnum.NURSE_WATCH.value() == itemData.fromDeviceType) {
+                //移动设备
+                frameName = itemData.fromMemberName
+            } else {
+                //其他
+                frameName = itemData.fromFrameFullName
+                memberName = itemData.fromMemberName
+            }
+
+            holder?.callingBedName?.text = frameName
+            holder?.callingName?.text = memberName
+            if (itemData.createDate != null) {
+                holder?.callingTime?.text = TimeTransition.stampToDateTime(itemData.createDate * 1000)
+            }
+
+            holder?.callingAccept?.setOnClickListener {
+                EventBus.getDefault().post(MessageEvent(callingItem, Constant.EVENT_ACCEPT_CALL))
+                removeCall(itemData, true)
+            }
+
+            /*holder?.callingReject?.setOnClickListener {
+                removeCall(itemData)
+            }*/
+        } catch (ex : Exception) {
+            ex.printStackTrace()
+        }
+    }
+
+    override fun getItemCount(): Int {
+        return callingData.size
+    }
+
+    fun addCall(callingItem: CallingItem) {
+        synchronized(this) {
+            val iterator = NurseHomeActivity.callingList.iterator()
+            while (iterator.hasNext()) {
+                val it = iterator.next()
+                if (callingItem.interactionVO.fromDeviceId == it.interactionVO.fromDeviceId) {
+                    iterator.remove()
+                }
+            }
+            NurseHomeActivity.callingList.add(callingItem)
+            updateCallList()
+        }
+    }
+
+    private fun updateCallList() {
+        callingData.clear()
+        callingData.addAll(NurseHomeActivity.callingList)
+        notifyDataSetChanged()
+
+        if (updateCallback != null) {
+            updateCallback?.onUpdate()
+        }
+    }
+
+    fun removeCall(interactionVO: InteractionVO, stop: Boolean) {
+        if (stop) {
+            RingPlayHelper.stopRingTone()
+            SpeechUtil.getInstance().stopSpeak(true)
+        }
+
+        synchronized(this) {
+            val iterator = NurseHomeActivity.callingList.iterator()
+            while (iterator.hasNext()) {
+                val it = iterator.next()
+                if (interactionVO.id.equals(it.interactionVO.id)) {
+                    iterator.remove()
+                }
+            }
+
+            updateCallList()
+        }
+    }
+
+    fun removeCallByPos(position: Int, stop: Boolean) {
+        if (stop) {
+            RingPlayHelper.stopRingTone()
+            SpeechUtil.getInstance().stopSpeak(true)
+        }
+
+        synchronized(this) {
+            val removeItem = callingData.get(position)
+            EventBus.getDefault().post(MessageEvent(removeItem, Constant.EVENT_REJECT_CALL))
+            val iterator = NurseHomeActivity.callingList.iterator()
+            while (iterator.hasNext()) {
+                val it = iterator.next()
+                if (removeItem.interactionVO.id.equals(it.interactionVO.id)) {
+                    iterator.remove()
+                }
+            }
+
+            updateCallList()
+        }
+    }
+
+    fun setUpdateCallback(callBack: UpdateCallback) {
+        updateCallback = callBack
+    }
+
+
+
+    class ParentViewHolder : RecyclerView.ViewHolder {
+        var callingBedName : TextView
+        var callingName : TextView
+        var callingTime : TextView
+        var callingAccept : ImageView
+        var callingReject : ImageView
+
+        constructor(itemView: View): super(itemView) {
+            callingBedName = itemView.findViewById(R.id.tv_calling_bed_name)
+            callingName = itemView.findViewById(R.id.tv_calling_custom_name)
+            callingTime = itemView.findViewById(R.id.tv_calling_time)
+            callingAccept = itemView.findViewById(R.id.btn_call_accept)
+            callingReject = itemView.findViewById(R.id.btn_call_reject)
+        }
+    }
+
+    interface UpdateCallback {
+        fun onUpdate()
+    }
+}

+ 103 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/CostItemAdapter.kt

@@ -0,0 +1,103 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.middleware.model.dto.FeeConfigByGroupNameDto
+import com.wdkl.ncs.android.middleware.model.dto.FeeConfigDto
+import kotlin.math.cos
+
+class CostItemAdapter : RecyclerView.Adapter<CostItemAdapter.ParentViewHolder> {
+
+    private var context: Context
+    private var mainData: ArrayList<FeeConfigByGroupNameDto>
+
+    constructor(context: Context, data: ArrayList<FeeConfigByGroupNameDto>) {
+        this.context = context
+        this.mainData = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParentViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_cost_main_view, parent, false)
+        val viewHolder = ParentViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
+        holder?.costGroupName?.text = mainData.get(position).feeGroupName
+        val cost = BaseApplication.appContext.getString(R.string.cost_subtotal, mainData.get(position).subtotal)
+        holder?.costGroupTotal?.text = cost
+
+        val layoutManager = LinearLayoutManager(context)
+        holder?.costDetail?.layoutManager = layoutManager
+        holder?.costDetail?.adapter = CostDetailAdapter(mainData.get(position).feeConfigList)
+    }
+
+    override fun getItemCount(): Int {
+        return mainData.size
+    }
+
+    fun updateData(data: ArrayList<FeeConfigByGroupNameDto>) {
+        mainData = data
+        notifyDataSetChanged()
+    }
+
+    class ParentViewHolder : RecyclerView.ViewHolder {
+        var costGroupName : TextView
+        var costGroupTotal : TextView
+        var costDetail : RecyclerView
+
+        constructor(itemView: View): super(itemView) {
+            costGroupName = itemView.findViewById(R.id.tv_cost_group_name)
+            costGroupTotal = itemView.findViewById(R.id.tv_cost_group_total)
+            costDetail = itemView.findViewById(R.id.rv_cost_detail)
+        }
+    }
+
+    class CostDetailAdapter : RecyclerView.Adapter<CostDetailAdapter.ChildViewHolder> {
+        private var costData: List<FeeConfigDto>
+
+        constructor(data: List<FeeConfigDto>) {
+            costData = data
+        }
+
+        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChildViewHolder {
+            val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_cost_detail, parent, false)
+            val viewHolder = ChildViewHolder(view)
+
+            return viewHolder
+        }
+
+        override fun onBindViewHolder(holder: ChildViewHolder, position: Int) {
+            holder?.costName?.text = costData.get(position).feeName
+            holder?.costValue?.text = "" + costData.get(position).feeValue
+            holder?.costId?.text = costData.get(position).feeKeyCode
+            holder?.costUnit?.text = costData.get(position).feeUnit
+        }
+
+        override fun getItemCount(): Int {
+            return costData.size
+        }
+
+        class ChildViewHolder : RecyclerView.ViewHolder {
+            var costName : TextView
+            var costValue : TextView
+            var costId : TextView
+            var costUnit : TextView
+
+            constructor(item : View) : super(item) {
+                costName = item.findViewById(R.id.tv_item_cost_name)
+                costValue = item.findViewById(R.id.tv_item_cost_value)
+                costId = item.findViewById(R.id.tv_item_cost_id)
+                costUnit = item.findViewById(R.id.tv_item_cost_unit)
+            }
+        }
+    }
+}

+ 76 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/DoctorHostAdapter.kt

@@ -0,0 +1,76 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterDoctorHostBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+import com.wdkl.ncs.android.middleware.model.dos.DeviceDO
+import com.wdkl.ncs.android.middleware.model.vo.FrameRoomVO
+/**
+ * 医生机适配器
+ */
+class DoctorHostAdapter(val data:ArrayList<DeviceDO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterDoctorHostBinding>, DeviceDO>(){
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return GridLayoutHelper(3).then {
+            self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0,0,0,0)
+        }
+
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterDoctorHostBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.doctorNameTv.text = itemData.name
+        }
+    }
+
+
+}

+ 103 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/ExamAdapter.kt

@@ -0,0 +1,103 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Context
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.util.TimeTransition
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.middleware.model.dto.ExaminationConfigByGroupNameDto
+import com.wdkl.ncs.android.middleware.model.dto.ExaminationConfigDto
+
+class ExamAdapter : RecyclerView.Adapter<ExamAdapter.ParentViewHolder>{
+
+    private var context: Context
+    private var data: ArrayList<ExaminationConfigByGroupNameDto>
+
+    constructor(context: Context, data: ArrayList<ExaminationConfigByGroupNameDto>) {
+        this.context = context
+        this.data = data
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ParentViewHolder {
+        val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_exam_main_view, parent, false)
+        val viewHolder = ParentViewHolder(view)
+
+        return viewHolder
+    }
+
+    override fun onBindViewHolder(holder: ParentViewHolder, position: Int) {
+        holder?.examGroupName?.text = this.data.get(position).examinationGroupName
+
+        val layoutManager = LinearLayoutManager(context)
+        holder?.examDetail?.layoutManager = layoutManager
+        holder?.examDetail?.adapter = ExamDetailAdapter(this.data.get(position).examinationConfigList)
+    }
+
+    override fun getItemCount(): Int {
+        return this.data.size
+    }
+
+    fun updateData(data: ArrayList<ExaminationConfigByGroupNameDto>) {
+        this.data = data
+        notifyDataSetChanged()
+    }
+
+    class ParentViewHolder : RecyclerView.ViewHolder {
+        var examGroupName : TextView
+        var examDetail : RecyclerView
+
+        constructor(itemView: View): super(itemView) {
+            examGroupName = itemView.findViewById(R.id.tv_exam_group_name)
+            examDetail = itemView.findViewById(R.id.rv_exam_detail)
+        }
+    }
+
+
+    //子项
+    class ExamDetailAdapter : RecyclerView.Adapter<ExamDetailAdapter.ChildViewHolder> {
+        private var examData: List<ExaminationConfigDto>
+
+        constructor(data: List<ExaminationConfigDto>) {
+            examData = data
+        }
+
+        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ChildViewHolder {
+            val view = LayoutInflater.from(parent?.context).inflate(R.layout.item_exam_detail, parent, false)
+            val viewHolder = ChildViewHolder(view)
+
+            return viewHolder
+        }
+
+        override fun onBindViewHolder(holder: ChildViewHolder, position: Int) {
+            holder?.examName?.text = examData.get(position).examinationName
+            holder?.examValue?.text = examData.get(position).examinationValue
+            val desc = BaseApplication.appContext.getString(R.string.exam_desc, examData.get(position).examinationDescription)
+            val time = BaseApplication.appContext.getString(R.string.exam_time, TimeTransition.stampToDateTime(examData.get(position).examinationTime * 1000))
+            holder?.examDesc?.text = desc
+            holder?.examTime?.text = time
+        }
+
+        override fun getItemCount(): Int {
+            return examData.size
+        }
+
+        class ChildViewHolder : RecyclerView.ViewHolder {
+            var examName : TextView
+            var examValue : TextView
+            var examDesc : TextView
+            var examTime : TextView
+
+            constructor(item : View) : super(item) {
+                examName = item.findViewById(R.id.tv_item_exam_name)
+                examValue = item.findViewById(R.id.tv_item_exam_value)
+                examDesc = item.findViewById(R.id.tv_item_exam_desc)
+                examTime = item.findViewById(R.id.tv_item_exam_time)
+            }
+        }
+    }
+}

+ 121 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedAdapter.kt

@@ -0,0 +1,121 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.graphics.Color
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterHospitalFramePartBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+import com.wdkl.ncs.android.middleware.model.vo.FrameBed
+
+
+class FrameBedAdapter(val data: ArrayList<FrameBed>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterHospitalFramePartBinding>, FrameBed>() {
+    var TAG = FrameBedAdapter::class.java.getSimpleName()
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        Log.i("FrameBedVosAdapter", "" + data.size)
+
+        return GridLayoutHelper(3).then { self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0, 10, 0, 0)
+        }
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterHospitalFramePartBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_hospital_frame_part)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterHospitalFramePartBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            if (itemData.named != null) {
+                binding.patientNameTv.text = itemData.named
+            } else {
+                binding.patientImagev.setImageResource(R.drawable.kong_chuang)
+                binding.patientNameTv.setText(R.string.empty_bed)
+            }
+
+            if (itemData.age != null) {
+                binding.patientAgeTv.text = itemData.age.toString() + itemData.ageUnit
+            } else {
+                binding.patientAgeTv.text = "--"
+            }
+
+            if (itemData.configName != null) {
+                binding.tvNurseConfigName.text = itemData.configName
+                if (!TextUtils.isEmpty(itemData.colorRgb)) {
+                    binding.tvNurseConfigColor.visibility = View.VISIBLE
+                    binding.tvNurseConfigColor.setBackgroundColor(Color.parseColor("#" + itemData.colorRgb))
+                    binding.tvNurseConfigColor.text = itemData.optionName
+                } else {
+                    binding.tvNurseConfigColor.text = ""
+                    binding.tvNurseConfigColor.visibility = View.INVISIBLE
+                }
+            } else {
+                binding.tvNurseConfigName.text = ""
+                binding.tvNurseConfigColor.text = ""
+                binding.tvNurseConfigColor.visibility = View.INVISIBLE
+            }
+
+            if (itemData.sex != null) {
+                binding.sexImagev.visibility = View.VISIBLE
+                if (itemData.sex == 1) {
+                    binding.sexImagev.setImageResource(R.drawable.man)
+                    binding.patientImagev.setImageResource(R.drawable.bing_ren_xiang_qing_man)
+                } else {
+                    binding.sexImagev.setImageResource(R.drawable.nv)
+                    binding.patientImagev.setImageResource(R.drawable.bing_ren_xiang_qing)
+                }
+            } else {
+                binding.sexImagev.visibility = View.GONE
+            }
+            binding.roomNumberTv.text = itemData.fullName
+            //Log.e("FrameBedVosAdapter ", "FrameBedVosAdapter...." + itemData.customerName)
+        }
+    }
+}

+ 60 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosAdapter.kt

@@ -0,0 +1,60 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.util.Log
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterFrameBedVosBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.middleware.model.vo.FrameBedVO
+
+/**
+ * 首页病房适配器
+ */
+class FrameBedVosAdapter(val data:ArrayList<FrameBedVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterFrameBedVosBinding>,FrameBedVO>(){
+    var TAG = FrameBedVosAdapter::class.java.getSimpleName()
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        Log.i("FrameBedVosAdapter",""+data.size)
+        return LinearLayoutHelper(0,data.size)
+    }
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterFrameBedVosBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_bed_vos)
+    }
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterFrameBedVosBinding>, position: Int) {
+        holder?.bind {
+            binding ->
+            val itemData = getItem(position)
+            Log.e("FrameBedVosAdapter ","FrameBedVosAdapter...."+itemData.customerName)
+        }
+    }
+}

+ 148 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FrameBedVosConfinementAdapter.kt

@@ -0,0 +1,148 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.graphics.Color
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterHospitalFramePartBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+import com.wdkl.ncs.android.middleware.model.vo.FrameBedVO
+
+
+class FrameBedVosConfinementAdapter(val data: ArrayList<FrameBedVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterHospitalFramePartBinding>, FrameBedVO>() {
+    var TAG = FrameBedVosConfinementAdapter::class.java.getSimpleName()
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        Log.i("FrameBedVosAdapter", "" + data.size)
+
+        return GridLayoutHelper(3).then { self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0, 10, 0, 0)
+        }
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterHospitalFramePartBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_hospital_frame_part)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterHospitalFramePartBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            if (itemData.customerName != null) {
+                binding.patientNameTv.text = itemData.customerName
+            } else {
+                binding.patientImagev.setImageResource(R.drawable.kong_chuang)
+                binding.patientNameTv.setText(R.string.empty_bed)
+            }
+
+            if (itemData.customerAge != null) {
+                binding.patientAgeTv.text = itemData.customerAge.toString() + itemData.customerAgeUnit
+            } else {
+                binding.patientAgeTv.text = "--"
+            }
+
+            binding.roomNumberTv.text = itemData.frameBed.fullName
+            binding.roomNumberTv.setTextColor(Color.parseColor("#2F9DF1"))
+
+            var critical = false
+            binding.rlBedInfo.setBackgroundResource(R.drawable.item_selector)
+            if (itemData.nurseConfigDtos != null && itemData.nurseConfigDtos.size > 0) {
+                for (nurseConfig in itemData.nurseConfigDtos) {
+                    if (nurseConfig.isBool_critical != null && nurseConfig.isBool_critical) {
+                        binding.roomNumberTv.setTextColor(Color.WHITE)
+                        //病危标识
+                        binding.rlBedInfo.setBackgroundResource(R.drawable.item_selector_critical)
+                        binding.tvNurseConfigName.text = nurseConfig.nurseConfigName
+                        if (!TextUtils.isEmpty(nurseConfig.nurseColorRbg)) {
+                            binding.tvNurseConfigColor.visibility = View.VISIBLE
+                            binding.tvNurseConfigColor.setBackgroundColor(Color.parseColor("#" + nurseConfig.nurseColorRbg))
+                            binding.tvNurseConfigColor.text = nurseConfig.nurseOptionName
+                        } else {
+                            binding.tvNurseConfigColor.text = ""
+                            binding.tvNurseConfigColor.visibility = View.INVISIBLE
+                        }
+                        critical = true
+                        break
+                    }
+                }
+
+                if (!critical) {
+                    val nurseItem = itemData.nurseConfigDtos.get(0)
+                    binding.tvNurseConfigName.text = nurseItem.nurseConfigName
+                    if (!TextUtils.isEmpty(nurseItem.nurseColorRbg)) {
+                        binding.tvNurseConfigColor.visibility = View.VISIBLE
+                        binding.tvNurseConfigColor.setBackgroundColor(Color.parseColor("#" + nurseItem.nurseColorRbg))
+                        binding.tvNurseConfigColor.text = nurseItem.nurseOptionName
+                    } else {
+                        binding.tvNurseConfigColor.text = ""
+                        binding.tvNurseConfigColor.visibility = View.INVISIBLE
+                    }
+                }
+            } else {
+                binding.tvNurseConfigName.text = ""
+                binding.tvNurseConfigColor.text = ""
+                binding.tvNurseConfigColor.visibility = View.INVISIBLE
+            }
+
+            if (itemData.customerSex != null) {
+                binding.sexImagev.visibility = View.VISIBLE
+                if (itemData.customerSex == 1) {
+                    binding.sexImagev.setImageResource(R.drawable.man)
+                    binding.patientImagev.setImageResource(R.drawable.bing_ren_xiang_qing_man)
+                } else {
+                    binding.sexImagev.setImageResource(R.drawable.nv)
+                    binding.patientImagev.setImageResource(R.drawable.bing_ren_xiang_qing)
+                }
+            } else {
+                binding.sexImagev.visibility = View.GONE
+            }
+
+            //Log.e("FrameBedVosAdapter ", "FrameBedVosAdapter...." + itemData.customerName)
+        }
+    }
+}

+ 108 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/FramePartItemAdapter.kt

@@ -0,0 +1,108 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Context
+import android.util.Log
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterFramePartItemBinding
+import com.wdkl.ncs.android.component.nursehome.fragment.FramePartFragment
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.middleware.model.vo.FrameRoomVO
+
+/**
+ * 首页病床适配器
+ */
+class FramePartItemAdapter(var context: Context, var mListener: FramePartFragment.OnItemListener?,
+                           val data:ArrayList<FrameRoomVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterFramePartItemBinding>,FrameRoomVO>(){
+var TAG = FramePartItemAdapter::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager2: VirtualLayoutManager
+    private lateinit var delegateAdapter2: DelegateAdapter
+    var frameBedVosAdapter:FrameBedVosAdapter? = null
+
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        Log.i("abc",data.toString());
+        return LinearLayoutHelper(0,data.size)
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterFramePartItemBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_frame_part_item)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterFramePartItemBinding>, position: Int) {
+        holder?.bind {
+            binding ->
+            val itemData = getItem(position)
+            binding.wardTv.text = itemData.frameRoom.name
+
+            val frameBedVos =  itemData.frameBedList
+            Log.e("frameBedVOs","frameBedVOs "+frameBedVos.size)
+            if(frameBedVos.size>0) {
+                //病床
+                /**初始化LayoutMannager*/
+                virtualLayoutManager2 = VirtualLayoutManager(context)
+                virtualLayoutManager2.setOrientation(VirtualLayoutManager.HORIZONTAL)
+                frameBedVosAdapter = FrameBedVosAdapter(ArrayList())
+                /**初始化适配器*/
+                delegateAdapter2 = DelegateAdapter(virtualLayoutManager2)
+                delegateAdapter2.addAdapter(frameBedVosAdapter)
+
+
+                /**配置到RecycleView*/
+                binding.sickbedRev.layoutManager = virtualLayoutManager2
+                binding.sickbedRev.adapter = delegateAdapter2
+
+                frameBedVosAdapter!!.data.clear()
+                Log.e("frameBedVOs", "frameBedVOs " + frameBedVos.size)
+                frameBedVosAdapter!!.data.addAll(frameBedVos)
+                frameBedVosAdapter!!.notifyDataSetChanged()
+                frameBedVosAdapter!!.setOnItemClickListener { data, position ->
+
+                    Log.e("frameBedVosAdapter", "frameBedVosAdapter..... ")
+                    mListener?.theBedInformation(data)
+                }
+            }
+
+        }
+    }
+
+
+
+
+}

+ 44 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/InpatientWardAdapter.kt

@@ -0,0 +1,44 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterCallRecordsItemBinding
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterInpatientWardBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.middleware.model.vo.CallingHistoryVO
+
+class InpatientWardAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterInpatientWardBinding>, String>(){
+
+
+    override fun dataProvider(): Any {
+        return data
+    }
+
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    override fun getItemCount(): Int {
+        return data.size
+    }
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,data.size)
+    }
+
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterInpatientWardBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_inpatient_ward)
+    }
+
+
+
+
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterInpatientWardBinding>, position: Int) {
+        holder?.bind {
+          binding ->
+            val itemData = getItem(position)
+            binding.checkBox.text = itemData
+        }
+    }
+}

+ 65 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/LedItemAdapter.kt

@@ -0,0 +1,65 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.TextView
+import androidx.recyclerview.widget.RecyclerView
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.led.LedItem
+import com.wdkl.ncs.android.component.nursehome.led.LedManagerUtils
+
+class LedItemAdapter: RecyclerView.Adapter<LedItemAdapter.ViewHolder> {
+    private var data: ArrayList<LedItem>
+    private var clickListener: OnClickListener?=null
+    private var clickPos = -1
+
+    constructor(data: ArrayList<LedItem>) {
+        this.data = data
+    }
+
+    override fun onCreateViewHolder(p0: ViewGroup, p1: Int): ViewHolder {
+        val view = LayoutInflater.from(p0?.context).inflate(R.layout.adapter_led_item, p0, false)
+        return ViewHolder(view)
+    }
+
+    override fun onBindViewHolder(p0: ViewHolder, p1: Int) {
+        if (p1 == clickPos) {
+            p0?.ledName?.setBackgroundResource(R.color.main_color)
+        } else {
+            p0?.ledName?.setBackgroundResource(R.color.white)
+        }
+        p0?.ledName?.setText(data.get(p1).ip)
+        p0?.ledName?.setOnClickListener {
+            if (clickListener != null) {
+                clickListener?.onClick(data.get(p1))
+                clickPos = p0.adapterPosition
+                notifyDataSetChanged()
+            }
+        }
+    }
+
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    fun update() {
+        data = LedManagerUtils.getInstance().ledList
+        notifyDataSetChanged()
+    }
+
+    class ViewHolder : RecyclerView.ViewHolder {
+        var ledName : TextView = itemView.findViewById(R.id.tv_led_name)
+
+        constructor(itemView: View): super(itemView)
+    }
+
+    fun setOnItemClickListener(listener: OnClickListener){
+        clickListener = listener
+    }
+
+    interface OnClickListener{
+        fun onClick(item: LedItem)
+    }
+}

+ 56 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/NumAdapter.java

@@ -0,0 +1,56 @@
+package com.wdkl.ncs.android.component.nursehome.adapter;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+
+public class NumAdapter extends BaseAdapter {
+    private String[] num;
+    private Context context;
+
+    public NumAdapter(String[] numbers, Context context) {
+        this.num = numbers;
+        this.context = context;
+    }
+
+
+    @Override
+    public int getCount() {
+        return num.length;
+    }
+
+    @Override
+    public Object getItem(int position) {
+        return num[position];
+    }
+
+    @Override
+    public long getItemId(int position) {
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        ViewHolder viewHolder;
+        if (convertView == null) {
+            convertView = LayoutInflater.from(context).inflate(R.layout.digital_item, null);
+            viewHolder = new ViewHolder();
+            viewHolder.numTv = convertView.findViewById(R.id.tv_number);
+            convertView.setTag(viewHolder);
+        } else {
+            viewHolder = (ViewHolder) convertView.getTag();
+        }
+        viewHolder.numTv.setText(num[position]);
+
+        return convertView;
+    }
+
+    static class ViewHolder {
+        TextView numTv;
+    }
+}

+ 70 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/NurseMoveAdapter.kt

@@ -0,0 +1,70 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterMobileDeviceBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+import com.wdkl.ncs.android.middleware.model.vo.WatchUsingVO
+
+class NurseMoveAdapter(val data:ArrayList<WatchUsingVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterMobileDeviceBinding>, WatchUsingVO>(){
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return GridLayoutHelper(3).then {
+            self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0,6,0,6)
+        }
+
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterMobileDeviceBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_mobile_device)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterMobileDeviceBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.mobileNameTv.text = itemData.clerkName
+        }
+    }
+}

+ 74 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/OtherHostAdapter.kt

@@ -0,0 +1,74 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterOtherHostBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+import com.wdkl.ncs.android.middleware.model.dos.DeviceDO
+
+/**
+ * 其它主机适配器
+ */
+class OtherHostAdapter (val data:ArrayList<DeviceDO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterOtherHostBinding>, DeviceDO>(){
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return GridLayoutHelper(2).then {
+            self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0,0,0,0)
+        }
+
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterOtherHostBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_other_host)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterOtherHostBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.tvOtherHost.text = "ID: " + itemData.id + "\n" + itemData.name
+        }
+    }
+
+}

+ 71 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/ResponsibilityBedAdapter.kt

@@ -0,0 +1,71 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterResponsibilityBedBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+
+/**
+ * 医生负责的床位适配器
+ */
+class ResponsibilityBedAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterResponsibilityBedBinding>, String>(){
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return GridLayoutHelper(2).then { self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0, 10, 0, 0)
+        }
+    }
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterResponsibilityBedBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_responsibility_bed)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterResponsibilityBedBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.responsibilityBedTv.text = itemData
+        }
+
+    }
+
+
+}

+ 58 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/SickbedAdapter.kt

@@ -0,0 +1,58 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.content.Context
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.LinearLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterSickbedBinding
+import com.wdkl.ncs.android.component.nursehome.fragment.FramePartFragment
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.middleware.model.vo.FrameRoomVO
+
+class SickbedAdapter(var context: Context, var mListener: FramePartFragment.OnItemListener?,
+                     val data:ArrayList<FrameRoomVO>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterSickbedBinding>, FrameRoomVO>() {
+
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterSickbedBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_sickbed)
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return LinearLayoutHelper(0,data.size)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterSickbedBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+        }
+    }
+
+}

+ 69 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/adapter/VisitManagementAdapter.kt

@@ -0,0 +1,69 @@
+package com.wdkl.ncs.android.component.nursehome.adapter
+
+import android.view.ViewGroup
+import com.alibaba.android.vlayout.LayoutHelper
+import com.alibaba.android.vlayout.layout.GridLayoutHelper
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.AdapterDoctorHostBinding
+import com.wdkl.ncs.android.lib.adapter.BaseDelegateAdapter
+import com.wdkl.ncs.android.lib.utils.BaseRecyclerViewHolder
+import com.wdkl.ncs.android.lib.utils.then
+
+class VisitManagementAdapter(val data:ArrayList<String>) : BaseDelegateAdapter<BaseRecyclerViewHolder<AdapterDoctorHostBinding>, String>(){
+    /**
+     * 数据提供者
+     */
+    override fun dataProvider(): Any {
+        return data
+    }
+    /**
+     * Item坐标
+     */
+    override fun itemFilter(position: Int): Boolean {
+        return true
+    }
+    /**
+     * 获取Item总数
+     */
+    override fun getItemCount(): Int {
+        return data.size
+    }
+
+    /**
+     * 创建LayoutHelper
+     */
+    override fun onCreateLayoutHelper(): LayoutHelper {
+        return GridLayoutHelper(2).then {
+            self ->
+            /**取消自动填充*/
+            self.setAutoExpand(false)
+
+            /**设置左右间距*/
+            self.hGap = 10
+
+            /**设置上下间距*/
+            self.vGap = 10
+
+            /**设置Margin*/
+            self.setMargin(0,10,0,0)
+        }
+
+    }
+
+    /**
+     * 创建ViewHolder
+     */
+    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BaseRecyclerViewHolder<AdapterDoctorHostBinding> {
+        return BaseRecyclerViewHolder.build(parent, R.layout.adapter_doctor_host)
+    }
+
+    /**
+     * 绑定数据
+     */
+    override fun onBindViewHolder(holder: BaseRecyclerViewHolder<AdapterDoctorHostBinding>, position: Int) {
+        holder?.bind { binding ->
+            val itemData = getItem(position)
+            binding.doctorNameTv.text = itemData
+        }
+    }
+}

+ 104 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/agreement/FloorActionAgreement.kt

@@ -0,0 +1,104 @@
+//package com.wdkl.ncs.android.component.home.agreement
+//
+//import android.view.MenuItem
+//import android.view.View
+//import com.wdkl.ncs.android.middleware.model.BannerModel
+//import com.wdkl.ncs.android.middleware.model.FloorItem
+//import com.wdkl.ncs.android.middleware.model.FloorMenuModel
+//
+///**
+// * Created by LDD on 2018/10/16.
+// */
+//interface FloorActionAgreement {
+//
+//    fun pointMall()
+//
+//    fun secKill()
+//
+//    fun groupMall()
+//
+//    fun couponHall()
+//
+//    fun toShop(id :Int)
+//
+//    fun toWeb(url :String)
+//
+//    fun searchGoodsForKeyWord(keyword :String)
+//
+//    fun searchGoodsForCatrgory(catId :Int,text :String)
+//
+//    fun goods(goodsId :Int)
+//
+//    fun floorHandle(view :View , item :Any){
+//
+//        view.setOnClickListener {
+//            event(item)
+//        }
+//
+//    }
+//
+//    fun event(item :Any){
+//        if (item is BannerModel){
+//            if(item.action == "URL"){
+//                if(item.value.contains("point")){
+//                    pointMall()
+//                }else if(item.value.contains("group")){
+//                    groupMall()
+//                }else if(item.value.contains("sec")){
+//                    secKill()
+//                }else{
+//                    toWeb(item.value)
+//                }
+//            }else if(item.action == "KEYWORD"){
+//                searchGoodsForKeyWord(item.value)
+//            }else if(item.action == "GOODS"){
+//                goods(item.value.toInt())
+//            }else if(item.action == "CATEGORY"){
+//                searchGoodsForCatrgory(item.value.toInt(),"搜索结果")
+//            }else if(item.action == "SHOP"){
+//                toShop(item.value.toInt())
+//            }
+//        }
+//        if (item is FloorItem){
+//            if(item.opt!!.type == "URL"){
+//                if(item.opt!!.value.contains("point")){
+//                    pointMall()
+//                }else if(item.opt!!.value.contains("group")){
+//                    groupMall()
+//                }else if(item.opt!!.value.contains("sec")){
+//                    secKill()
+//                }else{
+//                    toWeb(item.opt!!.value)
+//                }
+//            }else if(item.opt!!.type == "KEYWORD"){
+//                searchGoodsForKeyWord(item.opt!!.value)
+//            }else if(item.opt!!.type == "GOODS"){
+//                goods(item.opt!!.value.toInt())
+//            }else if(item.opt!!.type == "CATEGORY"){
+//                searchGoodsForCatrgory(item.opt!!.value.toInt(),"搜索结果")
+//            }else if(item.opt!!.type == "SHOP"){
+//                toShop(item.opt!!.value.toInt())
+//            }
+//        }
+//        if (item is FloorMenuModel){
+//            if (item.action.contains("points-mall")){
+//                pointMall()
+//            }else if (item.action.contains("group-buy")){
+//                groupMall()
+//            }else if (item.action.contains("seckill")){
+//                secKill()
+//            }else if (item.action.contains("goods")){
+//                goods(item.action.removePrefix("/goods/").toInt())
+//            }else if(item.action.contains("coupons")){
+//                couponHall()
+//            }else{
+//                toWeb(item.action)
+//            }
+//        }
+//    }
+//
+//
+//
+//
+//
+//}

+ 35 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/di/NurseHomeComponent.kt

@@ -0,0 +1,35 @@
+package com.wdkl.ncs.android.component.nursehome.di
+
+import com.wdkl.ncs.android.component.nursehome.activity.*
+import com.wdkl.ncs.android.component.nursehome.fragment.*
+import com.wdkl.ncs.android.middleware.di.ApplicationComponent
+import dagger.Component
+
+/**
+ * 依赖注入入口
+ */
+@Component(dependencies = arrayOf(ApplicationComponent::class))
+interface NurseHomeComponent{
+    fun inject(activity: RegisterActivity)
+    fun inject(activity: NurseHomeActivity)
+    fun inject(activity: FramePartFragment)
+    fun inject(activity: BroadcastFragment)
+    fun inject(activity: VisitManagementFragment)
+    fun inject(activity: DoctorHostFragment)
+    fun inject(activity: BedsInTheWardFragment)
+    fun inject(activity: SickbedFragment)
+    fun inject(activity: NurseMoveFragment)
+    fun inject(activity: OtherHostFragment)
+
+    fun inject(activity: TrustManagementFragment)
+    fun inject(activity: SystemSettingsFragment)
+
+    fun inject(activity: CallRecordsFragment)
+    fun inject(activity: InpatientWardFragment)
+    fun inject(activity: AppUpdateActivity)
+    fun inject(activity: TestActivity)
+    fun inject(activity: TestFragment)
+    //new
+    fun inject(activity: CallingHostActivationActivity)
+
+}

+ 42 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/RebootDialogHelper.java

@@ -0,0 +1,42 @@
+package com.wdkl.ncs.android.component.nursehome.dialog;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.Button;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.util.AppUpdateHelper;
+
+
+public class RebootDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_restart_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        Button btn_cancel = contentView.findViewById(R.id.server_cancel_button);
+        Button server_determine_button = contentView.findViewById(R.id.server_determine_button);
+        btn_cancel.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+            }
+        });
+        server_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+                AppUpdateHelper.reboot(activity);
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+    }
+}

+ 76 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/ServicesDialogHelper.java

@@ -0,0 +1,76 @@
+package com.wdkl.ncs.android.component.nursehome.dialog;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.model.vo.FrameBedVO;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.showMessage;
+
+public class ServicesDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity, ClickListener clickListener) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_server_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        Button server_determine_button = contentView.findViewById(R.id.server_determine_button);
+        Button server_cancel_button = contentView.findViewById(R.id.server_cancel_button);
+        EditText server_ed = contentView.findViewById(R.id.server_ed);
+        server_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                if(server_ed.getText().toString().equals("")){
+                    showMessage("服务器地址不能为空");
+                    return;
+                }
+
+                CommonUtils.setUrl(BaseApplication.appContext, server_ed.getText().toString());
+                if (clickListener != null) {
+                    String IP = server_ed.getText().toString();
+                    clickListener.onClick(IP);
+                }
+                alertDialog.dismiss();
+            }
+        });
+        server_cancel_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                server_ed.setText("");
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+//        //设置dialog宽高及位置
+//        try {
+//            Window window = alertDialog.getWindow();
+//            WindowManager.LayoutParams lp = window.getAttributes();
+//            lp.width = 680;
+//            lp.height = 440;
+//            lp.gravity = Gravity.CENTER;
+//            window.setAttributes(lp);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+    }
+
+    public interface ClickListener{
+        void onClick(String bedVO);
+    }
+}

+ 70 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/dialog/SystemDialogHelper.java

@@ -0,0 +1,70 @@
+package com.wdkl.ncs.android.component.nursehome.dialog;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.EditText;
+
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.push;
+import static com.wdkl.ncs.android.lib.utils.ExtendMethodsKt.showMessage;
+
+public class SystemDialogHelper {
+
+    private static AlertDialog alertDialog;
+
+    public static void showDialog(Activity activity) {
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.main_password_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        Button password_cancel_button = contentView.findViewById(R.id.password_cancel_button);
+        Button password_determine_button = contentView.findViewById(R.id.password_determine_button);
+        EditText password_ed = contentView.findViewById(R.id.password_ed);
+        password_cancel_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                alertDialog.dismiss();
+            }
+        });
+        password_determine_button.setOnClickListener(v -> {
+            if (alertDialog != null && alertDialog.isShowing()) {
+                String passwprd =password_ed.getText().toString();
+                if (passwprd.equals("888")){
+//                    Intent intent = new Intent();
+//                    intent.setClass(activity, SystemActivity.class);
+//                    activity.startActivity(intent);
+                } else {
+                    showMessage(R.string.invalid_password);
+                }
+                alertDialog.dismiss();
+            }
+        });
+        alertDialog = builder.create();
+        alertDialog.setCanceledOnTouchOutside(true);
+        alertDialog.setCancelable(true);
+        alertDialog.show();
+
+//        //设置dialog宽高及位置
+//        try {
+//            Window window = alertDialog.getWindow();
+//            WindowManager.LayoutParams lp = window.getAttributes();
+//            lp.width = 680;
+//            lp.height = 440;
+//            lp.gravity = Gravity.CENTER;
+//            window.setAttributes(lp);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+    }
+}

+ 98 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BaseCallFragment.kt

@@ -0,0 +1,98 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import org.greenrobot.eventbus.EventBus
+
+abstract class BaseCallFragment: Fragment(), View.OnTouchListener {
+
+    private var layout: View? = null
+
+    protected lateinit var baseActivity: BaseToolActivity
+
+    //通话状态:0-去电, 1-来电
+    protected var callState : Int = 0
+    protected var onlyAudio: Boolean = true
+
+    protected var targetId: String? = null
+    //是否探视
+    protected var visiting: Boolean = false
+    //呼叫名称
+    protected var callName: String? = null
+    protected var tid: String? = ""
+
+    //protected var gEngineKit: SkyEngineKit? = null
+
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        retainInstance = true
+        callState = requireArguments().getInt("call_state")
+        onlyAudio = requireArguments().getBoolean("audio_only")
+        targetId = requireArguments().getString("targetId")
+        visiting = requireArguments().getBoolean("visiting")
+        callName = requireArguments().getString("call_name")
+        tid = requireArguments().getString("tcp_tid")
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        if (layout == null) {
+            layout = inflater.inflate(getLayId(), null)
+        }
+
+        /**初始化宿主Activity*/
+        baseActivity = getActivity() as BaseToolActivity
+
+        return layout
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        view.setOnTouchListener(this)
+
+        init()
+        bindEvent()
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+        destroy()
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    protected abstract fun getLayId(): Int
+
+    protected abstract fun init()
+
+    protected abstract fun bindEvent()
+
+    protected abstract fun destroy()
+
+
+    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+        return true
+    }
+
+    //返回主界面
+    protected fun backToMain() {
+        EventBus.getDefault().post(MessageEvent("BackCall", Constant.EVENT_REMOVE_CALL_FRAGMENT))
+    }
+
+}

+ 128 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BedsInTheWardFragment.kt

@@ -0,0 +1,128 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.FramePartItemAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentBedsInTheWardBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.BedsInTheWardContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.BedsInTheWardPresenter
+import com.wdkl.ncs.android.middleware.model.vo.FrameBedVO
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import kotlinx.android.synthetic.main.fragment_beds_in_the_ward.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 病区病床Fragment
+ */
+class BedsInTheWardFragment : BaseFragment<BedsInTheWardPresenter, FragmentBedsInTheWardBinding>(), BedsInTheWardContract.View{
+    var TAG = BedsInTheWardFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    private var adapter: FramePartItemAdapter? = null
+//    var mListener: OnItemListener? = null
+
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_beds_in_the_ward
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+//        /**初始化LayoutMannager*/
+//        virtualLayoutManager = VirtualLayoutManager(this.activity)
+//
+//        /**初始化适配器*/
+//        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+//
+//        adapter = FramePartItemAdapter(this.activity,mListener,ArrayList())
+//        delegateAdapter.addAdapter(adapter)
+//        mViewDataBinding.refresh.setRefreshFooter(ClassicsFooter(activity))
+//
+//        /**配置到RecycleView*/
+//        listView.layoutManager = virtualLayoutManager
+//        listView.adapter = delegateAdapter
+
+
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+    /**
+     *显示数据
+     */
+    override fun showData() {
+    }
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    /**
+     * 更新病区数据
+     */
+    fun updateData(data: String) {
+        showMessage(data)
+
+}
+
+//    fun setOnItemListener(mListener: OnItemListener) {
+//        this.mListener = mListener
+//    }
+//
+//    interface OnItemListener {
+//        fun theBedInformation(data: FrameBedVO)
+//    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//        var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+    }
+
+}

+ 336 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/BroadcastFragment.kt

@@ -0,0 +1,336 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.content.Context
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.CompoundButton
+import android.widget.LinearLayout
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.BroadcastAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentBroadcastBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.BroadcastContract
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.NurseHomeActivityContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.BroadcastPresenter
+import com.wdkl.ncs.android.middleware.model.dos.BroadcastDO
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+
+import kotlinx.android.synthetic.main.add_the_timing.*
+import kotlinx.android.synthetic.main.add_the_timing.view.*
+import kotlinx.android.synthetic.main.fragment_broadcast.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 广播管理界面
+ */
+class BroadcastFragment : BaseFragment<BroadcastPresenter, FragmentBroadcastBinding>(), BroadcastContract.View, View.OnClickListener {
+    var TAG = BroadcastFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    //录音适配器
+    var broadcastAdapter: BroadcastAdapter? = null
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_broadcast
+    }
+
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    /**
+     *初始化操作
+     */
+    override fun init() {
+
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        broadcastAdapter = BroadcastAdapter(this, ArrayList())
+        delegateAdapter.addAdapter(broadcastAdapter)
+
+        /**配置到RecycleView*/
+        broadcast_recyv.layoutManager = virtualLayoutManager
+        broadcast_recyv.adapter = delegateAdapter
+
+
+        //临时模拟测试数据
+        var other_hostList = ArrayList<String>()
+        other_hostList.add("录音1")
+        other_hostList.add("录音2")
+        other_hostList.add("录音3")
+        other_hostList.add("录音4")
+        other_hostList.add("录音5")
+        other_hostList.add("录音6")
+        other_hostList.add("录音7")
+        other_hostList.add("录音8")
+        other_hostList.add("录音9")
+        other_hostList.add("录音10")
+        other_hostList.add("录音11")
+
+        broadcastAdapter!!.data.clear()
+        broadcastAdapter!!.data.addAll(other_hostList)
+        Log.i(TAG, "录音数量 " + other_hostList.size)
+        broadcastAdapter!!.notifyDataSetChanged()
+
+
+    }
+
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+    }
+
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+
+    /**
+     *显示数据
+     */
+    override fun showData(data: ArrayList<BroadcastDO>) {
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    /**
+     *
+     */
+    fun addTheTiming(position: Int) {
+        broadcast_relayout.visibility = View.GONE
+        set_the_timer_relalyout.visibility = View.VISIBLE
+        add_the_timing_tv.setOnClickListener(this)
+    }
+    var timingViewTag =0
+    var  timingViewList = ArrayList<View>()
+    var  timingViews = ArrayList<View>()
+
+    override fun onClick(p0: View) {
+        when (p0.id) {
+            R.id.add_the_timing_tv -> {
+
+                var failedPop = LayoutInflater.from(this.activity).inflate(R.layout.add_the_timing, null)
+
+                failedPop.setTag(timingViewTag++)
+                timingViewList.add(failedPop)
+//                Log.e(TAG,"timingViewList "+timingViewList.size)
+                timing_linlyout.addView(failedPop)
+
+
+                failedPop.monday_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                        showMessage("选中周一")
+                    }else{
+
+                        showMessage("取消选中周一")
+                    }
+                }
+
+                failedPop.tuesday_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.wednesday_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.friday_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.saturday_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.week_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                //
+                failedPop.area_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+
+                failedPop.the_second_area_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.three_areas_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.the_four_areas_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.five_area_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+                failedPop.six_area_chebox.setOnCheckedChangeListener { compoundButton, b ->
+                    if(b){
+
+                    }else{
+
+                    }
+
+                }
+
+
+                /**
+                 * 立即播放按钮
+                 */
+                failedPop.play_immediately_bt.setOnClickListener{
+
+                    showMessage("ceshiaaaa"+failedPop.getTag())
+                }
+                /**
+                 * 删除按钮
+                 */
+                failedPop.delete_bt.setOnClickListener{
+                    showMessage("sssss"+failedPop.getTag())
+
+                    Log.e(TAG,"failedPop.getTag() "+failedPop.getTag())
+                    Log.e(TAG,"timingViewList "+timingViewList.size)
+
+//                    timing_linlyout.removeView(vS.get(failedPop.getTag() as Int))
+//                    vS.remove(vS.get(failedPop.getTag() as Int))
+
+                    for (timingView in timingViewList){
+                        if(timingView.getTag() == failedPop.getTag()){
+                            Log.e(TAG,"timingView.getTag() "+timingView.getTag())
+                            timingViews.add(timingView)
+                        }
+                    }
+                    timing_linlyout.removeView(timingViews.get(0))
+                    timingViewList.removeAll(timingViews)
+                    timingViews.clear()
+
+                }
+                /**
+                 * 试听按钮
+                 */
+                failedPop.audition_bt.setOnClickListener{
+
+                }
+                /**
+                 * 暂停按钮
+                 */
+                failedPop.suspend_bt.setOnClickListener{
+
+
+                }
+                /**
+                 * 保存按钮
+                 */
+                failedPop.save_bt.setOnClickListener{
+
+                }
+
+
+
+
+
+            }
+            R.id.play_immediately_bt -> {
+
+            }
+
+
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//        var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+    }
+}

+ 436 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/CallRecordsFragment.kt

@@ -0,0 +1,436 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.util.Log
+import android.view.View
+import androidx.recyclerview.widget.ItemTouchHelper
+import androidx.recyclerview.widget.RecyclerView
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.google.gson.Gson
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.adapter.CallRecordsItemAdapter
+import com.wdkl.ncs.android.component.nursehome.adapter.CallingItemAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentCallRecordsBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.nursehome.util.*
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.entity.CallingItem
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.CallRecordsFragmentContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.CallRecordsFragmentPresenter
+import com.wdkl.ncs.android.middleware.model.vo.EventVO
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+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.TcpModel
+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
+import kotlinx.android.synthetic.main.fragment_call_records.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * 呼叫记录Fragment
+ */
+class CallRecordsFragment: BaseFragment<CallRecordsFragmentPresenter, FragmentCallRecordsBinding>(), CallRecordsFragmentContract.View,
+    View.OnClickListener, CallingItemAdapter.UpdateCallback {
+
+    var TAG = CallRecordsFragment::class.java.getSimpleName()
+
+    private val adapter = CallRecordsItemAdapter(ArrayList())
+    private var callingAdapter: CallingItemAdapter? = null
+
+    /**
+     * @Name  virtualLayoutManager
+     * @Type  VirtualLayoutManager
+     * @Note  VLayoutManager
+     */
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+
+    private lateinit var delegateAdapter: DelegateAdapter
+
+    private var eventName = ""
+
+    private var language = "zh"
+
+    //加载历史记录条数
+    private val pageSize: Int = 15
+    //数据的初始页数
+    private var page: Int = 1
+    //查询历史记录类型
+    private var listType: Int = 1
+
+    override fun getLayId(): Int {
+        return R.layout.fragment_call_records
+    }
+
+
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+        delegateAdapter.addAdapter(adapter)
+        mViewDataBinding.refresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        listView.layoutManager = virtualLayoutManager
+        listView.adapter = delegateAdapter
+
+        callingAdapter = CallingItemAdapter(activity, ArrayList())
+        rv_calling_list.layoutManager = VirtualLayoutManager(activity)
+        rv_calling_list.adapter = callingAdapter
+
+        val touchCallback: ItemTouchHelper.Callback =
+            object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
+                override fun onMove(
+                        recyclerView: RecyclerView,
+                        viewHolder: RecyclerView.ViewHolder,
+                        target: RecyclerView.ViewHolder
+                ): Boolean {
+                    return false
+                }
+
+                override fun onSwiped(
+                    viewHolder: RecyclerView.ViewHolder,
+                    direction: Int
+                ) {
+                    val pos = viewHolder.adapterPosition
+                    if (callingAdapter != null && pos < callingAdapter!!.itemCount) {
+                        callingAdapter!!.removeCallByPos(pos, true)
+                    }
+                }
+            }
+        val itemTouchHelper = ItemTouchHelper(touchCallback)
+        itemTouchHelper.attachToRecyclerView(rv_calling_list)
+
+        callingAdapter?.setUpdateCallback(this)
+
+        presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+
+        language = LocaleMangerUtils.getApplicationLocale().language
+    }
+
+    /**
+     * 按钮监听
+     */
+    override fun onClick(p0: View) {
+        when(p0.id){
+            //当前呼叫记录
+            R.id.calling_linlyout -> {
+                showCallList()
+            }
+
+            //未接历史记录
+            R.id.no_answer_calls_linlyout -> {
+                //如果还要来电未接则不切换,且提示用户
+                if (NurseHomeActivity.callingList.size > 0) {
+                    showMessage(R.string.event_todo_tips)
+                    return
+                }
+
+                ll_call_list.visibility = View.GONE
+                ll_call_record_list.visibility = View.VISIBLE
+                calling_imagev.visibility = View.GONE
+                call_records_imagev.visibility = View.GONE
+                no_answer_calls_imagev.visibility = View.VISIBLE
+                if (listType != 1) {
+                    page = 1
+                    listType = 1
+                    presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+                }
+            }
+
+            //所有历史记录
+            R.id.call_records_linlyout -> {
+                //如果还要来电未接则不切换,且提示用户
+                if (NurseHomeActivity.callingList.size > 0) {
+                    showMessage(R.string.event_todo_tips)
+                    return
+                }
+
+                ll_call_list.visibility = View.GONE
+                ll_call_record_list.visibility = View.VISIBLE
+                calling_imagev.visibility = View.GONE
+                no_answer_calls_imagev.visibility = View.GONE
+                call_records_imagev.visibility = View.VISIBLE
+                if (listType != 0) {
+                    page = 1
+                    listType = 0
+                    presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+                }
+            }
+
+            //其他历史记录
+            R.id.other_linlyout -> {
+
+            }
+        }
+    }
+
+    fun showCallList() {
+        calling_imagev.visibility = View.VISIBLE
+        call_records_imagev.visibility = View.GONE
+        no_answer_calls_imagev.visibility = View.GONE
+        ll_call_list.visibility = View.VISIBLE
+        ll_call_record_list.visibility = View.GONE
+    }
+
+    override fun onUpdate() {
+        val num = NurseHomeActivity.callingList.size
+        if (num > 9) {
+            calling_num_tv.visibility = View.VISIBLE
+            calling_num_tv.text = "9+"
+            showCallList()
+        } else if (num > 0) {
+            calling_num_tv.visibility = View.VISIBLE
+            calling_num_tv.text = "" + num
+            showCallList()
+        } else {
+            calling_num_tv.visibility = View.GONE
+        }
+    }
+
+    override fun bindEvent() {
+        //点击监听
+        mViewDataBinding.noAnswerCallsLinlyout.setOnClickListener(this)
+        mViewDataBinding.callRecordsLinlyout.setOnClickListener(this)
+        mViewDataBinding.otherLinlyout.setOnClickListener(this)
+        mViewDataBinding.callingLinlyout.setOnClickListener(this)
+
+        configRefresh()
+    }
+
+    override fun destory() {
+    }
+
+    override fun onError(message: String, type: Int) {
+        refresh.finishRefresh()
+        //errorLog("error",message)
+        showMessage(message)
+    }
+
+    override fun start() {
+    }
+
+    override fun renderFloor(data: ArrayList<InteractionVO>) {
+        Log.e(TAG,"CallRecordsFragment走了。。。"+data.size)
+
+        refresh.finishRefresh()
+        if (page == 1) {
+            refresh.resetNoMoreData()
+            adapter.data.clear()
+            if (data.size > 0) {
+                for (item in data) {
+                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType
+                        || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
+                        || TcpType.REINFORCE.name == item.actionType) {
+                        //if (item.actionDirectionType == 1 || item.actionDirectionType == 2 || item.actionDirectionType == 3) {
+                            adapter.data.add(item)
+                        //}
+                    }
+                }
+                Log.i("abc1"," " + adapter.data.size);
+            }
+            adapter.notifyDataSetChanged()
+            refresh.finishLoadMore()
+        } else {
+            if (data.size > 0) {
+                for (item in data) {
+                    if (TcpType.VIDEO.name == item.actionType || TcpType.VOICE.name == item.actionType
+                        || TcpType.ENTRACEGUARD.name == item.actionType || TcpType.SOS.name == item.actionType
+                        || TcpType.REINFORCE.name == item.actionType) {
+                        //if (item.actionDirectionType == 1 || item.actionDirectionType == 2 || item.actionDirectionType == 3) {
+                            adapter.data.add(item)
+                        //}
+                    }
+                }
+                adapter.notifyDataSetChanged()
+                refresh.finishLoadMore()
+            } else {
+                refresh.finishLoadMoreWithNoMoreData()
+            }
+        }
+
+    }
+
+    override fun showEventdata(data: EventVO) {
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    private fun configRefresh(){
+        //下拉刷新
+        mViewDataBinding.refresh.setOnRefreshListener {
+            page = 1
+            presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+        }
+        //上拉加载更多
+        mViewDataBinding.refresh.setOnLoadMoreListener {
+            page += 1
+            presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+        }
+    }
+
+    private fun updateRecord() {
+        page = 1
+        presenter.loadFloor(page, pageSize, Constant.part_id, listType, eventName)
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_REFRESH_CALL_LIST -> {
+                Log.d("tcp", "refresh call list")
+                updateRecord()
+            }
+
+            Constant.EVENT_TCP_MSG -> {
+                val tcpModel = messageEvent.getMessage() as TcpModel
+                Log.d("tcp", "tcpType: " + tcpModel.type + ", tcpAction: " + tcpModel.action)
+                if (tcpModel.type == TcpType.VOICE) {
+                    val interactionVO = Gson().fromJson(tcpModel.data.toString(), InteractionVO::class.java)
+                    if (tcpModel.action == TcpAction.VoiceAction.CALL) {
+                        //返回呼叫成功tcp
+                        val responseTcpModel = VoiceUtil.voiceSuccessHost(tcpModel.tid, tcpModel.toId, tcpModel.fromId)
+                        TcpClient.getInstance().sendMsg(responseTcpModel.toJson())
+
+                        //1.更新点阵屏信息显示
+                        LedHelper.updateLedInfo(interactionVO, true, false)
+
+                        //2.语音播报
+                        if (Constant.CALL_STATE != Constant.CALL_CALLING
+                            && Constant.CALL_STATE != Constant.CALL_OUTGOING
+                            && Constant.CALL_STATE != Constant.CALL_VISIT_CALLING
+                        ) {
+                            if (SettingConfig.getTtsMode(activity) == SettingConfig.TTS_ON) {
+                                var frameName: String? = ""
+                                if (DeviceTypeEnum.DOCTOR_HOST.value() == interactionVO.fromDeviceType
+                                    || DeviceTypeEnum.NURSE_HOST.value() == interactionVO.fromDeviceType
+                                    || DeviceTypeEnum.OTHER_HOST.value() == interactionVO.fromDeviceType) {
+                                    //医生机,护士主机,其他主机,总控主机等
+                                    frameName = interactionVO.fromDeviceName
+                                } else if (DeviceTypeEnum.NURSE_WATCH.value() == interactionVO.fromDeviceType) {
+                                    //移动设备
+                                    frameName = interactionVO.fromMemberName
+                                } else {
+                                    //其他
+                                    if (Locale.CHINESE.getLanguage().equals(language)) {
+                                        frameName = Util.appendSpace(interactionVO.fromFrameFullName.replace("-", ","))
+                                    } else {
+                                        frameName = interactionVO.fromFrameFullName.replace("-", "")
+                                    }
+                                }
+                                val text = BaseApplication.appContext.getString(R.string.voice_call_speech, frameName)
+                                SpeechUtil.getInstance().addSpeech(text, false)
+                            } else if (SettingConfig.getTtsMode(activity) == SettingConfig.RING_ON) {
+                                RingPlayHelper.playRingTone(activity, R.raw.ring_tone, true)
+                            } else if (SettingConfig.getTtsMode(activity) == SettingConfig.MUSIC_ON) {
+                                RingPlayHelper.playRingTone(activity, R.raw.incoming_call, true)
+                            }
+                        }
+
+                        //3.刷新呼叫列表
+                        updateRecord()
+                        val item = CallingItem(tcpModel.tid, System.currentTimeMillis(), interactionVO, tcpModel.action)
+                        if (callingAdapter != null) {
+                            callingAdapter?.addCall(item)
+                        }
+                    } else if (tcpModel.action == TcpAction.VoiceAction.CANCEL || tcpModel.action == TcpAction.VoiceAction.VOICE_OFF) {
+                        //对方取消呼叫或者呼叫已被其他主机处理(接听或拒绝)
+                        LedHelper.updateLedInfo(interactionVO, false, false)
+                        if (SettingConfig.getTtsMode(activity) == SettingConfig.TTS_ON) {
+                            var frameName: String? = ""
+                            if (DeviceTypeEnum.DOCTOR_HOST.value() == interactionVO.fromDeviceType
+                                || DeviceTypeEnum.NURSE_HOST.value() == interactionVO.fromDeviceType
+                                || DeviceTypeEnum.OTHER_HOST.value() == interactionVO.fromDeviceType) {
+                                //医生机,护士主机,其他主机,总控主机等
+                                frameName = interactionVO.fromDeviceName
+                            } else if (DeviceTypeEnum.NURSE_WATCH.value() == interactionVO.fromDeviceType) {
+                                //移动设备
+                                frameName = interactionVO.fromMemberName
+                            } else {
+                                //其他
+                                if (Locale.CHINESE.getLanguage().equals(language)) {
+                                    frameName = Util.appendSpace(interactionVO.fromFrameFullName.replace("-", ","))
+                                } else {
+                                    frameName = interactionVO.fromFrameFullName.replace("-", "")
+                                }
+                            }
+                            val text = BaseApplication.appContext.getString(R.string.voice_call_speech, frameName)
+                            SpeechUtil.getInstance().removeSpeak(text)
+                        } else {
+                            //如果呼叫列表只有一个呼叫了,说明删除这个之后就清空了,此时关闭铃声或音乐
+                            if (NurseHomeActivity.callingList.size == 1) {
+                                RingPlayHelper.stopRingTone()
+                            }
+                        }
+
+                        if (callingAdapter != null) {
+                            callingAdapter?.removeCall(interactionVO, false)
+                        }
+                    }
+                }
+            }
+
+            Constant.EVENT_HOOK_OFF -> {
+                //接听呼叫列表中第一个电话
+                if (NurseHomeActivity.callingList.size > 0) {
+                    val callingItem = NurseHomeActivity.callingList.get(0)
+                    val itemData = callingItem.interactionVO
+                    LedHelper.updateLedInfo(itemData, false, false)
+                    EventBus.getDefault().post(MessageEvent(callingItem, Constant.EVENT_ACCEPT_CALL))
+                    if (callingAdapter != null) {
+                        callingAdapter?.removeCall(itemData, true)
+                    }
+                }
+            }
+
+            Constant.EVENT_TRANSFER_CALL -> {
+                val transferData = messageEvent.getMessage() as InteractionVO
+                if (callingAdapter != null) {
+                    callingAdapter?.removeCall(transferData, false)
+                }
+            }
+
+            Constant.EVENT_REMOVE_CALL -> {
+                val callingItem = messageEvent.getMessage() as CallingItem
+                //VoiceUtil.rejectAudioCall(Constants.ids, interactionVO.fromDeviceId, interactionVO.id)
+                val callTcp = VoiceUtil.voiceReject(callingItem.tid, Constant.DEVICE_ID, callingItem.interactionVO.fromDeviceId, callingItem.interactionVO.id)
+                TcpClient.getInstance().sendMsg(callTcp.toJson())
+                LedHelper.updateLedInfo(callingItem.interactionVO, false, false)
+                if (callingAdapter != null) {
+                    callingAdapter?.removeCall(callingItem.interactionVO, false)
+                }
+            }
+        }
+    }
+}

+ 177 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/DoctorHostFragment.kt

@@ -0,0 +1,177 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+
+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.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.DoctorHostAdapter
+
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentDoctorHostBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.DoctorHostContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.DoctorHostPresenter
+import com.wdkl.ncs.android.middleware.model.dos.DeviceDO
+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.tcp.enums.DeviceTypeEnum
+import kotlinx.android.synthetic.main.fragment_doctor_host.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 医生主机Fragment
+ */
+class DoctorHostFragment: BaseFragment<DoctorHostPresenter, FragmentDoctorHostBinding>(), DoctorHostContract.View, View.OnClickListener {
+    var TAG = DoctorHostFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    //医生适配器
+    private var doctorHostAdapter: DoctorHostAdapter? = null
+
+    private var selectDevice: DeviceDO? = null
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_doctor_host
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        doctorHostAdapter = DoctorHostAdapter(ArrayList())
+        delegateAdapter.addAdapter(doctorHostAdapter)
+        mViewDataBinding.doctorHostRefresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        doctor_host_recyv.layoutManager = virtualLayoutManager
+        doctor_host_recyv.adapter = delegateAdapter
+
+        if (Constant.part_id != -1) {
+            presenter.loadDoctorHost(DeviceTypeEnum.DOCTOR_HOST.value(), Constant.part_id)
+        }
+
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        doctorHostAdapter?.setOnItemClickListener { data, position ->
+            selectDevice = data
+
+            tv_doctor_name_title.text = data.name
+        }
+        call_doctor_host.setOnClickListener(this)
+
+        doctor_host_refresh.setOnRefreshListener {
+            if (Constant.part_id != -1) {
+                presenter.loadDoctorHost(DeviceTypeEnum.DOCTOR_HOST.value(), Constant.part_id)
+            }
+        }
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+    /**
+     *显示数据
+     */
+    override fun showDoctorDevices(devices: ArrayList<DeviceDO>) {
+        //显示所有医生主机,排除自己
+        doctorHostAdapter!!.data.clear()
+        //排除本机
+        if (devices.size > 0) {
+            for (hostDevice in devices) {
+                if (hostDevice.id != Constant.DEVICE_ID) {
+                    doctorHostAdapter!!.data.add(hostDevice)
+                }
+            }
+        }
+        doctorHostAdapter!!.notifyDataSetChanged()
+
+        doctor_host_refresh.finishRefresh()
+    }
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+        doctor_host_refresh.finishRefresh()
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    override fun onClick(p0: View?) {
+        if (selectDevice != null) {
+            //呼出时停止语音播报及铃声
+            SpeechUtil.getInstance().stopSpeak(true)
+            RingPlayHelper.stopRingTone()
+
+            if (Constant.TCP_CONNECTED) {
+                Constant.CALL_TYPE = 0
+                val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, selectDevice!!.id)
+                val transaction = object : TcpCallback(callTcp.tid) {
+                    override fun onSuccess(jsonObject: JSONObject) {
+                        super.onSuccess(jsonObject)
+                    }
+
+                    override fun onFailed(jsonObject: JSONObject) {
+                        // 这里写发送失败的方法
+                        val callbackString = jsonObject.getString(CALLBACK)
+                        showMessage("call fail: $callbackString")
+                        super.onFailed(jsonObject)
+                    }
+                }
+                TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+            } else {
+                showMessage(R.string.net_error)
+            }
+        } else {
+            showMessage(R.string.no_device)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        //
+    }
+}

+ 246 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/EntraceGuardVideoFragment.kt

@@ -0,0 +1,246 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.MotionEvent
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import com.alibaba.fastjson.JSON
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+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.EntraceGuardUtil
+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.middleware.utils.StringUtil
+import com.wdkl.ncs.janus.client.CallSessionCallback
+import com.wdkl.ncs.janus.client.JanusClient
+import com.wdkl.ncs.janus.client.VideoRoomCallback
+import com.wdkl.ncs.janus.entity.Room
+import com.wdkl.ncs.janus.rtc.WebRTCEngine
+import com.wdkl.ncs.janus.util.JanusConstant
+import com.wdkl.ncs.janus.util.EnumType
+
+import kotlinx.android.synthetic.main.fragment_entraceguard_video.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.webrtc.SurfaceViewRenderer
+
+
+import java.math.BigInteger
+
+/**
+ * 门禁机请求开门视频界面fragment
+ */
+class EntraceGuardVideoFragment : Fragment(), CallSessionCallback, View.OnTouchListener {
+
+    private var layout: View? = null
+    protected lateinit var baseActivity: BaseToolActivity
+
+    private var isMute: Boolean = true
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    var interactionVO: InteractionVO? = null
+    var tcpModel: TcpModel? = null
+
+    var janusClient: JanusClient? = null
+
+    var videoRoomCallback: VideoRoomCallback? = null
+    var room: Room? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        EventBus.getDefault().register(this)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        if (layout == null) {
+            layout = inflater.inflate(R.layout.fragment_entraceguard_video, null)
+        }
+
+        /**初始化宿主Activity*/
+        baseActivity = getActivity() as BaseToolActivity
+
+        return layout
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        EntraceGuardUtil.acceptStranger(tcpModel)
+
+        //初始化 engine
+        WebRTCEngine.getInstance().init(true, context)
+
+        //初始化 janusClient
+        janusClient = JanusClient(JanusConstant.JANUS_URL, Constant.SIP_ID!!.toBigInteger())
+        //初始化房间
+        janusClient!!.callState = EnumType.CallState.Incoming
+        room = Room(interactionVO!!.fromSipId.toBigInteger())
+        videoRoomCallback = VideoRoomCallback(janusClient, room, Constant.SIP_ID!!.toBigInteger())
+        videoRoomCallback!!.callSessionCallback = this
+        janusClient!!.setJanusCallback(videoRoomCallback)
+
+        init()
+        bindEvent()
+
+        view.setOnTouchListener(this)
+    }
+
+    override fun onTouch(v: View?, event: MotionEvent?): Boolean {
+        return true
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        RingPlayHelper.stopRingTone()
+        EventBus.getDefault().unregister(this)
+    }
+
+
+    private fun init() {
+        janusClient!!.connect(-1, false)
+        title.setText(interactionVO!!.fromDeviceName.toString() + "," + StringUtil.getResString(R.string.call_entrance_guard))
+        WebRTCEngine.getInstance().toggleSpeaker(false)
+        RingPlayHelper.playRingTone(activity, R.raw.door_bell, true)
+        speaker_on.isSelected = isMute
+    }
+
+    private fun bindEvent() {
+        unlock_door.setOnClickListener {
+            var tcpModel = EntraceGuardUtil.unlockDoor(interactionVO)
+            TcpClient.getInstance().sendMsg(tcpModel.toJson())
+            callEnd()
+            DeviceChannel.calling = false
+            backToMain()
+        }
+
+        sky_voice_call_hangup.setOnClickListener {
+            //发送挂断消息
+            //TcpClient.getInstance().sendMsg(EntraceGuardUtil.hangup(interactionVO).toJson())
+            EntraceGuardUtil.hangupHost(tcpModel)
+            //结束sip通话
+            callEnd()
+            DeviceChannel.calling = false
+            backToMain()
+        }
+
+        speaker_on.setOnClickListener {
+            isMute = !isMute
+            WebRTCEngine.getInstance().muteAudio(isMute)
+            WebRTCEngine.getInstance().toggleSpeaker(!isMute)
+            speaker_on.isSelected = isMute
+            TcpClient.getInstance().sendMsg(EntraceGuardUtil.toggleAudio(interactionVO, isMute).toJson())
+            RingPlayHelper.stopRingTone()
+        }
+
+    }
+
+    private fun backToMain() {
+        DeviceChannel.calling = false
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        RingPlayHelper.stopRingTone()
+        EventBus.getDefault().post(MessageEvent("BackCall", Constant.EVENT_REMOVE_CALL_FRAGMENT))
+    }
+
+    private fun callEnd() {
+        if (janusClient!!.webSocketChannel != null) {
+            janusClient!!.callState = EnumType.CallState.Idle
+            janusClient!!.leaveRoom()
+            janusClient!!.setJanusCallback(null)
+            janusClient!!.disConnect()
+
+        }
+    }
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_TCP_MSG -> {
+                Log.i("EventMessage", "EventMessage:" + messageEvent.toString())
+                var tcpModel = messageEvent.getMessage() as TcpModel
+
+                if (tcpModel.getType() == TcpType.ENTRACEGUARD) { //超时未响应,结束通话退出界面
+                    if (tcpModel.action == TcpAction.EntraceGuardAction.TIMEOUT) {
+                        val curInteractionVO = JSON.parseObject(tcpModel.data.toString(), InteractionVO::class.java)
+                        if (interactionVO != null && interactionVO!!.id == curInteractionVO.id) {
+                            callEnd()
+                            backToMain()
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+    override fun didRoomCreated() {
+
+    }
+
+    override fun didChangeState(var1: EnumType.CallState?) {
+
+    }
+
+    override fun didDisconnected(userId: String?) {
+
+    }
+
+    override fun didCreateLocalVideoTrack() {
+
+    }
+
+    override fun didError(error: String?) {
+
+    }
+
+    override fun didHangUp(handlerId: BigInteger?) {
+
+    }
+
+    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
+        handler.post {
+            WebRTCEngine.getInstance().toggleSpeaker(true)
+            WebRTCEngine.getInstance().muteAudio(true)
+
+            val surfaceView = WebRTCEngine.getInstance().setupRemoteVideo(userId, false)
+            Log.e("video_call", "didReceiveRemoteVideoTrack: surfaceView=$surfaceView")
+            if (surfaceView != null) {
+                remoteSurfaceView = surfaceView as SurfaceViewRenderer
+                remote_video_surface.removeAllViews()
+
+                /*if (remoteSurfaceView != null && remoteSurfaceView!!.parent != null) {
+                    (remoteSurfaceView!!.parent as ViewGroup).removeView(remoteSurfaceView)
+                }*/
+                remote_video_surface.addView(remoteSurfaceView)
+            }
+        }
+    }
+
+    override fun didCallEndWithReason(var1: EnumType.CallEndReason?) {
+
+    }
+
+    override fun didChangeMode(isAudioOnly: Boolean) {
+
+    }
+
+    override fun didUserLeave(userId: BigInteger?) {
+
+    }
+}

+ 273 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/EntraceGuardVideoFragment.kt.bak

@@ -0,0 +1,273 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.Bundle
+import android.os.Handler
+import android.os.Looper
+import android.support.v4.app.Fragment
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.core.voip.VoipEvent
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.middleware.common.Constants
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+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.EntraceGuardUtil
+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.middleware.utils.MessageEvent
+import com.wdkl.skywebrtc.CallSession
+import com.wdkl.skywebrtc.EnumType
+import com.wdkl.skywebrtc.SkyEngineKit
+import com.wdkl.skywebrtc.except.NotInitializedException
+import kotlinx.android.synthetic.main.fragment_entraceguard_video.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.webrtc.SurfaceViewRenderer
+
+/**
+ * 门禁机请求开门视频界面fragment
+ */
+class EntraceGuardVideoFragment : Fragment(), CallSession.CallSessionCallback {
+
+    private var layout: View? = null
+    protected lateinit var baseActivity: BaseToolActivity
+
+    protected var gEngineKit: SkyEngineKit? = null
+
+    private var isMute: Boolean = true
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    var interactionVO: InteractionVO? = null
+    var tcpModel: TcpModel? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        EventBus.getDefault().register(this)
+    }
+
+    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+        if (layout == null) {
+            layout = inflater.inflate(R.layout.fragment_entraceguard_video, null)
+        }
+
+        /**初始化宿主Activity*/
+        baseActivity = getActivity() as BaseToolActivity
+
+        return layout
+    }
+
+    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+        EntraceGuardUtil.acceptStranger(tcpModel)
+
+        try {
+            SkyEngineKit.init(VoipEvent())
+            gEngineKit = SkyEngineKit.Instance()
+        } catch (e: NotInitializedException) {
+            SkyEngineKit.init(VoipEvent())
+            try {
+                gEngineKit = SkyEngineKit.Instance()
+            } catch (ex: NotInitializedException) {
+                ex.printStackTrace()
+                baseActivity.finish()
+            }
+        }
+
+        init()
+        bindEvent()
+    }
+
+
+    override fun onDestroy() {
+        super.onDestroy()
+        RingPlayHelper.stopRingTone()
+        EventBus.getDefault().unregister(this)
+    }
+
+
+    private fun init() {
+        val session = gEngineKit?.getCurrentSession()
+        if (session != null) {
+            session.setSessionCallback(this)
+        }
+        title.setText(interactionVO!!.fromDeviceName + ",请求开门")
+        RingPlayHelper.playRingTone(activity, R.raw.door_bell, true)
+        speaker_on.isSelected = isMute
+
+    }
+
+    private fun bindEvent() {
+
+        unlock_door.setOnClickListener {
+            var tcpModel = EntraceGuardUtil.unlockDoor(interactionVO)
+            TcpClient.getInstance().sendMsg(tcpModel.toJson())
+            SkyEngineKit.Instance().endCall()
+            Constants.CALL_STATE = Constants.CALL_STANDBY
+            DeviceChannel.calling = false
+            backToMain()
+        }
+
+        sky_voice_call_hangup.setOnClickListener {
+
+            //发送挂断消息
+            TcpClient.getInstance().sendMsg(EntraceGuardUtil.hangup(interactionVO).toJson())
+            //结束sip通话
+            SkyEngineKit.Instance().endCall()
+            Constants.CALL_STATE = Constants.CALL_STANDBY
+            DeviceChannel.calling = false
+            backToMain()
+        }
+
+        speaker_on.setOnClickListener {
+            var session = gEngineKit?.currentSession
+            if (session != null) {
+                isMute = !isMute
+                session.toggleMuteAudio(isMute)
+                session.toggleSpeaker(!isMute)
+                speaker_on.isSelected = isMute
+                TcpClient.getInstance().sendMsg(EntraceGuardUtil.toggleAudio(interactionVO, isMute).toJson())
+            }
+            RingPlayHelper.stopRingTone()
+        }
+
+    }
+
+    private fun backToMain() {
+
+        RingPlayHelper.stopRingTone()
+        EventBus.getDefault().post(MessageEvent("BackCall", Constants.EVENT_REMOVE_CALL_FRAGMENT))
+    }
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constants.EVENT_JOIN_HOME_READY -> {
+                Log.i("wdkl", "准备加入房间")
+                val session = SkyEngineKit.Instance().getCurrentSession()
+                if (session != null) {
+                    session.toggleSpeaker(false)
+                    session.toggleMuteAudio(true)
+                    Log.d("WDKL", "session = " + session + "; session.getState() = " + session.state + ",roomId=" + session.roomId)
+                    session.setSessionCallback(this)
+                    session.joinHome(session.roomId)
+                }else{ //会话未成功建立
+                    EntraceGuardUtil.rejectStranger(interactionVO)
+                    backToMain()
+                }
+            }
+            Constants.EVENT_TCP_MSG -> {
+                var tcpModel = messageEvent.getMessage() as TcpModel
+                if (tcpModel.getType() == TcpType.ENTRACEGUARD) { //超时未响应,结束通话退出界面
+                    if(tcpModel.action == TcpAction.EntraceGuardAction.TIMEOUT){
+                        SkyEngineKit.Instance().endCall()
+                        backToMain()
+                    }
+
+                }
+            }
+        }
+    }
+
+
+    //视频来电接通
+    private fun joinVideoCall() {
+        val session = gEngineKit?.getCurrentSession()
+        if (session != null) {
+            Log.e("dds", "video call session state: " + session.state)
+
+//            if (session.state == EnumType.CallState.Incoming) {
+//                val surfaceView = gEngineKit!!.currentSession.setupLocalVideo(false)
+//                if (surfaceView != null) {
+//                    localSurfaceView = surfaceView as SurfaceViewRenderer
+//                    localSurfaceView!!.setZOrderMediaOverlay(false)
+//                    fullscreen_video_frame.addView(localSurfaceView)
+//                }
+//
+//                session.joinHome(session.roomId)
+//                session.toggleSpeaker(true)
+//            } else if (session.state == EnumType.CallState.Idle) {
+//                callEnd()
+//                return
+//            }
+
+//            Handler().postDelayed({
+//                if (session.state == EnumType.CallState.Connected){
+//                    //showCalling(onlyAudio)
+//                } else {
+//                    gEngineKit?.endCall()
+//                    callEnd()
+//                }
+//            }, 2000)
+        }
+    }
+
+    override fun didChangeState(var1: EnumType.CallState?) {
+
+    }
+
+    override fun didDisconnected(userId: String?) {
+
+    }
+
+    override fun didCreateLocalVideoTrack() {
+
+    }
+
+    override fun didError(error: String?) {
+
+    }
+
+    //处理远端视频画面
+    override fun didReceiveRemoteVideoTrack(userId: String?) {
+        Log.e("dds", "didReceiveRemoteVideoTrack  userId: " + userId)
+        handler.post {
+            val session = gEngineKit!!.currentSession
+            if (session != null) {
+//                //本地画面
+//                if (localSurfaceView != null) {
+//                    localSurfaceView!!.setZOrderMediaOverlay(true)
+//                    if (outGoing) {
+//                        if (localSurfaceView!!.parent != null) {
+//                            (localSurfaceView!!.parent as ViewGroup).removeView(localSurfaceView)
+//                        }
+//                        pip_video_frame!!.addView(localSurfaceView)
+//                    }
+//                }
+
+                //远端画面
+                val surfaceView = gEngineKit!!.currentSession.setupRemoteVideo(userId, false)
+                Log.e("dds", "didReceiveRemoteVideoTrack,surfaceView = $surfaceView")
+                if (surfaceView != null) {
+                    remoteSurfaceView = surfaceView as SurfaceViewRenderer
+                    remote_video_surface.removeAllViews()
+//                        if (remoteSurfaceView!!.parent != null) {
+//                            (remoteSurfaceView!!.parent as ViewGroup).removeView(remoteSurfaceView)
+//                        }
+                    remote_video_surface.addView(remoteSurfaceView)
+                }
+            }
+        }
+    }
+
+    override fun didCallEndWithReason(var1: EnumType.CallEndReason?) {
+
+    }
+
+    override fun didChangeMode(isAudioOnly: Boolean) {
+
+    }
+
+    override fun didUserLeave(userId: String?) {
+
+    }
+}

+ 495 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/FramePartFragment.kt

@@ -0,0 +1,495 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+
+import android.text.TextUtils
+import android.text.method.ScrollingMovementMethod
+import android.util.Log
+import android.view.View
+import androidx.recyclerview.widget.LinearLayoutManager
+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.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.adapter.*
+
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentFramePartBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil
+import com.wdkl.ncs.android.component.nursehome.util.TimeTransition
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.debugLog
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.FramePartContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.FramePartPresenter
+import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
+import com.wdkl.ncs.android.middleware.model.dos.RemarkDO
+import com.wdkl.ncs.android.middleware.model.dto.ExaminationConfigByGroupNameDto
+import com.wdkl.ncs.android.middleware.model.dto.FeeConfigByGroupNameDto
+import com.wdkl.ncs.android.middleware.model.vo.*
+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.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+
+import kotlinx.android.synthetic.main.fragment_frame_part.*
+import kotlinx.android.synthetic.main.right_basic_information.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 首页病房病床Fragment
+ */
+class FramePartFragment: BaseFragment<FramePartPresenter, FragmentFramePartBinding>(), FramePartContract.View {
+    var TAG = FramePartFragment::class.java.getSimpleName()
+
+    private var adapter: FrameBedVosConfinementAdapter? = null
+
+    private var feeAdapter: CostItemAdapter? = null
+
+    private var examAdapter: ExamAdapter? = null
+
+    private var clickTime: Long = 0
+
+    var frame = FrameBedVO()
+
+    /**
+     * @Name  virtualLayoutManager
+     * @Type  VirtualLayoutManager
+     * @Note  VLayoutManager
+     */
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+
+    /**
+     * @Name  delegateAdapter
+     * @Type  DelegateAdapter
+     * @Note  七巧板适配器
+     */
+    private lateinit var delegateAdapter: DelegateAdapter
+
+
+     var mListener:OnItemListener? = null
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:32
+     * @Note   提供layoutID
+     * @return layoutId
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_frame_part
+    }
+
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:33
+     * @Note   初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:33
+     * @Note   初始化操作
+     */
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        adapter = FrameBedVosConfinementAdapter(ArrayList())
+        delegateAdapter.addAdapter(adapter)
+        mViewDataBinding.refresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        listView.layoutManager = virtualLayoutManager
+        listView.adapter = delegateAdapter
+
+        //滚动显示
+        tv_nurse_config.movementMethod = ScrollingMovementMethod.getInstance()
+        tv_advice_info.movementMethod = ScrollingMovementMethod.getInstance()
+        tv_illness_info.movementMethod = ScrollingMovementMethod.getInstance()
+
+        //费用
+        feeAdapter = CostItemAdapter(activity, ArrayList())
+        val layoutManager = LinearLayoutManager(this.activity)
+        rv_fee_config.layoutManager = layoutManager
+        rv_fee_config.adapter = feeAdapter
+
+        //检验
+        examAdapter = ExamAdapter(activity, ArrayList())
+        val layoutManager2 = VirtualLayoutManager(this.activity)
+        rv_exam_config.layoutManager = layoutManager2
+        rv_exam_config.adapter = examAdapter
+
+        presenter.loadData(Constant.part_id)
+
+    }
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:33
+     * @Note   绑定事件
+     */
+    override fun bindEvent() {
+        adapter?.setOnItemClickListener { data, position ->
+            frame = data
+            basic_radio.isChecked = true
+
+            if (data.frameBed != null) {
+                if (data.customerName != null) {
+                    name_tv.text = data.customerName
+                    age_tv.text = "" + data.customerAge + data.customerAgeUnit
+                    roomNumber.text = data.frameBed.fullName
+                    if (data.customerSex != null) {
+                        if (data.customerSex == 1) {
+                            head_portrait_imagev.setImageResource(R.drawable.bing_ren_xiang_qing_man)
+                            gender_imagev.setImageResource(R.drawable.man)
+                            gender_imagev.visibility = View.VISIBLE
+                        } else {
+                            head_portrait_imagev.setImageResource(R.drawable.bing_ren_xiang_qing)
+                            gender_imagev.setImageResource(R.drawable.nv)
+                            gender_imagev.visibility = View.VISIBLE
+                        }
+                    } else {
+                        gender_imagev.visibility = View.GONE
+                        head_portrait_imagev.setImageResource(R.drawable.kong_chuang)
+                    }
+                    if (data.customerInDate != null) {
+                        time_tv.text = TimeTransition.stampToDate(data.customerInDate * 1000)
+                    }
+
+                } else {
+                    name_tv.setText(R.string.empty_bed)
+                    age_tv.setText(R.string.empty)
+                    roomNumber.text = data.frameBed.fullName
+                    gender_imagev.visibility = View.GONE
+                    time_tv.setText(R.string.empty)
+                    mobile_tv.setText(R.string.empty)
+                    head_portrait_imagev.setImageResource(R.drawable.kong_chuang)
+                }
+            }
+
+            //默认
+            tv_doctor_name.setText(R.string.empty)
+            tv_nurse_name.setText(R.string.empty)
+            tv_nurse_config.setText(R.string.empty)
+            tv_advice_info.setText(R.string.empty)
+            tv_illness_info.setText(R.string.empty)
+            feeAdapter?.updateData(ArrayList())
+            examAdapter?.updateData(ArrayList())
+
+            //加载对应床位人员数据
+            if (data.customerId != null) {
+                presenter.loadCustomerInfo(data.customerId)
+            }
+        }
+
+        call_the_voice_tv.setOnClickListener {
+            //语音呼叫
+            if (System.currentTimeMillis() - clickTime < 3000) {
+                showMessage(R.string.call_wait)
+            } else {
+                if (frame.customerName != null && frame.bedDeviceId != null) {
+                    //呼出时停止语音播报及铃声
+                    SpeechUtil.getInstance().stopSpeak(true)
+                    RingPlayHelper.stopRingTone()
+                    if (NurseHomeActivity.checkIncomingCall(frame.bedDeviceId)) {
+                        showMessage(R.string.call_in_list)
+                    } else {
+                        //通话之前先判断webrtc socket是否连接上,否则不能建立通话
+                        if (Constant.TCP_CONNECTED) {
+                            Constant.CALL_TYPE = 0
+                            val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, frame.bedDeviceId)
+                            val transaction = object : TcpCallback(callTcp.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    super.onSuccess(jsonObject)
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                    val callbackString = jsonObject.getString(CALLBACK)
+                                    showMessage("call fail: $callbackString")
+                                    super.onFailed(jsonObject)
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+                        } else {
+                            showMessage(R.string.net_error)
+                        }
+                    }
+                } else {
+                    showMessage(R.string.no_custom)
+                }
+            }
+            clickTime = System.currentTimeMillis()
+        }
+
+        if (!Constant.supportCamera) {
+            //call_the_video_tv.isEnabled = false
+            //call_the_video_tv.setTextColor(Color.parseColor("#e8e8e8"))
+            call_the_video_tv.visibility = View.GONE
+        }
+
+        call_the_video_tv.setOnClickListener {
+            //视频呼叫
+            if (System.currentTimeMillis() - clickTime < 3000) {
+                showMessage(R.string.call_wait)
+            } else {
+                if (frame.customerName != null && frame.bedDeviceId != null) {
+                    //呼出时停止语音播报及铃声
+                    SpeechUtil.getInstance().stopSpeak(true)
+                    RingPlayHelper.stopRingTone()
+                    if (NurseHomeActivity.checkIncomingCall(frame.bedDeviceId)) {
+                        showMessage(R.string.call_in_list)
+                    } else {
+                        //通话之前先判断webrtc socket是否连接上,否则不能建立通话
+                        if (Constant.TCP_CONNECTED) {
+                            Constant.CALL_TYPE = 1
+                            val callTcp = VoiceUtil.videoCall(Constant.DEVICE_ID, frame.bedDeviceId)
+                            val transaction = object : TcpCallback(callTcp.tid) {
+                                override fun onSuccess(jsonObject: JSONObject) {
+                                    super.onSuccess(jsonObject)
+                                }
+
+                                override fun onFailed(jsonObject: JSONObject) {
+                                    // 这里写发送失败的方法
+                                    val callbackString = jsonObject.getString(CALLBACK)
+                                    showMessage("call fail: $callbackString")
+                                    super.onFailed(jsonObject)
+                                }
+                            }
+                            TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+                        } else {
+                            showMessage(R.string.net_error)
+                        }
+                    }
+                } else {
+                    showMessage(R.string.no_custom)
+                }
+            }
+        }
+
+        group_custom_info.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.basic_radio) {
+                rl_basic_info.visibility = View.VISIBLE
+                ll_fee_config.visibility = View.GONE
+                ll_exam_config.visibility = View.GONE
+            } else if (checkedId == R.id.fee_radio) {
+                rl_basic_info.visibility = View.GONE
+                ll_fee_config.visibility = View.VISIBLE
+                ll_exam_config.visibility = View.GONE
+            } else if (checkedId == R.id.exam_radio) {
+                rl_basic_info.visibility = View.GONE
+                ll_fee_config.visibility = View.GONE
+                ll_exam_config.visibility = View.VISIBLE
+            }
+        }
+
+        configRefresh()
+    }
+
+    override fun showCustomerInfo(data: CustomerInfoVO) {
+        //基本信息
+        if (SettingConfiguration.getInstance().doctorValid == 1) {
+            doctor_duty_relalyout.visibility = View.VISIBLE
+            advice_layout.visibility = View.VISIBLE
+            illness_layout.visibility = View.VISIBLE
+        } else {
+            doctor_duty_relalyout.visibility = View.GONE
+            advice_layout.visibility = View.GONE
+            illness_layout.visibility = View.GONE
+        }
+        if (SettingConfiguration.getInstance().nurseValid == 1) {
+            nurse_duty_relalyout.visibility = View.VISIBLE
+        } else {
+            nurse_duty_relalyout.visibility = View.GONE
+        }
+        tv_doctor_title.text = SettingConfiguration.getInstance().doctorTitle
+        tv_nurse_title.text = SettingConfiguration.getInstance().nurseTitle
+
+        tv_doctor_name.text = data.doctorName
+        tv_nurse_name.text = data.nurseName
+        var nurseConfigs = ""
+        if (data.list != null) {
+            for (e in data.list) {
+                nurseConfigs = nurseConfigs + e.nurseOptionAndConfigName + "\n"
+            }
+        }
+        tv_nurse_config.text = nurseConfigs
+        tv_advice_info.text = data.advice
+        tv_illness_info.text = data.illnessDesc
+
+        //费用信息
+        if (data.feeConfigByGroupNameList != null) {
+            var feeList = ArrayList<FeeConfigByGroupNameDto>()
+            feeList.addAll(data.feeConfigByGroupNameList)
+            feeAdapter?.updateData(feeList)
+        }
+
+        //检验信息
+        if (data.examinationConfigByGroupNameList != null) {
+            var examList = ArrayList<ExaminationConfigByGroupNameDto>()
+            examList.addAll(data.examinationConfigByGroupNameList)
+            examAdapter?.updateData(examList)
+        }
+    }
+
+    override fun showPersonMemoAndRemarkData(data: ArrayList<RemarkDO>) {
+
+    }
+
+    override fun showFamilyMembersData(data: FamilyMembersVO) {
+
+    }
+
+    override fun showTaskData(data: TaskVO) {
+
+    }
+
+    override fun onNoNet() {
+
+    }
+
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:34
+     * @Note   页面销毁回调
+     */
+    override fun destory() {
+        //debugLog("HomeFragment","Destory")
+    }
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:35
+     * @Note   处理错误信息
+     * @param  message  错误信息
+     */
+    override fun onError(message: String, type: Int) {
+        refresh.finishRefresh()
+        //errorLog("error",message)
+        showMessage(message)
+    }
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:37
+     * @Note   耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/8/16 下午4:08
+     * @Note   渲染楼层
+     * @param  data  数据
+     */
+    override fun showData(data: FramePartVO) {
+        if (data.frameRoomVos != null){
+            val frameRoomVos = data.frameRoomVos as ArrayList<FrameRoomVO>
+            val frameBedVO = ArrayList<FrameBedVO>()
+            val emptyFrameBedVOs = ArrayList<FrameBedVO>()
+
+            for (frameRoomVo in frameRoomVos) {
+                val frameBedVOs = frameRoomVo.frameBedList
+                if (frameBedVOs != null && frameBedVOs.size > 0) {
+                    for (bedVO in frameBedVOs) {
+                        if (TextUtils.isEmpty(bedVO.customerName)) {
+                            emptyFrameBedVOs.add(bedVO)
+                        } else {
+                            frameBedVO.add(bedVO)
+                        }
+                    }
+                }
+            }
+            CommonUtils.setInBedVos(frameBedVO)
+
+            adapter!!.data.clear()
+            adapter!!.data.addAll(frameBedVO)
+            adapter!!.data.addAll(emptyFrameBedVOs)
+            Log.i(TAG, "empty bed: " + emptyFrameBedVOs.size + ", custom bed: " + frameBedVO.size);
+            adapter!!.notifyDataSetChanged()
+        }
+        refresh.finishRefresh()
+        refresh.finishLoadMore()
+    }
+
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:36
+     * @Note   操作完成
+     * @param  message 完成信息
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:37
+     * @Note   配置刷新监听处理
+     */
+    private fun configRefresh(){
+        refresh.setOnRefreshListener {
+            presenter.loadData(Constant.part_id)
+        }
+    }
+    /**
+     * @author LDD
+     * @From   HomeFragment
+     * @Date   2018/1/19 下午5:39
+     * @Note   处理网络状态
+     * @param  state 网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+    fun setOnItemListener(mListener: OnItemListener) {
+        this.mListener = mListener
+    }
+
+    interface OnItemListener {
+        fun theBedInformation(data: FrameBedVO)
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_TCP_MSG -> {
+                var tcpModel = messageEvent.getMessage() as TcpModel
+                if (tcpModel.action == TcpAction.DataAction.REFRESH) {
+                    //更新数据
+                    presenter.loadData(Constant.part_id)
+                }
+            }
+        }
+    }
+}

+ 143 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/InpatientWardFragment.kt

@@ -0,0 +1,143 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.util.Log
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.InpatientWardAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentInpatientWardBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.InpatientWardContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.InpatientWardPresenter
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+
+import kotlinx.android.synthetic.main.fragment_inpatient_ward.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 病区列表Fragment
+ */
+class InpatientWardFragment : BaseFragment<InpatientWardPresenter, FragmentInpatientWardBinding>(), InpatientWardContract.View {
+    var TAG = InpatientWardFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    private val inpatientWardAdapter = InpatientWardAdapter(ArrayList())
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_inpatient_ward
+    }
+
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    /**
+     *初始化操作
+     */
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+        delegateAdapter.addAdapter(inpatientWardAdapter)
+
+        /**配置到RecycleView*/
+        inpatient_ward_recview.layoutManager = virtualLayoutManager
+        inpatient_ward_recview.adapter = delegateAdapter
+
+
+        var data = ArrayList<String>()
+        data.add("测试1")
+        data.add("测试2")
+        data.add("测试3")
+        data.add("测试4")
+        data.add("测试5")
+        data.add("测试6")
+        data.add("测试7")
+        data.add("测试8")
+
+
+        //临时模拟数据
+        if (data.size > 0) {
+            inpatientWardAdapter.data.clear()
+            inpatientWardAdapter.data.addAll(data)
+            Log.i(TAG, " " + data.size)
+            inpatientWardAdapter.notifyDataSetChanged()
+        }
+
+
+    }
+
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        inpatientWardAdapter.setOnItemClickListener { data, position ->
+            BedsInTheWardFragment().updateData(data)
+
+        }
+    }
+
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+
+    }
+
+    /**
+     *显示数据
+     */
+    override fun showData() {
+
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+
+    }
+
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//        var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+    }
+}
+

+ 277 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/LedSettingsFragment.kt

@@ -0,0 +1,277 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.Bundle
+
+import android.text.TextUtils
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.SeekBar
+import androidx.fragment.app.Fragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.enation.javashop.utils.base.tool.BaseToolActivity
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.adapter.LedItemAdapter
+import com.wdkl.ncs.android.component.nursehome.led.LedItem
+import com.wdkl.ncs.android.component.nursehome.led.LedManagerUtils
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.nursehome.util.NetHelper
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+
+import kotlinx.android.synthetic.main.fragment_led_settings.*
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class LedSettingsFragment: Fragment() {
+
+    protected lateinit var baseActivity: BaseToolActivity
+
+    private var adapter: LedItemAdapter? = null
+
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+        retainInstance = true
+    }
+
+    override fun onCreateView(
+        inflater: LayoutInflater,
+        container: ViewGroup?,
+        savedInstanceState: Bundle?
+    ): View {
+
+        /**初始化宿主Activity*/
+        baseActivity = activity as BaseToolActivity
+
+        return inflater.inflate(R.layout.fragment_led_settings, null)
+    }
+
+    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+        super.onViewCreated(view, savedInstanceState)
+
+        adapter = LedItemAdapter(LedManagerUtils.getInstance().ledList)
+        val layoutManager = LinearLayoutManager(baseActivity)
+        recycler_led_list.layoutManager = layoutManager
+        recycler_led_list.adapter = adapter
+
+        if (LedManagerUtils.getInstance().ledList.size == 0) {
+            tv_led_empty_titile.visibility = View.VISIBLE
+        } else {
+            tv_led_empty_titile.visibility = View.GONE
+        }
+
+        adapter?.setOnItemClickListener(object : LedItemAdapter.OnClickListener{
+            override fun onClick(item: LedItem) {
+                val resolution = BaseApplication.appContext.getString(R.string.led_resolution, item.resolution)
+                tv_led_type.setText(resolution)
+                if (item.voiceOn) {
+                    tv_led_voice_on.setText(R.string.led_voice_on)
+                } else {
+                    tv_led_voice_on.setText(R.string.led_voice_off)
+                }
+                val font = BaseApplication.appContext.getString(R.string.led_font_size, item.fontSize)
+                tv_led_font_size.setText(font)
+
+                btn_ping.visibility = View.VISIBLE
+                btn_ping.setOnClickListener {
+                    //ping点阵屏设备
+                    if (!TextUtils.isEmpty(item.ip)) {
+                        val ipStr = item.ip
+                        //showMessage("ping $ipStr start...")
+                        Thread {
+                            val result = NetHelper.ping(item.ip, 2, null)
+                            activity?.runOnUiThread {
+                                if (result) {
+                                    showMessage("ping $ipStr success")
+                                } else {
+                                    showMessage("ping $ipStr failed")
+                                }
+                            }
+                            Log.e("ping", "ping result: $ipStr $result")
+                        }.start()
+                    }
+                }
+            }
+        })
+
+        init()
+        bindEvent()
+    }
+
+    private fun init() {
+        val ledProgramTime = SettingConfig.getLedProgramTime(baseActivity)
+        val ledVoiceVolume = SettingConfig.getLedVoiceVolume(baseActivity)
+        val ledVoiceTimes = SettingConfig.getLedVoiceTimes(baseActivity)
+        val ledInfoType = SettingConfig.getLedInfoType(baseActivity)
+        val info = SettingConfig.getLedCustomInfo(baseActivity)
+
+        val ledDuration = BaseApplication.appContext.getString(R.string.led_info_duration, ledProgramTime)
+        tv_led_program_time.setText(ledDuration)
+        skb_led_program_time.progress = ledProgramTime
+
+        val ledVolume = BaseApplication.appContext.getString(R.string.led_voice_volume, ledVoiceVolume)
+        tv_led_volume.setText(ledVolume)
+        skb_led_volume.progress = ledVoiceVolume
+
+        val ledTimes = BaseApplication.appContext.getString(R.string.led_voice_times, ledVoiceTimes)
+        tv_led_voice_times.setText(ledTimes)
+        skb_led_voice_times.progress = ledVoiceTimes
+
+        //led_refresh.setRefreshFooter(ClassicsFooter(activity))
+
+        if (ledInfoType == 1) {
+            rb_custom_info.isChecked = true
+            led_custom_content.visibility = View.VISIBLE
+            led_custom_content.setText(info)
+        } else {
+            rb_date_time.isChecked = true
+            led_custom_content.visibility = View.INVISIBLE
+        }
+    }
+
+    private fun bindEvent() {
+        btn_sync_time.setOnClickListener {
+            LedManagerUtils.getInstance().syncTime()
+        }
+
+        btn_reset_led.setOnClickListener {
+            LedManagerUtils.getInstance().removeAllProgram()
+        }
+
+        btn_check_font.setOnClickListener {
+            LedManagerUtils.getInstance().checkFontFile()
+        }
+
+        btn_power_on_off.setOnClickListener {
+            LedManagerUtils.getInstance().powerOnOff()
+        }
+
+        btn_update_font.setOnClickListener {
+            LedManagerUtils.getInstance().copyFont()
+        }
+
+        led_refresh.setOnRefreshListener {
+            (activity as NurseHomeActivity).loadLedDevice()
+        }
+
+        skb_led_program_time.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+                val duration = BaseApplication.appContext.getString(R.string.led_info_duration, progress)
+                tv_led_program_time.setText(duration)
+            }
+
+            override fun onStartTrackingTouch(seekBar: SeekBar?) {
+                //
+            }
+
+            override fun onStopTrackingTouch(seekBar: SeekBar?) {
+                if (seekBar!!.progress < 5) {
+                    val text = BaseApplication.appContext.getString(R.string.less_then, 5)
+                    showMessage(text)
+                    seekBar.progress = 5
+                }
+                SettingConfig.setLedProgramTime(baseActivity, seekBar.progress)
+            }
+        })
+
+        skb_led_volume.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+                val volume = BaseApplication.appContext.getString(R.string.led_voice_volume, progress)
+                tv_led_volume.setText(volume)
+            }
+
+            override fun onStartTrackingTouch(seekBar: SeekBar?) {
+                //
+            }
+
+            override fun onStopTrackingTouch(seekBar: SeekBar?) {
+                if (seekBar!!.progress <= 0) {
+                    val text = BaseApplication.appContext.getString(R.string.less_then, 1)
+                    showMessage(text)
+                    seekBar.progress = 1
+                }
+                SettingConfig.setLedVoiceVolume(baseActivity, seekBar.progress)
+            }
+        })
+
+        skb_led_voice_times.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
+            override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
+                val times = BaseApplication.appContext.getString(R.string.led_voice_times, progress)
+                tv_led_voice_times.setText(times)
+            }
+
+            override fun onStartTrackingTouch(seekBar: SeekBar?) {
+                //
+            }
+
+            override fun onStopTrackingTouch(seekBar: SeekBar?) {
+                if (seekBar!!.progress <= 0) {
+                    val text = BaseApplication.appContext.getString(R.string.less_then, 1)
+                    showMessage(text)
+                    seekBar.progress = 1
+                }
+                SettingConfig.setLedVoiceTimes(baseActivity, seekBar.progress)
+            }
+        })
+
+        val info = SettingConfig.getLedCustomInfo(baseActivity)
+        group_led_info_type.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.rb_date_time) {
+                led_custom_content.visibility = View.INVISIBLE
+            } else {
+                led_custom_content.setText(info)
+                led_custom_content.visibility = View.VISIBLE
+            }
+        }
+    }
+
+    override fun onStart() {
+        EventBus.getDefault().register(this)
+        super.onStart()
+    }
+
+    override fun onStop() {
+        EventBus.getDefault().unregister(this)
+        super.onStop()
+    }
+
+    override fun onDestroyView() {
+        super.onDestroyView()
+
+        if (group_led_info_type.checkedRadioButtonId == R.id.rb_date_time) {
+            SettingConfig.setLedInfoType(baseActivity, 0)
+            SettingConfig.setLedCustomInfo(baseActivity, "")
+        } else {
+            val info = led_custom_content.text.toString()
+            SettingConfig.setLedInfoType(baseActivity, 1)
+            SettingConfig.setLedCustomInfo(baseActivity, info)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_UPDATE_LED -> {
+                if (led_refresh != null) {
+                    led_refresh.finishRefresh()
+                }
+                if (LedManagerUtils.getInstance().ledList.size == 0) {
+                    tv_led_empty_titile.visibility = View.VISIBLE
+                } else {
+                    tv_led_empty_titile.visibility = View.GONE
+                }
+                if (adapter != null) {
+                    adapter!!.update()
+                }
+            }
+        }
+    }
+}

+ 198 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/NurseMoveFragment.kt

@@ -0,0 +1,198 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+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.net.engine.model.NetState
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.NurseMoveAdapter
+import com.wdkl.ncs.android.component.nursehome.adapter.ResponsibilityBedAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentNurseMoveBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.NurseMoveContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.NurseMovePresenter
+import com.wdkl.ncs.android.middleware.model.dos.FrameDO
+import com.wdkl.ncs.android.middleware.model.vo.WatchUsingVO
+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 kotlinx.android.synthetic.main.fragment_nurse_move.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class NurseMoveFragment : BaseFragment<NurseMovePresenter,FragmentNurseMoveBinding>(), NurseMoveContract.View, View.OnClickListener {
+    var TAG = NurseMoveFragment::class.java.getSimpleName()
+
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    //护士适配器
+    var nurseMoveAdapter: NurseMoveAdapter? = null
+
+    private lateinit var bedVirtualLayoutManager: VirtualLayoutManager
+    private lateinit var bedDelegateAdapter: DelegateAdapter
+
+    //护士责任床位适配器
+    private var responsibilityBedAdapter: ResponsibilityBedAdapter? = null
+
+    private var selectMobile: WatchUsingVO? = null
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_nurse_move
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        nurseMoveAdapter = NurseMoveAdapter(ArrayList())
+        delegateAdapter.addAdapter(nurseMoveAdapter)
+        mViewDataBinding.nurseMobileRefresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        nurse_mobile_rv.layoutManager = virtualLayoutManager
+        nurse_mobile_rv.adapter = delegateAdapter
+
+        /**初始化LayoutMannager*/
+        bedVirtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        bedDelegateAdapter = DelegateAdapter(bedVirtualLayoutManager)
+        responsibilityBedAdapter = ResponsibilityBedAdapter(ArrayList())
+        bedDelegateAdapter.addAdapter(responsibilityBedAdapter)
+
+        /**配置到RecycleView*/
+        nurse_duty_sickbed_rev.layoutManager = bedVirtualLayoutManager
+        nurse_duty_sickbed_rev.adapter = bedDelegateAdapter
+
+        if (Constant.part_id != -1) {
+            presenter.getMobileDevice(Constant.part_id)
+        }
+        
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        nurseMoveAdapter?.setOnItemClickListener { data, position ->
+            selectMobile = data
+            tv_manager_bed_title.text = data.clerkName + " " + getString(R.string.responsible_bed)
+
+            responsibilityBedAdapter!!.data.clear()
+            presenter.getResponsibleBeds(data.id)
+        }
+
+        nurse_mobile_refresh.setOnRefreshListener {
+            if (Constant.part_id != -1) {
+                presenter.getMobileDevice(Constant.part_id)
+            }
+        }
+
+        call_nurse_mobile.setOnClickListener(this)
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+    /**
+     *显示数据
+     */
+    override fun showMobileDevice(data: ArrayList<WatchUsingVO>) {
+        nurseMoveAdapter!!.data.clear()
+        nurseMoveAdapter!!.data.addAll(data)
+        nurseMoveAdapter!!.notifyDataSetChanged()
+
+        nurse_mobile_refresh.finishRefresh()
+    }
+
+    override fun showResponsibleBeds(beds: ArrayList<FrameDO>) {
+        Log.i(TAG, "责任病床数量 " + beds.size)
+        if (beds.size > 0) {
+            for (bed in beds) {
+                responsibilityBedAdapter!!.data.add(bed.fullName)
+            }
+        }
+        responsibilityBedAdapter!!.notifyDataSetChanged()
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+        responsibilityBedAdapter!!.notifyDataSetChanged()
+        nurse_mobile_refresh.finishRefresh()
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    override fun onClick(p0: View?) {
+        if (selectMobile != null) {
+            //呼出时停止语音播报及铃声
+            SpeechUtil.getInstance().stopSpeak(true)
+            RingPlayHelper.stopRingTone()
+
+            if (Constant.TCP_CONNECTED) {
+                Constant.CALL_TYPE = 0
+                val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, selectMobile!!.id)
+                val transaction = object : TcpCallback(callTcp.tid) {
+                    override fun onSuccess(jsonObject: JSONObject) {
+                        super.onSuccess(jsonObject)
+                    }
+
+                    override fun onFailed(jsonObject: JSONObject) {
+                        // 这里写发送失败的方法
+                        val callbackString = jsonObject.getString(CALLBACK)
+                        showMessage("call fail: $callbackString")
+                        super.onFailed(jsonObject)
+                    }
+                }
+                TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+            } else {
+                showMessage(R.string.net_error)
+            }
+        } else {
+            showMessage(R.string.no_device)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        //
+    }
+}

+ 185 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/OtherHostFragment.kt

@@ -0,0 +1,185 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+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.net.engine.model.NetState
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.OtherHostAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentOtherHostBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.OtherHostContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.OtherHostPresenter
+import com.wdkl.ncs.android.middleware.model.dos.DeviceDO
+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.enums.DeviceTypeEnum
+
+import kotlinx.android.synthetic.main.fragment_other_host.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 其它主机Fragment
+ */
+class OtherHostFragment : BaseFragment<OtherHostPresenter, FragmentOtherHostBinding>(), OtherHostContract.View, View.OnClickListener {
+    var TAG = OtherHostFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    //护士适配器
+    var otherHostAdapter: OtherHostAdapter? = null
+
+    private var selectDevice: DeviceDO? = null
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_other_host
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        otherHostAdapter = OtherHostAdapter(ArrayList())
+        delegateAdapter.addAdapter(otherHostAdapter)
+        mViewDataBinding.otherHostRefresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        rv_other_host.layoutManager = virtualLayoutManager
+        rv_other_host.adapter = delegateAdapter
+
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        group_host.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.rb_other_host) {
+                //加载所有护士主机
+                otherHostAdapter!!.data.clear()
+                if (Constant.part_id != -1) {
+                    presenter.loadAllHostDevice(Constant.part_id)
+                }
+            } else if (checkedId == R.id.rb_manager_host) {
+                //加载总控主机
+                otherHostAdapter!!.data.clear()
+                if (Constant.hospital_id != -1) {
+                    presenter.loadHostDevice(DeviceTypeEnum.NURSE_HOST.value(), Constant.hospital_id)
+                }
+            }
+        }
+
+        otherHostAdapter?.setOnItemClickListener { data, position ->
+            selectDevice = data
+
+            tv_device_name_title.text = data.name
+        }
+
+        call_other_host.setOnClickListener(this)
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+
+    override fun showDevice(devices: ArrayList<DeviceDO>) {
+        otherHostAdapter!!.data.clear()
+        otherHostAdapter!!.data.addAll(devices)
+        //Log.i(TAG,"其它主机数量 " + devices.size)
+        otherHostAdapter!!.notifyDataSetChanged()
+    }
+
+    override fun showAllHostDevice(devices: ArrayList<DeviceDO>) {
+        //显示所有护士主机,排除自己
+        if (devices.size > 0) {
+            for (hostDevice in devices) {
+                if (hostDevice.id != Constant.DEVICE_ID) {
+                    otherHostAdapter!!.data.add(hostDevice)
+                }
+            }
+        }
+        //Log.i(TAG, "其它主机数量 " + devices.size)
+        otherHostAdapter!!.notifyDataSetChanged()
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+        otherHostAdapter!!.notifyDataSetChanged()
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    override fun onClick(p0: View?) {
+        if (selectDevice != null) {
+            //呼出时停止语音播报及铃声
+            SpeechUtil.getInstance().stopSpeak(true)
+            RingPlayHelper.stopRingTone()
+
+            if (Constant.TCP_CONNECTED) {
+                Constant.CALL_TYPE = 0
+                val callTcp = VoiceUtil.voiceCall(Constant.DEVICE_ID, selectDevice!!.id)
+                val transaction = object : TcpCallback(callTcp.tid) {
+                    override fun onSuccess(jsonObject: JSONObject) {
+                        super.onSuccess(jsonObject)
+                    }
+
+                    override fun onFailed(jsonObject: JSONObject) {
+                        // 这里写发送失败的方法
+                        val callbackString = jsonObject.getString(CALLBACK)
+                        showMessage("call fail: $callbackString")
+                        super.onFailed(jsonObject)
+                    }
+                }
+                TcpClient.getInstance().sendTcp(callTcp, false, transaction)
+            } else {
+                showMessage(R.string.net_error)
+            }
+        } else {
+            showMessage(R.string.no_device)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+    }
+}

+ 112 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SickbedFragment.kt

@@ -0,0 +1,112 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.FrameBedVosAdapter
+import com.wdkl.ncs.android.component.nursehome.adapter.FramePartItemAdapter
+import com.wdkl.ncs.android.component.nursehome.adapter.SickbedAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentSickbedBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SickbedContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SickbedPresenter
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+
+import kotlinx.android.synthetic.main.fragment_frame_part.*
+import kotlinx.android.synthetic.main.fragment_sickbed.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 病床Fragment
+ */
+class SickbedFragment:BaseFragment<SickbedPresenter,FragmentSickbedBinding>(),SickbedContract.View {
+    var TAG = SickbedFragment::class.java.getSimpleName()
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+   var sickbedAdapter : SickbedAdapter? = null
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_sickbed
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+//        /**初始化LayoutMannager*/
+//        virtualLayoutManager = VirtualLayoutManager(this.activity)
+//
+//        /**初始化适配器*/
+//        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+//
+//        sickbedAdapter = SickbedAdapter(this.activity,mListener,ArrayList())
+//        delegateAdapter.addAdapter(sickbedAdapter)
+//        mViewDataBinding.sickbed_refresh.setRefreshFooter(ClassicsFooter(activity))
+//
+//        /**配置到RecycleView*/
+//        sickbed_recyv.layoutManager = virtualLayoutManager
+//        sickbed_recyv.adapter = delegateAdapter
+
+
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+    /**
+     *显示数据
+     */
+    override fun showData() {
+    }
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+ @Subscribe(threadMode = ThreadMode.MAIN)
+ fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//  var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+ }
+
+}

+ 304 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SipCallFragment.kt

@@ -0,0 +1,304 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.text.TextUtils
+import android.util.Log
+import android.view.View
+import com.google.gson.Gson
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.service.WdklSipService
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
+import com.wdkl.ncs.android.middleware.model.dos.InteractionDO
+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.TcpModel
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpAction
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+import com.wdkl.ncs.android.middleware.utils.AudioRouteUtils
+import kotlinx.android.synthetic.main.sky_voice_call_layout.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.linphone.core.Core
+
+class SipCallFragment: BaseCallFragment() {
+    private val TAG = "SipCallFragment"
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    private var callEnded: Boolean = false
+
+    private var outGoing: Boolean = false
+
+    //呼叫倒计时
+    lateinit var countDownTimer: CountDownTimer
+
+
+    private var sipCore: Core? = null
+
+    override fun getLayId(): Int {
+        return R.layout.sky_voice_call_layout
+    }
+
+    override fun init() {
+        initCountDownTimer()
+
+        sipCore = WdklSipService.getCore()
+
+//        Log.d(TAG, "callState: $callState, local sip: ${Constants.sip_id}, target sip: ${Constants.targetSipId}")
+        when (callState) {
+            0 -> {
+                //发起通话
+                outGoing = true
+                showCallView(true)
+                Constant.CALL_STATE = Constant.CALL_OUTGOING
+                DeviceChannel.calling = true
+                RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_back2, true)
+            }
+
+            1 -> {
+                //接受通话
+                outGoing = false
+                showCallView(false)
+                Constant.CALL_STATE = Constant.CALL_CALLING
+                DeviceChannel.calling = true
+            }
+        }
+    }
+
+    private fun initCountDownTimer() {
+        if (SettingConfiguration.getInstance().sipOvertime <= 0) {
+            SettingConfiguration.getInstance().sipOvertime = 30
+        }
+
+        countDownTimer = object: CountDownTimer(SettingConfiguration.getInstance().sipOvertime * 1000L, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                //
+            }
+
+            override fun onFinish() {
+                //呼叫超时,退出呼叫界面
+                showMessage("无响应")
+                DeviceChannel.calling = false
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                //VoiceUtil.cancelAudioCall(Constants.ids, Constants.targetDeviceId)
+                cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                callEnd(false)
+            }
+        }
+    }
+
+    override fun bindEvent() {
+        //通话挂断
+        sky_voice_call_hangup.setOnClickListener {
+            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                callEnd(true)
+            } else {
+                countDownTimer.cancel()
+                //VoiceUtil.cancelAudioCall(Constants.ids, Constants.targetDeviceId)
+                cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                callEnd(false)
+            }
+
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            DeviceChannel.calling = false
+        }
+    }
+
+    private fun callTerminate() {
+        if (sipCore != null && sipCore!!.callsNb > 0) {
+            var call = sipCore!!.currentCall
+            if (call == null) {
+                call = sipCore!!.calls[0]
+            }
+            call!!.terminate()
+        }
+    }
+
+    override fun destroy() {
+        RingPlayHelper.stopRingTone()
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        DeviceChannel.calling = false
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+        handler.removeCallbacksAndMessages(null)
+    }
+
+    //开始接听
+    private fun showCallView(outgoing: Boolean) {
+        sky_call_name.text = callName
+        if (outgoing) {
+            countDownTimer.start()
+            sky_voice_call_calling_text.setText(R.string.call_in_calling)
+        } else {
+            sky_voice_call_calling_text.setText(R.string.call_connecting)
+        }
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_timer.visibility = View.GONE
+    }
+
+    private fun showCalling(audioOnly: Boolean) {
+        if (callEnded) {
+            return
+        }
+
+        if (Constant.hookOn) {
+            //免提
+            toggleSpeaker(true)
+        } else {
+            //听筒
+            toggleSpeaker(false)
+        }
+
+        if (audioOnly) {
+            ll_voice_call.visibility = View.VISIBLE
+        } else {
+            //显示视频画面
+            fullscreen_video_frame.visibility = View.VISIBLE
+            pip_video_frame.visibility = View.VISIBLE
+            ll_voice_call.visibility = View.GONE
+
+            if (visiting) {
+                visit_list_view.setVisibility(View.VISIBLE)
+            }
+        }
+
+        sky_voice_call_calling_text.setText(R.string.call_in_call)
+        sky_voice_call_timer.visibility = View.VISIBLE
+        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
+        sky_voice_call_timer.start()
+    }
+
+    private fun cancelCall(fromId: Int, toId: Int?, interactionId: Int?) {
+        val callTcp = VoiceUtil.voiceCancel(tid, fromId, toId, interactionId)
+        TcpClient.getInstance().sendMsg(callTcp.toJson())
+    }
+
+    //通话结束
+    private fun callEnd(handoff: Boolean) {
+        Log.e(TAG, ">>>>>>>>>>> call end !!!!!!!!!!!!!!!!!!")
+        RingPlayHelper.stopRingTone()
+        countDownTimer.cancel()
+
+        synchronized(this) {
+            if (callEnded) {
+                return
+            }
+            callEnded = true
+
+            if (sky_voice_call_timer != null) {
+                sky_voice_call_timer.stop()
+            }
+
+            callTerminate()
+
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            DeviceChannel.calling = false
+            if (handoff) {
+                //VoiceUtil.handoffAudioCall(Constants.ids, Constants.fromId, Constants.interactionId)
+                val callTcp = VoiceUtil.voiceHandoff(tid, Constant.DEVICE_ID, Constant.fromId, Constant.interactionId)
+                TcpClient.getInstance().sendMsg(callTcp.toJson())
+            }
+            Constant.interactionId = null
+
+            backToMain()
+        }
+    }
+
+    private fun toggleSpeaker(enable: Boolean) {
+        Log.d(TAG, "toggle speaker: $enable, sipCore: $sipCore")
+        if ( sipCore == null) {
+            return
+        }
+
+        if (enable) {
+            AudioRouteUtils.routeAudioToSpeaker(sipCore!!)
+        } else {
+            AudioRouteUtils.routeAudioToEarpiece(sipCore!!)
+        }
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_TCP_MSG -> {
+                if (messageEvent.getMessage() is TcpModel) {
+                    val curTcpModel = messageEvent.getMessage() as TcpModel
+                    if (curTcpModel.type == TcpType.VOICE) {
+                        val curIt = Gson().fromJson(curTcpModel.data.toString(), InteractionDO::class.java)
+                        if (curTcpModel.action == TcpAction.VoiceAction.HANDOFF) {
+                            //对方挂断,不论我方呼出或呼入
+                            if (Constant.interactionId == curIt.id) {
+                                callEnd(false)
+                            }
+                        } else if (curTcpModel.action == TcpAction.VoiceAction.ACCEPT) {//对方接受语音
+                            RingPlayHelper.stopRingTone()
+                            sky_voice_call_calling_text.setText(R.string.call_connecting)
+                            Constant.interactionId = curIt.id
+                            Constant.fromId = curTcpModel.fromId
+                            DeviceChannel.calling = true
+                            Constant.CALL_STATE = Constant.CALL_CALLING
+                            countDownTimer.cancel()
+
+                            if (sipCore == null || TextUtils.isEmpty(curIt.toSipId)) {
+                                //通话失败,重置并返回主界面
+                                showMessage("Core或targetSipId为空!")
+                                Constant.CALL_STATE = Constant.CALL_STANDBY
+                                if (sky_voice_call_timer != null) {
+                                    sky_voice_call_timer.stop()
+                                }
+                                callEnd(true)
+                            } else {
+                                val addressToCall = sipCore!!.interpretUrl(curIt.toSipId)
+                                val params = sipCore!!.createCallParams(null)
+                                params?.isVideoEnabled = false
+                                if (addressToCall != null) {
+                                    sipCore!!.inviteAddressWithParams(addressToCall, params!!)
+                                    Log.d(TAG, ">>>>>>>>>>> invite address: " + addressToCall.asString())
+                                }
+                            }
+                        } else if (curTcpModel.action == TcpAction.VoiceAction.REJECT) {//对方拒绝
+                            if (Constant.interactionId == curIt.id) {
+                                showMessage("对方拒绝")
+                                Constant.CALL_STATE = Constant.CALL_STANDBY
+                                DeviceChannel.calling = false
+                                callEnd(false)
+                            }
+                        }
+                    }
+                }
+            }
+
+            Constant.EVENT_END_CALL -> {
+                Log.d(TAG, ">>>>>>>>>>>>>> EVENT_END_CALL")
+                if (messageEvent.getMessage() is String) {
+                    val str = messageEvent.getMessage() as String
+                    if (str.equals("cancel")) {
+                        cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                        callEnd(false)
+                    } else {
+                        callEnd(true)
+                    }
+                }
+            }
+
+            Constant.SIP_CONNECTED -> {
+                showCalling(true)
+            }
+
+            Constant.EVENT_TOGGLE_SPEAKER -> {
+                toggleSpeaker(false)
+            }
+        }
+    }
+
+}

+ 432 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SkyCallFragment.kt

@@ -0,0 +1,432 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.os.CountDownTimer
+import android.os.Handler
+import android.os.Looper
+import android.os.SystemClock
+import android.util.Log
+import android.view.View
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.alibaba.fastjson.JSONObject
+import com.google.gson.Gson
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.BedItemAdapter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.component.nursehome.util.RingPlayHelper
+import com.wdkl.ncs.android.lib.base.BaseApplication
+import com.wdkl.ncs.android.lib.utils.AppTool
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO
+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.VideoUtil
+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
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType
+import com.wdkl.ncs.android.middleware.utils.CommonUtils
+import com.wdkl.ncs.android.middleware.utils.StringUtil
+import com.wdkl.ncs.janus.client.CallSessionCallback
+import com.wdkl.ncs.janus.client.JanusClient
+import com.wdkl.ncs.janus.client.VideoRoomCallback
+import com.wdkl.ncs.janus.entity.Room
+import com.wdkl.ncs.janus.rtc.WebRTCEngine
+import com.wdkl.ncs.janus.util.JanusConstant
+import com.wdkl.ncs.janus.util.EnumType
+import kotlinx.android.synthetic.main.sky_voice_call_layout.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import org.webrtc.SurfaceViewRenderer
+import java.math.BigInteger
+
+class SkyCallFragment: BaseCallFragment(), CallSessionCallback {
+    private val TAG = "SkyCallFragment"
+
+    private var localSurfaceView: SurfaceViewRenderer? = null
+    private var remoteSurfaceView: SurfaceViewRenderer? = null
+
+    private var bedItemAdapter: BedItemAdapter? = null
+
+    private val handler = Handler(Looper.getMainLooper())
+
+    private var callEnded: Boolean = false
+    private var outGoing: Boolean = false
+    private var acceptCall = false
+
+    private var janusClient: JanusClient? = null
+    private var room: Room?=null
+    private var videoRoomCallback: VideoRoomCallback? = null
+
+    //呼叫倒计时
+    lateinit var countDownTimer: CountDownTimer
+
+    override fun getLayId(): Int {
+        return R.layout.sky_voice_call_layout
+    }
+
+    override fun init() {
+        initCountDownTimer()
+        //初始化 engine
+        WebRTCEngine.getInstance().init(true, BaseApplication.appContext)
+        //初始化 janusClient
+        janusClient = JanusClient(JanusConstant.JANUS_URL, Constant.SIP_ID!!.toBigInteger())
+
+        if (visiting) {
+            bedItemAdapter = BedItemAdapter(baseActivity, CommonUtils.getInBedVOS())
+            visit_list_view.setAdapter(bedItemAdapter)
+            visit_list_view.setLayoutManager(VirtualLayoutManager(baseActivity))
+            visit_list_view.setVisibility(View.GONE)
+            fullscreen_video_frame.setOnClickListener(View.OnClickListener {
+                if (visit_list_view.getVisibility() == View.GONE) {
+                    visit_list_view.setVisibility(View.VISIBLE)
+                } else {
+                    visit_list_view.setVisibility(View.GONE)
+                }
+            })
+
+            bindListener()
+        }
+
+        Log.d(TAG, "out call callState: $callState, local sip: ${Constant.SIP_ID}, target sip: ${Constant.targetSipId}")
+        when (callState) {
+            0 -> {
+                //发起通话
+                outGoing = true
+                janusClient!!.callState = EnumType.CallState.Outgoing
+                room = Room(Constant.SIP_ID!!.toBigInteger())
+                showCallView(true)
+                Constant.CALL_STATE = Constant.CALL_OUTGOING
+                DeviceChannel.calling = true
+                RingPlayHelper.playRingTone(BaseApplication.appContext, R.raw.ring_back2, true)
+            }
+
+            1 -> {
+                //如果是模拟分机呼叫则需要主机来创建房间发起通话
+                if (Constant.fromDeviceType == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+                    outGoing = true
+                    janusClient!!.callState = EnumType.CallState.Outgoing
+                    room = Room(Constant.SIP_ID!!.toBigInteger())
+                    showCallView(false)
+                    Constant.CALL_STATE = Constant.CALL_CALLING
+                    DeviceChannel.calling = true
+                } else {
+                    //接受通话
+                    outGoing = false
+                    janusClient!!.callState = EnumType.CallState.Incoming
+                    room = Room(Constant.targetSipId!!.toBigInteger())
+                    showCallView(false)
+                    Constant.CALL_STATE = Constant.CALL_CALLING
+                    DeviceChannel.calling = true
+                }
+                acceptCall = true
+            }
+        }
+
+        videoRoomCallback = VideoRoomCallback(janusClient, room, Constant.SIP_ID!!.toBigInteger())
+        videoRoomCallback!!.callSessionCallback = this
+        janusClient!!.setJanusCallback(videoRoomCallback)
+        janusClient!!.connect(-1, false)
+
+        Constant.IN_CALL = true
+    }
+
+    private fun initCountDownTimer() {
+        if (SettingConfiguration.getInstance().sipOvertime <= 0) {
+            SettingConfiguration.getInstance().sipOvertime = 30
+        }
+
+        countDownTimer = object: CountDownTimer(SettingConfiguration.getInstance().sipOvertime*1000L, 1000) {
+            override fun onTick(millisUntilFinished: Long) {
+                //
+            }
+
+            override fun onFinish() {
+                //呼叫超时,退出呼叫界面
+                showMessage(R.string.no_response)
+                DeviceChannel.calling = false
+                Constant.CALL_STATE = Constant.CALL_STANDBY
+                //VoiceUtil.cancelAudioCall(Constants.ids, Constants.targetDeviceId)
+                cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                callEnd(false)
+            }
+        }
+    }
+
+    private fun bindListener() {
+        bedItemAdapter!!.setInvitClickListener { bedVO ->
+            Constant.visitedId = bedVO.bedDeviceId
+            visit_list_view.setVisibility(View.GONE)
+            Constant.visit_bed_name = bedVO.frameBed.fullName
+
+            //VideoUtil.sendInviteVideoCall(Constants.ids, bedVO.bedDeviceId, Constants.interactionId, Constants.targetSipId)
+            val callTcp = VideoUtil.videoInviteHOST(tid, Constant.DEVICE_ID, bedVO.bedDeviceId, Constant.interactionId, Constant.targetSipId)
+            TcpClient.getInstance().sendMsg(callTcp.toJson())
+        }
+    }
+
+    override fun bindEvent() {
+        //通话挂断
+        sky_voice_call_hangup.setOnClickListener {
+            if (Constant.CALL_STATE == Constant.CALL_CALLING) {
+                callEnd(true)
+            } else {
+                countDownTimer.cancel()
+                //VoiceUtil.cancelAudioCall(Constants.ids, Constants.targetDeviceId)
+                cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                callEnd(false)
+            }
+
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            DeviceChannel.calling = false
+        }
+    }
+
+    override fun destroy() {
+        //RingPlayHelper.stopRingTone()
+        Constant.CALL_STATE = Constant.CALL_STANDBY
+        DeviceChannel.calling = false
+        if (sky_voice_call_timer != null) {
+            sky_voice_call_timer.stop()
+        }
+        handler.removeCallbacksAndMessages(null)
+        Constant.IN_CALL = false
+    }
+
+    //开始接听
+    private fun showCallView(outgoing: Boolean) {
+        if (outgoing) {
+            countDownTimer.start()
+            sky_voice_call_calling_text.text = StringUtil.getResString(R.string.call_in_calling) + " " + callName
+        } else {
+            sky_call_name.text = callName
+            sky_voice_call_calling_text.setText(R.string.call_connecting)
+        }
+        sky_voice_call_outgoing.visibility = View.VISIBLE
+        sky_voice_call_timer.visibility = View.GONE
+    }
+
+    private fun showCalling(audioOnly: Boolean) {
+        if (callEnded) {
+            return
+        }
+
+        sky_call_name.text = callName
+        if (audioOnly) {
+            ll_voice_call.visibility = View.VISIBLE
+        } else {
+            //显示视频画面
+            fullscreen_video_frame.visibility = View.VISIBLE
+            pip_video_frame.visibility = View.VISIBLE
+            ll_voice_call.visibility = View.GONE
+
+            if (visiting) {
+                visit_list_view.setVisibility(View.VISIBLE)
+            }
+        }
+
+        sky_voice_call_calling_text.setText(R.string.call_in_call)
+        sky_voice_call_timer.visibility = View.VISIBLE
+        sky_voice_call_timer.base = SystemClock.elapsedRealtime()
+        sky_voice_call_timer.start()
+    }
+
+    private fun cancelCall(fromId: Int, toId: Int?, interactionId: Int?) {
+        val callTcp = VoiceUtil.voiceCancel(tid, fromId, toId, interactionId)
+        TcpClient.getInstance().sendMsg(callTcp.toJson())
+    }
+
+    //通话结束
+    private fun callEnd(handoff: Boolean) {
+        Log.e(TAG, "call end !!!!!!!!!!!!!!!!!!")
+        RingPlayHelper.stopRingTone()
+        countDownTimer.cancel()
+
+        synchronized(this) {
+            if (callEnded) {
+                return
+            }
+            callEnded = true
+
+            if (sky_voice_call_timer != null) {
+                sky_voice_call_timer.stop()
+            }
+
+            if (janusClient != null && janusClient!!.webSocketChannel !=null) {
+                janusClient!!.callState = EnumType.CallState.Idle
+                if (outGoing){
+                    if (janusClient!!.currentHandleId !=null) {
+                        janusClient!!.destroyRoom(janusClient!!.currentHandleId, null)
+                    }
+                } else {
+                    janusClient!!.leaveRoom()
+                }
+
+                janusClient!!.setJanusCallback(null)
+                janusClient!!.disConnect()
+            }
+
+            Constant.CALL_STATE = Constant.CALL_STANDBY
+            DeviceChannel.calling = false
+            if (handoff) {
+                //VoiceUtil.handoffAudioCall(Constants.ids, Constants.fromId, Constants.interactionId)
+                val callTcp = VoiceUtil.voiceHandoff(tid, Constant.DEVICE_ID, Constant.fromId, Constant.interactionId)
+                TcpClient.getInstance().sendMsg(callTcp.toJson())
+            }
+            Constant.interactionId = null
+
+            backToMain()
+        }
+    }
+
+
+    /********************************************************
+     ********************* webrtc通话回调 ********************
+     * 注意: 如涉及到UI更新的需要在主线程处理,务必注意
+     *******************************************************/
+    //************************* 通话回调 *******************//
+    override fun didRoomCreated() {
+        //房间创建成功,如果是接听通话则通知对方加入通话
+        if (!callEnded && acceptCall) {
+            Log.d(TAG, "room created, accept call...")
+            val callTcp = VoiceUtil.voiceAccept(tid, Constant.DEVICE_ID, Constant.fromId, Constant.interactionId)
+            TcpClient.getInstance().sendMsg(callTcp.toJson())
+        }
+    }
+
+    override fun didChangeState(var1: EnumType.CallState?) {
+        handler.post {
+            if (var1 == EnumType.CallState.Connected) {
+                Log.e(TAG, "didChangeState: " + var1)
+                if (var1 == EnumType.CallState.Connected && !callEnded) {
+                    RingPlayHelper.stopRingTone()
+                    Constant.CALL_STATE = Constant.CALL_CALLING
+                    DeviceChannel.calling = true
+                    //更新界面显示
+                    showCalling(onlyAudio)
+                }
+
+                if (Constant.hookOn) {
+                    WebRTCEngine.getInstance().toggleSpeaker(true)
+                } else {
+                    //手柄拿起,听筒模式
+                    WebRTCEngine.getInstance().toggleSpeaker(false)
+                }
+            }
+        }
+    }
+
+    override fun didDisconnected(userId: String?) {
+        Log.w(TAG, "didDisconnected")
+        handler.post {
+            if (userId.equals(Constant.targetSipId)) {
+                showMessage(R.string.call_disconnect)
+                callEnd(true)
+            }
+        }
+    }
+
+    override fun didCreateLocalVideoTrack() {
+    }
+
+    override fun didError(error: String?) {
+        Log.e(TAG, "didError: " + error)
+        handler.post {
+            showMessage(R.string.call_error)
+            callEnd(true)
+        }
+    }
+
+    override fun didHangUp(handlerId: BigInteger) {
+        Log.e("hangup", "socket hangup")
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+    override fun didReceiveRemoteVideoTrack(userId: BigInteger?) {
+        // TODO("Not yet implemented")
+    }
+
+
+    override fun didCallEndWithReason(var1: EnumType.CallEndReason?) {
+        //
+    }
+
+    override fun didUserLeave(userId: BigInteger?) {
+        Log.w(TAG, "didUserLeave")
+        handler.post {
+            callEnd(true)
+        }
+    }
+
+    override fun didChangeMode(isAudioOnly: Boolean) {
+        Log.w(TAG,"didChangeMode")
+    }
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        when (messageEvent.getType()) {
+            Constant.EVENT_TCP_MSG -> {
+                if (messageEvent.getMessage() is TcpModel) {
+                    val curTcpModel = messageEvent.getMessage() as TcpModel
+                    if (curTcpModel.getType() == TcpType.VOICE) {
+                        val curInteractionVO = Gson().fromJson(curTcpModel.data.toString(), InteractionVO::class.java)
+                        if (curTcpModel.getAction() == TcpAction.VoiceAction.HANDOFF) {
+                            //对方挂断,不论我方呼出或呼入
+                            if (Constant.interactionId == curInteractionVO.id) {
+                                callEnd(false)
+                            }
+                        } else if (curTcpModel.getAction() == TcpAction.VoiceAction.ACCEPT) {//对方接受语音
+                            RingPlayHelper.stopRingTone()
+                            sky_voice_call_calling_text.setText(R.string.call_connecting)
+                            Constant.interactionId = curInteractionVO.id
+                            Constant.fromId = curTcpModel.fromId
+                            DeviceChannel.calling = true
+                            Constant.CALL_STATE = Constant.CALL_CALLING
+                            countDownTimer.cancel()
+                        } else if (curTcpModel.getAction() == TcpAction.VoiceAction.REJECT) {//对方拒绝
+                            if (Constant.interactionId == curInteractionVO.id) {
+                                showMessage(R.string.call_reject)
+                                Constant.CALL_STATE = Constant.CALL_STANDBY
+                                DeviceChannel.calling = false
+                                callEnd(false)
+                            }
+                        } /*else if (curTcpModel.getAction() == TcpAction.VoiceAction.CALLING) {//对方通话中
+                            showMessage(R.string.call_busy)
+                            AppTool.Time.delay(800) {
+                                Constants.CALL_STATE = Constants.CALL_STANDBY
+                                DeviceChannel.calling = false
+                                callEnd(false)
+                            }
+                        } else if (curTcpModel.getAction() == TcpAction.VoiceAction.FAILED) {//对方不在线 呼叫失败
+                            //showMessage("对方离线或不存在,呼叫失败")
+                            AppTool.Time.delay(800) {
+                                Constants.CALL_STATE = Constants.CALL_STANDBY
+                                DeviceChannel.calling = false
+                                callEnd(false)
+                            }
+                        }*/
+                    }
+                }
+            }
+
+            Constant.EVENT_END_CALL -> {
+                if (messageEvent.getMessage() is String) {
+                    val str = messageEvent.getMessage() as String
+                    if (str.equals("cancel")) {
+                        cancelCall(Constant.DEVICE_ID, Constant.targetDeviceId, Constant.interactionId)
+                        callEnd(false)
+                    } else {
+                        callEnd(true)
+                    }
+                }
+            }
+        }
+    }
+
+}

+ 787 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/SystemSettingsFragment.kt

@@ -0,0 +1,787 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.app.NotificationManager
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.provider.Settings
+import android.util.Log
+import android.view.View
+import android.widget.AdapterView
+import android.widget.SeekBar
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.BuildConfig
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.activity.NurseHomeActivity
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentSystemSettingsBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.component.nursehome.util.*
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.utils.showMessage
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SystemSettingsContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SystemSettingsPresenter
+import com.wdkl.ncs.android.middleware.model.bean.SettingConfiguration
+import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
+
+
+import kotlinx.android.synthetic.main.fragment_system_settings.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+import java.io.DataOutputStream
+import java.io.IOException
+import java.util.*
+import kotlin.collections.ArrayList
+
+/**
+ * 设置Fragment
+ */
+class SystemSettingsFragment:BaseFragment<SystemSettingsPresenter,FragmentSystemSettingsBinding>(),SystemSettingsContract.View, View.OnClickListener, SeekBar.OnSeekBarChangeListener {
+    var TAG = SystemSettingsFragment::class.java.getSimpleName()
+    var partSettingDO = PartSettingDO()
+
+    private var clickTime: Long = 0
+    private var clickTimes: Int = 1
+    private var originTime: Int = 1
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_system_settings
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+        //设置白昼初始值和结束值
+        var initialValue = doubleslide_withoutrule.timeToArray(0, SettingConfig.getInitialDayTime(this.activity))
+        var endValue = doubleslide_withoutrule.timeToArray(1, SettingConfig.getEndOfDay(this.activity))
+
+        Log.e(TAG,"endValue "+endValue +" "+ SettingConfig.getEndOfDay(this.activity)  + ", startValue: " + initialValue + " " + SettingConfig.getInitialDayTime(this.activity))
+//        var initialValue = SettingConfig. getInitialDayTimeLocation(this.activity)
+//        var endValue = SettingConfig.getEndOfDayLocation(this.activity)
+        doubleslide_withoutrule.update(initialValue,endValue)
+
+        if (SettingConfig.TTS_ON == SettingConfig.getTtsMode(this.activity)) {
+            if (Constant.TTS_STATUS == 2) {
+                radio_tts.isChecked = true
+            } else {
+                radio_ring.isChecked = true
+            }
+        } else if (SettingConfig.RING_ON == SettingConfig.getTtsMode(this.activity)) {
+            radio_ring.isChecked = true
+        } else if (SettingConfig.MUSIC_ON == SettingConfig.getTtsMode(this.activity)) {
+            radio_music.isChecked = true
+        }
+
+        if (SettingConfig.getTransferCall(activity)) {
+            radio_transfer_on.isChecked = true
+        } else {
+            radio_transfer_off.isChecked = true
+        }
+
+        if (SettingConfig.getSosCallNameOn(activity)) {
+            radio_sos_name_on.isChecked = true
+        } else {
+            radio_sos_name_off.isChecked = true
+        }
+
+        if (SettingConfig.getLoopCall(activity)) {
+            radio_loop_call_on.isChecked = true
+        } else {
+            radio_loop_call_off.isChecked = true
+        }
+
+        if (SettingConfig.getSipEnabled(activity)) {
+            radio_sip_on.isChecked = true
+        } else {
+            radio_sip_off.isChecked = true
+        }
+
+        if (SettingConfig.getVoiceNumeric(activity)) {
+            radio_voice_numeric_on.isChecked = true
+        } else {
+            radio_voice_numeric_off.isChecked = true
+        }
+
+        if (Locale.CHINESE.getLanguage().equals(LocaleMangerUtils.getApplicationLocale().language)) {
+            ll_call_voice_numeric.visibility = View.VISIBLE
+        }
+
+        //语音播报次数
+        call_number_tv.text = SettingConfig.getCallNumber(this.activity).toString()
+        call_number_seekb.setProgress((SettingConfig.getCallNumber(this.activity)))
+        //主机白天亮度
+        main_engine_daytime_brightness_tv.text = SettingConfig.getMainEngineDaytimeBrightness(this.activity).toString()
+        main_engine_daytime_brightness_seekb.setProgress(SettingConfig.getMainEngineDaytimeBrightness(this.activity))
+        //主机晚上亮度
+        host_night_brightness_tv.text = SettingConfig.getHostNightBrightness(this.activity).toString()
+        host_night_brightness_tv_seekb.setProgress(SettingConfig.getHostNightBrightness(this.activity))
+        //todo 根据白天晚上设置亮度
+
+        //主机白天系统音量
+        host_daytime_volume_tv.text = SettingConfig.getHostDaytimeVolume(this.activity).toString()
+        host_daytime_volume_seekb.setProgress(SettingConfig.getHostDaytimeVolume(this.activity))
+        //主机晚上系统音量
+        host_night_volume_tv.text = SettingConfig.getHostNightVolume(this.activity).toString()
+        host_night_volume_seekb.setProgress(SettingConfig.getHostNightVolume(this.activity))
+        //todo 根据白天晚上设置系统音量
+
+        //主机免提录入音量
+        hands_free_input_volume_of_host_machine_tv.text = SettingConfig.getHandsFreeInputVolumeOfHostMachine(this.activity).toString()
+        hands_free_input_volume_of_host_machine_seekb.setProgress(SettingConfig.getHandsFreeInputVolumeOfHostMachine(this.activity))
+        //主机手柄免提录入音量
+        host_handle_input_volume_tv.text = SettingConfig.getHostHandleInputVolume(this.activity).toString()
+        host_handle_input_volume_seekb.setProgress(SettingConfig.getHostHandleInputVolume(this.activity))
+        //todo 根据白天晚上设置录入音量
+
+
+        //主机免提播放音量
+        host_hands_free_play_volume_tv.text = SettingConfig.getHostHandsFreePlayVolume(this.activity).toString()
+        host_hands_free_play_volume_seekb.setProgress(SettingConfig.getHostHandsFreePlayVolume(this.activity))
+        //主机手柄播放音量
+        host_gamepad_play_volume_tv.text = SettingConfig.getHostGamepadPlayVolume(this.activity).toString()
+        host_gamepad_play_volume_seekb.setProgress(SettingConfig.getHostGamepadPlayVolume(this.activity))
+        //todo 根据白天晚上设置播放音量
+
+        //通话模式
+        if(SettingConfig.single_pass_mode == SettingConfig.getTalkMode(this.activity)){
+            single_pass_mode_radiobt.isChecked = true
+        }else{
+            two_way_mode_radiobt.isChecked = true
+        }
+
+        //分机白天亮度设置
+        extension_daytime_brightness_tv.text = SettingConfig.getExtensionDaytimeBrightness(this.activity).toString()
+        extension_daytime_brightness_seekb.setProgress(SettingConfig.getExtensionDaytimeBrightness(this.activity))
+        //分机晚上亮度设置
+        extension_night_brightness_tv.text = SettingConfig.getExtensionNightBrightness(this.activity).toString()
+        extension_night_brightness_seekb.setProgress(SettingConfig.getExtensionNightBrightness(this.activity))
+        //todo 根据白天晚上设置分机亮度
+
+        //分机LED白天亮度设置
+        extension_daytime_led_brightness_tv.text = SettingConfig.getExtensionDaytimeLEDBrightness(this.activity).toString()
+        extension_daytime_led_brightness_seekb.setProgress(SettingConfig.getExtensionDaytimeLEDBrightness(this.activity))
+        //分机LED晚上亮度设置
+        extension_night_led_brightness_tv.text = SettingConfig.getExtensionNightLEDBrightness(this.activity).toString()
+        extension_night_led_brightness_seekb.setProgress(SettingConfig.getExtensionNightLEDBrightness(this.activity))
+        //todo 根据白天晚上设置分机led亮度
+
+
+        //分机白天系统音量设置
+        extension_daytime_system_volume_tv.text = SettingConfig.getExtensionDaytimeSystemVolume(this.activity).toString()
+        extension_daytime_system_volume_seekb.setProgress(SettingConfig.getExtensionDaytimeSystemVolume(this.activity))
+        //分机晚上统音量设置
+        extension_night_system_volume_tv.text = SettingConfig.getExtensionNightSystemVolume(this.activity).toString()
+        extension_night_system_volume_seekb.setProgress(SettingConfig.getExtensionNightSystemVolume(this.activity))
+        //todo 根据白天晚上设置分机系统音量
+
+        //分机手柄录入音量
+        the_extension_handle_records_the_volume_tv.text = SettingConfig.getTheExtensionHandleRecordsTheVolume(this.activity).toString()
+        the_extension_handle_records_the_volume_seekb.setProgress(SettingConfig.getTheExtensionHandleRecordsTheVolume(this.activity))
+        //todo 根据白天晚上设置分机系统音量
+
+
+        //分机通话音量
+        extension_call_volume_tv.text = SettingConfig.getExtensionCallVolume(this.activity).toString()
+        extension_call_volume_seekb.setProgress(SettingConfig.getExtensionCallVolume(this.activity))
+        //todo 根据白天晚上设置分机通话音量
+
+        //传统转换盒系统音量
+        change_box_system_volume_tv.text = SettingConfig.getChangeBoxSystemVolume(this.activity).toString()
+        change_box_system_volume_seekb.setProgress(SettingConfig.getChangeBoxSystemVolume(this.activity))
+        //todo 根据白天晚上设置传统转换盒系统音量
+
+        //门口机白天亮度设置
+        door_machine_daytime_brightness_tv.text = SettingConfig.getDoorMachineDaytimeBrightness(this.activity).toString()
+        door_machine_daytime_brightness_seekb.setProgress(SettingConfig.getDoorMachineDaytimeBrightness(this.activity))
+        //门口机晚上亮度设置
+        door_machine_night_brightness_tv.text = SettingConfig.getDoorMachineNightBrightness(this.activity).toString()
+        door_machine_night_brightness_seekb.setProgress(SettingConfig.getDoorMachineNightBrightness(this.activity))
+        //todo 根据白天晚上设置门口亮度
+
+        //门口机通话音量
+        door_phone_volume_tv.text = SettingConfig.getDoorPhoneVolume(this.activity).toString()
+        door_phone_volume_seekb.setProgress(SettingConfig.getDoorPhoneVolume(this.activity))
+        //todo 根据白天晚上设置门口通话音量
+        partSettingDO.id = SettingConfiguration.getInstance().id
+        partSettingDO.unionId = SettingConfiguration.getInstance().unionId
+        partSettingDO.createTime = SettingConfiguration.getInstance().createTime
+        partSettingDO.partId = Constant.part_id
+        partSettingDO.dayStart = SettingConfig. getInitialDayTime(this.activity)+":00"
+        partSettingDO.dayLight = SettingConfig.getMainEngineDaytimeBrightness(this.activity)
+        //partSettingDO.dayVol = SettingConfig.getHostDaytimeVolume(this.activity)
+        partSettingDO.dayVol = SettingConfiguration.getInstance().dayVol
+        partSettingDO.dayRingVol = SettingConfig.getHostDaytimeVolume(this.activity)
+        partSettingDO.dayRingTimes = SettingConfig.getCallNumber(this.activity)
+        partSettingDO.dayNurseLed = SettingConfig.getExtensionDaytimeLEDBrightness(this.activity)
+        partSettingDO.dayDoorVol = SettingConfig.getDoorPhoneVolume(this.activity)
+        partSettingDO.dayBedVol = SettingConfig.getExtensionDaytimeSystemVolume(this.activity)
+        partSettingDO.dayTransferBoxVol = SettingConfiguration.getInstance().dayTransferBoxVol
+        partSettingDO.dayTransferBoxSystemVol = SettingConfiguration.getInstance().dayTransferBoxSystemVol
+        partSettingDO.nightStart = SettingConfig.getEndOfDay(this.activity)+":00"
+        partSettingDO.nightLight = SettingConfig.getHostNightBrightness(this.activity)
+        //partSettingDO.nightVol = SettingConfig.getHostNightVolume(this.activity)
+        partSettingDO.nightVol = SettingConfiguration.getInstance().nightVol
+        partSettingDO.nightRingVol = SettingConfig.getHostNightVolume(this.activity)
+        partSettingDO.nightRingTimes = SettingConfig.getCallNumber(this.activity)
+        partSettingDO.nightNurseLed = SettingConfiguration.getInstance().nightNurseLed
+        partSettingDO.nightDoorVol = SettingConfiguration.getInstance().nightDoorVol
+        partSettingDO.nightBedVol = SettingConfig.getExtensionNightSystemVolume(this.activity)
+        partSettingDO.nightTransferBoxVol = SettingConfiguration.getInstance().nightTransferBoxVol
+        partSettingDO.nightTransferBoxSystemVol = SettingConfiguration.getInstance().nightTransferBoxSystemVol
+        partSettingDO.sleepSecondsNurse = SettingConfiguration.getInstance().sleepSecondsNurse
+        partSettingDO.sleepSecondsDoor = SettingConfiguration.getInstance().sleepSecondsDoor
+        partSettingDO.sleepSecondsBed = SettingConfiguration.getInstance().sleepSecondsBed
+        partSettingDO.sipOvertime = SettingConfiguration.getInstance().sipOvertime
+        partSettingDO.transferDuration = SettingConfiguration.getInstance().transferDuration
+        partSettingDO.transferDurationLeader = SettingConfiguration.getInstance().transferDurationLeader
+
+
+        software_and_information_tv.setText("Version: V" + BuildConfig.VERSION_NAME + "_" + BuildConfig.VERSION_CODE)
+        software_and_information_tv.setOnLongClickListener {
+            Constant.autoUpdate = false
+            (activity as NurseHomeActivity).checkApp()
+
+            return@setOnLongClickListener true
+        }
+        software_and_information_tv.setOnClickListener {
+            val time = System.currentTimeMillis()
+            if (time - clickTime < 1500) {
+                clickTimes++
+            } else {
+                clickTimes = 1
+            }
+
+            if (clickTimes > 9) {
+                if (AppUtil.openNetwrokDebug()) {
+                    showMessage(R.string.enable_debug)
+                }
+                clickTimes = 1
+            }
+            clickTime = time
+        }
+        tv_device_ip.setText(NetHelper.getInstance().localIP)
+
+        save_settings_tv.setOnClickListener(this)
+        system_settings_tv.setOnClickListener(this)
+        language_settings_tv.setOnClickListener(this)
+        sip_test.setOnClickListener(this)
+
+        originTime = SettingConfig.getCallStayTime(activity)
+        spinner_call_stay_time.setSelection(originTime)
+    }
+
+    //开启网络调试
+    /*private fun openNetwrokDebug() {
+        val commands = arrayListOf(
+            "/system/bin/sh",
+            "setprop service.adb.tcp.port 5555",
+            "stop adbd",
+            "start adbd"
+        )
+        try {
+            RunAsRoot(commands)
+            showMessage("start Debug")
+        } catch (e: IOException) {
+            e.printStackTrace()
+        }
+    }
+
+    private fun RunAsRoot(cmds: ArrayList<String>) {
+        val p = Runtime.getRuntime().exec("su")
+        val os = DataOutputStream(p.outputStream)
+        for (tmpCmd in cmds) {
+            os.writeBytes(
+                """
+            $tmpCmd
+            
+            """.trimIndent()
+            )
+        }
+        os.writeBytes("exit\n")
+        os.flush()
+    }*/
+
+
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+        //白昼监听
+        doubleslide_withoutrule.setOnRangeListener { low, big, lowTime, bigTime ->
+            SettingConfig.setInitialDayTimeLocation(this.activity, String.format("%.0f", low))
+            SettingConfig.setInitialDayTime(this.activity,lowTime)
+            SettingConfig.setEndOfDayLocation(this.activity, String.format("%.0f", big))
+            SettingConfig.setEndOfDay(this.activity,bigTime)
+
+            partSettingDO.dayStart = lowTime+":00"
+            partSettingDO.nightStart = bigTime+":00"
+        }
+
+        group_tts_set.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_tts) {
+                if (Constant.TTS_STATUS == 2) {
+                    showMessage(R.string.tts_enabled)
+                    SettingConfig.setTtsMode(this.activity, SettingConfig.TTS_ON)
+                } else {
+                    showMessage(R.string.tts_invalid)
+                    radio_ring.isChecked = true
+                    SettingConfig.setTtsMode(this.activity, SettingConfig.RING_ON)
+                }
+            } else if (checkedId == R.id.radio_ring) {
+                SettingConfig.setTtsMode(this.activity, SettingConfig.RING_ON)
+            } else if (checkedId == R.id.radio_music) {
+                SettingConfig.setTtsMode(this.activity, SettingConfig.MUSIC_ON)
+            }
+        }
+
+        group_call_transfer.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_transfer_on) {
+                SettingConfiguration.getInstance().transferCall = true
+                SettingConfig.setTransferCall(activity, true)
+                WarningDialogHelper.showDialog(activity, false)
+            } else {
+                SettingConfiguration.getInstance().transferCall = false
+                SettingConfig.setTransferCall(activity, false)
+                WarningDialogHelper.showDialog(activity, false)
+            }
+        }
+
+        group_sos_call_name.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_sos_name_on) {
+                SettingConfig.setSosCallNameOn(activity, true)
+            } else {
+                SettingConfig.setSosCallNameOn(activity, false)
+            }
+        }
+
+        spinner_call_stay_time.setOnItemSelectedListener(object : AdapterView.OnItemSelectedListener {
+            override fun onItemSelected(
+                parent: AdapterView<*>?,
+                view: View,
+                position: Int,
+                id: Long
+            ) {
+                Log.d(TAG, "select pos: $position, origin: $originTime")
+                if (originTime != position) {
+                    SettingConfig.setCallStayTime(activity, position)
+                    WarningDialogHelper.showDialog(activity, false)
+                }
+            }
+
+            override fun onNothingSelected(parent: AdapterView<*>?) {
+                //
+            }
+        })
+
+        group_loop_call.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_loop_call_on) {
+                SettingConfig.setLoopCall(activity, true)
+            } else {
+                SettingConfig.setLoopCall(activity, false)
+            }
+        }
+
+        group_sip.setOnCheckedChangeListener { group, checkedId ->
+            PasswordDialogHelper.showPasswordDialog(activity) {
+                if (checkedId == R.id.radio_sip_on) {
+                    SettingConfig.setSipEnable(activity, true)
+                } else {
+                    SettingConfig.setSipEnable(activity, false)
+                }
+
+                WarningDialogHelper.showDialog(activity, true)
+            }
+        }
+
+        group_call_voice_numeric.setOnCheckedChangeListener { group, checkedId ->
+            if (checkedId == R.id.radio_voice_numeric_on) {
+                SettingConfig.setVoiceNumeric(activity, true)
+            } else {
+                SettingConfig.setVoiceNumeric(activity, false)
+            }
+        }
+
+        //播报次数加减
+        call_number_decrease_tv.setOnClickListener(this)
+        call_number_add_tv.setOnClickListener(this)
+        call_number_seekb.setOnSeekBarChangeListener(this)
+        //主机白天夜晚亮度设置
+        main_engine_daytime_brightness_seekb.setOnSeekBarChangeListener(this)
+        host_night_brightness_tv_seekb.setOnSeekBarChangeListener(this)
+        //主机白天晚上声音设置
+        host_daytime_volume_seekb.setOnSeekBarChangeListener(this)
+        host_night_volume_seekb.setOnSeekBarChangeListener(this)
+        //主机录入音量设置
+        hands_free_input_volume_of_host_machine_seekb.setOnSeekBarChangeListener(this)
+        host_handle_input_volume_seekb.setOnSeekBarChangeListener(this)
+        //主机播放音量设置
+        host_hands_free_play_volume_seekb.setOnSeekBarChangeListener(this)
+        host_gamepad_play_volume_seekb.setOnSeekBarChangeListener(this)
+        //通话模式
+        talk_mode_radiogrp.setOnCheckedChangeListener { radioGroup, i ->
+            if(i == R.id.single_pass_mode_radiobt){//单工模式
+                SettingConfig.setTalkMode(this.activity,SettingConfig.single_pass_mode)
+
+            }else if(i == R.id.two_way_mode_radiobt){//双工模式
+                SettingConfig.setTalkMode(this.activity, SettingConfig.two_way_mode)
+            }
+
+        }
+
+        //分机亮度设置
+        extension_daytime_brightness_seekb.setOnSeekBarChangeListener(this)
+        extension_night_brightness_seekb.setOnSeekBarChangeListener(this)
+        //分机LED亮度设置
+        extension_daytime_led_brightness_seekb.setOnSeekBarChangeListener(this)
+        extension_night_led_brightness_seekb.setOnSeekBarChangeListener(this)
+        //分机系统声音设置
+        extension_daytime_system_volume_seekb.setOnSeekBarChangeListener(this)
+        extension_night_system_volume_seekb.setOnSeekBarChangeListener(this)
+        //分机手柄录入音量
+        the_extension_handle_records_the_volume_seekb.setOnSeekBarChangeListener(this)
+        //分机通话音量
+        extension_call_volume_seekb.setOnSeekBarChangeListener(this)
+        //传统转换盒系统音量
+        change_box_system_volume_seekb.setOnSeekBarChangeListener(this)
+        //门口机晚上亮度音量
+        door_machine_daytime_brightness_seekb.setOnSeekBarChangeListener(this)
+        door_machine_night_brightness_seekb.setOnSeekBarChangeListener(this)
+        //门口机晚上亮度音量
+        door_phone_volume_seekb.setOnSeekBarChangeListener(this)
+    }
+
+    override fun onClick(p0: View) {
+        when (p0.id) {
+            R.id.call_number_decrease_tv -> {
+                call_number_seekb.setProgress(call_number_seekb.progress - 1)
+                partSettingDO.dayRingTimes = call_number_seekb.progress
+                partSettingDO.nightRingTimes = call_number_seekb.progress
+                SettingConfig.setCallNumber(this.activity, partSettingDO.dayRingTimes)
+            }
+            R.id.call_number_add_tv -> {
+                call_number_seekb.setProgress(call_number_seekb.progress + 1)
+                partSettingDO.dayRingTimes = call_number_seekb.progress
+                partSettingDO.nightRingTimes = call_number_seekb.progress
+                SettingConfig.setCallNumber(this.activity, partSettingDO.dayRingTimes)
+            }
+            R.id.save_settings_tv -> {
+                uploadingData(partSettingDO)
+            }
+            R.id.system_settings_tv -> {
+                PasswordDialogHelper.showPasswordDialog(activity) {
+                    val intent = Intent(Settings.ACTION_SETTINGS)
+                    startActivity(intent)
+                }
+            }
+            R.id.language_settings_tv -> {
+                LanguageSetDialogHelper.showDialog(activity)
+            }
+            R.id.sip_test -> {
+                PasswordDialogHelper.showPasswordDialog(activity) {
+//                    val intent = Intent()
+//                    intent.setClass(activity, SipTestActivity::class.java)
+//                    startActivity(intent)
+                }
+            }
+        }
+    }
+
+
+    /**
+     * 滑动过程调用
+     */
+    override fun onProgressChanged(p0: SeekBar, p1: Int, p2: Boolean) {
+        when (p0.id) {
+            R.id.call_number_seekb -> { //播报次数
+                call_number_tv.text = p1.toString()
+            }
+            R.id.main_engine_daytime_brightness_seekb -> {//主机白天亮度
+                main_engine_daytime_brightness_tv.text = p1.toString()
+                ScreenManagerUtil().setScreenBrightness(this.activity, Math.ceil(2.54 * p1).toInt())
+            }
+            R.id.host_night_brightness_tv_seekb -> {//主机夜晚亮度
+                host_night_brightness_tv.text = p1.toString()
+                ScreenManagerUtil().setScreenBrightness(this.activity, Math.ceil(2.54 * p1).toInt())
+            }
+            R.id.host_daytime_volume_seekb -> { //主机白天系统音量
+                host_daytime_volume_tv.text = p1.toString()
+                setTheSystemVolume(p1)
+            }
+            R.id.host_night_volume_seekb -> { //主机夜晚系统音量
+                host_night_volume_tv.text = p1.toString()
+                setTheSystemVolume(p1)
+            }
+            R.id.hands_free_input_volume_of_host_machine_seekb -> { //主机免提录入音量
+                hands_free_input_volume_of_host_machine_tv.text = p1.toString()
+                //todo 这里需要配合语音通话 视屏通话通讯使用
+            }
+            R.id.host_handle_input_volume_seekb -> { //主机手柄录入音量
+                host_handle_input_volume_tv.text = p1.toString()
+                //todo 这里需要配合语音通话 视屏通话通讯使用
+            }
+            R.id.host_hands_free_play_volume_seekb -> { //主机免提播放音量
+                host_hands_free_play_volume_tv.text = p1.toString()
+                //todo 这里需要配合语音通话 视屏通话通讯使用
+            }
+            R.id.host_gamepad_play_volume_seekb -> { //主机手柄播放音量
+                host_gamepad_play_volume_tv.text = p1.toString()
+                //todo 这里需要配合语音通话 视屏通话通讯使用
+            }
+            R.id.extension_daytime_brightness_seekb -> { //分机白天亮度设置
+                extension_daytime_brightness_tv.text = p1.toString()
+            }
+            R.id.extension_night_brightness_seekb -> { //分机晚上亮度设置
+                extension_night_brightness_tv.text = p1.toString()
+            }
+            R.id.extension_daytime_led_brightness_seekb -> { //分机LED白天亮度设置
+                extension_daytime_led_brightness_tv.text = p1.toString()
+            }
+            R.id.extension_night_led_brightness_seekb -> { //分机LED晚上亮度设置
+                extension_night_led_brightness_tv.text = p1.toString()
+            }
+            R.id.extension_daytime_system_volume_seekb -> { //分机白天系统音量
+                extension_daytime_system_volume_tv.text = p1.toString()
+            }
+            R.id.extension_night_system_volume_seekb -> { //分机晚上系统音量
+                extension_night_system_volume_tv.text = p1.toString()
+            }
+            R.id.the_extension_handle_records_the_volume_seekb -> { //分机手柄录入音量
+                the_extension_handle_records_the_volume_tv.text = p1.toString()
+            }
+            R.id.extension_call_volume_seekb -> { //分机通话音量
+                extension_call_volume_tv.text = p1.toString()
+            }
+            R.id.change_box_system_volume_seekb -> { //传统转换盒系统音量
+                change_box_system_volume_tv.text = p1.toString()
+            }
+            R.id.door_machine_daytime_brightness_seekb -> { //门口机白天亮度
+                door_machine_daytime_brightness_tv.text = p1.toString()
+            }
+            R.id.door_machine_night_brightness_seekb -> { //门口机晚上亮度
+                door_machine_night_brightness_tv.text = p1.toString()
+            }
+            R.id.door_phone_volume_seekb -> { //门口机通话音量
+                door_phone_volume_tv.text = p1.toString()
+            }
+
+        }
+    }
+
+    /**
+     * 滑动开始调用
+     */
+    override fun onStartTrackingTouch(p0: SeekBar) {
+
+    }
+
+    /**
+     * 滑动停止调用
+     */
+    override fun onStopTrackingTouch(p0: SeekBar) {
+        //todo 保存到本地并上传到服务器
+        when (p0.id) {
+            R.id.call_number_seekb -> { //播报次数
+                SettingConfig.setCallNumber(this.activity,p0.progress)
+                partSettingDO.dayRingTimes = p0.progress
+                partSettingDO.nightRingTimes = p0.progress
+            }
+            R.id.main_engine_daytime_brightness_seekb -> { //主机白天亮度
+                SettingConfig.setMainEngineDaytimeBrightness(this.activity,p0.progress)
+                partSettingDO.dayLight = p0.progress
+            }
+            R.id.host_night_brightness_tv_seekb -> { //主机夜晚亮度
+                SettingConfig.setHostNightBrightness(this.activity,p0.progress)
+                partSettingDO.nightLight = p0.progress
+            }
+            R.id.host_daytime_volume_seekb -> { //主机白天系统音量
+                SettingConfig.setHostDaytimeVolume(this.activity,p0.progress)
+                //partSettingDO.dayVol = p0.progress
+                partSettingDO.dayRingVol = p0.progress
+            }
+            R.id.host_night_volume_seekb -> { //主机夜晚系统音量
+                SettingConfig.setHostNightVolume(this.activity,p0.progress)
+                //partSettingDO.nightVol = p0.progress
+                partSettingDO.nightRingVol = p0.progress
+            }
+
+            R.id.hands_free_input_volume_of_host_machine_seekb -> { //主机免提录入音量
+                SettingConfig.setHandsFreeInputVolumeOfHostMachine(this.activity,p0.progress)
+            }
+            R.id.host_handle_input_volume_seekb -> { //主机手柄录入音量
+                SettingConfig.setHostHandleInputVolume(this.activity,p0.progress)
+            }
+            R.id.host_hands_free_play_volume_seekb -> { //主机免提播放音量
+                SettingConfig.setHostHandsFreePlayVolume(this.activity,p0.progress)
+            }
+            R.id.host_gamepad_play_volume_seekb -> { //主机手柄播放音量
+                SettingConfig.setHostGamepadPlayVolume(this.activity,p0.progress)
+            }
+            R.id.extension_daytime_brightness_seekb -> { //分机白天亮度设置
+                SettingConfig.setExtensionDaytimeBrightness(this.activity,p0.progress)
+            }
+            R.id.extension_night_brightness_seekb -> { //分机晚上亮度设置
+                SettingConfig.setExtensionNightBrightness(this.activity,p0.progress)
+            }
+            R.id.extension_daytime_led_brightness_seekb -> { //分机LED白天亮度设置
+                SettingConfig.setExtensionDaytimeLEDBrightness(this.activity,p0.progress)
+                partSettingDO.dayNurseLed = p0.progress
+            }
+            R.id.extension_night_led_brightness_seekb -> { //分机LED晚上亮度设置
+                SettingConfig.setExtensionNightLEDBrightness(this.activity,p0.progress)
+                partSettingDO.nightNurseLed = p0.progress
+            }
+            R.id.extension_daytime_system_volume_seekb -> { //分机白天系统音量
+                SettingConfig.setExtensionDaytimeSystemVolume(this.activity,p0.progress)
+                partSettingDO.dayBedVol = p0.progress
+            }
+            R.id.extension_night_system_volume_seekb -> { //分机晚上系统音量
+                SettingConfig.setExtensionNightSystemVolume(this.activity,p0.progress)
+                partSettingDO.nightBedVol = p0.progress
+            }
+            R.id.the_extension_handle_records_the_volume_seekb -> { //分机手柄录入音量
+                SettingConfig.setTheExtensionHandleRecordsTheVolume(this.activity,p0.progress)
+            }
+            R.id.extension_call_volume_seekb -> { //分机通话音量
+                SettingConfig.setExtensionCallVolume(this.activity,p0.progress)
+            }
+            R.id.change_box_system_volume_seekb -> { //传统转换盒系统音量
+                SettingConfig.setChangeBoxSystemVolume(this.activity,p0.progress)
+                partSettingDO.dayTransferBoxSystemVol = p0.progress
+                partSettingDO.dayTransferBoxVol = p0.progress
+                partSettingDO.nightTransferBoxSystemVol = p0.progress
+                partSettingDO.nightTransferBoxVol = p0.progress
+            }
+            R.id.door_machine_daytime_brightness_seekb -> { //门口机白天亮度
+                SettingConfig.setDoorMachineDaytimeBrightness(this.activity,p0.progress)
+            }
+            R.id.door_machine_night_brightness_seekb -> { //门口机晚上亮度
+                SettingConfig.setDoorMachineNightBrightness(this.activity,p0.progress)
+            }
+            R.id.door_phone_volume_seekb -> { //门口机通话音量
+                SettingConfig.setDoorPhoneVolume(this.activity,p0.progress)
+                partSettingDO.dayDoorVol = p0.progress
+                partSettingDO.nightDoorVol = p0.progress
+            }
+        }
+    }
+
+    /**
+     * 设置系统音量
+     */
+    fun setTheSystemVolume(value:Int){
+        //todo 这里需要优化 滑动的时候会调起很多个打开权限的界面
+        if (value <= 15) {
+            val nm = this.activity.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !nm.isNotificationPolicyAccessGranted) {
+//                showAlterDialog()
+
+                val intent = Intent(Settings.ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS)
+                startActivity(intent)
+
+            } else {
+                VoiceManagerUtil.setSystemVoice(this.activity, value)
+                VoiceManagerUtil.setMusicVoice(this.activity, value)
+            }
+        } else {
+            VoiceManagerUtil.setSystemVoice(this.activity, value)
+            VoiceManagerUtil.setMusicVoice(this.activity, value)
+        }
+
+    }
+
+   fun uploadingData(partSettingDO:PartSettingDO){
+//       createTime: Int, updateTime: Int, partId: Int, dayStart: String, dayLight: Int,
+//       dayVol: Int, dayRingVol: Int, dayRingTimes: Int, dayNurseLed: Int, dayDoorVol: Int,
+//       dayBedVol: Int, dayTransferBoxVol: Int, dayTransferBoxSystemVol: Int, nightStart: String,
+//       nightLight: Int, nightVol: Int, nightRingVol: Int, nightRingTimes: Int, nightNurseLed: Int,
+//       nightDoorVol: Int, nightBedVol: Int, nightTransferBoxVol: Int, nightTransferBoxSystemVol: Int,
+//       sleepSecondsNurse: Int, sleepSecondsDoor: Int, sleepSecondsBed: Int, sipOvertime: Int) {
+       if(SettingConfiguration.getInstance().id != null) {
+           partSettingDO.updateTime = System.currentTimeMillis()/1000
+           presenter.setSettingData(
+               partSettingDO.id,
+               partSettingDO.unionId,
+               partSettingDO.createTime.toInt(),
+               partSettingDO.updateTime.toInt(),
+               partSettingDO.partId,
+               partSettingDO.dayStart,
+               partSettingDO.dayLight,
+               partSettingDO.dayVol,
+               partSettingDO.dayRingVol,
+               partSettingDO.dayRingTimes,
+               partSettingDO.dayNurseLed,
+               partSettingDO.dayDoorVol,
+               partSettingDO.dayBedVol,
+               partSettingDO.dayTransferBoxVol,
+               partSettingDO.dayTransferBoxSystemVol,
+               partSettingDO.nightStart,
+               partSettingDO.nightLight,
+               partSettingDO.nightVol,
+               partSettingDO.nightRingVol,
+               partSettingDO.nightRingTimes,
+               partSettingDO.nightNurseLed,
+               partSettingDO.nightDoorVol,
+               partSettingDO.nightBedVol,
+               partSettingDO.nightTransferBoxVol,
+               partSettingDO.nightTransferBoxSystemVol,
+               partSettingDO.sleepSecondsNurse,
+               partSettingDO.sleepSecondsDoor,
+               partSettingDO.sleepSecondsBed,
+               partSettingDO.sipOvertime,
+               partSettingDO.transferDuration,
+               partSettingDO.transferDurationLeader
+           )
+       } else {
+           showMessage(R.string.settings_failed)
+       }
+
+   }
+
+    /**
+     *面销毁回调
+     */
+    override fun destory() {
+    }
+
+    override fun showData(data: PartSettingDO) {
+        showMessage(R.string.settings_success)
+        (activity as NurseHomeActivity).showHome()
+    }
+
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+    }
+}

+ 202 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/TestFragment.kt

@@ -0,0 +1,202 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.hardware.Camera
+import android.view.SurfaceHolder
+import android.view.View
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.TestFragmentLayBinding
+import com.wdkl.ncs.android.component.nursehome.helper.RecordHelper
+import com.wdkl.ncs.android.component.nursehome.helper.SoundPoolManager
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.component.nursehome.util.MediaPlayHelper
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.SystemSettingsContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.SystemSettingsPresenter
+import com.wdkl.ncs.android.middleware.model.dos.PartSettingDO
+import kotlinx.android.synthetic.main.test_fragment_lay.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+class TestFragment : BaseFragment<SystemSettingsPresenter, TestFragmentLayBinding>(), SystemSettingsContract.View {
+    val TAG = "TestFragment"
+
+    var info = ""
+    var buttonTest = false
+    var testButton1 = false
+    var testButton2 = false
+    var testButton3 = false
+
+    private var mCamera: Camera? = null
+
+    override fun getLayId(): Int {
+        return R.layout.test_fragment_lay
+    }
+
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    override fun init() {
+        SoundPoolManager.getInstance().playSound(4, 1.0f, 1.0f, 0)
+
+        startCameraPreview()
+    }
+
+    override fun bindEvent() {
+        test_finish.setOnClickListener {
+            activity.finish()
+        }
+    }
+
+    private fun startTest() {
+        Thread {
+            info += "\r\n--> 麦克风测试:\r\n"
+            showInfo(info)
+            SoundPoolManager.getInstance().playSound(3, 1.0f, 1.0f, 0)
+            Thread.sleep(2000)
+            info += "开始录音...\r\n"
+            showInfo(info)
+            RecordHelper.getInstance().recordTestStart()
+            Thread.sleep(2500)
+            RecordHelper.getInstance().recordTestStop()
+            Thread.sleep(500)
+            info += "播放录音...\r\n"
+            showInfo(info)
+            MediaPlayHelper.getInstance().playUrlMusic(RecordHelper.getInstance().audiofilePath, 1.0f, false)
+
+            Thread.sleep(3000)
+            RecordHelper.getInstance().deleteAudioFile()
+
+            info += "===测试结束!===\r\n"
+            showInfo(info)
+
+            Thread.sleep(1000)
+            activity.runOnUiThread {
+                if (test_finish != null) {
+                    test_finish.visibility = View.VISIBLE
+                }
+            }
+        }.start()
+    }
+
+    private fun showInfo(text: String) {
+        activity.runOnUiThread {
+            if (tv_test_info != null) {
+                tv_test_info.text = text
+            }
+        }
+    }
+
+    private fun startCameraPreview() {
+        val num = Camera.getNumberOfCameras()
+        if (num > 0) {
+            try {
+                mCamera = Camera.open()
+            } catch (e: Exception) {
+                tv_camera.visibility = View.VISIBLE
+                tv_camera.text = "摄像头打开失败"
+                e.printStackTrace()
+                return
+            }
+
+            camera_preview_surface.getHolder().addCallback(object : SurfaceHolder.Callback {
+                override fun surfaceCreated(holder: SurfaceHolder) {
+                    /**
+                     * The SurfaceHolder must already contain a surface when this method is called.
+                     * If you are using SurfaceView, you will need to register a SurfaceHolder.Callback
+                     * with SurfaceHolder#addCallback(SurfaceHolder.Callback) and wait for
+                     * SurfaceHolder.Callback#surfaceCreated(SurfaceHolder) before
+                     * calling setPreviewDisplay() or starting preview.
+                     * 相机的预览必须在surfaceCreated后调用,否则黑屏且没有任何提示哦
+                     */
+
+                    try {
+                        mCamera!!.setPreviewDisplay(camera_preview_surface.getHolder())
+                        mCamera!!.startPreview()
+                    } catch (e: Exception) {
+                        e.printStackTrace()
+                    }
+                }
+
+                override fun surfaceChanged(
+                    holder: SurfaceHolder,
+                    format: Int,
+                    width: Int,
+                    height: Int
+                ) {
+                    //
+                }
+
+                override fun surfaceDestroyed(holder: SurfaceHolder) {
+                    //
+                }
+            })
+        } else {
+            tv_camera.visibility = View.VISIBLE
+            tv_camera.text = "没有摄像头"
+        }
+    }
+
+    override fun destory() {
+        if (mCamera != null) {
+            mCamera!!.stopPreview()
+            mCamera!!.release()
+            mCamera = null
+        }
+    }
+
+    override fun showData(data: PartSettingDO) {
+        //
+    }
+
+    override fun onError(message: String, type: Int) {
+        //
+    }
+
+    override fun complete(message: String, type: Int) {
+    }
+
+    override fun start() {
+    }
+
+    override fun networkMonitor(state: NetState) {
+        state.filter(onWifi = {
+
+        },onMobile = {
+
+        },offline = {
+
+        })
+    }
+
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+        if (Constant.EVENT_SERIAL_TEST == messageEvent.getType()) {
+            if (!buttonTest) {
+                val message = messageEvent.getMessage() as String
+                if (message == "call1" && !testButton1) {
+                    info += " ##面板呼叫键## "
+                    testButton1 = true
+                } else if (message == "hook_on" && !testButton2) {
+                    info += " ##手柄放下## "
+                    testButton2 = true
+                } else if (message == "hook_off" && !testButton3) {
+                    info += " ##手柄拿起## "
+                    testButton3 = true
+                }
+
+                showInfo(info)
+
+                if (testButton1 && testButton2 && testButton3) {
+                    buttonTest = true
+                    startTest()
+                }
+            }
+        }
+    }
+}

+ 85 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/TrustManagementFragment.kt

@@ -0,0 +1,85 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import com.enation.javashop.net.engine.model.NetState
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentTrustManagementBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.TrustManagementContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.TrustManagementPresenter
+import com.wdkl.ncs.android.middleware.model.dos.DeviceDO
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/**
+ * 托管Fragment
+ */
+class TrustManagementFragment:BaseFragment<TrustManagementPresenter,FragmentTrustManagementBinding>(),TrustManagementContract.View {
+    var TAG = TrustManagementFragment::class.java.getSimpleName()
+
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_trust_management
+    }
+    /**
+     *初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+    /**
+     *初始化操作
+     */
+    override fun init() {
+    }
+    /**
+     *绑定事件
+     */
+    override fun bindEvent() {
+    }
+    /**
+     *页面销毁回调
+     */
+    override fun destory() {
+    }
+    /**
+     *显示数据
+     */
+    override fun showData(devices: ArrayList<DeviceDO>) {
+
+    }
+    /**
+     *处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+    /**
+     *耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+    /**
+     *耗时加载开始
+     */
+    override fun start() {
+    }
+    /**
+     *处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//        var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+    }
+}

+ 173 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/fragment/VisitManagementFragment.kt

@@ -0,0 +1,173 @@
+package com.wdkl.ncs.android.component.nursehome.fragment
+
+import android.util.Log
+import com.alibaba.android.vlayout.DelegateAdapter
+import com.alibaba.android.vlayout.VirtualLayoutManager
+import com.enation.javashop.net.engine.model.NetState
+import com.scwang.smartrefresh.layout.footer.ClassicsFooter
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.component.nursehome.adapter.VisitManagementAdapter
+import com.wdkl.ncs.android.component.nursehome.databinding.FragmentVisitManagementBinding
+import com.wdkl.ncs.android.component.nursehome.launch.NurseHomeLaunch
+import com.wdkl.ncs.android.lib.base.BaseFragment
+import com.wdkl.ncs.android.lib.vo.filter
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import com.wdkl.ncs.android.middleware.logic.contract.nursehome.VisitManagementContract
+import com.wdkl.ncs.android.middleware.logic.presenter.nursehome.VisitManagementPresenter
+import com.wdkl.ncs.android.middleware.tcp.dto.TcpModel
+
+import kotlinx.android.synthetic.main.fragment_visit_management.*
+import org.greenrobot.eventbus.Subscribe
+import org.greenrobot.eventbus.ThreadMode
+
+/***
+ * 探视管理Fragment
+ */
+class VisitManagementFragment: BaseFragment<VisitManagementPresenter,FragmentVisitManagementBinding>(),VisitManagementContract.View {
+    var TAG = VisitManagementFragment::class.java.getSimpleName()
+
+
+    private lateinit var virtualLayoutManager: VirtualLayoutManager
+    private lateinit var delegateAdapter: DelegateAdapter
+    //护士适配器
+    var visitManagementAdapter: VisitManagementAdapter? = null
+    
+    
+    /**
+     * 提供layoutID
+     */
+    override fun getLayId(): Int {
+        return R.layout.fragment_visit_management
+    }
+
+    /**
+     * 初始化依赖注入
+     */
+    override fun bindDagger() {
+        NurseHomeLaunch.component.inject(this)
+    }
+
+    /**
+     * 初始化操作
+     */
+    override fun init() {
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+
+        visitManagementAdapter = VisitManagementAdapter(ArrayList())
+        delegateAdapter.addAdapter(visitManagementAdapter)
+        mViewDataBinding.visitTheHostRefresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        visit_the_host_recyv.layoutManager = virtualLayoutManager
+        visit_the_host_recyv.adapter = delegateAdapter
+
+
+        //临时模拟测试数据
+        var visit_the_hostList = ArrayList<String>()
+        visit_the_hostList.add("探视分机1")
+        visit_the_hostList.add("探视分机2")
+        visit_the_hostList.add("探视分机3")
+        visit_the_hostList.add("探视分机4")
+        visit_the_hostList.add("探视分机5")
+        visit_the_hostList.add("探视分机6")
+        visit_the_hostList.add("探视分机7")
+        visit_the_hostList.add("探视分机8")
+        visit_the_hostList.add("探视分机9")
+        visit_the_hostList.add("探视分机10")
+        visit_the_hostList.add("探视分机11")
+
+        visitManagementAdapter!!.data.clear()
+        visitManagementAdapter!!.data.addAll(visit_the_hostList)
+        Log.i(TAG,"探视主机数量 " + visit_the_hostList.size)
+        visitManagementAdapter!!.notifyDataSetChanged()
+
+
+
+        /**初始化LayoutMannager*/
+        virtualLayoutManager = VirtualLayoutManager(this.activity)
+        /**初始化适配器*/
+        delegateAdapter = DelegateAdapter(virtualLayoutManager)
+        visitManagementAdapter = VisitManagementAdapter(ArrayList())
+        delegateAdapter.addAdapter(visitManagementAdapter)
+        mViewDataBinding.visualExtensionRefresh.setRefreshFooter(ClassicsFooter(activity))
+
+        /**配置到RecycleView*/
+        visual_extension_recyv.layoutManager = virtualLayoutManager
+        visual_extension_recyv.adapter = delegateAdapter
+        //临时模拟测试数据
+        var visualExtensionList = ArrayList<String>()
+        visualExtensionList.add("可视分机1")
+        visualExtensionList.add("可视分机2")
+        visualExtensionList.add("可视分机3")
+        visualExtensionList.add("可视分机4")
+        visualExtensionList.add("可视分机5")
+        visualExtensionList.add("可视分机6")
+        visualExtensionList.add("可视分机7")
+        visualExtensionList.add("可视分机8")
+        visualExtensionList.add("可视分机9")
+        visualExtensionList.add("可视分机10")
+        visualExtensionList.add("可视分机11")
+
+        visitManagementAdapter!!.data.clear()
+        visitManagementAdapter!!.data.addAll(visualExtensionList)
+        Log.i(TAG,"可视分机数量 " + visualExtensionList.size)
+        visitManagementAdapter!!.notifyDataSetChanged()
+        
+        
+    }
+
+    /**
+     * 绑定事件
+     */
+    override fun bindEvent() {
+    }
+
+    /**
+     * 页面销毁回调
+     */
+    override fun destory() {
+    }
+
+    /**
+     * 显示数据
+     */
+    override fun showData() {
+    }
+
+    /**
+     * 处理错误信息
+     */
+    override fun onError(message: String, type: Int) {
+    }
+
+    /**
+     * 耗时加载完成
+     */
+    override fun complete(message: String, type: Int) {
+    }
+
+    /**
+     * 耗时加载开始
+     */
+    override fun start() {
+    }
+
+    /**
+     * 处理网络状态
+     */
+    override fun networkMonitor(state: NetState) {
+    }
+
+    @Subscribe(threadMode = ThreadMode.MAIN)
+    fun onMoonEvent(messageEvent: MessageEvent) {
+//        Log.e(TAG,"收到tcp消息")
+//        var messageEvent = messageEvent.getMessage() as TcpModel
+//        if(messageEvent.getAction() === TcpAction.EventAction.KEY_CLICK){
+//
+//            Log.e(TAG,"收到tcp消息"+messageEvent.toJson())
+//        }
+    }
+}

+ 58 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/HardTools.java

@@ -0,0 +1,58 @@
+package com.wdkl.ncs.android.component.nursehome.hardware;
+
+
+import android.app.Application;
+import android.content.Context;
+
+import com.wdkl.ncs.android.component.nursehome.activity.AppUpdateActivity;
+
+
+public  class HardTools {
+
+    public HardTools() {
+
+    }
+    //初始化
+    public void init(){}
+    //退出
+    public void unInit(){}
+    //是否卸载旧版本
+    public void uninstallApp(Context context , boolean isuninstall, String name){}
+    //串口设置
+//    public void setSerial(CallingbedActivity callingbedActivity){}
+    //检查launch版本
+    public void checkLaunch(){}
+    //紧急按钮Start
+    public void setSOSStart(){}
+    //紧急按钮Stop
+    public void setSOSStop(){}
+    //门灯颜色
+    public void setDoorLight(int type){}
+    //重置设备
+    public void resetDevice(){}
+    //重置设备 XCrashUtils
+    public void resetDevicex(Application application){}
+    //注册方式
+    public void Registration(Context context ){}
+    //安装方式1
+    public void installApk(AppUpdateActivity context ){}
+    //安装方式2
+    public void startInstallApk(AppUpdateActivity context ){}
+
+
+    //提供卡号
+    public  void offerCardData(String data){}
+    //提供按键数据
+    public void offerKeyBoardData(String data){}
+    //是否开启灯光
+    public  void enableLed(boolean isEnable){}
+    public  void enableIRLed(boolean isEnable){}
+    public  void enableControlLed(boolean isEnable,int id){}
+    //麦克风
+    //
+
+    public void enalbeNet(boolean isEnable){}
+    //设置voip 初始化配置
+    public void setVoipConfig(){}
+
+}

+ 27 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/HardWareFactroy.java

@@ -0,0 +1,27 @@
+package com.wdkl.ncs.android.component.nursehome.hardware;
+
+
+import com.wdkl.ncs.android.component.nursehome.BuildConfig;
+import com.wdkl.ncs.android.component.nursehome.hardware.imp.Z3128HardTools;
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+/**
+ * 硬件设备控制适配类
+ *
+ * **/
+public  class HardWareFactroy {
+    //不同硬件设备控制类替换即可
+    private static HardTools hardTools;
+    public static HardTools getHardTools() {
+        if(null == hardTools) {
+            if( BuildConfig.flag.equals(Constant.DEV_Z_RK3128))
+                hardTools = Z3128HardTools.getInstance();
+            else if(BuildConfig.flag.equals(Constant.DEV_W_DCH)){
+//                hardTools = WdchHardTools.getInstance();
+            }
+        }
+        return hardTools ;
+    }
+
+
+}

+ 158 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/hardware/imp/Z3128HardTools.java

@@ -0,0 +1,158 @@
+package com.wdkl.ncs.android.component.nursehome.hardware.imp;
+
+import android.app.Application;
+import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+import android.util.Log;
+
+
+import com.wdkl.ncs.android.component.nursehome.activity.AppUpdateActivity;
+import com.wdkl.ncs.android.component.nursehome.hardware.HardTools;
+
+import com.wdkl.ncs.android.component.nursehome.util.AppUpdateHelper;
+import com.wdkl.ncs.android.component.nursehome.util.NetHelper;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.utils.AppUtil;
+
+import java.util.List;
+
+import serialporttest.utils.SerialPortUtil;
+import serialporttest.utils.SerialPortUtil433;
+
+import static com.google.common.collect.ComparisonChain.start;
+
+/**
+ * Z-3128硬件控制类
+ *
+ * */
+public class Z3128HardTools extends HardTools {
+
+    public static final String HARDWDT_SERVICE = "Z3128HardTools";
+    private Application app;
+
+
+    private static class Z3128HardToolsHolder{
+        private final  static Z3128HardTools z3128HardTools = new Z3128HardTools();
+    }
+
+    public static Z3128HardTools getInstance(){
+        return Z3128HardToolsHolder.z3128HardTools;
+    }
+
+    @Override
+    public void init() {
+        SerialPortUtil.getInstance().openSerialPort();
+        //开启串口心跳 //区分大朝华和
+
+        SerialPortUtil.getInstance().startHeartBeat();
+
+    }
+
+    @Override
+    public void unInit() {
+        SerialPortUtil.getInstance().closeHeart();
+        SerialPortUtil.getInstance().closeSerialPort();
+    }
+
+    @Override
+    public void resetDevice() {
+//        SerialPortHelper.resetDevice();
+    }
+    @Override
+    public void resetDevicex(Application application) {
+        AppUpdateHelper.reboot(application);
+    }
+    @Override
+    public void Registration(Context context) {
+        //获取mac地址
+        Constant.LOCAL_MAC = NetHelper.getInstance().getMacAddress();
+        Constant.DEVICE_REGISTER_ID = Constant.LOCAL_MAC;
+    }
+
+//    @Override
+//    public void setSerial(CallingbedActivity callingbedActivity) {
+//        try {
+//            //串口监听
+////            setSerialListener()
+//            Thread.sleep(2000); // 延时1500毫秒 (1.5秒)
+//            SerialPortHelper.setSosLight("0");
+//            SerialPortHelper.setHandsMIC(true);
+//            SerialPortHelper.setCallStatus("0");
+//
+//            //默认门灯白色
+//            SerialPortHelper.setDoorLight(1, "111");
+//
+//
+//
+//        } catch (InterruptedException e) {
+//            e.printStackTrace();
+//        }
+//    }
+
+    @Override
+    public void uninstallApp(Context context, boolean isuninstall, String name) {
+        //卸载原来二代系统apk
+        if (isuninstall) {
+            Thread thread = new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    // 在子线程中执行的代码
+                    if (checkAppExist(context,name)) {
+                        AppUtil.uninstallApp(name);
+                    }
+                }
+            });
+        }
+    }
+
+    @Override
+    public void setSOSStart() {
+//        SOSHelper.sosStart();
+    }
+
+    @Override
+    public void setSOSStop() {
+//        SOSHelper.sosStop();
+    }
+    @Override
+    public void setDoorLight(int type) {
+//        if (type==1){
+//            //绿色
+//            SerialPortHelper.setDoorLight(1, Constant.nursingColor);
+//        }else if (type==2){
+//            //白色
+//            SerialPortHelper.setDoorLight(1, "111"); //白色
+//        }else if (type==3){
+//            //红色
+//            SerialPortHelper.setDoorLight(1, "200"); //红色闪烁
+//        }else if (type==4){
+//            //红色
+//            SerialPortHelper.setDoorLight(0, "000"); //关闭
+//        }
+    }
+
+    @Override
+    public void installApk(AppUpdateActivity context) {
+    }
+
+    @Override
+    public void startInstallApk(AppUpdateActivity context) {
+
+    }
+
+    private boolean checkAppExist(Context context, String name) {
+        PackageManager packageManager = context.getPackageManager();
+        List<PackageInfo> packageInfoList = packageManager.getInstalledPackages(0);
+        boolean appExist = false;
+        for (PackageInfo pInfo : packageInfoList) {
+            if (name.equals(pInfo.packageName)) {
+                appExist = true;
+                break;
+            }
+        }
+        Log.e("wdkl_app", "callingdoor app exist: " + appExist);
+        return appExist;
+    }
+}

+ 126 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/helper/RecordHelper.java

@@ -0,0 +1,126 @@
+package com.wdkl.ncs.android.component.nursehome.helper;
+
+import android.media.MediaRecorder;
+import android.os.Environment;
+import android.util.Log;
+
+import java.io.File;
+import java.io.IOException;
+
+public class RecordHelper {
+    private static final String VOICE_MSG_FILE_PATH = Environment.getExternalStorageDirectory().getPath() + "/VoiceMsg";
+    private String audiofilePath;
+    private MediaRecorder mediaRecorder;
+    private static RecordHelper sInstance = null;
+    private boolean recording = false;
+
+    private final static Object lock = new Object();
+
+    public RecordHelper() {
+    }
+
+    public static RecordHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (RecordHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new RecordHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    public void init() {
+        //创建音频文件路径
+        File file = new File(VOICE_MSG_FILE_PATH);
+        if (!file.exists()) {
+            file.mkdir();
+        }
+    }
+
+    public void startRecord() {
+        audiofilePath = VOICE_MSG_FILE_PATH + "/" + System.currentTimeMillis() + "_voice.mp3";
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (lock) {
+                    try {
+                        mediaRecorder = new MediaRecorder();
+                        mediaRecorder.setOutputFile(audiofilePath);
+                        mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风
+                        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置MediaRecorder录制的音频格式
+                        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 设置MediaRecorder录制音频的编码为amr
+                        mediaRecorder.prepare();
+                        mediaRecorder.start();
+                        recording = true;
+                    } catch (IOException e) {
+                        Log.i("error", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+                    }
+                }
+            }
+        }).start();
+    }
+
+    public void stopRecord() {
+        synchronized (lock) {
+            try {
+                mediaRecorder.stop();
+                mediaRecorder.release();
+                mediaRecorder = null;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                recording = false;
+            }
+        }
+    }
+
+    public void recordTestStart() {
+        audiofilePath = VOICE_MSG_FILE_PATH + "/" + System.currentTimeMillis() + "_voice.mp3";
+        synchronized (lock) {
+            try {
+                mediaRecorder = new MediaRecorder();
+                mediaRecorder.setOutputFile(audiofilePath);
+                mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);// 设置MediaRecorder的音频源为麦克风
+                mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);// 设置MediaRecorder录制的音频格式
+                mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);// 设置MediaRecorder录制音频的编码为amr
+                mediaRecorder.prepare();
+                mediaRecorder.start();
+                recording = true;
+            } catch (IOException e) {
+                Log.i("error", "call startAmr(File mRecAudioFile) failed!" + e.getMessage());
+            }
+        }
+    }
+
+    public void recordTestStop() {
+        synchronized (lock) {
+            try {
+                mediaRecorder.stop();
+                mediaRecorder.release();
+                mediaRecorder = null;
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                recording = false;
+            }
+        }
+    }
+
+    public void deleteAudioFile(String path) {
+        synchronized (lock) {
+            File file = new File(path);
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+    }
+
+    public void deleteAudioFile() {
+        deleteAudioFile(audiofilePath);
+    }
+
+    public String getAudiofilePath() {
+        return audiofilePath;
+    }
+}

+ 83 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/helper/SoundPoolManager.java

@@ -0,0 +1,83 @@
+package com.wdkl.ncs.android.component.nursehome.helper;
+
+import android.media.AudioAttributes;
+import android.media.AudioManager;
+import android.media.SoundPool;
+import android.os.Build;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.util.HashMap;
+
+public class SoundPoolManager {
+
+    private static SoundPoolManager instance;
+    private SoundPool soundPool;
+    private HashMap<Integer, Integer> soundID = new HashMap<>();
+    private boolean isLoaded = false;
+    private boolean inited = false;
+
+    public static SoundPoolManager getInstance() {
+        if (instance == null) {
+            instance = new SoundPoolManager();
+        }
+        return instance;
+    }
+
+    public void init() {
+        if (inited) {
+            return;
+        }
+
+        if(Build.VERSION.SDK_INT > 21){
+            SoundPool.Builder builder = new SoundPool.Builder();
+            //传入音频数量
+            builder.setMaxStreams(4);
+            //AudioAttributes是一个封装音频各种属性的方法
+            AudioAttributes.Builder attrBuilder = new AudioAttributes.Builder();
+            //设置音频流的合适的属性
+            attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC);//STREAM_MUSIC
+            //加载一个AudioAttributes
+            builder.setAudioAttributes(attrBuilder.build());
+            soundPool = builder.build();
+        }else{
+            soundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 0);
+        }
+
+        //来电
+        soundID.put(1, soundPool.load(BaseApplication.appContext, R.raw.incoming_call, 1));
+        //去电
+        soundID.put(2, soundPool.load(BaseApplication.appContext, R.raw.outgoing_call, 1));
+        //测试
+        soundID.put(3, soundPool.load(BaseApplication.appContext, R.raw.mic_test, 1));
+        soundID.put(4, soundPool.load(BaseApplication.appContext, R.raw.test_start, 1));
+        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
+            @Override
+            public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
+                isLoaded = true;
+                inited = true;
+            }
+        });
+    }
+
+    public int playSound(int index, float leftVol, float rightVol, int loop) {
+        try {
+            if (isLoaded) {
+                return soundPool.play(soundID.get(index), leftVol, rightVol, 1, loop, 1);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return -1;
+    }
+
+    public void stopPlaySound(int streamId) {
+        soundPool.stop(streamId);
+    }
+
+    public void release() {
+        soundPool.release();
+    }
+}

+ 24 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/launch/NurseHomeLaunch.kt

@@ -0,0 +1,24 @@
+package com.wdkl.ncs.android.component.nursehome.launch
+
+import com.enation.javashop.android.jrouter.external.annotation.Router
+import com.wdkl.ncs.android.component.nursehome.di.DaggerNurseHomeComponent
+import com.wdkl.ncs.android.component.nursehome.di.NurseHomeComponent
+import com.wdkl.ncs.android.lib.base.BaseLaunch
+import com.wdkl.ncs.android.middleware.di.DaggerManager
+
+/**
+ * home模块启动类 代替Application 在壳工程Application中反射调用
+ */
+@Router(path = "/nursehome/launch")
+class NurseHomeLaunch : BaseLaunch() {
+    companion object {
+        lateinit var component: NurseHomeComponent
+    }
+
+    override fun moduleInit() {
+        component = DaggerNurseHomeComponent
+                .builder()
+                .applicationComponent(DaggerManager.APPLICATION_COMPONENT)
+                .build()
+    }
+}

+ 576 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedC2MManager.java

@@ -0,0 +1,576 @@
+package com.wdkl.ncs.android.component.nursehome.led;
+
+import android.app.Application;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.listenvision.LedC2M;
+import com.listenvision.model.VoiceModel;
+import com.wdkl.ncs.android.component.nursehome.util.LocaleMangerUtils;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimerTask;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+public class LedC2MManager extends LedManager {
+    private static final String TAG = "ledC2M";
+
+    private Application application;
+    private LedC2M ledC2M;
+    private static ArrayList<LedItem> ledList = new ArrayList<>();
+    private static List<LedProgram> programTextList = new ArrayList<>();
+    private static List<String> voiceProgramList = new ArrayList<>();
+    private static String voiceText;
+    private static String deleteVoiceText;
+    private static boolean stopVoice = false;
+
+    private static long LED_TIMEOUT = 30*60*1000L;
+
+    private final static Object lockObject = new Object();
+
+    private boolean isPowerOn = true;
+
+    @Override
+    public void init(Application application) {
+        ledC2M = new LedC2M();
+        ledC2M.init(application);
+        this.application = application;
+        File file = new File(Constant.C2M_LED_FONT_PATH);
+        if (file.exists()) {
+                Constant.ledFontExist=true;
+        } else {
+            copyFont();
+        }
+
+        initScheduledExecutor();
+    }
+
+    @Override
+    public void copyFont() {
+        super.copyFont();
+        if (ledC2M != null) {
+            ledC2M.copyFontFile(new LedC2M.LedFontCheck() {
+                @Override
+                public void onChecked(boolean check) {
+                    Constant.ledFontExist=check;
+                    //ExtendMethodsKt.showMessage("字库文件copy完成...");
+                    Log.d(TAG, "led font copy end...");
+                }
+            });
+        }
+    }
+
+    private void initScheduledExecutor() {
+        TimerTask timerTask = new TimerTask() {
+            @Override
+            public void run() {
+                synchronized (lockObject) {
+                    //每分钟查询一次点阵屏节目,超过5分钟的将自动移除
+                    Iterator<LedProgram> iterator = programTextList.iterator();
+                    long curTime = System.currentTimeMillis();
+                    boolean update = false;
+                    while (iterator.hasNext()) {
+                        if (curTime - iterator.next().getTime() > LED_TIMEOUT) {
+                            iterator.remove();
+                            update = true;
+                        }
+                    }
+
+                    if (update) {
+                        sendProgramStart();
+                    }
+                }
+            }
+        };
+        ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
+        executor.scheduleAtFixedRate(timerTask,60,90, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public void initIpList() {
+        getLedDeviceIpList();
+    }
+
+    private void getLedDeviceIpList() {
+        //
+    }
+
+    @Override
+    public void setLedIpList(ArrayList<LedItem> list) {
+        ledList.clear();
+        if (list != null && list.size() > 0) {
+            ledList.addAll(list);
+        }
+    }
+
+    @Override
+    public ArrayList<LedItem> getLedList() {
+        return ledList;
+    }
+
+    private final ExecutorService updateThreadPool = Executors.newSingleThreadExecutor();
+    private SendProgramThread programThread;
+
+    //语音节目udp
+    private void sendVoiceUdp(String ip) {
+        int server_port = 9999;
+        String text = "";
+        byte[] data;
+
+        if (stopVoice) {
+            data = VoiceModel.getStopVoiceData();
+        } else {
+            text = voiceText;
+            for (int j = 0; j < 2; j++) {
+                text = text + "," + voiceText;
+            }
+            data = VoiceModel.getVoiceData(text);
+        }
+
+        DatagramSocket s = null;
+        try {
+            s = new DatagramSocket();
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        InetAddress local = null;
+        try {
+            local = InetAddress.getByName(ip);
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+
+        if (data != null) {
+            if (Constant.OPEN_DEBUG) {
+                Log.d(TAG, "udp send voice text: " + voiceText + ", voice data hex string: " + VoiceModel.bytesToHexString(data));
+            }
+            DatagramPacket p = new DatagramPacket(data, data.length, local,
+                    server_port);
+            try {
+                s.send(p);
+                s.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    //语音节目-tcp
+    private void sendVoiceTcp(String ip) {
+        try {
+            byte[] data;
+            String text = "";
+
+            if (stopVoice) {
+                data = VoiceModel.getStopVoiceData();
+            } else {
+                text = voiceText;
+                int loop = SettingConfig.getLedVoiceTimes(BaseApplication.appContext) - 1;
+                for (int j = 0; j < loop; j++) {
+                    text = text + "," + voiceText;
+                }
+                String volume = Integer.toString(SettingConfig.getLedVoiceVolume(BaseApplication.appContext));
+                text = "[v" + volume +"]" + text;
+                data = VoiceModel.getVoiceData(text);
+            }
+
+            Socket socket = new Socket(ip, 10000);
+            OutputStream outputStream = socket.getOutputStream();
+            if (Constant.OPEN_DEBUG) {
+                Log.d(TAG, "socket connect: " + socket.isConnected());
+            }
+
+            if (socket.isConnected() && data != null) {
+                if (Constant.OPEN_DEBUG) {
+                    Log.d(TAG, "tcp send voice text: " + voiceText + ", voice data hex string: " + VoiceModel.bytesToHexString(data));
+                }
+                outputStream.write(data);
+                socket.close();
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    //文字节目
+    public class SendProgramThread implements Runnable {
+
+        @Override
+        public void run() {
+            //开始组建节目: 如果字体文件不存在则直接返回
+            if (!Constant.LED_EXIST) {
+                return;
+            }
+
+            if (ledList.size() == 0) {
+                return;
+            }
+
+            int infoType = SettingConfig.getLedInfoType(application);
+            if (programTextList.size() == 0) {
+                //默认节目
+                for (LedItem ledItem : ledList) {
+                    if (ledItem != null) {
+                        //停止语音
+                        stopVoice = true;
+                        long h = createDefaultProgram(ledItem.getResolution(), ledItem.getFontSize(), infoType, 3);
+                        if (h != 0) {
+                            int result = ledC2M.NetWorkSend(ledItem.getIp(), h);
+                            //语音节目
+                            if (ledItem.getVoiceOn()) {
+                                sendVoiceTcp(ledItem.getIp());
+                            }
+
+                            if (Constant.OPEN_DEBUG) {
+                                Log.d(TAG, "send default program to " + ledItem.getIp() + ", result: " + result);
+                            }
+                            ledC2M.DeleteProgram(h);
+                        }
+                    }
+                }
+            } else {
+                //呼叫信息节目
+                //当前正在播放的语音和将要移除的语音相同
+                if (voiceProgramList.size() > 0) {
+                    voiceText = voiceProgramList.get(0);
+                    if (voiceText.equals(deleteVoiceText)) {
+                        stopVoice = true;
+                    } else {
+                        stopVoice = false;
+                    }
+                    voiceProgramList.remove(voiceText);
+                } else {
+                    stopVoice = true;
+                }
+                Log.d(TAG, "voiceText: " + voiceText + ", deleteVoiceText: " + deleteVoiceText);
+
+                for (LedItem ledItem : ledList) {
+                    if (ledItem != null) {
+                        long h = createCallingProgram(ledItem.getResolution(), ledItem.getFontSize());
+                        if (h != 0) {
+                            int result = ledC2M.NetWorkSend(ledItem.getIp(), h);
+                            //语音节目
+                            if (ledItem.getVoiceOn()) {
+                                sendVoiceTcp(ledItem.getIp());
+                            }
+
+                            if (Constant.OPEN_DEBUG) {
+                                Log.d(TAG, "send calling program to " + ledItem.getIp() + ", result: " + result);
+                            }
+                            ledC2M.DeleteProgram(h);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    private long createDefaultProgram(String ledResolution, int fontSize, int type, int savaType) {
+        long hProgram = 0;
+        String language = LocaleMangerUtils.getApplicationLocale().getLanguage();
+        if (type == 0) {
+            //仅显示时间
+            if (LedItem.TYPE_64_16.equals(ledResolution)) {
+                //64x16
+                hProgram = ledC2M.CreateProgram(64, 16, 1,1,savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 64, 16, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            0, 0, 0, 0, 1, 1, 0,
+                            0, 0xff, 0, 0xff, 2, 0xff, 1);
+                } else {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 64, 16, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            0, 0, 0, 0, 1, 1, 0,
+                            4, 0xff, 0, 0xff, 2, 0xff, 1);
+                }
+            } else if (LedItem.TYPE_128_16.equals(ledResolution)) {
+                //128x16
+                hProgram = ledC2M.CreateProgram(128, 16, 1,1,savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 16, Constant.C2M_LED_FONT_PATH,
+                        16, 0xff, 0, 0, 0,
+                        1, 0, 1, 1, 1, 1, 0,
+                        4, 0xff, 0, 0xff, 2, 0xff, 0);
+            } else {
+                //默认为128x32
+                hProgram = ledC2M.CreateProgram(128, 32, 1,1, savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 32, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            1, 0, 1, 1, 1, 1, 1,
+                            0, 0xff, 0, 0xff, 2, 0xff, 1);
+                } else {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 32, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            1, 0, 1, 1, 1, 1, 1,
+                            4, 0xff, 0, 0xff, 2, 0xff, 1);
+                }
+            }
+        } else if (type == 1) {
+            //显示时间和自定义内容
+            String text = SettingConfig.getLedCustomInfo(application);
+            if (LedItem.TYPE_64_16.equals(ledResolution)) {
+                //64x16
+                hProgram = ledC2M.CreateProgram(64, 16, 1,1,savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 64, 16, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            0, 0, 0, 0, 1, 1, 0,
+                            0, 0xff, 0, 0xff, 2, 0xff, 1);
+                } else {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 64, 16, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            0, 0, 0, 0, 1, 1, 0,
+                            4, 0xff, 0, 0xff, 2, 0xff, 1);
+                }
+                if (!TextUtils.isEmpty(text)) {
+                    ledC2M.AddProgram(hProgram, 1, 10, 1);
+                    ledC2M.AddImageTextArea(hProgram, 1, 1, 0, 0, 64, 16, 0);
+                    ledC2M.AddMultiLineTextToImageTextArea(hProgram, 1, 1, 0, text, Constant.C2M_LED_FONT_PATH, 16, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+                }
+            } else if (LedItem.TYPE_128_16.equals(ledResolution)){
+                //128x16
+                hProgram = ledC2M.CreateProgram(128, 16, 1,1,savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 16, Constant.C2M_LED_FONT_PATH,
+                        16, 0xff, 0, 0, 0,
+                        1, 0, 1, 1, 1, 1, 0,
+                        4, 0xff, 0, 0xff, 2, 0xff, 0);
+                if (!TextUtils.isEmpty(text)) {
+                    ledC2M.AddProgram(hProgram, 1, 10, 1);
+                    ledC2M.AddImageTextArea(hProgram, 1, 1, 0, 0, 128, 16, 0);
+                    ledC2M.AddMultiLineTextToImageTextArea(hProgram, 1, 1, 0, text, Constant.C2M_LED_FONT_PATH, fontSize, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+                }
+            } else {
+                //128x32
+                hProgram = ledC2M.CreateProgram(128, 32, 1,1,savaType);
+                ledC2M.AddProgram(hProgram, 0, 10, 1);
+                if (Locale.CHINESE.getLanguage().equals(language)) {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 32,Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            1, 0, 1, 1, 1, 1, 1,
+                            0, 0xff, 0, 0xff, 2, 0xff, 1);
+                } else {
+                    ledC2M.AddDigitalClockArea(hProgram, 0, 1, 0, 0, 128, 32, Constant.C2M_LED_FONT_PATH,
+                            16, 0xff, 0, 0, 0,
+                            1, 0, 1, 1, 1, 1, 1,
+                            4, 0xff, 0, 0xff, 2, 0xff, 1);
+                }
+
+                if (!TextUtils.isEmpty(text)) {
+                    ledC2M.AddProgram(hProgram, 1, 10, 1);
+                    ledC2M.AddImageTextArea(hProgram, 1, 1, 0, 0, 128, 32, 0);
+                    ledC2M.AddMultiLineTextToImageTextArea(hProgram, 1, 1, 0, text, Constant.C2M_LED_FONT_PATH, fontSize, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+                }
+            }
+        }
+
+        return hProgram;
+    }
+
+    private long createCallingProgram(String ledResolution, int fontSize) {
+        long hProgram = 0;
+        if (LedItem.TYPE_64_16.equals(ledResolution)) {
+            //64x16
+            hProgram = ledC2M.CreateProgram(64, 16, 1, 1, 3);
+            for (int i = 0; i < programTextList.size(); i++) {
+                String text = programTextList.get(i).getText();
+                ledC2M.AddProgram(hProgram, i, SettingConfig.getLedProgramTime(BaseApplication.appContext), 1);
+                ledC2M.AddImageTextArea(hProgram, i, 1, 0, 0, 64, 16, 0);
+                ledC2M.AddMultiLineTextToImageTextArea(hProgram, i, 1, 0, text, Constant.C2M_LED_FONT_PATH, 16, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+            }
+        } else if (LedItem.TYPE_128_16.equals(ledResolution)){
+            //128x16
+            hProgram = ledC2M.CreateProgram(128, 16, 1, 1, 3);
+            for (int i = 0; i < programTextList.size(); i++) {
+                ledC2M.AddProgram(hProgram, i, SettingConfig.getLedProgramTime(BaseApplication.appContext), 1);
+                ledC2M.AddImageTextArea(hProgram, i, 1, 0, 0, 128, 16, 0);
+                ledC2M.AddMultiLineTextToImageTextArea(hProgram, i, 1, 0, programTextList.get(i).getText(), Constant.C2M_LED_FONT_PATH, fontSize, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+            }
+        } else {
+            //128x32
+            hProgram = ledC2M.CreateProgram(128, 32, 1, 1, 3);
+            for (int i = 0; i < programTextList.size(); i++) {
+                ledC2M.AddProgram(hProgram, i, SettingConfig.getLedProgramTime(BaseApplication.appContext), 1);
+                ledC2M.AddImageTextArea(hProgram, i, 1, 0, 0, 128, 32, 0);
+                ledC2M.AddMultiLineTextToImageTextArea(hProgram, i, 1, 0, programTextList.get(i).getText(), Constant.C2M_LED_FONT_PATH, fontSize, 0xff, 0, 0, 0, 4, 5, 3, 1, 1);
+            }
+        }
+
+        return hProgram;
+    }
+
+
+    //更新节目方法: text -- 节目内容,action -- 方式: 1-发送节目,2-删除节目
+    @Override
+    public synchronized void updateProgram(String text, int action) {
+        synchronized (lockObject) {
+            if (text == null) {
+                return;
+            }
+
+            switch (action) {
+                case 1:
+                    //先查找列表中是否存在该节目,存在则删除
+                    Iterator<LedProgram> iterator = programTextList.iterator();
+                    while (iterator.hasNext()) {
+                        if (text.equals(iterator.next().getText())) {
+                            iterator.remove();
+                        }
+                    }
+
+                    LedProgram ledProgram = new LedProgram(text, System.currentTimeMillis());
+                    programTextList.add(0, ledProgram);
+                    voiceProgramList.add(0, text);
+                    deleteVoiceText = "";
+                    break;
+                case 2:
+                    boolean deleted = false;
+                    Iterator<LedProgram> iterator2 = programTextList.iterator();
+                    while (iterator2.hasNext()) {
+                        if (text.equals(iterator2.next().getText())) {
+                            iterator2.remove();
+                            deleteVoiceText = text;
+                            deleted = true;
+                            break;
+                        }
+                    }
+                    if (!deleted) {
+                        return;
+                    }
+                    break;
+            }
+
+            sendProgramStart();
+        }
+    }
+
+    private void sendProgramStart() {
+        if (programThread == null) {
+            programThread = new SendProgramThread();
+        }
+        updateThreadPool.execute(programThread);
+    }
+
+    private void sendDefaultProgram(final boolean needReboot) {
+        //停止语音
+        stopVoice = true;
+
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (lockObject) {
+                    //如果字体文件不存在则直接返回
+                    if (!Constant.LED_EXIST) {
+                        return;
+                    }
+
+                    if (ledList.size() == 0) {
+                        return;
+                    }
+
+                    int infoType = SettingConfig.getLedInfoType(application);
+                    for (LedItem ledItem : ledList) {
+                        if (ledItem != null) {
+                            long h = createDefaultProgram(ledItem.getResolution(), ledItem.getFontSize(), infoType, 0);
+                            if (h != 0) {
+                                int result = ledC2M.NetWorkSend(ledItem.getIp(), h);
+                                //语音节目
+                                //if (Constants.Companion.getLedVoiceOn() == 1) {
+                                //    sendVoiceTcp(ledItem.getIp());
+                                //}
+
+                                if (Constant.OPEN_DEBUG) {
+                                    Log.d(TAG, "send default program to " + ledItem.getIp() + ", result: " + result);
+                                }
+                                ledC2M.DeleteProgram(h);
+                            }
+
+                            if (needReboot) {
+                                ledC2M.PowerOnOff(ledItem.getIp(), 2);
+                            }
+                        }
+                    }
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void updateDefaultProgram() {
+        //无呼叫节目时更新默认节目
+        if (programTextList.size() == 0) {
+            sendDefaultProgram(true);
+        }
+    }
+
+    @Override
+    public void removeAllProgram() {
+        programTextList.clear();
+        sendDefaultProgram(true);
+    }
+
+    @Override
+    public void syncTime() {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (lockObject) {
+                    for (int i = 0; i < ledList.size(); i++) {
+                        ledC2M.AdjustTime(ledList.get(i).getIp());
+                    }
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void powerOnOff() {
+        new Thread(new Runnable() {
+            @Override
+            public void run() {
+                synchronized (lockObject) {
+                    if (isPowerOn) {
+                        for (int i = 0; i < ledList.size(); i++) {
+                            ledC2M.PowerOnOff(ledList.get(i).getIp(), 1);
+                        }
+                        isPowerOn = false;
+                    } else {
+                        for (int i = 0; i < ledList.size(); i++) {
+                            ledC2M.PowerOnOff(ledList.get(i).getIp(), 0);
+                        }
+                        isPowerOn = true;
+                    }
+                }
+            }
+        }).start();
+    }
+
+    @Override
+    public void release() {
+        programTextList.clear();
+    }
+}

+ 59 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedItem.java

@@ -0,0 +1,59 @@
+package com.wdkl.ncs.android.component.nursehome.led;
+
+public class LedItem {
+    /*
+    * Led点阵屏相关参数:
+    * type:点阵屏类型,128x32代表128x32点阵,64x16代表64x16点阵,默认为128x32
+     */
+
+    public static final String TYPE_128_32 = "128x32";
+    public static final String TYPE_128_16 = "128x16";
+    public static final String TYPE_64_16 = "64x16";
+
+    private String resolution;
+    private String ip;
+    private boolean voiceOn;
+    private int fontSize;
+
+    public LedItem() {
+    }
+
+    public LedItem(String resolution, String ip, boolean voiceOn, int fontSize) {
+        this.resolution = resolution;
+        this.ip = ip;
+        this.voiceOn = voiceOn;
+        this.fontSize = fontSize;
+    }
+
+    public String getResolution() {
+        return resolution;
+    }
+
+    public void setResolution(String resolution) {
+        this.resolution = resolution;
+    }
+
+    public String getIp() {
+        return ip;
+    }
+
+    public void setIp(String ip) {
+        this.ip = ip;
+    }
+
+    public boolean getVoiceOn() {
+        return voiceOn;
+    }
+
+    public void setVoiceOn(boolean voiceOn) {
+        this.voiceOn = voiceOn;
+    }
+
+    public int getFontSize() {
+        return fontSize;
+    }
+
+    public void setFontSize(int fontSize) {
+        this.fontSize = fontSize;
+    }
+}

+ 52 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedManager.java

@@ -0,0 +1,52 @@
+package com.wdkl.ncs.android.component.nursehome.led;
+
+import android.app.Application;
+
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.io.File;
+import java.util.ArrayList;
+
+public abstract class LedManager {
+
+    //初始化
+    public abstract void init(Application application);
+
+    //获取所有LED屏ip地址
+    public abstract void initIpList();
+
+    public abstract void setLedIpList(ArrayList<LedItem> list);
+
+    //获取点阵屏列表
+    public abstract ArrayList<LedItem> getLedList();
+
+    //更新节目: text -- 节目内容,action -- 方式: 1-发送节目,2-删除节目,3-发送默认节目
+    public abstract void updateProgram(String text, int action);
+
+    //更新默认节目
+    public abstract void updateDefaultProgram();
+
+    public abstract void removeAllProgram();
+
+    public abstract void syncTime();
+
+    public abstract void powerOnOff();
+
+    public abstract void release();
+
+    public long checkLedFont() {
+        File file = new File(Constant.C2M_LED_FONT_PATH);
+        if (file.exists()) {
+            Constant.LED_EXIST=true;
+            return file.length();
+        } else {
+            Constant.LED_EXIST=false;
+            return -1;
+        }
+    }
+
+    public void copyFont() {
+        //
+    }
+}

+ 104 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedManagerUtils.java

@@ -0,0 +1,104 @@
+package com.wdkl.ncs.android.component.nursehome.led;
+
+import android.app.Application;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
+
+import java.util.ArrayList;
+
+public class LedManagerUtils {
+    private static LedManagerUtils instance = null;
+    private LedManager ledManager;
+
+    public static LedManagerUtils getInstance(){
+        if (instance == null){
+            synchronized (LedManagerUtils.class){
+                if (instance == null){
+                    instance = new LedManagerUtils();
+                }
+            }
+        }
+        return instance;
+    }
+
+    public void ledInit(Application application) {
+        //灵信C2M
+        ledManager = new LedC2MManager();
+        ledManager.init(application);
+    }
+
+    public void initIp() {
+        if (ledManager != null) {
+            ledManager.initIpList();
+        }
+    }
+
+    public void setLedList(ArrayList<LedItem> list) {
+        if (ledManager != null) {
+            ledManager.setLedIpList(list);
+        }
+    }
+
+    public void updateProgram(String text, int action) {
+        if (ledManager != null) {
+            ledManager.updateProgram(text, action);
+        }
+    }
+
+    public void updateDefaultProgram() {
+        if (ledManager != null) {
+            ledManager.updateDefaultProgram();
+        }
+    }
+
+    public ArrayList<LedItem> getLedList() {
+        if (ledManager != null) {
+            return ledManager.getLedList();
+        }
+        return new ArrayList<>();
+    }
+
+    public void removeAllProgram() {
+        if (ledManager != null) {
+            ledManager.removeAllProgram();
+        }
+    }
+
+    public void syncTime() {
+        if (ledManager != null) {
+            ledManager.syncTime();
+        }
+    }
+
+    public void powerOnOff() {
+        if (ledManager != null) {
+            ledManager.powerOnOff();
+        }
+    }
+
+    public void checkFontFile() {
+        if (ledManager != null) {
+            long size = ledManager.checkLedFont();
+            if (size > 0) {
+                String text = BaseApplication.appContext.getString(R.string.led_font_file_size, size);
+                ExtendMethodsKt.showMessage(text);
+            } else {
+                ExtendMethodsKt.showMessage(R.string.led_no_font);
+            }
+        }
+    }
+
+    public void copyFont() {
+        if (ledManager != null) {
+            ledManager.copyFont();
+        }
+    }
+
+    public void release() {
+        if (ledManager != null) {
+            ledManager.release();
+        }
+    }
+}

+ 28 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/led/LedProgram.java

@@ -0,0 +1,28 @@
+package com.wdkl.ncs.android.component.nursehome.led;
+
+public class LedProgram {
+
+    private String text;
+    private long time;
+
+    public LedProgram(String text, long time) {
+        this.text = text;
+        this.time = time;
+    }
+
+    public String getText() {
+        return text;
+    }
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+    public long getTime() {
+        return time;
+    }
+
+    public void setTime(long time) {
+        this.time = time;
+    }
+}

+ 100 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/AppService.kt

@@ -0,0 +1,100 @@
+package com.wdkl.ncs.android.component.nursehome.service
+
+import android.app.Notification
+import android.app.NotificationChannel
+import android.app.NotificationManager
+import android.app.Service
+import android.content.Context
+import android.content.Intent
+import android.os.Binder
+import android.os.Build
+import android.os.IBinder
+import com.wdkl.ncs.android.component.nursehome.R
+import com.wdkl.ncs.android.middleware.common.Constant
+import com.wdkl.ncs.android.middleware.common.MessageEvent
+import org.greenrobot.eventbus.EventBus
+import serialporttest.utils.SerialPortUtil
+import com.wdkl.ncs.android.middleware.common.SerialType
+import serialporttest.utils.SerialPortUtilHost
+
+class AppService : Service(), SerialPortUtilHost.ISerialPortOnclickEvent, SerialPortUtilHost.IForkSpringSwiData {
+    private val TAG = AppService::class.java.simpleName
+    internal var myBinder = ServiceBinder()
+
+    private var notificationManager: NotificationManager? = null
+    private var notificationId: String = "channelId-0"
+    private var notificationName: String = "wdkl-host"
+
+    override fun onCreate() {
+        super.onCreate()
+
+        notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            var channel = NotificationChannel(
+                    notificationId,
+                    notificationName,
+                    NotificationManager.IMPORTANCE_HIGH
+            );
+            notificationManager!!.createNotificationChannel(channel)
+        }
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            startForeground(110, getNotification())//开前台服务
+        }
+
+        setSerialListner()
+        SerialPortUtil.getInstance().powerIndicator(1)
+    }
+
+    private fun getNotification(): Notification {
+        var builder: Notification.Builder = Notification.Builder(this)
+                .setSmallIcon(R.mipmap.ic_launcher)
+                .setContentTitle("service")
+                .setContentText("service is running")
+                .setOnlyAlertOnce(true)
+        //设置Notification的ChannelID,否则不能正常显示
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            builder.setChannelId(notificationId);
+        }
+        var notification: Notification = builder.build();
+        return notification;
+    }
+
+    //设置串口监听
+    private fun setSerialListner() {
+        SerialPortUtilHost.getInstance().setOnDataReceiveListener(this, this)
+    }
+
+    override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
+        return super.onStartCommand(intent, flags, startId)
+    }
+
+
+    override fun onBind(intent: Intent): IBinder {
+        return myBinder
+    }
+
+    //呼叫键串口消息
+    override fun serialPortBedOnclick(buffer: ByteArray) {
+        EventBus.getDefault().post(MessageEvent(SerialType(0, buffer[0].toInt()), Constant.EVENT_SERIAL_PORT))
+
+    }
+
+    //手柄串口消息
+    override fun forkSpringData(data: Int) {
+        EventBus.getDefault().post(MessageEvent(SerialType(1, data), Constant.EVENT_SERIAL_PORT))
+    }
+
+    override fun onDestroy() {
+        super.onDestroy()
+        stopForeground(true)// 停止前台服务--参数:表示是否移除之前的通知
+        SerialPortUtil.getInstance().closeHeart()
+        SerialPortUtil.getInstance().closeSerialPort()
+    }
+
+    inner class ServiceBinder : Binder() {
+        fun doThings() {}
+    }
+
+}

+ 215 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/RTCKeepLiveService.java.bak

@@ -0,0 +1,215 @@
+package com.wdkl.ncs.android.component.nursehome.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+import android.support.annotation.Nullable;
+
+import com.starrtc.demo.utils.AEvent;
+import com.starrtc.demo.utils.IEventListener;
+
+
+/**
+ * Created by zhangjt on 2017/8/6.
+ */
+
+public class RTCKeepLiveService extends Service implements IEventListener {
+    private String TAG = RTCKeepLiveService.class.getSimpleName();
+
+    private String DeviceSipId = "";
+    @Nullable
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+    }
+
+    @Override
+    public void onDestroy()
+    {
+        super.onDestroy();
+        removeListener();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+//        try {
+//            if(intent != null){
+//                DeviceSipId = intent.getStringExtra("DeviceSipId");
+//            }
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+        initSDK();
+        return super.onStartCommand(intent, flags, startId);
+    }
+
+    private void initSDK(){
+//        MLOC.init(this);
+        initFree();
+    }
+
+    private boolean isLogin = false;
+    //开放版SDK初始化
+    private void initFree(){
+//        MLOC.d("RTCKeepLiveService","initFree");
+//        isLogin = XHClient.getInstance().getIsOnline();
+//        Log.e("RTCKeepLiveService","isLogin "+isLogin);
+//        Log.e("RTCKeepLiveService","MLOC.userId  "+MLOC.userId);
+//        if(!isLogin){
+//            if(!MLOC.userId.equals(DeviceSipId)){
+////                MLOC.userId = ""+(new Random().nextInt(900000)+100000);
+////                MLOC.userId = "0000";
+////                MLOC.saveUserId(MLOC.userId);
+//
+//                MLOC.userId = DeviceSipId;
+//                Log.e(TAG,"userId "+DeviceSipId);
+//                MLOC.saveUserId(MLOC.userId);
+//
+//            }
+            addListener();
+
+//            XHCustomConfig customConfig =  XHCustomConfig.getInstance(this);
+//            customConfig.setChatroomServerUrl(MLOC.CHATROOM_SERVER_URL);
+//            customConfig.setLiveSrcServerUrl(MLOC.LIVE_SRC_SERVER_URL);
+//            customConfig.setLiveVdnServerUrl(MLOC.LIVE_VDN_SERVER_URL);
+//            customConfig.setImServerUrl(MLOC.IM_SERVER_URL);
+//            customConfig.setVoipServerUrl(MLOC.VOIP_SERVER_URL);
+//            customConfig.setLogEnable(false); //关闭SDK调试日志
+////            customConfig.setDefConfigOpenGLESEnable(false);
+////            customConfig.setDefConfigCameraId(1);//设置默认摄像头方向  0后置  1前置
+////            customConfig.setDefConfigVideoSize(XHConstants.XHCropTypeEnum.STAR_VIDEO_CONFIG_360BW_640BH_180SW_320SH);
+//            customConfig.setLogDirPath(Environment.getExternalStorageDirectory().getPath()+"/starrtcLog");
+////            customConfig.setDefConfigCamera2Enable(false);
+////            StarCamera.setFrameBufferEnable(false);
+//            customConfig.initSDKForFree(MLOC.userId, new IXHErrorCallback() {
+//                @Override
+//                public void error(final String errMsg, Object data) {
+//                    MLOC.e("RTCKeepLiveService","error:"+errMsg);
+//                    MLOC.showMsg(RTCKeepLiveService.this,errMsg);
+//                }
+//            },new Handler());
+//
+//            XHClient.getInstance().getChatManager().addListener(new XHChatManagerListener());
+//            XHClient.getInstance().getGroupManager().addListener(new XHGroupManagerListener());
+//            XHClient.getInstance().getVoipManager().addListener(new XHVoipManagerListener());
+//            XHClient.getInstance().getVoipP2PManager().addListener(new XHVoipP2PManagerListener());
+//            XHClient.getInstance().getLoginManager().addListener(new XHLoginManagerListener());
+//            XHVideoSourceManager.getInstance().setVideoSourceCallback(new DemoVideoSourceCallback());
+//
+//            XHClient.getInstance().getLoginManager().loginFree(new IXHResultCallback() {
+//                @Override
+//                public void success(Object data) {
+//                    MLOC.d("RTCKeepLiveService","loginSuccess");
+//                    isLogin = true;
+//                }
+//                @Override
+//                public void failed(final String errMsg) {
+//                    MLOC.d("RTCKeepLiveService","loginFailed "+errMsg);
+//                    MLOC.showMsg(RTCKeepLiveService.this,errMsg);
+//                }
+//            });
+//        }
+    }
+
+    @Override
+    public void dispatchEvent(String aEventID, boolean success, Object eventObj) {
+        switch (aEventID){
+            case AEvent.AEVENT_VOIP_REV_CALLING:{
+//                Intent intent = new Intent(this, VoipRingingActivity.class);
+//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+//                intent.putExtra("targetId",eventObj.toString());
+//                startActivity(intent);
+            }
+            break;
+            case AEvent.AEVENT_VOIP_REV_CALLING_AUDIO:{
+                //todo 原生startRTC 语音呼入 启动原生的activity
+//                Intent intent = new Intent(this, VoipAudioRingingActivity.class);
+//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+//                intent.putExtra("targetId",eventObj.toString());
+//                startActivity(intent);
+                //todo 原生startRTC 语音呼入 启动自己修改的activity
+//                Intent intent = new Intent(this, RTCVoipAudioRingingActivity.class);
+//                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+//                intent.putExtra("targetId",eventObj.toString());
+//                startActivity(intent);
+//
+//                Log.e("TAG","本地启动。。。");
+
+            }
+            break;
+            case AEvent.AEVENT_VOIP_P2P_REV_CALLING:
+//                if(MLOC.canPickupVoip){
+//                    Intent intent = new Intent(this, VoipP2PRingingActivity.class);
+//                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+//                    intent.putExtra("targetId",eventObj.toString());
+//                    startActivity(intent);
+//                }
+                break;
+            case AEvent.AEVENT_VOIP_P2P_REV_CALLING_AUDIO:
+//                if(MLOC.canPickupVoip){
+//                    Intent intent = new Intent(this, VoipP2PRingingActivity.class);
+//                    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK );
+//                    intent.putExtra("targetId",eventObj.toString());
+//                    startActivity(intent);
+//                }
+                break;
+            case AEvent.AEVENT_C2C_REV_MSG:
+            case AEvent.AEVENT_REV_SYSTEM_MSG:
+//                MLOC.hasNewC2CMsg = true;
+                break;
+            case AEvent.AEVENT_GROUP_REV_MSG:
+//                MLOC.hasNewGroupMsg = true;
+                break;
+            case AEvent.AEVENT_LOGOUT:
+//                removeListener();
+//                this.stopSelf();
+                break;
+            case AEvent.AEVENT_USER_KICKED:
+            case AEvent.AEVENT_CONN_DEATH:
+//                MLOC.d("RTCKeepLiveService","AEVENT_USER_KICKED OR AEVENT_CONN_DEATH");
+//                XHClient.getInstance().getLoginManager().loginFree(new IXHResultCallback() {
+//                    @Override
+//                    public void success(Object data) {
+//                        MLOC.d("RTCKeepLiveService","loginSuccess");
+//                        isLogin = true;
+//                    }
+//                    @Override
+//                    public void failed(final String errMsg) {
+//                        MLOC.d("RTCKeepLiveService","loginFailed "+errMsg);
+//                        MLOC.showMsg(RTCKeepLiveService.this,errMsg);
+//                    }
+//                });
+                break;
+        }
+    }
+
+    private void addListener(){
+        AEvent.addListener(AEvent.AEVENT_LOGOUT,this);
+        AEvent.addListener(AEvent.AEVENT_VOIP_REV_CALLING,this);
+        AEvent.addListener(AEvent.AEVENT_VOIP_REV_CALLING_AUDIO,this);
+        AEvent.addListener(AEvent.AEVENT_VOIP_P2P_REV_CALLING,this);
+        AEvent.addListener(AEvent.AEVENT_C2C_REV_MSG,this);
+        AEvent.addListener(AEvent.AEVENT_REV_SYSTEM_MSG,this);
+        AEvent.addListener(AEvent.AEVENT_GROUP_REV_MSG,this);
+        AEvent.addListener(AEvent.AEVENT_USER_KICKED,this);
+        AEvent.addListener(AEvent.AEVENT_CONN_DEATH,this);
+    }
+
+    private void removeListener(){
+        AEvent.removeListener(AEvent.AEVENT_LOGOUT,this);
+        AEvent.removeListener(AEvent.AEVENT_VOIP_REV_CALLING,this);
+        AEvent.removeListener(AEvent.AEVENT_VOIP_REV_CALLING_AUDIO,this);
+        AEvent.removeListener(AEvent.AEVENT_VOIP_P2P_REV_CALLING,this);
+        AEvent.removeListener(AEvent.AEVENT_C2C_REV_MSG,this);
+        AEvent.removeListener(AEvent.AEVENT_REV_SYSTEM_MSG,this);
+        AEvent.removeListener(AEvent.AEVENT_GROUP_REV_MSG,this);
+        AEvent.removeListener(AEvent.AEVENT_USER_KICKED,this);
+        AEvent.removeListener(AEvent.AEVENT_CONN_DEATH,this);
+    }
+
+}

+ 330 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/service/WdklSipService.java

@@ -0,0 +1,330 @@
+package com.wdkl.ncs.android.component.nursehome.service;
+
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.util.Log;
+import android.widget.Toast;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.activity.CallActivity;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.middleware.common.MessageEvent;
+
+
+import org.greenrobot.eventbus.EventBus;
+import org.linphone.core.Call;
+import org.linphone.core.CallParams;
+import org.linphone.core.Core;
+import org.linphone.core.CoreListenerStub;
+import org.linphone.core.Factory;
+import org.linphone.core.LogCollectionState;
+import org.linphone.core.PayloadType;
+import org.linphone.core.ProxyConfig;
+import org.linphone.core.RegistrationState;
+import org.linphone.mediastream.Version;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Timer;
+import java.util.TimerTask;
+
+public class WdklSipService extends Service {
+    private static final String START_SIPPHONE_LOGS = " ==== Device information dump ====";
+
+    private static final String PREFER_PAYLOAD = "PUMU";
+
+    //单例化服务,以便全局调用
+    private static WdklSipService sInstance;
+
+    private NotificationManager notificationManager = null;
+    private String notificationId = "channelId0";
+    private String notificationName = "sip_service";
+
+    private Handler mHandler;
+    private Timer mTimer;
+
+    private Core mCore;
+    private CoreListenerStub mCoreListener;
+
+    public static boolean sipTesting = false;
+
+    public static boolean isReady() {
+        return sInstance != null;
+    }
+
+    public static WdklSipService getInstance() {
+        return sInstance;
+    }
+
+    public static Core getCore() {
+
+        return sInstance.mCore;
+    }
+
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return null;
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            NotificationChannel channel = new NotificationChannel(
+                    notificationId,
+                    notificationName,
+                    NotificationManager.IMPORTANCE_HIGH
+            );
+            channel.enableVibration(true);
+            channel.enableLights(true);
+            channel.setBypassDnd(true);
+            channel.setShowBadge(true);
+            channel.setSound(null, null);
+            notificationManager.createNotificationChannel(channel);
+        }
+
+        //首次调用必须使用 Factory相关方法
+        //这里开户调试日志及设置路径
+        String basePath = getFilesDir().getAbsolutePath();
+        Factory.instance().setLogCollectionPath(basePath);
+        Factory.instance().enableLogCollection(LogCollectionState.Enabled);
+        Factory.instance().setDebugMode(false, getString(R.string.wdkl_app_name));
+
+        //收集一些设备信息
+        Log.i("sipCall", START_SIPPHONE_LOGS);
+        dumpDeviceInformation();
+        dumpInstalledLinphoneInformation();
+
+        mHandler = new Handler();
+        //主监听器,根据事件调用界面
+        mCoreListener = new CoreListenerStub() {
+            @Override
+            public void onCallStateChanged(Core core, Call call, Call.State state, String message) {
+                if (!SettingConfig.getSipEnabled(BaseApplication.appContext)) {
+                    return;
+                }
+
+                Toast.makeText(WdklSipService.this, message, Toast.LENGTH_SHORT).show();
+                Log.d("sipCall", ">>>>>>>>>>>> call state: " + state + ", " + call.getRemoteAddress().asString());
+
+                if (state == Call.State.IncomingReceived || state == Call.State.IncomingEarlyMedia) {
+                    //Toast.makeText(WdklSipService.this, "Incoming call", Toast.LENGTH_LONG).show();
+                    //来电时将自动接听
+                    CallParams params = getCore().createCallParams(call);
+                    call.acceptWithParams(params);
+                } else if (state == Call.State.Connected) {
+                    if (sipTesting) {
+                        //通话已建立完成,打开通话界面
+                        Intent intent = new Intent(WdklSipService.this, CallActivity.class);
+                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                        startActivity(intent);
+                    } else {
+                        EventBus.getDefault().post(new MessageEvent("sip_connected", Constant.SIP_CONNECTED));
+                    }
+                } else if (state == Call.State.End || state == Call.State.Released){
+                    EventBus.getDefault().post(new MessageEvent("handoff", Constant.EVENT_END_CALL));
+                }
+            }
+
+            @Override
+            public void onRegistrationStateChanged(Core core, ProxyConfig cfg, RegistrationState state, String message) {
+                if (!SettingConfig.getSipEnabled(BaseApplication.appContext)) {
+                    return;
+                }
+
+                EventBus.getDefault().post(new MessageEvent(state, Constant.EVENT_SIP_REGISTER_STATUS));
+            }
+        };
+
+        try {
+            //复制一些源资源
+            //默认配置只能在首次时安装一次
+            copyIfNotExist(R.raw.linphonerc_default, basePath + "/.wdkl_sip_rc");
+            //用户配置,每次复制
+            copyFromPackage(R.raw.linphonerc_factory, "wdkl_sip_rc");
+        } catch (IOException ioe) {
+            Log.e("sipCall",ioe.getMessage());
+        }
+
+        //创建SIP核心并加载监听器
+        mCore = Factory.instance()
+                .createCore(basePath + "/.wdkl_sip_rc", basePath + "/wdkl_sip_rc", this);
+        mCore.addListener(mCoreListener);
+        //SIP核心配置完成
+        configureCore();
+    }
+
+    private Notification getNotification() {
+        Notification.Builder builder = new Notification.Builder(this)
+                .setSmallIcon(R.mipmap.ic_launcher)
+                .setContentTitle("sip service")
+                .setContentText("running...")
+                .setOnlyAlertOnce(true);
+
+        //设置Notification的ChannelID,否则不能正常显示
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            builder.setChannelId(notificationId);
+        }
+
+        return builder.build();
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+            startForeground(11, getNotification()); //开前台服务
+        }
+
+        super.onStartCommand(intent, flags, startId);
+        //Toast.makeText(WdklSipService.this, "sip服务已启动", Toast.LENGTH_SHORT).show();
+
+        //如果服务已经在运行,则返回
+        if (sInstance != null) {
+            return START_STICKY;
+        }
+
+        //一旦服务启动,则一直保持
+        sInstance = this;
+
+        //SIP核心在创建和配置完成后,开启
+        mCore.start();
+        //必须定时运行 SIP核心 iterate()
+        TimerTask lTask = new TimerTask() {
+            @Override
+            public void run() {
+                mHandler.post(
+                        new Runnable() {
+                            @Override
+                            public void run() {
+                                if (mCore != null) {
+                                    mCore.iterate();
+                                }
+                            }
+                        });
+            }
+        };
+        mTimer = new Timer("wdkl sip scheduler");
+        mTimer.schedule(lTask, 0, 20);
+
+        return START_STICKY;
+    }
+
+    @Override
+    public void onDestroy() {
+        mCore.removeListener(mCoreListener);
+        mTimer.cancel();
+        mCore.stop();
+        // A stopped Core can be started again
+        // To ensure resources are freed, we must ensure it will be garbage collected
+        mCore = null;
+        // Don't forget to free the singleton as well
+        sInstance = null;
+
+        super.onDestroy();
+    }
+
+    @Override
+    public void onTaskRemoved(Intent rootIntent) {
+        // For this sample we will kill the Service at the same time we kill the app
+        stopSelf();
+
+        super.onTaskRemoved(rootIntent);
+    }
+
+    private void configureCore() {
+        // We will create a directory for user signed certificates if needed
+        String basePath = getFilesDir().getAbsolutePath();
+        String userCerts = basePath + "/user-certs";
+        File f = new File(userCerts);
+        if (!f.exists()) {
+            if (!f.mkdir()) {
+                Log.e("sipCall",userCerts + " can't be created.");
+            }
+        }
+        mCore.setUserCertificatesPath(userCerts);
+
+        //音频部分, 这里增加了一个遍历, 用于设置指定的音频格式.
+        PayloadType[] payloads = mCore.getAudioPayloadTypes();
+        for(int i = 0; i < payloads.length; i ++){
+            PayloadType pt = payloads[i];
+            //Log.i("sipCall", ">>>>>>>>>>>>>>>>>1 " + pt.getMimeType() + " = " + pt.enabled());
+            if (pt.getMimeType().equals("PCMU")
+//                    || pt.getMimeType().equals("PUMA")
+//                    || pt.getMimeType().equals("GSM")
+            ){
+                pt.enable(true);
+            } else {
+                pt.enable(false);
+            }
+        }
+        mCore.setAudioPayloadTypes(payloads);
+    }
+
+    private void dumpDeviceInformation() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("DEVICE=").append(Build.DEVICE).append("\n");
+        sb.append("MODEL=").append(Build.MODEL).append("\n");
+        sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
+        sb.append("SDK=").append(Build.VERSION.SDK_INT).append("\n");
+        sb.append("Supported ABIs=");
+        for (String abi : Version.getCpuAbis()) {
+            sb.append(abi).append(", ");
+        }
+        sb.append("\n");
+        Log.i("sipCall",sb.toString());
+    }
+
+    private void dumpInstalledLinphoneInformation() {
+        PackageInfo info = null;
+        try {
+            info = getPackageManager().getPackageInfo(getPackageName(), 0);
+        } catch (PackageManager.NameNotFoundException nnfe) {
+            Log.e("sipCall",nnfe.getMessage());
+        }
+
+        if (info != null) {
+            Log.i(
+                    "[Service] sipphone version is ",
+                    info.versionName + " (" + info.versionCode + ")");
+        } else {
+            Log.i("sipCall","[Service] sipphone version is unknown");
+        }
+    }
+
+    private void copyIfNotExist(int ressourceId, String target) throws IOException {
+        File lFileToCopy = new File(target);
+        if (!lFileToCopy.exists()) {
+            copyFromPackage(ressourceId, lFileToCopy.getName());
+        }
+    }
+
+    private void copyFromPackage(int ressourceId, String target) throws IOException {
+        FileOutputStream lOutputStream = openFileOutput(target, 0);
+        InputStream lInputStream = getResources().openRawResource(ressourceId);
+        int readByte;
+        byte[] buff = new byte[8048];
+        while ((readByte = lInputStream.read(buff)) != -1) {
+            lOutputStream.write(buff, 0, readByte);
+        }
+        lOutputStream.flush();
+        lOutputStream.close();
+        lInputStream.close();
+    }
+}

+ 839 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/settingconfig/SettingConfig.java

@@ -0,0 +1,839 @@
+package com.wdkl.ncs.android.component.nursehome.settingconfig;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.wdkl.ncs.android.component.nursehome.util.SpeechUtil;
+
+
+public class SettingConfig {
+
+
+    private static final String SP_NAME = "SP_FUNCTION";
+
+    //白昼设置白天的初始时间设置
+    private static final String KEY_SP_INITIAL_DAY_TIME = "KEY_SP_INITIAL_DAY_TIME";
+    private static final String initial_day_time = "06:00";
+    private static final String KEY_SP_INITIAL_DAY_TIME_LOCATION = "KEY_SP_INITIAL_DAY_TIME_LOCATION";
+    private static final String initial_day_time_location = "12";
+
+
+    //白昼设置白天的结束时间设置
+    private static final String KEY_SP_END_OF_DAY = "KEY_SP_END_OF_DAY";
+    private static final String end_of_day = "18:30";
+    //白昼设置白天的结束时间设置
+    private static final String KEY_SP_END_OF_DAY_LOCATION = "KEY_SP_END_OF_DAY_LOCATION";
+    private static final String end_of_day_location = "38";
+
+    //播报次数
+    private static final String KEY_SP_CALL_NUMBER = "KEY_SP_CALL_NUMBER";
+    private static final int call_number = 2;
+
+    //主机白天亮度
+    private static final String KEY_SP_MAIN_ENGINE_DAYTIME_BRIGHTNESS = "KEY_SP_MAIN_ENGINE_DAYTIME_BRIGHTNESS";
+    private static final int main_engine_daytime_brightness = 70;
+    //主机晚上亮度
+    private static final String KEY_SP_HOST_NIGHT_BRIGHTNESS = "KEY_SP_HOST_NIGHT_BRIGHTNESS";
+    private static final int host_night_brightness = 50;
+
+    //主机白天系统音量
+    private static final String KEY_SP_HOST_DAYTIME_VOLUME = "KEY_SP_HOST_DAYTIME_VOLUME";
+    private static final int host_daytime_volume = 100;
+    //主机晚上系统音量
+    private static final String KEY_SP_HOST_NIGHT_VOLUME = "KEY_SP_HOST_NIGHT_VOLUME";
+    private static final int host_night_volume = 80;
+
+    //主机免提录入音量
+    private static final String KEY_SP_HANDS_FREE_INPUT_VOLUME_OF_HOST_MACHINE = "KEY_SP_HANDS_FREE_INPUT_VOLUME_OF_HOST_MACHINE";
+    private static final int hands_free_input_volume_of_host_machine = 50;
+    //主机手柄录入音量
+    private static final String KEY_SP_HANDS_FREE_INPUT_VOLUME = "KEY_SP_HANDS_FREE_INPUT_VOLUME";
+    private static final int host_handle_input_volume = 30;
+
+    //主机免提播放音量
+    private static final String KEY_SP_HOST_HANDS_FREE_PLAY_VOLUME = "KEY_SP_HOST_HANDS_FREE_PLAY_VOLUME";
+    private static final int host_hands_free_play_volume = 90;
+    //主机手柄播放音量
+    private static final String KEY_SP_HOST_GAMEPAD_PLAY_VOLUME = "KEY_SP_HOST_GAMEPAD_PLAY_VOLUME";
+    private static final int host_gamepad_play_volume = 40;
+
+    //语音播报模式
+    private static final String KEY_SP_TTS_MODE = "KEY_SP_TTS_MODE";
+    public static final int RING_ON = 0;  //铃声
+    public static final int TTS_ON = 1;  //tts
+    public static final int MUSIC_ON = 2;  //音乐
+
+    //默认语言
+    private static final String KEY_LANGUAGE_ID = "KEY_LANGUAGE_ID";
+    private static final String KEY_LANGUAGE_MODE = "KEY_LANGUAGE_MODE";
+    private static final String KEY_CALL_STAY_TIME = "KEY_CALL_STAY_TIME";
+
+    //通话模式
+    private static final String KEY_SP_TALK_MODE = "KEY_SP_TALK_MODE";
+    public static final int single_pass_mode = 0;  //单工模式
+    public static final int two_way_mode = 1;      //双工模式
+
+    //分机白天亮度
+    private static final String KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS = "KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS";
+    private static final int extension_daytime_brightness = 70;
+    //分机晚上亮度
+    private static final String KEY_SP_EXTENSION_NIGHT_BRIGHTNESS = "KEY_SP_EXTENSION_NIGHT_BRIGHTNESS";
+    private static final int extension_night_brightness = 50;
+
+    //分机LED白天亮度
+    private static final String KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS = "KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS";
+    private static final int extension_daytime_led_brightness = 70;
+    //分机LED晚上亮度
+    private static final String KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS = "KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS";
+    private static final int extension_night_led_brightness = 50;
+
+    //分机白天系统音量
+    private static final String KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME = "KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME";
+    private static final int extension_daytime_system_volume = 70;
+    //分机晚上系统音量
+    private static final String KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME = "KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME";
+    private static final int extension_night_system_volume = 50;
+
+    //分机手柄录入音量
+    private static final String KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME = "KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME";
+    private static final int the_extension_handle_records_the_volume = 50;
+
+    //分机通话音量
+    private static final String KEY_SP_EXTENSION_CALL_VOLUME = "KEY_SP_EXTENSION_CALL_VOLUME";
+    private static final int extension_call_volume = 70;
+
+
+    //传统转换盒系统音量
+    private static final String KEY_SP_CHANGE_BOX_SYSTEM_VOLUME = "KEY_SP_CHANGE_BOX_SYSTEM_VOLUME";
+    private static final int change_box_system_volume = 70;
+
+
+    //门口机白天亮度
+    private static final String KEY_SP_DOOR_MACHINE_DAYTIME_BRIGHTNESS = "KEY_SP_DOOR_MACHINE_DAYTIME_BRIGHTNESS";
+    private static final int door_machine_daytime_brightness = 70;
+    //门口机晚上亮度
+    private static final String KEY_SP_DOOR_MACHINE_NIGHT_BRIGHTNESS = "KEY_SP_DOOR_MACHINE_NIGHT_BRIGHTNESS";
+    private static final int door_machine_night_brightness = 50;
+
+
+    //门口机通话音量
+    private static final String KEY_SP_DOOR_PHONE_VOLUME = "KEY_SP_DOOR_PHONE_VOLUME";
+    private static final int door_phone_volume = 70;
+
+    //点阵屏相关参数
+    private static final String KEY_SP_LED_PROGRAM_TIME = "KEY_SP_LED_PROGRAM_TIME";
+    private static final String KEY_SP_LED_VOICE_VOLUME = "KEY_SP_LED_VOICE_VOLUME";
+    private static final String KEY_SP_LED_VOICE_TIMES = "KEY_SP_LED_VOICE_TIMES";
+    private static final String KEY_SP_LED_INFO_TYPE = "KEY_SP_LED_INFO_TYPE";
+    private static final String KEY_SP_LED_CUSTOM_INFO = "KEY_SP_LED_CUSTOM_INFO";
+
+    //app上次启动时间
+    private static final String KEY_SP_APP_START_TIME = "KEY_SP_APP_START_TIME";
+
+    //呼叫转移开关
+    private static final String KEY_SP_CALL_TRANSFER = "KEY_SP_CALL_TRANSFER";
+    private static final String KEY_SP_SOS_NAME = "KEY_SP_SOS_NAME";
+    private static final String KEY_SP_LED_CONTROL = "KEY_SP_LED_CONTROL";
+    private static final String KEY_SP_LOOP_CALL = "KEY_SP_LOOP_CALL";
+
+    //是否使用sip通话
+    private static final String KEY_SP_SIP_ENABLE = "KEY_SP_SIP_ENABLE";
+
+    private static final String KEY_SP_VOICE_NUMERIC = "KEY_SP_VOICE_NUMERIC";
+
+    //语音播报模式
+    public static int getTtsMode(Context context) {
+        return getSP(context).getInt(KEY_SP_TTS_MODE, TTS_ON);
+    }
+
+    public static void setTtsMode(Context context, int mode) {
+        getEditor(context).putInt(KEY_SP_TTS_MODE, mode).apply();
+    }
+
+    public static boolean getTransferCall(Context context) {
+        return getSP(context).getBoolean(KEY_SP_CALL_TRANSFER, false);
+    }
+
+    public static void setTransferCall(Context context, boolean on) {
+        getEditor(context).putBoolean(KEY_SP_CALL_TRANSFER, on).apply();
+    }
+
+    public static int getLanguageId(Context context) {
+        //0--auto, 1--English, 2--中文, 3--西班牙语, 4--俄语
+        return getSP(context).getInt(KEY_LANGUAGE_ID, 2);
+    }
+
+    public static void setLanguageId(Context context, int id) {
+        getEditor(context).putInt(KEY_LANGUAGE_ID, id).apply();
+    }
+
+    public static int getLanguageMode(Context context) {
+        return getSP(context).getInt(KEY_LANGUAGE_MODE, 0);
+    }
+
+    public static void setLanguageMode(Context context, int mode) {
+        getEditor(context).putInt(KEY_LANGUAGE_MODE, mode).apply();
+    }
+
+    public static int getCallStayTime(Context context) {
+        return getSP(context).getInt(KEY_CALL_STAY_TIME, 2);
+    }
+
+    public static void setCallStayTime(Context context, int value) {
+        getEditor(context).putInt(KEY_CALL_STAY_TIME, value).apply();
+    }
+
+    public static boolean getSosCallNameOn(Context context) {
+        return getSP(context).getBoolean(KEY_SP_SOS_NAME, false);
+    }
+
+    public static void setSosCallNameOn(Context context, boolean on) {
+        getEditor(context).putBoolean(KEY_SP_SOS_NAME, on).apply();
+    }
+
+    public static boolean getLedControl(Context context) {
+        return getSP(context).getBoolean(KEY_SP_LED_CONTROL, false);
+    }
+
+    public static void setLedControl(Context context, boolean control) {
+        getEditor(context).putBoolean(KEY_SP_LED_CONTROL, control).apply();
+    }
+
+    public static boolean getLoopCall(Context context) {
+        return getSP(context).getBoolean(KEY_SP_LOOP_CALL, false);
+    }
+
+    public static void setLoopCall(Context context, boolean loop) {
+        getEditor(context).putBoolean(KEY_SP_LOOP_CALL, loop).apply();
+    }
+
+    public static boolean getSipEnabled(Context context) {
+        return getSP(context).getBoolean(KEY_SP_SIP_ENABLE, false);
+    }
+
+    public static void setSipEnable(Context context, boolean enable) {
+        getEditor(context).putBoolean(KEY_SP_SIP_ENABLE, enable).apply();
+    }
+
+    public static boolean getVoiceNumeric(Context context) {
+        return getSP(context).getBoolean(KEY_SP_VOICE_NUMERIC, true);
+    }
+
+    public static void setVoiceNumeric(Context context, boolean enable) {
+        getEditor(context).putBoolean(KEY_SP_VOICE_NUMERIC, enable).apply();
+    }
+
+    /**
+     * 获取播报次数
+     *
+     * @return
+     */
+    public static int getCallNumber(Context context) {
+        return getSP(context).getInt(KEY_SP_CALL_NUMBER, call_number);
+    }
+
+    /**
+     * 设置播报次数
+     *
+     * @param value
+     */
+    public static void setCallNumber(Context context, int value) {
+        if (value > 0) {
+            SpeechUtil.getInstance().setSpeechLoopCount(value);
+        }
+        getEditor(context).putInt(KEY_SP_CALL_NUMBER, value).apply();
+    }
+
+
+    /**
+     * 获取主机白天亮度
+     *
+     * @return
+     */
+    public static int getMainEngineDaytimeBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_MAIN_ENGINE_DAYTIME_BRIGHTNESS, main_engine_daytime_brightness);
+    }
+
+    /**
+     * 设置主机白天亮度
+     *
+     * @param value
+     */
+    public static void setMainEngineDaytimeBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_MAIN_ENGINE_DAYTIME_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取主机晚上亮度
+     *
+     * @return
+     */
+    public static int getHostNightBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_HOST_NIGHT_BRIGHTNESS, host_night_brightness);
+    }
+
+    /**
+     * 设置主机晚上亮度
+     *
+     * @param value
+     */
+    public static void setHostNightBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HOST_NIGHT_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取主机白天系统音量
+     *
+     * @return
+     */
+    public static int getHostDaytimeVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_HOST_DAYTIME_VOLUME, host_daytime_volume);
+    }
+
+    /**
+     * 设置主机白天系统音量
+     *
+     * @param value
+     */
+    public static void setHostDaytimeVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HOST_DAYTIME_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取主机晚上系统音量
+     *
+     * @return
+     */
+    public static int getHostNightVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_HOST_NIGHT_VOLUME, host_night_volume);
+    }
+
+    /**
+     * 设置主机晚上系统音量
+     *
+     * @param value
+     */
+    public static void setHostNightVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HOST_NIGHT_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取主机免提录入音量
+     *
+     * @return
+     */
+    public static int getHandsFreeInputVolumeOfHostMachine(Context context) {
+        return getSP(context).getInt(KEY_SP_HANDS_FREE_INPUT_VOLUME_OF_HOST_MACHINE, hands_free_input_volume_of_host_machine);
+    }
+
+    /**
+     * 设置主机免提录入音量
+     *
+     * @param value
+     */
+    public static void setHandsFreeInputVolumeOfHostMachine(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HANDS_FREE_INPUT_VOLUME_OF_HOST_MACHINE, value).apply();
+    }
+
+    /**
+     * 获取主机手柄录入音量
+     *
+     * @return
+     */
+    public static int getHostHandleInputVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_HANDS_FREE_INPUT_VOLUME, host_handle_input_volume);
+    }
+
+    /**
+     * 设置主机手柄录入音量
+     *
+     * @param value
+     */
+    public static void setHostHandleInputVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HANDS_FREE_INPUT_VOLUME, value).apply();
+    }
+
+
+    /**
+     * 获取主机免提播放音量
+     *
+     * @return
+     */
+    public static int getHostHandsFreePlayVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_HOST_HANDS_FREE_PLAY_VOLUME, host_hands_free_play_volume);
+    }
+
+    /**
+     * 设置主机免提播放音量
+     *
+     * @param value
+     */
+    public static void setHostHandsFreePlayVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HOST_HANDS_FREE_PLAY_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取主机手柄播放音量
+     *
+     * @return
+     */
+    public static int getHostGamepadPlayVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_HOST_GAMEPAD_PLAY_VOLUME, host_gamepad_play_volume);
+    }
+
+    /**
+     * 设置主机手柄播放音量
+     *
+     * @param value
+     */
+    public static void setHostGamepadPlayVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_HOST_GAMEPAD_PLAY_VOLUME, value).apply();
+    }
+
+
+    /**
+     * 获取主机通话模式
+     *
+     * @return
+     */
+    public static int getTalkMode(Context context) {
+        return getSP(context).getInt(KEY_SP_TALK_MODE, two_way_mode);
+    }
+
+    /**
+     * 设置主机通话模式
+     *
+     * @param value
+     */
+    public static void setTalkMode(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_TALK_MODE, value).apply();
+    }
+
+    /**
+     * 获取分机白天亮度
+     *
+     * @return
+     */
+    public static int getExtensionDaytimeBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS, extension_daytime_brightness);
+    }
+
+    /**
+     * 设置分机白天亮度
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机晚上亮度
+     *
+     * @return
+     */
+    public static int getExtensionNightBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_BRIGHTNESS, extension_night_brightness);
+    }
+
+    /**
+     * 设置分机晚上亮度
+     *
+     * @param value
+     */
+    public static void setExtensionNightBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机LED白天亮度
+     *
+     * @return
+     */
+    public static int getExtensionDaytimeLEDBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS, extension_daytime_led_brightness);
+    }
+
+    /**
+     * 设置分机LED白天亮度
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeLEDBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_LED_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取分机LED晚上亮度
+     *
+     * @return
+     */
+    public static int getExtensionNightLEDBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS, extension_night_led_brightness);
+    }
+
+    /**
+     * 设置分机LED晚上亮度
+     *
+     * @param value
+     */
+    public static void setExtensionNightLEDBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_LED_BRIGHTNESS, value).apply();
+    }
+
+
+    /**
+     * 获取分机白天系统音量
+     *
+     * @return
+     */
+    public static int getExtensionDaytimeSystemVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME, extension_daytime_system_volume);
+    }
+
+    /**
+     * 设置分机白天系统音量
+     *
+     * @param value
+     */
+    public static void setExtensionDaytimeSystemVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_DAYTIME_SYSTEM_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取分机晚上系统音量
+     *
+     * @return
+     */
+    public static int getExtensionNightSystemVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME, extension_night_system_volume);
+    }
+
+    /**
+     * 设置分机晚上系统音量
+     *
+     * @param value
+     */
+    public static void setExtensionNightSystemVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_NIGHT_SYSTEM_VOLUME, value).apply();
+    }
+
+
+
+    /**
+     * 获取分机手柄录入音量
+     *
+     * @return
+     */
+    public static int getTheExtensionHandleRecordsTheVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME, the_extension_handle_records_the_volume);
+    }
+
+    /**
+     * 设置分机手柄录入音量
+     *
+     * @param value
+     */
+    public static void setTheExtensionHandleRecordsTheVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_THE_EXTENSION_HANDLR_RECORDS_THE_VOLUME, value).apply();
+    }
+
+
+    /**
+     * 获取分机通话音量
+     *
+     * @return
+     */
+    public static int getExtensionCallVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_EXTENSION_CALL_VOLUME, extension_call_volume);
+    }
+
+    /**
+     * 设置分机通话音量
+     *
+     * @param value
+     */
+    public static void setExtensionCallVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_EXTENSION_CALL_VOLUME, value).apply();
+    }
+
+
+
+
+    /**
+     * 获取传统转换盒系统音量
+     *
+     * @return
+     */
+    public static int getChangeBoxSystemVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_CHANGE_BOX_SYSTEM_VOLUME, change_box_system_volume);
+    }
+
+    /**
+     * 设置传统转换盒系统音量
+     *
+     * @param value
+     */
+    public static void setChangeBoxSystemVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_CHANGE_BOX_SYSTEM_VOLUME, value).apply();
+    }
+
+
+
+
+
+
+    /**
+     * 获取门口机白天亮度
+     *
+     * @return
+     */
+    public static int getDoorMachineDaytimeBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_DOOR_MACHINE_DAYTIME_BRIGHTNESS, door_machine_daytime_brightness);
+    }
+
+    /**
+     * 设置门口机白天亮度
+     *
+     * @param value
+     */
+    public static void setDoorMachineDaytimeBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_DOOR_MACHINE_DAYTIME_BRIGHTNESS, value).apply();
+    }
+
+    /**
+     * 获取门口机晚上亮度
+     *
+     * @return
+     */
+    public static int getDoorMachineNightBrightness(Context context) {
+        return getSP(context).getInt(KEY_SP_DOOR_MACHINE_NIGHT_BRIGHTNESS, door_machine_night_brightness);
+    }
+
+    /**
+     * 设置门口机晚上亮度
+     *
+     * @param value
+     */
+    public static void setDoorMachineNightBrightness(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_DOOR_MACHINE_NIGHT_BRIGHTNESS, value).apply();
+    }
+
+
+
+
+    /**
+     * 获取门口机通话音量
+     *
+     * @return
+     */
+    public static int getDoorPhoneVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_DOOR_PHONE_VOLUME, door_phone_volume);
+    }
+
+    /**
+     * 设置门口机通话音量
+     *
+     * @param value
+     */
+    public static void setDoorPhoneVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_DOOR_PHONE_VOLUME, value).apply();
+    }
+
+
+
+    /**
+     * 获取白昼设置白天的初始时间
+     *
+     * @return
+     */
+    public static String getInitialDayTime(Context context) {
+        return getSP(context).getString(KEY_SP_INITIAL_DAY_TIME, initial_day_time);
+    }
+
+    /**
+     * 设置白昼白天的初始时间
+     *
+     * @param value
+     */
+    public static void setInitialDayTime(Context context, String value) {
+        getEditor(context).putString(KEY_SP_INITIAL_DAY_TIME, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的初始时间位置
+     *
+     * @return
+     */
+    public static String getInitialDayTimeLocation(Context context) {
+        return getSP(context).getString(KEY_SP_INITIAL_DAY_TIME_LOCATION, initial_day_time_location);
+    }
+
+    /**
+     * 设置白昼白天的初始时间位置
+     *
+     * @param value
+     */
+    public static void setInitialDayTimeLocation(Context context, String value) {
+        getEditor(context).putString(KEY_SP_INITIAL_DAY_TIME_LOCATION, value).apply();
+    }
+
+
+
+    /**
+     * 设置白昼白天的结束时间
+     *
+     * @param value
+     */
+    public static void setEndOfDay(Context context, String value) {
+        getEditor(context).putString(KEY_SP_END_OF_DAY, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的结束时间
+     *
+     * @return
+     */
+    public static String getEndOfDay(Context context) {
+        return getSP(context).getString(KEY_SP_END_OF_DAY, end_of_day);
+    }
+
+    /**
+     * 设置白昼白天的结束时间位置
+     *
+     * @param value
+     */
+    public static void setEndOfDayLocation(Context context, String value) {
+        getEditor(context).putString(KEY_SP_END_OF_DAY_LOCATION, value).apply();
+    }
+
+    /**
+     * 获取白昼设置白天的结束时间位置
+     *
+     * @return
+     */
+    public static String getEndOfDayLocation(Context context) {
+        return getSP(context).getString(KEY_SP_END_OF_DAY_LOCATION, end_of_day_location);
+    }
+
+    /**
+     * 获取点阵屏节目显示时间
+     *
+     * @return
+     */
+    public static int getLedProgramTime(Context context) {
+        return getSP(context).getInt(KEY_SP_LED_PROGRAM_TIME, 6);
+    }
+
+    /**
+     * 设置点阵屏节目显示时间
+     *
+     * @param value
+     */
+    public static void setLedProgramTime(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_LED_PROGRAM_TIME, value).apply();
+    }
+
+    /**
+     * 获取点阵屏语音播报音量
+     *
+     * @return
+     */
+    public static int getLedVoiceVolume(Context context) {
+        return getSP(context).getInt(KEY_SP_LED_VOICE_VOLUME, 5);
+    }
+
+    /**
+     * 设置点阵屏语音播报音量
+     *
+     * @param value
+     */
+    public static void setLedVoiceVolume(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_LED_VOICE_VOLUME, value).apply();
+    }
+
+    /**
+     * 获取点阵屏语音播报次数
+     *
+     * @return
+     */
+    public static int getLedVoiceTimes(Context context) {
+        return getSP(context).getInt(KEY_SP_LED_VOICE_TIMES, 3);
+    }
+
+    /**
+     * 设置点阵屏语音播报次数
+     *
+     * @param value
+     */
+    public static void setLedVoiceTimes(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_LED_VOICE_TIMES, value).apply();
+    }
+
+    /**
+     * 获取点阵屏默认显示类型
+     *
+     * @return
+     */
+    public static int getLedInfoType(Context context) {
+        return getSP(context).getInt(KEY_SP_LED_INFO_TYPE, 0);
+    }
+
+    /**
+     * 设置点阵屏默认显示类型
+     *
+     * @param value
+     */
+    public static void setLedInfoType(Context context, int value) {
+        getEditor(context).putInt(KEY_SP_LED_INFO_TYPE, value).apply();
+    }
+
+    /**
+     * 获取点阵屏默认显示内容
+     *
+     * @return
+     */
+    public static String getLedCustomInfo(Context context) {
+        return getSP(context).getString(KEY_SP_LED_CUSTOM_INFO, "");
+    }
+
+    /**
+     * 设置点阵屏默认显示内容
+     *
+     * @param value
+     */
+    public static void setLedCustomInfo(Context context, String value) {
+        getEditor(context).putString(KEY_SP_LED_CUSTOM_INFO, value).apply();
+    }
+
+    /**
+     * 设置App启动时间
+     *
+     * @param value
+     */
+    public static void setAppStartTime(Context context, String value) {
+        getEditor(context).putString(KEY_SP_APP_START_TIME, value).apply();
+    }
+
+    /**
+     * 获取App启动时间
+     *
+     * @return
+     */
+    public static String getAppStartTime(Context context) {
+        return getSP(context).getString(KEY_SP_APP_START_TIME, "Unknow");
+    }
+
+
+
+
+    private static SharedPreferences getSP(Context context) {
+        return context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
+    }
+
+    private static SharedPreferences.Editor getEditor(Context context) {
+        return getSP(context).edit();
+    }
+
+
+}

+ 265 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AppUpdateHelper.java

@@ -0,0 +1,265 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Environment;
+
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.nursehome.activity.RegisterActivity;
+import com.wdkl.ncs.android.component.nursehome.service.WdklSipService;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import androidx.core.content.FileProvider;
+
+public class AppUpdateHelper {
+    private final static String TAG = "AppUpdate";
+
+    /**
+     * 下载的APK文件绝对路径
+     */
+    public static final String FILE_APK_PATH = Environment.getExternalStorageDirectory() + "/CallingHost";
+    /**
+     * 下载的APK文件的文件名
+     */
+    public static final String FILE_APK_NAME = "CallingHost.apk";
+
+    public static void updateApp(Context context, UpdateCallBack callBack) {
+        if (checkApkExit(context)) {
+            Log.d(TAG, "文件存在");
+        } else {
+            Log.d(TAG, "文件不存在");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+            return;
+        }
+
+        /*if (!checkApkAvailable(context, DownloadUtil.FILE_APK_PATH + "/" + DownloadUtil.FILE_APK_NAME)) {
+            ToastUtil.showToast("apk文件不匹配,升级失败!");
+            return;
+        }*/
+
+        String path = FILE_APK_PATH + "/" + FILE_APK_NAME;
+        //if (installApp(context.getPackageName(), path)) {
+        if (rootSilenceInstall(path)) {
+            Log.d(TAG, "安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        } else {
+            Log.d(TAG, "安装失败");
+            if (callBack != null) {
+                callBack.onFailed();
+            }
+        }
+
+        /*if (silentInstall(context, path)) {
+            Log.d(TAG, "app 安装成功");
+            if (callBack != null) {
+                callBack.onSuccess();
+            }
+        }*/
+    }
+
+
+    public static void installAPK(Context context) {
+        try {
+            File apkFile = new File(FILE_APK_PATH + "/" + FILE_APK_NAME);
+            if (!apkFile.exists()) {
+                return;
+            }
+
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//安装完成后打开新版本
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); // 给目标应用一个临时授权
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//判断版本大于等于7.0
+                //如果SDK版本>=24,即:Build.VERSION.SDK_INT >= 24,使用FileProvider兼容安装apk
+                String packageName = context.getApplicationContext().getPackageName();
+                String authority = new StringBuilder(packageName).append(".fileprovider").toString();
+                Uri apkUri = FileProvider.getUriForFile(context, authority, apkFile);
+                intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
+            } else {
+                intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
+            }
+            context.startActivity(intent);
+        } catch (Exception e) {
+        }
+    }
+
+    private static boolean checkApkExit(Context context) {
+        File file = new File(FILE_APK_PATH + "/" + FILE_APK_NAME);
+        return file.exists();
+    }
+
+    private static boolean checkApkAvailable(Context context, String path) {
+        try {
+            PackageManager pm = context.getPackageManager();
+            PackageInfo info = pm.getPackageArchiveInfo(path, 0);
+            ApplicationInfo applicationInfo = info.applicationInfo;
+            String newPkg = applicationInfo.packageName;
+            String curPkg = context.getPackageName();
+            Log.d(TAG, "new package: " + newPkg + ", cur package: " + curPkg);
+            if (curPkg.equals(newPkg)) {
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return false;
+    }
+
+    public static boolean silentInstall(Context context, String apkPath) {
+        PackageManager packageManager = context.getPackageManager();
+        Class pmClz = packageManager.getClass();
+        try {
+            if (Build.VERSION.SDK_INT >= 21) {
+                Log.d(TAG, "apk path: " + apkPath);
+                Class aClass = Class.forName("android.app.PackageInstallObserver");
+                Constructor constructor = aClass.getDeclaredConstructor();
+                constructor.setAccessible(true);
+                Object installObserver = constructor.newInstance();
+                Method method = pmClz.getDeclaredMethod("installPackage", Uri.class, aClass, int.class, String.class);
+                method.setAccessible(true);
+                method.invoke(packageManager, Uri.fromFile(new File(apkPath)), installObserver, 2, null);
+            } else {
+                Method method = pmClz.getDeclaredMethod("installPackage", Uri.class, Class.forName("android.content.pm.IPackageInstallObserver"), int.class, String.class);
+                method.setAccessible(true);
+                method.invoke(packageManager, Uri.fromFile(new File(apkPath)), null, 2, null);
+            }
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, e.toString());
+        }
+        return false;
+    }
+
+    public static boolean installApp(String packageName, String apkPath) {
+        Process process = null;
+        BufferedReader successResult = null;
+        BufferedReader errorResult = null;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder errorMsg = new StringBuilder();
+        Log.e(TAG, "install package: " + packageName + ", apkPath: " + apkPath);
+        try {
+            process = new ProcessBuilder("pm", "install", "-i", packageName, "-r", apkPath).start();
+            successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
+            String s;
+            while ((s = successResult.readLine()) != null) {
+                successMsg.append(s);
+            }
+            while ((s = errorResult.readLine()) != null) {
+                errorMsg.append(s);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (successResult != null) {
+                    successResult.close();
+                }
+                if (errorResult != null) {
+                    errorResult.close();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+            if (process != null) {
+                process.destroy();
+            }
+        }
+        Log.e(TAG, "" + errorMsg.toString());
+        //如果含有“success”认为安装成功
+        return successMsg.toString().equalsIgnoreCase("success");
+    }
+
+    public static boolean rootSilenceInstall(String path) {
+        Process process;
+        PrintWriter printWriter;
+        try {
+            process = Runtime.getRuntime().exec("su");
+            printWriter = new PrintWriter(process.getOutputStream());
+            printWriter.println("pm install -r " + path);
+            printWriter.flush();
+            printWriter.close();
+            int res = process.waitFor();
+            Log.e(TAG, "silent install res: " + res);
+            if (res == 0) {
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "rootSilenceInstall e:" + e.getMessage());
+            return false;
+        }
+    }
+
+    public static void reboot(Context context) {
+        if (Build.MODEL.equals("rk3128")) {
+            try {
+                Intent intent = new Intent(Intent.ACTION_REBOOT);
+                intent.putExtra("nowait", 1);
+                intent.putExtra("interval", 1);
+                intent.putExtra("window", 0);
+                context.sendBroadcast(intent);
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        } else {
+            Process process;
+            PrintWriter printWriter;
+            try {
+                process = Runtime.getRuntime().exec("su");
+                printWriter = new PrintWriter(process.getOutputStream());
+                printWriter.println("reboot");
+                printWriter.flush();
+                printWriter.close();
+                process.waitFor();
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    public static void restartApp(Context context) {
+        if (SettingConfig.getSipEnabled(context)) {
+            //停止服务
+            Intent serviceIntent = new Intent(context, WdklSipService.class);
+            context.stopService(serviceIntent);
+        }
+
+        //重新启动app
+        Intent mStartActivity = new Intent(context.getApplicationContext(), RegisterActivity.class);
+        mStartActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        int mPendingIntentId = 123456;
+        PendingIntent mPendingIntent = PendingIntent.getActivity(context.getApplicationContext(), mPendingIntentId, mStartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+        AlarmManager mgr = (AlarmManager) context.getApplicationContext().getSystemService(Context.ALARM_SERVICE);
+        mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 1500, mPendingIntent);
+
+        android.os.Process.killProcess(android.os.Process.myPid());
+        System.exit(0);
+    }
+
+    public interface UpdateCallBack {
+        void onFailed();
+        void onSuccess();
+    }
+}

+ 149 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AppUtil.java

@@ -0,0 +1,149 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.AlarmManager;
+import android.content.Context;
+import android.hardware.Camera;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Calendar;
+
+public class AppUtil {
+
+    public static void checkCameraSupport() {
+        int num = Camera.getNumberOfCameras();
+        if (num > 0) {
+            Constant.supportCamera=true;
+        } else {
+            Constant.supportCamera=false;
+        }
+    }
+
+    /**
+     * 设置系统时间
+     *
+     * @param time
+     */
+    public static void setSysTime(String time, String timeZone) {
+        try {
+            Process process = Runtime.getRuntime().exec("su");
+            if (null == process) return;
+            DataOutputStream os = new DataOutputStream(process.getOutputStream());
+            //os.writeBytes("setprop persist.sys.timezone Asia/Shanghai\n");
+            os.writeBytes("setprop persist.sys.timezone " + timeZone + "\n");
+            if (android.os.Build.VERSION.SDK_INT >= 24) {//7.1以上的系统
+                String datetime = changeTimeForm(time); //20211213:092314  ------  051315372019.00
+                os.writeBytes("/system/bin/date " + datetime + " set\n");
+            } else {
+                os.writeBytes("/system/bin/date -s " + time + "\n");//【时间格式 yyyyMMdd.HHmmss】"20131023.112800"
+            }
+            os.writeBytes("clock -w\n");
+            os.writeBytes("exit\n");
+            os.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static String changeTimeForm(String t) {
+        if (!TextUtils.isEmpty(t) && t.length() >= 15) {
+            String yyyy = substringByLengh(t, 0, 4);
+            String MMdd = substringByLengh(t, 4, 8);
+            String HHmm = substringByLengh(t, 9, 13);
+            String ss = substringByLengh(t, 13, 15);
+
+            return MMdd + HHmm + yyyy + "." + ss;
+        } else {
+            return "051315372019.00";
+        }
+    }
+
+    /**
+     * 字符串按索引截取
+     *
+     * @param str
+     * @return
+     */
+    public static String substringByLengh(String str, int start, int end) {
+        if (str == null) {
+            return "";
+        }
+        if (start > end) {
+            return "";
+        }
+        if (str.length() - 1 < start || str.length() < end) {
+            return "";
+        }
+
+        return str.substring(start, end);
+    }
+
+
+    public static void setSystemTime(Context context, int year, int month, int day, int hour, int minute, int mill) {
+        Calendar c = Calendar.getInstance();
+        c.set(Calendar.YEAR, year);
+        c.set(Calendar.MONTH, month);
+        c.set(Calendar.DAY_OF_MONTH, day);
+        c.set(Calendar.HOUR_OF_DAY, hour);
+        c.set(Calendar.MINUTE, minute);
+        c.set(Calendar.SECOND, mill);
+        c.set(Calendar.MILLISECOND, 0);
+        long when = c.getTimeInMillis();
+        if (when / 1000 < Integer.MAX_VALUE) {
+            ((AlarmManager) context.getSystemService(Context.ALARM_SERVICE)).setTime(when);
+        }
+    }
+
+    public static void setSystemTime(Context context, long timeMills, String timeZone) {
+        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        //alarmManager.setTimeZone("Asia/Shanghai");
+        alarmManager.setTimeZone(timeZone);
+        alarmManager.setTime(timeMills);
+    }
+
+    public static void changePingMode() {
+        Process process;
+        PrintWriter printWriter;
+        try {
+            process = Runtime.getRuntime().exec("su");
+            printWriter = new PrintWriter(process.getOutputStream());
+            printWriter.println("mount -o rw,remount -t auto /system");
+            printWriter.println("chmod 777 /system/bin/ping");
+            printWriter.println("exit");
+            printWriter.flush();
+            printWriter.close();
+            int res = process.waitFor();
+            Log.e("AppUtil", "changePingMode res: " + res);
+        } catch (Exception e) {
+            Log.e("AppUtil", "changePingMode exception:" + e.getMessage());
+        }
+    }
+
+    //开启网络调试
+    public static boolean openNetwrokDebug() {
+        try {
+            Process process = Runtime.getRuntime().exec("su");
+            if (null == process) {
+                return false;
+            }
+            DataOutputStream os = new DataOutputStream(process.getOutputStream());
+            os.writeBytes("setprop service.adb.tcp.port 5555\n");
+            os.writeBytes("stop adbd\n");
+            os.writeBytes("start adbd\n");
+            os.writeBytes("exit\n");
+            os.flush();
+            Constant.OPEN_DEBUG=true;
+
+            return true;
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+
+        return false;
+    }
+}

+ 199 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/AsyncPlayer.java

@@ -0,0 +1,199 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.os.SystemClock;
+import android.util.Log;
+
+import java.io.IOException;
+import java.util.LinkedList;
+
+/**
+ * 响铃相关类
+ */
+public class AsyncPlayer {
+    private static final int PLAY = 1;
+    private static final int STOP = 2;
+    private AudioManager audioManager;
+
+    private static final class Command {
+        int code;
+        Context context;
+        int resId;
+        boolean looping;
+        int stream;
+        long requestTime;
+
+        public String toString() {
+            return "{ code=" + code + " looping=" + looping + " stream=" + stream + " resId=" + resId + " }";
+        }
+    }
+
+    private final LinkedList mCmdQueue = new LinkedList();
+
+    private void startSound(Command cmd) {
+
+        try {
+            //MediaPlayer player = new MediaPlayer();
+            MediaPlayer player = MediaPlayer.create(cmd.context, cmd.resId);
+            player.setAudioStreamType(cmd.stream);
+            //player.setDataSource(cmd.context, cmd.uri);
+            player.setLooping(cmd.looping);
+            player.setVolume(1.0f, 1.0f);
+            //player.prepare();
+            player.start();
+            player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer mp) {
+                    mState = STOP;
+                }
+            });
+            if (mPlayer != null) {
+                mPlayer.release();
+            }
+            mPlayer = player;
+            Log.w(mTag, "start sound " + cmd.resId);
+        } catch (Exception e) {
+            Log.w(mTag, "error loading sound for " + cmd.resId, e);
+        }
+    }
+
+    private final class Thread extends java.lang.Thread {
+        Thread() {
+            super("AsyncPlayer-" + mTag);
+        }
+
+        public void run() {
+            while (true) {
+                Command cmd = null;
+
+                synchronized (mCmdQueue) {
+
+                    cmd = (Command) mCmdQueue.removeFirst();
+                }
+
+                switch (cmd.code) {
+                    case PLAY:
+                        startSound(cmd);
+                        break;
+                    case STOP:
+
+                        if (mPlayer != null) {
+                            mPlayer.stop();
+                            mPlayer.reset();
+                            mPlayer.release();
+                            mPlayer = null;
+                        } else {
+                            Log.w(mTag, "STOP command without a player");
+                        }
+                        break;
+                }
+
+                synchronized (mCmdQueue) {
+                    if (mCmdQueue.size() == 0) {
+
+                        mThread = null;
+                        releaseWakeLock();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private String mTag;
+    private Thread mThread;
+    private MediaPlayer mPlayer;
+    private PowerManager.WakeLock mWakeLock;
+
+    private int mState = STOP;
+
+    public AsyncPlayer(String tag) {
+        if (tag != null) {
+            mTag = tag;
+        } else {
+            mTag = "AsyncPlayer";
+        }
+    }
+
+    public void play(Context context, int res, boolean looping, int stream) {
+        Command cmd = new Command();
+        cmd.requestTime = SystemClock.uptimeMillis();
+        cmd.code = PLAY;
+        cmd.context = context;
+        cmd.resId = res;
+        cmd.looping = looping;
+        cmd.stream = stream;
+        synchronized (mCmdQueue) {
+            enqueueLocked(cmd);
+            mState = PLAY;
+        }
+    }
+
+    public void stop() {
+        synchronized (mCmdQueue) {
+            if (mState != STOP) {
+                Command cmd = new Command();
+                cmd.requestTime = SystemClock.uptimeMillis();
+                cmd.code = STOP;
+                enqueueLocked(cmd);
+                mState = STOP;
+            }
+        }
+    }
+
+    public boolean isPlay() {
+        return mState == PLAY;
+    }
+
+    private void enqueueLocked(Command cmd) {
+        mCmdQueue.add(cmd);
+        if (mThread == null) {
+            acquireWakeLock();
+            mThread = new Thread();
+            mThread.start();
+        }
+    }
+
+    public void setUsesWakeLock(Context context) {
+        if (mWakeLock != null || mThread != null) {
+            throw new RuntimeException("assertion failed mWakeLock=" + mWakeLock + " mThread=" + mThread);
+        }
+        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+    }
+
+    private void acquireWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.acquire();
+        }
+    }
+
+    private void releaseWakeLock() {
+        if (mWakeLock != null) {
+            mWakeLock.release();
+        }
+    }
+
+    private boolean isHeadphonesPlugged(Context context) {
+        if (audioManager == null) {
+            audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        }
+        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
+            AudioDeviceInfo[] audioDevices = audioManager.getDevices(AudioManager.GET_DEVICES_ALL);
+            for (AudioDeviceInfo deviceInfo : audioDevices) {
+                if (deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADPHONES
+                        || deviceInfo.getType() == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
+                    return true;
+                }
+            }
+            return false;
+        } else {
+            return audioManager.isWiredHeadsetOn();
+        }
+    }
+}

+ 92 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/CallDialogHelper.java

@@ -0,0 +1,92 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.media.AudioManager;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+
+
+public class CallDialogHelper {
+
+    private static AlertDialog callDialog;
+
+    public static void showCallDialog(Activity activity, int callType, String callText, View.OnClickListener hangupCall, View.OnClickListener acceptCall, View.OnClickListener rejectCall) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.call_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        LinearLayout outCall = contentView.findViewById(R.id.ll_call_outgoing);
+        ImageView hangup = contentView.findViewById(R.id.iv_hangup_call);
+
+        RelativeLayout inCall = contentView.findViewById(R.id.rl_call_incoming);
+        ImageView accept = contentView.findViewById(R.id.iv_accept_call);
+        ImageView reject = contentView.findViewById(R.id.iv_reject_call);
+        TextView inText = contentView.findViewById(R.id.tv_incoming_call_text);
+        TextView outText = contentView.findViewById(R.id.tv_out_call_text);
+
+        if (callType == 0) {
+            //去电
+            outCall.setVisibility(View.VISIBLE);
+            inCall.setVisibility(View.GONE);
+            outText.setText(callText);
+            RingPlayHelper.playRingTone(activity, R.raw.ring_back2, true);
+        } else {
+            //来电
+            outCall.setVisibility(View.GONE);
+            inCall.setVisibility(View.VISIBLE);
+            inText.setText(callText);
+            /*if (SettingConfig.getTtsMode(activity) == SettingConfig.TTS_OFF) {
+                RingPlayHelper.playRingTone(activity, R.raw.incoming_call, false);
+            }*/
+        }
+
+        hangup.setOnClickListener(hangupCall);
+        accept.setOnClickListener(acceptCall);
+        reject.setOnClickListener(rejectCall);
+
+        callDialog = builder.create();
+        callDialog.setCanceledOnTouchOutside(false);
+        callDialog.setCancelable(false);
+
+        //设置dialog宽高及位置
+        try {
+            Window window = callDialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            callDialog.show();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 600;
+            lp.height = 320;
+            lp.gravity = Gravity.CENTER;
+            //lp.alpha = 0.8f;//设置透明度
+            window.setAttributes(lp);
+
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        if (callDialog != null && callDialog.isShowing()) {
+            callDialog.dismiss();
+            RingPlayHelper.stopRingTone();
+            SpeechUtil.getInstance().stopSpeak(true);
+        }
+    }
+}

+ 14 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/EthernetWifiCallBack.java

@@ -0,0 +1,14 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+/**
+ * ======================以太网和wifi状态接口=====================
+ * Created by dengzhe on 2018/2/7.
+ */
+
+public interface EthernetWifiCallBack {
+
+    boolean ethernetStatus(boolean status);//以太网状态
+
+    boolean wifiStatus(boolean status);//wifi状态
+
+}

+ 190 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/HttpHelper.java

@@ -0,0 +1,190 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import okhttp3.Call;
+import okhttp3.Callback;
+import okhttp3.MediaType;
+import okhttp3.MultipartBody;
+import okhttp3.OkHttpClient;
+import okhttp3.Request;
+import okhttp3.RequestBody;
+import okhttp3.Response;
+
+import static com.wdkl.ncs.android.component.nursehome.util.AppUpdateHelper.FILE_APK_NAME;
+import static com.wdkl.ncs.android.component.nursehome.util.AppUpdateHelper.FILE_APK_PATH;
+
+public class HttpHelper {
+    private final static String TAG = "HttpHelper";
+    private static OkHttpClient okHttpClient = null;
+
+    /**
+     * @param url   服务器地址
+     * @param file  所要上传的文件
+     */
+    public static void upload(String url, File file, Object tag, final UploadCallback callback) {
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
+
+        RequestBody requestBody = new MultipartBody.Builder()
+                .setType(MultipartBody.FORM)
+                .addFormDataPart("file", file.getName(), RequestBody.create(MediaType.parse("multipart/form-data"), file))
+                .build();
+
+        Request request = new Request.Builder()
+                .url(url)
+                .tag(tag)
+                .post(requestBody)
+                .build();
+
+        okHttpClient.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                if (callback != null) {
+                    callback.onFail();
+                }
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) throws IOException {
+                Log.d(TAG, "upload file response: " + response.toString());
+               if( response.code()==200 && response.body() != null) {
+                   String data = response.body().string();
+                   //voice msg response: upload/file/202104102037715.mp3
+                   if (callback != null) {
+                       callback.onSuccess(data);
+                   }
+               } else {
+                   if (callback != null) {
+                       callback.onFail();
+                   }
+               }
+            }
+        });
+    }
+
+    public static void download(String url, Object tag, final DownloadListener listener) {
+        if (okHttpClient == null) {
+            okHttpClient = new OkHttpClient();
+        }
+
+        Request request = new Request.Builder()
+                .url(url)
+                .tag(tag)
+                .build();
+
+        okHttpClient.newCall(request).enqueue(new Callback() {
+            @Override
+            public void onFailure(Call call, IOException e) {
+                Log.d("download", "onFailure==" + e.toString());
+                if (listener != null) {
+                    listener.onDownloadFailed(); // 下载失败
+                }
+            }
+
+            @Override
+            public void onResponse(Call call, Response response) {
+                Log.d("download", "response==" + response.body().contentLength());
+                InputStream is = null;
+                byte[] buf = new byte[2048];
+                int len;
+                FileOutputStream fos = null;
+                try {
+                    is = response.body().byteStream();
+                    long total = response.body().contentLength();
+                    File file = new File(isHaveExistDir(new File(FILE_APK_PATH), new File(FILE_APK_PATH + "/" + FILE_APK_NAME)), FILE_APK_NAME);
+                    fos = new FileOutputStream(file);
+                    long sum = 0;
+                    while ((len = is.read(buf)) != -1) {
+                        fos.write(buf, 0, len);
+                        sum = sum + (long) len;
+                        //int progress = (int) (sum * 1.0f / total * 100);
+                        float sp = (float) sum / (float) total;
+                        int progress = (int) (sp * 100);
+                        Log.d("download", "progress==" + progress);
+                        if (listener != null) {
+                            listener.onDownloading(progress);// 下载中
+                        }
+                    }
+                    fos.flush();
+                    if (listener != null) {
+                        listener.onDownloadSuccess(); // 下载完成
+                    }
+                } catch (Exception e) {
+                    Log.d("download", "Exception==");
+                    if (listener != null) {
+                        listener.onDownloadFailed();
+                    }
+                } finally {
+                    try {
+                        if (is != null)
+                            is.close();
+                        if (fos != null)
+                            fos.close();
+                    } catch (IOException e) {
+                        Log.d("download", "IOException==");
+                    }
+                }
+            }
+        });
+    }
+
+    public static void cancelRequestByTag(Object tag) {
+        if (okHttpClient != null && tag != null) {
+            for (Call call : okHttpClient.dispatcher().queuedCalls()) {
+                if (tag.equals(call.request().tag())) {
+                    call.cancel();
+                }
+            }
+
+            for (Call call : okHttpClient.dispatcher().runningCalls()) {
+                if (tag.equals(call.request().tag())) {
+                    call.cancel();
+                }
+            }
+        }
+    }
+
+    private static String isHaveExistDir(File downloadFile, File sonFile) throws IOException {
+        Log.d("download", "downloadFile.mkdirs()==" + downloadFile.mkdirs());
+        Log.d("download", "sonFile.mkdir()==" + sonFile.mkdir());
+        if (!downloadFile.mkdirs()) {
+            downloadFile.createNewFile();
+        }
+        deleteAPKFile(sonFile);//只要文件名相同就可以自动替换(按道理此处不需要了,但为了保险起见还是先执行删除操作)。
+        return downloadFile.getAbsolutePath();
+    }
+
+    public static boolean deleteAPKFile(File downloadFile) {
+        return downloadFile.delete();
+    }
+
+
+    public interface UploadCallback{
+        void onFail();
+        void onSuccess(String data);
+    }
+
+    public interface DownloadListener {
+        /**
+         * 下载成功
+         */
+        void onDownloadSuccess();
+
+        /**
+         * @param progress 下载进度
+         */
+        void onDownloading(int progress);
+
+        /**
+         * 下载失败
+         */
+        void onDownloadFailed();
+    }
+}

+ 139 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LanguageSetDialogHelper.java

@@ -0,0 +1,139 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.os.Handler;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.RadioButton;
+import android.widget.RadioGroup;
+import android.widget.Spinner;
+import android.widget.Toast;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+
+public class LanguageSetDialogHelper {
+
+    private static AlertDialog dialog;
+    private static int selectIndex;
+
+    public static void showDialog(final Activity activity) {
+        if (dialog != null && dialog.isShowing()) {
+            return;
+        }
+
+        final int originIndex = LocaleMangerUtils.getCurrentLocaleIndex();
+        selectIndex = originIndex;
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.language_set_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        RadioButton btnYes = contentView.findViewById(R.id.rb_language_yes);
+        RadioButton btnNo = contentView.findViewById(R.id.rb_language_no);
+        final int mode = SettingConfig.getLanguageMode(activity);
+        if (mode == 0) {
+            btnYes.setChecked(true);
+        } else {
+            btnNo.setChecked(true);
+        }
+
+        Button buttonCancel = contentView.findViewById(R.id.cancel_button);
+        Button buttonConfirm = contentView.findViewById(R.id.confirm_button);
+        Spinner spinner = contentView.findViewById(R.id.spinner_language_select);
+        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(activity,
+                R.array.language_list, R.layout.spinner_item);
+        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+        spinner.setAdapter(adapter);
+        spinner.setSelection(originIndex);
+        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                Log.d("languageId", "pos: " + position + ", originIndex: " + originIndex);
+                selectIndex = position;
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+
+            }
+        });
+
+        RadioGroup languageGroup = contentView.findViewById(R.id.group_language_mode);
+        languageGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
+            @Override
+            public void onCheckedChanged(RadioGroup group, int checkedId) {
+                if (checkedId == R.id.rb_language_yes) {
+                    SettingConfig.setLanguageMode(activity, 0);
+                } else {
+                    SettingConfig.setLanguageMode(activity, 1);
+                }
+            }
+        });
+
+        buttonCancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        buttonConfirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                SettingConfig.setLanguageId(activity, selectIndex);
+
+                if (SettingConfig.getLanguageMode(activity) == 1) {
+                    if (selectIndex != originIndex) {
+                        Toast.makeText(activity, "restart now...", Toast.LENGTH_LONG).show();
+                        new Handler().postDelayed(new Runnable() {
+                            @Override
+                            public void run() {
+                                AppUpdateHelper.restartApp(activity);
+                            }
+                        }, 3000);
+                    }
+                } else {
+                    Toast.makeText(activity, "restart now...", Toast.LENGTH_LONG).show();
+                    new Handler().postDelayed(new Runnable() {
+                        @Override
+                        public void run() {
+                            AppUpdateHelper.restartApp(activity);
+                        }
+                    }, 3000);
+                }
+
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        dialog = builder.create();
+        //dialog.setCanceledOnTouchOutside(false);
+        //dialog.setCancelable(false);
+        dialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = dialog.getWindow();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 360;
+            lp.height = 320;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 120 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LedHelper.java

@@ -0,0 +1,120 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.util.Log;
+
+import com.google.common.base.Strings;
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+import com.wdkl.ncs.android.component.nursehome.led.LedManagerUtils;
+import com.wdkl.ncs.android.middleware.model.vo.InteractionVO;
+import com.wdkl.ncs.android.middleware.tcp.enums.DeviceTypeEnum;
+import com.wdkl.ncs.android.middleware.tcp.enums.TcpType;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+public class LedHelper {
+
+    public static void updateLedInfo(InteractionVO interactionVO, boolean isAdd, boolean emergency) {
+        //没有点阵屏设备,直接返回
+        if (!Constant.LED_EXIST) {
+            Log.e("led", "no led device.");
+            return;
+        }
+
+        if (interactionVO.getActionType().equals(TcpType.REINFORCE.name())) {
+            String frameName = CommonUtils.subStringBefore(interactionVO.getFromFrameFullName(), "-");
+            String reinforce = BaseApplication.appContext.getString(R.string.led_show_reinforce, frameName);
+            if (isAdd) {
+                //新增led节目
+                LedManagerUtils.getInstance().updateProgram(reinforce, 1);
+            } else {
+                //删除led节目
+                LedManagerUtils.getInstance().updateProgram(reinforce, 2);
+            }
+            return;
+        }
+
+        Log.d("led", "update led info, deviceType: " + interactionVO.getFromDeviceType() + ", frameName: " + interactionVO.getFromFrameFullName() + ", data: " + interactionVO.getData());
+        if (interactionVO.getFromDeviceType() == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                || interactionVO.getFromDeviceType() == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+            //如果交互记录中的fromdevice是分机,有可能是数字分机发送过来的紧急呼叫,需要特别处理
+            if (emergency) {
+                String frameName = CommonUtils.subStringBefore(interactionVO.getFromFrameFullName(), "-");
+                String sosCall = BaseApplication.appContext.getString(R.string.led_show_emergency_call, frameName);
+                if (isAdd) {
+                    //新增led节目
+                    LedManagerUtils.getInstance().updateProgram(sosCall, 1);
+                } else {
+                    //删除led节目
+                    LedManagerUtils.getInstance().updateProgram(sosCall, 2);
+                }
+            } else {
+                String frameName = interactionVO.getFromFrameFullName().replace("-", "");
+                String call = BaseApplication.appContext.getString(R.string.led_show_voice_call, frameName);
+                if (isAdd) {
+                    //新增led节目
+                    LedManagerUtils.getInstance().updateProgram(call, 1);
+                } else {
+                    //删除led节目
+                    LedManagerUtils.getInstance().updateProgram(call, 2);
+                }
+            }
+        } else if (interactionVO.getFromDeviceType() == DeviceTypeEnum.EMERGENCY_BUTTON.value()
+                || interactionVO.getFromDeviceType() == DeviceTypeEnum.SIMULATE_EMERGENCY_BUTTON.value()) {
+            //紧急呼叫
+            String frameName = CommonUtils.subStringBefore(interactionVO.getFromFrameFullName(), "-");
+            if (SettingConfig.getSosCallNameOn(BaseApplication.appContext)) {
+                frameName = interactionVO.getFromDeviceName();
+            }
+
+            if (Strings.isNullOrEmpty(interactionVO.getData())) {
+                if (isAdd) {
+                    //新增led节目
+                    LedManagerUtils.getInstance().updateProgram(interactionVO.getData(), 1);
+                } else {
+                    //删除led节目
+                    LedManagerUtils.getInstance().updateProgram(interactionVO.getData(), 2);
+                }
+            } else {
+                if (isAdd) {
+                    //新增led节目
+                    LedManagerUtils.getInstance().updateProgram(BaseApplication.appContext.getString(R.string.led_show_emergency_call, frameName), 1);
+                } else {
+                    //删除led节目
+                    LedManagerUtils.getInstance().updateProgram(BaseApplication.appContext.getString(R.string.led_show_emergency_call, frameName), 2);
+                }
+            }
+        } else if (interactionVO.getFromDeviceType() == DeviceTypeEnum.ALARM_BUTTON_SOS.value()
+                || interactionVO.getFromDeviceType() == DeviceTypeEnum.ALARM_433BUTTON.value()) {
+            String frameName = CommonUtils.subStringBefore(interactionVO.getFromFrameFullName(), "-");
+            if (Strings.isNullOrEmpty(interactionVO.getData())) {
+                frameName = BaseApplication.appContext.getString(R.string.led_show_emergency_call, frameName);
+            } else {
+                frameName = interactionVO.getData();
+            }
+
+            if (isAdd) {
+                //新增led节目
+                LedManagerUtils.getInstance().updateProgram(frameName, 1);
+            } else {
+                //删除led节目
+                LedManagerUtils.getInstance().updateProgram(frameName, 2);
+            }
+        }
+    }
+
+    public static void cancelLedInfo(InteractionVO interactionVO) {
+        //没有点阵屏设备,直接返回
+        if (!Constant.LED_EXIST) {
+            return;
+        }
+
+        if (interactionVO.getToDeviceType() == DeviceTypeEnum.DIGIT_BED_DEVICE.value()
+                || interactionVO.getToDeviceType() == DeviceTypeEnum.SIMULATE_BED_DEVICE.value()) {
+            String frameName = interactionVO.getToFrameFullName().replace("-", "");
+            String call = BaseApplication.appContext.getString(R.string.led_show_voice_call, frameName);
+            LedManagerUtils.getInstance().updateProgram(call, 2);
+        }
+    }
+}

+ 79 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/LocaleMangerUtils.java

@@ -0,0 +1,79 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.os.Build;
+import android.util.DisplayMetrics;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+import java.util.Locale;
+
+public class LocaleMangerUtils {
+
+    public static Locale getSystemLocale() {
+        return Locale.getDefault();
+    }
+
+    //获取当前语言id: 0--auto, 1--English, 2--中文, 3--俄语, 4--西班牙语
+    public static int getCurrentLocaleIndex() {
+        int languageSize = BaseApplication.appContext.getResources().getStringArray(R.array.language_list).length;
+        int index = SettingConfig.getLanguageId(BaseApplication.appContext);
+        //Log.d("wzl", "current language index: " + index);
+        if (index >= 0 && index <languageSize) {
+            return index;
+        } else {
+            return 0;
+        }
+    }
+
+    public static void setApplicationLanguageByIndex(Context context, int index) {
+        Locale locale = Locale.getDefault();
+        switch (index) {
+            case 0:
+                //
+                break;
+            case 1:
+                locale = Locale.ENGLISH;
+                break;
+            case 2:
+                locale = Locale.CHINESE;
+                break;
+            case 3:
+                locale = new Locale("es");
+                break;
+            case 4:
+                locale = new Locale("ru");
+                break;
+        }
+
+        setApplicationLanguage(context, locale);
+    }
+
+    public static void setApplicationLanguage(Context context, Locale locale) {
+        //Log.d("wzl", "set locale language: " + locale.getLanguage());
+        Configuration configuration = context.getResources().getConfiguration();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            configuration.setLocale(locale);
+        } else {
+            configuration.locale = locale;
+        }
+        // 更新context中的语言设置
+        Resources resources = context.getResources();
+        DisplayMetrics dm = resources.getDisplayMetrics();
+        resources.updateConfiguration(configuration, dm);
+    }
+
+    public static Locale getApplicationLocale() {
+        Configuration config = BaseApplication.appContext.getResources().getConfiguration();
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+            return config.locale;
+        } else {
+            return config.getLocales().get(0);
+        }
+    }
+
+}

+ 225 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/MediaPlayHelper.java

@@ -0,0 +1,225 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.media.AudioManager;
+import android.media.MediaPlayer;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+
+public class MediaPlayHelper {
+
+    private static MediaPlayHelper sInstance = null;
+    private MediaPlayer mediaPlayer;
+    private HandlerThread playHandlerThread;
+    private Handler playHandler;
+
+    private int mResId;
+    private String mUrl;
+    private float mVolume;
+    private boolean mLoop;
+
+    /**
+     * 播放res资源
+     */
+    public static final int PLAY_RES = 100;
+    /**
+     * 播放url资源
+     */
+    public static final int PLAY_URL = 101;
+    /**
+     * 停止
+     */
+    public static final int STOP = 102;
+    /**
+     * 释放
+     */
+    public static final int RELEASE = 103;
+
+
+    private MediaPlayHelper() {
+        createHandlerThread();
+    }
+
+    public static MediaPlayHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (MediaPlayHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new MediaPlayHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    private void createHandlerThread() {
+        if (playHandlerThread == null) {
+            playHandlerThread = new HandlerThread("playHandlerThread");
+            playHandlerThread.start();
+        }
+
+        if (playHandler == null) {
+            playHandler = new Handler(playHandlerThread.getLooper()) {
+                @Override
+                public void handleMessage(Message msg) {
+                    switch (msg.what) {
+                        case PLAY_RES:
+                            playResMusicNow();
+                            break;
+                        case PLAY_URL:
+                            playUrlMusicNow();
+                            break;
+                        case STOP:
+                            stopMusicNow();
+                            break;
+                        case RELEASE:
+                            releaseMediaNow();
+                            break;
+                        default:
+                            break;
+                    }
+                }
+            };
+        }
+    }
+
+    public void playResMusic(int id, float vol, boolean loop) {
+        mResId = id;
+        mVolume = vol;
+        mLoop = loop;
+        playHandler.sendEmptyMessage(PLAY_RES);
+    }
+
+    public void playUrlMusic(String url, float vol, boolean loop) {
+        mUrl = url;
+        mVolume = vol;
+        mLoop = loop;
+        playHandler.sendEmptyMessage(PLAY_URL);
+    }
+
+    public void stopMusic() {
+        playHandler.sendEmptyMessage(STOP);
+    }
+
+    public void releaseMusic() {
+        playHandler.sendEmptyMessage(RELEASE);
+    }
+
+    //播放本地res音频资源
+    private void playResMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.stop();
+            mediaPlayer.reset();
+            mediaPlayer.release();
+        }
+        mediaPlayer = MediaPlayer.create(BaseApplication.appContext, mResId);
+        try {
+            mediaPlayer.setLooping(mLoop);
+            mediaPlayer.setVolume(mVolume, mVolume);
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mediaPlayer.start();
+            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer player) {
+                    //playMusicComplete();
+                    //stopMusicNow();
+                }
+            });
+            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer player, int what, int extra) {
+                    //playMusicError();
+                    stopMusicNow();
+                    return false;
+                }
+            });
+        } catch (Exception e) {
+            //playMusicError();
+            e.printStackTrace();
+        }
+    }
+
+    //播放远程或本地存储音频资源
+    private void playUrlMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.stop();
+            mediaPlayer.reset();
+            mediaPlayer.release();
+        }
+        mediaPlayer = new MediaPlayer();
+        try {
+            mediaPlayer.reset();
+            mediaPlayer.setDataSource(mUrl);
+            mediaPlayer.setLooping(mLoop);
+            mediaPlayer.setVolume(mVolume, mVolume);
+            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
+            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
+                @Override
+                public void onPrepared(MediaPlayer player) {
+                    if (mediaPlayer != null) {
+                        mediaPlayer.start();
+                    }
+                }
+            });
+            mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
+                @Override
+                public void onCompletion(MediaPlayer player) {
+                    //playMusicComplete();
+                    //stopMusicNow();
+                }
+            });
+            mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
+                @Override
+                public boolean onError(MediaPlayer player, int what, int extra) {
+                    //playMusicError();
+                    stopMusicNow();
+                    return false;
+                }
+            });
+            mediaPlayer.prepareAsync();
+        } catch (Exception e) {
+            //playMusicError();
+            e.printStackTrace();
+        }
+    }
+
+    private void stopMusicNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.setOnPreparedListener(null);
+            mediaPlayer.setOnCompletionListener(null);
+            try {
+                //if (mediaPlayer.isPlaying()) {
+                    mediaPlayer.stop();
+                    mediaPlayer.reset();
+                    mediaPlayer.release();
+                //}
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+    }
+
+    private void releaseMediaNow() {
+        if (mediaPlayer != null) {
+            mediaPlayer.setOnPreparedListener(null);
+            mediaPlayer.setOnCompletionListener(null);
+            try {
+                mediaPlayer.stop();
+                mediaPlayer.reset();
+                mediaPlayer.release();
+            } catch (IllegalStateException e) {
+                e.printStackTrace();
+            }
+        }
+        mediaPlayer = null;
+    }
+
+    public boolean isMediaPlaying() {
+        if (mediaPlayer != null) {
+            return mediaPlayer.isPlaying();
+        }
+        return false;
+    }
+}

+ 571 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/NetHelper.java

@@ -0,0 +1,571 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.annotation.SuppressLint;
+import android.bluetooth.BluetoothAdapter;
+import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Build;
+import android.text.TextUtils;
+
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.utils.EthernetUtils;
+import com.wdkl.ncs.android.lib.utils.NetParam;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+
+
+public class NetHelper {
+    private WifiManager wifiManager;
+    private ConnectivityManager connManager;
+    private static NetHelper sInstance = null;
+
+    private static Timer timerNetStatus = null;
+    private static final int SCHEDULE_TIME = 30000;
+    public static boolean NetConn = false;
+
+    /**
+     * 以太网是否ping成功
+     */
+    public static final String ETHERNETSTATUS = "ethernetStatus";
+
+    public NetHelper() {
+    }
+
+    public static NetHelper getInstance() {
+        if (sInstance == null) {
+            synchronized (NetHelper.class) {
+                if (sInstance == null) {
+                    sInstance = new NetHelper();
+                }
+            }
+        }
+        return sInstance;
+    }
+
+    public void init() {
+        wifiManager = (WifiManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
+        connManager = (ConnectivityManager) BaseApplication.appContext.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
+    }
+
+    public static void startNetCheck() {
+        if (timerNetStatus != null) {
+            timerNetStatus.purge();
+        }
+        timerNetStatus = new Timer();
+        timerNetStatus.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                NetConn = ping(getLocalElement(3), 2, null);
+
+//                EventBus.getDefault().post(new MessageEvent(ETHERNETSTATUS, EVENT_INTERNETPING));//循环检测SIP,以太网ping状态
+            }
+        }, 10, SCHEDULE_TIME);
+    }
+
+    /**
+     * ping 网络
+     *
+     * @param host
+     * @param pingCount
+     * @param stringBuffer
+     * @return
+     */
+    public static boolean ping(String host, int pingCount, StringBuffer stringBuffer) {
+        String line = null;
+        Process process = null;
+        BufferedReader successReader = null;
+        String command = "ping -c " + pingCount + " " + host;
+        boolean isSuccess = false;
+        try {
+            process = Runtime.getRuntime().exec(command);
+            if (process == null) {
+                append(stringBuffer, "ping fail:process is null.");
+                return false;
+            }
+            successReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+            while ((line = successReader.readLine()) != null) {
+                append(stringBuffer, line);
+            }
+            int status = process.waitFor();
+            if (status == 0) {
+                append(stringBuffer, "exec cmd success:" + command);
+                isSuccess = true;
+            } else {
+                append(stringBuffer, "exec cmd fail.");
+                isSuccess = false;
+            }
+            append(stringBuffer, "exec finished.");
+        } catch (IOException e) {
+        } catch (InterruptedException e) {
+        } finally {
+            if (process != null) {
+                process.destroy();
+            }
+            if (successReader != null) {
+                try {
+                    successReader.close();
+                } catch (IOException e) {
+                }
+            }
+        }
+
+        return isSuccess;
+    }
+
+    private static void append(StringBuffer stringBuffer, String text) {
+        if (stringBuffer != null) {
+            stringBuffer.append(text + "\n");
+        }
+    }
+
+    /**
+     * 获取网关  Waderson
+     * <p>
+     * 1 WIFI情况下获取网关 2 有线网络下的DHCP模式连接 3 有线网络其他连接方式:比如静态ip、pppoe拨号、ipoe拨号等
+     */
+    public static String getLocalElement(int type) {
+        String e = "";
+        if (1 == type) {
+            //e = getLocalElementByWifi();
+        } else if (2 == type) {
+            e = getLocalElementByDhcp();
+        } else if (3 == type) {
+            e = getLocalElementByIp();
+        }
+        if (!TextUtils.isEmpty(e) && e.length() >= 11 && e.length() <= 15) {
+            return e;
+        } else {
+            return "192.168.101.1";
+        }
+    }
+
+
+    /**
+     * 有线网络下的DHCP模式连接
+     */
+    public static String getLocalElementByDhcp() {
+        BufferedReader bufferedReader = null;
+        String str2 = "";
+        String str3 = "getprop dhcp.eth0.gateway";
+        Process exec;
+        BufferedReader bufferedReader2 = null;
+        try {
+            exec = Runtime.getRuntime().exec(str3);
+            try {
+                bufferedReader2 = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+            } catch (Throwable th3) {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+            }
+            try {
+                str3 = bufferedReader2.readLine();
+                if (str3 != null) {
+                    TextUtils.isEmpty(str3);
+                }
+                try {
+                    bufferedReader2.close();
+                } catch (IOException iOException222) {
+                    iOException222.printStackTrace();
+                }
+                if (exec != null) {
+                    try {
+                        exec.exitValue();
+                    } catch (Exception e5) {
+                    }
+                }
+            } catch (IOException e6) {
+                str3 = str2;
+                if (bufferedReader2 != null) {
+                    bufferedReader2.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+                return str3;
+            }
+        } catch (IOException e62) {
+            bufferedReader2 = null;
+            exec = null;
+            str3 = str2;
+            if (bufferedReader2 != null) {
+                try {
+                    bufferedReader2.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+            return str3;
+        } catch (Throwable th4) {
+            exec = null;
+            if (bufferedReader != null) {
+                try {
+                    bufferedReader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+        }
+        return str3;
+    }
+
+    /**
+     * 有线网络其他连接方式:比如静态ip、pppoe拨号、ipoe拨号等
+     */
+    public static String getLocalElementByIp() {
+        BufferedReader bufferedReader = null;
+        String result = "";
+        String str2 = "";
+        String str3 = "ip route list table 0";
+        Process exec;
+        BufferedReader bufferedReader2 = null;
+        try {
+            exec = Runtime.getRuntime().exec(str3);
+            try {
+                bufferedReader2 = new BufferedReader(new InputStreamReader(exec.getInputStream()));
+            } catch (Throwable th3) {
+                if (bufferedReader != null) {
+                    bufferedReader.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+            }
+            try {
+                str2 = bufferedReader2.readLine();
+                if (str2 != null) {
+                    str2 = str2.trim();
+                    String[] strings = str2.split("\\s+");
+                    if (strings.length > 3) {
+                        result = strings[2];
+                    }
+                }
+                try {
+                    bufferedReader2.close();
+                } catch (IOException iOException222) {
+                    iOException222.printStackTrace();
+                }
+                if (exec != null) {
+                    try {
+                        exec.exitValue();
+                    } catch (Exception e5) {
+                    }
+                }
+            } catch (IOException e6) {
+                if (bufferedReader2 != null) {
+                    bufferedReader2.close();
+                }
+                if (exec != null) {
+                    exec.exitValue();
+                }
+                return result;
+            }
+        } catch (IOException e62) {
+            bufferedReader2 = null;
+            exec = null;
+            if (bufferedReader2 != null) {
+                try {
+                    bufferedReader2.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+            return result;
+        } catch (Throwable th4) {
+            exec = null;
+            if (bufferedReader != null) {
+                try {
+                    bufferedReader.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (exec != null) {
+                exec.exitValue();
+            }
+        }
+        return result;
+    }
+
+    /**
+     * 得到MAC
+     *
+     * @return String
+     */
+    public String getMacAddress() {
+
+        if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.O || Build.MODEL.equals("rk3368")){//小于安卓8 走这里
+            String mac = "";
+            try {
+                mac = getLocalMacAddressFromIp();
+                if (TextUtils.isEmpty(mac)) {
+                    mac = getNetworkMac();
+                }
+                if (TextUtils.isEmpty(mac)) {
+                    mac = tryGetWifiMac();
+                }
+            } catch (Exception e) {
+            }
+            return mac;
+        }else {//大于安卓8走这里
+            List<NetworkInterface> interfaces = null;
+            try {
+                interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+                for (NetworkInterface networkInterface : interfaces) {
+                    if (networkInterface != null && TextUtils.isEmpty(networkInterface.getName()) == false) {
+                        if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
+                            byte[] macBytes = networkInterface.getHardwareAddress();
+                            if (macBytes != null && macBytes.length > 0) {
+                                StringBuilder str = new StringBuilder();
+                                for (byte b : macBytes) {
+                                    str.append(String.format("%02X:", b));
+                                }
+                                if (str.length() > 0) {
+                                    str.deleteCharAt(str.length() - 1);
+                                }
+                                return str.toString();
+                            }
+                        }
+                    }
+                }
+            } catch (SocketException e) {
+                e.printStackTrace();
+            }
+            return "unknown";
+
+        }
+    }
+
+    /**
+     * 兼容安卓5-10 获取Mac地址
+     * @return
+     */
+    public String getMacAddress2() {
+        List<NetworkInterface> interfaces = null;
+        try {
+            interfaces = Collections.list(NetworkInterface.getNetworkInterfaces());
+            for (NetworkInterface networkInterface : interfaces) {
+                if (networkInterface != null && TextUtils.isEmpty(networkInterface.getName()) == false) {
+                    if ("wlan0".equalsIgnoreCase(networkInterface.getName())) {
+                        byte[] macBytes = networkInterface.getHardwareAddress();
+                        if (macBytes != null && macBytes.length > 0) {
+                            StringBuilder str = new StringBuilder();
+                            for (byte b : macBytes) {
+                                str.append(String.format("%02X:", b));
+                            }
+                            if (str.length() > 0) {
+                                str.deleteCharAt(str.length() - 1);
+                            }
+                            return str.toString();
+                        }
+                    }
+                }
+            }
+        } catch (SocketException e) {
+            e.printStackTrace();
+        }
+        return "unknown";
+    }
+
+    public static NetParam getNetInfo(Context context) {
+        try {
+            int type = EthernetUtils.getEthUseDhcpOrStaticIp(context);
+            if ( type == 1) {
+                //静态ip
+                return EthernetUtils.getEthInfoFromStaticIp(context);
+            } else if (type == 2){
+                //动态IP
+                return EthernetUtils.getEthInfoFromDhcp(context);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    /**
+     * 通过WiFiManager获取mac地址
+     * 这个方法Android 7.0是获取不到的,返回的是null,其实是返回“02:00:00:00:00:00”
+     *
+     * @return
+     */
+    public String tryGetWifiMac() {
+        String mac;
+        WifiInfo wi = wifiManager.getConnectionInfo();
+        if (wi == null || wi.getMacAddress() == null) {
+            mac = null;
+        }
+        if ("02:00:00:00:00:00".equals(wi.getMacAddress().trim())) {
+            mac = null;
+        } else {
+            mac = wi.getMacAddress().trim();
+        }
+        return mac;
+    }
+
+    /**
+     * 通过网络接口获取
+     *
+     * @return
+     */
+    public static String getNetworkMac() {
+        try {
+            List<NetworkInterface> all = Collections.list(NetworkInterface.getNetworkInterfaces());
+            for (NetworkInterface nif : all) {
+                // if (!nif.getName().equalsIgnoreCase("wlan0") && !nif.getName().equalsIgnoreCase("eth0") && !nif.getName().equalsIgnoreCase("eth1"))
+                if (!nif.getName().equalsIgnoreCase("eth0") && !nif.getName().equalsIgnoreCase("eth1") && !nif.getName().equalsIgnoreCase("eth2"))
+                    continue;
+                byte[] macBytes = nif.getHardwareAddress();
+                if (macBytes == null) {
+                    return null;
+                }
+                StringBuilder res1 = new StringBuilder();
+                for (byte b : macBytes) {
+                    res1.append(String.format("%02X:", b));
+                }
+                if (res1.length() > 0) {
+                    res1.deleteCharAt(res1.length() - 1);
+                }
+                return res1.toString();
+            }
+        } catch (Exception ex) {
+            ex.printStackTrace();
+        }
+        return null;
+    }
+
+
+    /**
+     * 根据IP地址获取MAC地址
+     *
+     * @return
+     */
+    @SuppressLint("NewApi")
+    public static String getLocalMacAddressFromIp() {
+        String strMacAddr = null;
+        try {
+            // 获得IpD地址
+            InetAddress ip = getLocalInetAddress();
+            byte[] b = NetworkInterface.getByInetAddress(ip)
+                    .getHardwareAddress();
+            StringBuffer buffer = new StringBuffer();
+            for (int i = 0; i < b.length; i++) {
+                if (i != 0) {
+                    buffer.append(':');
+                }
+                String str = Integer.toHexString(b[i] & 0xFF);
+                buffer.append(str.length() == 1 ? 0 + str : str);
+            }
+            strMacAddr = buffer.toString().toUpperCase();
+
+        } catch (Exception e) {
+
+        }
+
+        return strMacAddr;
+    }
+
+    /**
+     * 获取移动设备本地IP
+     *
+     * @return
+     */
+    public static InetAddress getLocalInetAddress() {
+        InetAddress ip = null;
+        try {
+            // 列举
+            Enumeration<NetworkInterface> en_netInterface = NetworkInterface
+                    .getNetworkInterfaces();
+            while (en_netInterface.hasMoreElements()) {// 是否还有元素
+                NetworkInterface ni = (NetworkInterface) en_netInterface
+                        .nextElement();// 得到下一个元素
+                Enumeration<InetAddress> en_ip = ni.getInetAddresses();// 得到一个ip地址的列举
+                while (en_ip.hasMoreElements()) {
+                    ip = en_ip.nextElement();
+                    if (!ip.isLoopbackAddress()
+                            && ip.getHostAddress().indexOf(":") == -1)
+                        break;
+                    else
+                        ip = null;
+                }
+
+                if (ip != null) {
+                    break;
+                }
+            }
+        } catch (SocketException e) {
+
+            e.printStackTrace();
+        }
+        return ip;
+    }
+
+    //获取本地ip地址
+    public String getLocalIP() {
+        try {
+            for (Enumeration<NetworkInterface> enNetI = NetworkInterface.getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
+                NetworkInterface netI = enNetI.nextElement();
+                for (Enumeration<InetAddress> enumIpAddr = netI.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
+                    InetAddress inetAddress = enumIpAddr.nextElement();
+                    if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
+                        return inetAddress.getHostAddress();
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public static boolean isBTConnected() {
+        BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
+        if (btAdapter != null) {
+            return btAdapter.getState() == BluetoothAdapter.STATE_ON;
+        }
+
+        return false;
+    }
+
+    public int getNetworkType() {
+        if (connManager != null && connManager.getActiveNetworkInfo() != null) {
+            return connManager.getActiveNetworkInfo().getType();
+        }
+
+        return -1;
+    }
+
+    public boolean networkAvailable() {
+        if (connManager != null && connManager.getActiveNetworkInfo() != null) {
+            return connManager.getActiveNetworkInfo().isConnected();
+        }
+
+        return false;
+    }
+}

+ 122 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/PasswordDialogHelper.java

@@ -0,0 +1,122 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.GridView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.adapter.NumAdapter;
+
+
+public class PasswordDialogHelper {
+
+    private static AlertDialog dialog;
+    private static String pwd = "";
+
+    public static void showPasswordDialog(final Activity activity, final ClickListener listener) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.password_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        final String[] numbers = {"1","2","3","4","5","6","7","8","9"};
+        final TextView password = contentView.findViewById(R.id.tv_psw_view);
+        GridView gridView = contentView.findViewById(R.id.grid_psw);
+        NumAdapter adapter = new NumAdapter(numbers, activity);
+        gridView.setAdapter(adapter);
+        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                if (pwd.length() <= 2) {
+                    pwd = pwd + numbers[position];
+                    password.setText(pwd);
+                }
+                Log.d("password", "input password len: " + pwd.length() + "--" + pwd);
+            }
+        });
+
+        TextView delete = contentView.findViewById(R.id.btn_delete);
+        TextView cancel = contentView.findViewById(R.id.btn_cancel);
+        TextView confirm = contentView.findViewById(R.id.btn_confirm);
+        delete.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Log.d("password", "delete password len: " + pwd.length() + "--" + pwd);
+                if (pwd.length() > 1) {
+                    pwd = pwd.substring(0, pwd.length()-1);
+                    password.setText(pwd);
+                } else {
+                    pwd = "";
+                    password.setText(pwd);
+                    password.setHint(R.string.input_password);
+                }
+            }
+        });
+
+        cancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+        confirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if ("888".equals(pwd)) {
+                    if (listener != null) {
+                        listener.onConfirm();
+                    }
+                    dismissCallDialog();
+                } else {
+                    Toast.makeText(activity, R.string.invalid_password, Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+
+        dialog = builder.create();
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.setCancelable(false);
+        dialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = dialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 400;
+            lp.height = 480;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        pwd = "";
+        if (dialog != null && dialog.isShowing()) {
+            dialog.dismiss();
+        }
+    }
+
+    public interface ClickListener {
+        void onConfirm();
+    }
+}

+ 39 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/RingPlayHelper.java

@@ -0,0 +1,39 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+public class RingPlayHelper {
+
+    private static AsyncPlayer ringPlayer;
+    private final static Handler handler = new Handler(Looper.getMainLooper()) {
+        @Override
+        public void handleMessage(Message msg) {
+            if (ringPlayer != null) {
+                ringPlayer.stop();
+            }
+        }
+    };
+
+    public static void playRingTone(Context context, int res, boolean loop) {
+        if (ringPlayer == null) {
+            ringPlayer = new AsyncPlayer(null);
+        }
+
+        if (!ringPlayer.isPlay()) {
+            ringPlayer.play(context, res, loop, AudioManager.STREAM_MUSIC);
+            handler.removeCallbacksAndMessages(null);
+            handler.sendEmptyMessageDelayed(10, 60000);
+        }
+    }
+
+    public static void stopRingTone() {
+        handler.removeCallbacksAndMessages(null);
+        if (ringPlayer != null) {
+            ringPlayer.stop();
+        }
+    }
+}

+ 233 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/SPUtils.java

@@ -0,0 +1,233 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * @Author: WangYong on 2020/11/3
+ * @Description:
+ */
+public class SPUtils {
+    public SPUtils() {
+        /* cannot be instantiated */
+        throw new UnsupportedOperationException("cannot be instantiated");
+    }
+
+    // 系统语言
+    private final String SP_NAME = "language_setting";
+    private final String TAG_LANGUAGE = "language_select";
+    private static volatile SPUtils instance;
+    private final SharedPreferences mSharedPreferences;
+    private Locale systemCurrentLocal = Locale.CHINESE;
+
+    public SPUtils(Context context) {
+        mSharedPreferences = context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
+    }
+
+    public void saveLanguage(int select) {
+        SharedPreferences.Editor edit = mSharedPreferences.edit();
+        edit.putInt(TAG_LANGUAGE, select);
+        edit.commit();
+    }
+
+    public int getSelectLanguage() {
+        return mSharedPreferences.getInt(TAG_LANGUAGE, 1);
+    }
+
+    public Locale getSystemCurrentLocal() {
+        return systemCurrentLocal;
+    }
+
+    public void setSystemCurrentLocal(Locale local) {
+        systemCurrentLocal = local;
+    }
+
+    public static SPUtils getInstance(Context context) {
+        if (instance == null) {
+            synchronized (SPUtils.class) {
+                if (instance == null) {
+                    instance = new SPUtils(context);
+                }
+            }
+        }
+        return instance;
+    }
+
+    /**
+     * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法
+     *
+     * @param context
+     * @param key
+     * @param object
+     */
+    public static void put(Context context, String key, Object object) {
+
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+
+        if (object instanceof String) {
+            editor.putString(key, (String) object);
+        } else if (object instanceof Integer) {
+            editor.putInt(key, (Integer) object);
+        } else if (object instanceof Boolean) {
+            editor.putBoolean(key, (Boolean) object);
+        } else if (object instanceof Float) {
+            editor.putFloat(key, (Float) object);
+        } else if (object instanceof Long) {
+            editor.putLong(key, (Long) object);
+        } else {
+            editor.putString(key, object.toString());
+        }
+
+        SharedPreferencesCompat.apply(editor);
+    }
+
+
+    /**
+     * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值
+     *
+     * @param context
+     * @param key
+     * @param defaultObject
+     * @return
+     */
+    public static Object get(Context context, String key, Object defaultObject) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+
+        if (defaultObject instanceof String) {
+            return sp.getString(key, (String) defaultObject);
+        } else if (defaultObject instanceof Integer) {
+            return sp.getInt(key, (Integer) defaultObject);
+        } else if (defaultObject instanceof Boolean) {
+            return sp.getBoolean(key, (Boolean) defaultObject);
+        } else if (defaultObject instanceof Float) {
+            return sp.getFloat(key, (Float) defaultObject);
+        } else if (defaultObject instanceof Long) {
+            return sp.getLong(key, (Long) defaultObject);
+        }
+
+        return null;
+    }
+
+
+//
+//    /**
+//     * 获取token
+//     *
+//     * @return
+//     */
+//    public static String getToken(Context context) {
+//        return (String) get(context, Constant.APP_UUID, "");
+//    }
+
+    /**
+     * 移除某个key值已经对应的值
+     *
+     * @param context
+     * @param key
+     */
+    public static void remove(Context context, String key) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.remove(key);
+        SharedPreferencesCompat.apply(editor);
+    }
+
+    /**
+     * 清除所有数据
+     *
+     * @param context
+     */
+    public static void clear(Context context) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        SharedPreferences.Editor editor = sp.edit();
+        editor.clear();
+        SharedPreferencesCompat.apply(editor);
+    }
+
+    /**
+     * 查询某个key是否已经存在
+     *
+     * @param context
+     * @param key
+     * @return
+     */
+    public static boolean contains(Context context, String key) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        return sp.contains(key);
+    }
+
+    /**
+     * 返回所有的键值对
+     *
+     * @param context
+     * @return
+     */
+    public static Map<String, ?> getAll(Context context) {
+        SharedPreferences sp = context.getSharedPreferences(Constant.PREFERENCE_USER, Context.MODE_PRIVATE);
+        return sp.getAll();
+    }
+//
+//    /**
+//     * 存放mac地址
+//     *
+//     * @return
+//     */
+//    public static String getMac() {
+//        return (String) get(MyApplication.getAppContext(),Constant.MAC_ADDRESS, "");
+//    }
+//
+//    public static void setMac(Context context,String macAddress) {
+//        put(context,Constant.MAC_ADDRESS, macAddress);
+//    }
+
+    /**
+     * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
+     *
+     * @author zhy
+     */
+    private static class SharedPreferencesCompat {
+        private static final Method sApplyMethod = findApplyMethod();
+
+        /**
+         * 反射查找apply的方法
+         *
+         * @return
+         */
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        private static Method findApplyMethod() {
+            try {
+                Class clz = SharedPreferences.Editor.class;
+                return clz.getMethod("apply");
+            } catch (NoSuchMethodException e) {
+            }
+
+            return null;
+        }
+
+        /**
+         * 如果找到则使用apply执行,否则使用commit
+         *
+         * @param editor
+         */
+        public static void apply(SharedPreferences.Editor editor) {
+            try {
+                if (sApplyMethod != null) {
+                    sApplyMethod.invoke(editor);
+                    return;
+                }
+            } catch (IllegalArgumentException e) {
+            } catch (IllegalAccessException e) {
+            } catch (InvocationTargetException e) {
+            }
+            editor.commit();
+        }
+    }
+}

+ 81 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/ScreenManagerUtil.kt

@@ -0,0 +1,81 @@
+package com.wdkl.ncs.android.component.nursehome.util
+
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.provider.Settings
+import android.util.Log
+
+class ScreenManagerUtil {
+
+
+    /**
+     * @return 0--255
+     */
+    fun getScreenBrightness(context: Context): Int {
+        var screenBrightness = 150
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.System.canWrite(context)) {
+                val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
+                intent.data = Uri.parse("package:" + context.packageName)
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                context.startActivity(intent)
+            } else {
+                //有了权限,具体的动作
+                try {
+                    screenBrightness = Settings.System.getInt(context.contentResolver,
+                            Settings.System.SCREEN_BRIGHTNESS)
+                } catch (e: Settings.SettingNotFoundException) {
+                    e.printStackTrace()
+                }
+
+            }
+        } else {
+            try {
+                screenBrightness = Settings.System.getInt(context.contentResolver,
+                        Settings.System.SCREEN_BRIGHTNESS)
+            } catch (e: Settings.SettingNotFoundException) {
+                e.printStackTrace()
+            }
+
+        }
+
+        return screenBrightness
+    }
+
+
+    /**
+     * 保存当前的屏幕亮度值,并使之生效
+     *
+     * @param paramInt 0-255
+     */
+    fun setScreenBrightness(context: Context, paramInt: Int) {
+
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+            if (!Settings.System.canWrite(context)) {
+                val intent = Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS)
+                intent.data = Uri.parse("package:" + context.packageName)
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+                context.startActivity(intent)
+            } else {
+                //有了权限,具体的动作
+                Settings.System.putInt(context.contentResolver,
+                        Settings.System.SCREEN_BRIGHTNESS, paramInt)
+                val uri = Settings.System
+                        .getUriFor("screen_brightness")
+                Log.w("当前亮度", "当前亮度======" + getScreenBrightness(context))
+                context.contentResolver.notifyChange(uri, null)
+            }
+        } else {
+            Settings.System.putInt(context.contentResolver,
+                    Settings.System.SCREEN_BRIGHTNESS, paramInt)
+            val uri = Settings.System
+                    .getUriFor("screen_brightness")
+            Log.w("当前亮度", "当前亮度======" + getScreenBrightness(context))
+            context.contentResolver.notifyChange(uri, null)
+        }
+
+    }
+}

+ 159 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/ServerConfigDialogHelper.java

@@ -0,0 +1,159 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.EditText;
+import android.widget.GridView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.adapter.NumAdapter;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.lib.utils.ExtendMethodsKt;
+import com.wdkl.ncs.android.middleware.utils.CommonUtils;
+
+
+public class ServerConfigDialogHelper {
+
+    private static AlertDialog callDialog;
+    private static String pwd = "";
+
+    public static void showPasswordDialog(final Activity activity) {
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.server_config_dialog_lay, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+
+        final String[] numbers = {"1","2","3","4","5","6","7","8","9"};
+        final TextView password = contentView.findViewById(R.id.tv_psw_view);
+        final LinearLayout llPwd = contentView.findViewById(R.id.ll_password);
+        final LinearLayout llServer = contentView.findViewById(R.id.ll_server_config);
+        GridView gridView = contentView.findViewById(R.id.grid_psw);
+        NumAdapter adapter = new NumAdapter(numbers, activity);
+        gridView.setAdapter(adapter);
+        gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            @Override
+            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+                if (pwd.length() <= 2) {
+                    pwd = pwd + numbers[position];
+                    password.setText(pwd);
+                }
+                Log.d("serverIp", "input password len: " + pwd.length() + "--" + pwd);
+            }
+        });
+
+        TextView delete = contentView.findViewById(R.id.btn_delete);
+        TextView cancel = contentView.findViewById(R.id.btn_cancel);
+        TextView confirm = contentView.findViewById(R.id.btn_confirm);
+        delete.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Log.d("serverIp", "delete password len: " + pwd.length() + "--" + pwd);
+                if (pwd.length() > 1) {
+                    pwd = pwd.substring(0, pwd.length()-1);
+                    password.setText(pwd);
+                } else {
+                    pwd = "";
+                    password.setText(pwd);
+                    password.setHint(R.string.input_password);
+                }
+            }
+        });
+
+        cancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+        confirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if ("666".equals(pwd)) {
+                    llPwd.setVisibility(View.GONE);
+                    llServer.setVisibility(View.VISIBLE);
+                } else {
+                    Toast.makeText(activity, R.string.invalid_password, Toast.LENGTH_SHORT).show();
+                }
+            }
+        });
+
+        final EditText editUrl = contentView.findViewById(R.id.edit_url);
+        final EditText editPort = contentView.findViewById(R.id.edit_port);
+        final EditText editSipUrl = contentView.findViewById(R.id.edit_sip_url);
+        final EditText editSipPort = contentView.findViewById(R.id.edit_sip_port);
+        TextView saveConfig = contentView.findViewById(R.id.btn_save_config);
+        TextView cancelConfig = contentView.findViewById(R.id.btn_cancel_config);
+        editUrl.setText(CommonUtils.getUrl(BaseApplication.appContext));
+        editPort.setText(CommonUtils.getUrlPort(BaseApplication.appContext));
+        //editSipUrl.setText(CommonUtils.getSipUrl(BaseApplication.appContext));
+        //editSipPort.setText(CommonUtils.getSipPort(BaseApplication.appContext));
+        saveConfig.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                String url = editUrl.getText().toString();
+                String port = editPort.getText().toString();
+                if (TextUtils.isEmpty(url) || TextUtils.isEmpty(port)) {
+                    ExtendMethodsKt.showMessage("参数不能为空");
+                } else {
+                    //保存配置
+                    CommonUtils.setUrl(BaseApplication.appContext, editUrl.getText().toString());
+                    CommonUtils.setUrlPort(BaseApplication.appContext, editPort.getText().toString());
+                    //CommonUtils.setSipUrl(BaseApplication.appContext, editSipUrl.getText().toString());
+                    //CommonUtils.setSipPort(BaseApplication.appContext, editSipPort.getText().toString());
+                    dismissCallDialog();
+                }
+            }
+        });
+        cancelConfig.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                dismissCallDialog();
+            }
+        });
+
+
+        callDialog = builder.create();
+        callDialog.setCanceledOnTouchOutside(false);
+        callDialog.setCancelable(false);
+        callDialog.show();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = callDialog.getWindow();
+            window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 400;
+            lp.height = 480;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+
+            window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE
+                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
+                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                    | View.SYSTEM_UI_FLAG_FULLSCREEN);
+            window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static void dismissCallDialog() {
+        pwd = "";
+        if (callDialog != null && callDialog.isShowing()) {
+            callDialog.dismiss();
+        }
+    }
+}

+ 255 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/SpeechUtil.java

@@ -0,0 +1,255 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+public class SpeechUtil {
+    private static final String TAG = "SpeechUtil";
+
+    private TextToSpeech textToSpeech;
+    private static SpeechUtil speech;
+    private int speakIndex = 0;
+    private int loopCount = 2;
+    private int loopIndex = 0;
+    private boolean isStop = true;
+    public volatile static ArrayList<String> speechTextList = new ArrayList<>();
+    private Thread speechThread;
+    private boolean isSpeechLoop = true;
+    private String speakSpeech;
+    private final Object lockObject = new Object();
+
+    public static SpeechUtil getInstance() {
+        if (speech == null) {
+            synchronized (SpeechUtil.class) {
+                if (speech == null) {
+                    speech = new SpeechUtil();
+                }
+            }
+        }
+        return speech;
+    }
+
+    public void init(Context context, final TtsCallback callback) {
+        final String language = LocaleMangerUtils.getApplicationLocale().getLanguage();
+        Log.d(TAG, "app locale language: " + language);
+        if (Locale.CHINESE.getLanguage().equals(language)) {
+            textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+                @Override
+                public void onInit(int status) {
+                    if (status == TextToSpeech.SUCCESS) {
+                        int supported = textToSpeech.setLanguage(Locale.CHINESE);
+                        if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
+                            Constant.TTS_STATUS=1;
+                            Log.d(TAG, "onInit: 当前不支持中文");
+                            if (callback != null) {
+                                callback.onInit(false);
+                            }
+                        } else {
+                            Constant.TTS_STATUS=2;
+                            Log.d(TAG, "onInit: 支持中文");
+                            if (callback != null) {
+                                callback.onInit(true);
+                            }
+                        }
+                        Log.d(TAG, "onInit: TTS引擎初始化成功");
+                    } else {
+                        Constant.TTS_STATUS=0;
+                        Log.d(TAG, "onInit: TTS引擎初始化失败");
+                        if (callback != null) {
+                            callback.onInit(false);
+                        }
+                    }
+                }
+            }, "com.iflytek.speechcloud");
+            textToSpeech.setSpeechRate(0.5f);
+        } else {
+            textToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+                @Override
+                public void onInit(int status) {
+                    if (status == TextToSpeech.SUCCESS) {
+                        int supported = textToSpeech.setLanguage(new Locale(language));
+                        if ((supported != TextToSpeech.LANG_AVAILABLE) && (supported != TextToSpeech.LANG_COUNTRY_AVAILABLE)) {
+                            Constant.TTS_STATUS=1;
+                            Log.d(TAG, "onInit: 当前不支持" + language);
+                            if (callback != null) {
+                                callback.onInit(false);
+                            }
+                        } else {
+                            Constant.TTS_STATUS=2;
+                            Log.d(TAG, "onInit: 支持" + language);
+                            if (callback != null) {
+                                callback.onInit(true);
+                            }
+                        }
+                        Log.d(TAG, "onInit: TTS引擎初始化成功");
+                    } else {
+                        Constant.TTS_STATUS=0;
+                        Log.d(TAG, "onInit: TTS引擎初始化失败");
+                        if (callback != null) {
+                            callback.onInit(false);
+                        }
+                    }
+                }
+            }, "com.google.android.tts");
+            textToSpeech.setSpeechRate(0.8f);
+        }
+
+    }
+
+    public void addSpeech(String text, boolean emergency) {
+        synchronized (lockObject) {
+            Log.d(TAG, "start add text speech: " + text);
+
+            if (speechTextList.contains(text)) {
+                return;
+            }
+            Log.d(TAG, "truely add text speech: " + text);
+
+            if (emergency) {
+                speechTextList.add(0, text);
+                stopSpeak(false);
+            } else {
+                speechTextList.add(text);
+            }
+            startSpeechThread();
+        }
+    }
+
+    public synchronized void speak(final String text) {
+        Log.d(TAG, "tts speak: " + text);
+
+        isStop = false;
+        textToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, null, "uniqueId");
+        textToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
+            @Override
+            public void onStart(String utteranceId) {
+                //LogUtil.d(TAG, "speak onStart..." + utteranceId);
+            }
+
+            @Override
+            public void onDone(String utteranceId) {
+                speakIndex++;
+                //LogUtil.d(TAG, "speak onDone...index: " + speakIndex + ", loop: " + loopCount);
+                if (speakIndex < loopCount) {
+                    //循环播报
+                    speak(text);
+                } else {
+                    //语音播报完毕
+                    speakIndex = 0;
+                    isStop = true;
+                }
+            }
+
+            @Override
+            public void onError(String utteranceId) {
+                isStop = true;
+                Log.d(TAG, "speak onError..." + utteranceId);
+            }
+        });
+    }
+
+    public void stopSpeak(boolean removeAll) {
+        if (removeAll) {
+            speechTextList.clear();
+        }
+        if (textToSpeech != null && textToSpeech.isSpeaking()) {
+            textToSpeech.stop();
+            isStop = true;
+            speakIndex = 0;
+            loopIndex = 0;
+
+            Log.d(TAG, "stop speak removeAll: " + removeAll);
+        }
+    }
+
+    public void removeSpeak(String text) {
+        synchronized (lockObject) {
+            if (!TextUtils.isEmpty(text) && !TextUtils.isEmpty(speakSpeech)) {
+                Log.d(TAG, "remove speak: " + text);
+
+                if (text.equals(speakSpeech) && textToSpeech.isSpeaking()) {
+                    textToSpeech.stop();
+                    speechTextList.remove(text);
+                    isStop = true;
+                    speakIndex = 0;
+                } else {
+                    speechTextList.remove(text);
+                }
+            }
+        }
+    }
+
+    public void setSpeechLoopCount(int count) {
+        loopCount = count;
+    }
+
+    public void release() {
+        speechTextList.clear();
+        isStop = true;
+        speakIndex = 0;
+        if (textToSpeech != null) {
+            textToSpeech.stop();
+            textToSpeech.shutdown();
+            textToSpeech = null;
+        }
+    }
+
+    public void startSpeechThread() {
+        if (null == speechThread) {
+            speechThread = new Thread(new SpeechRunnable());
+            speechThread.start();
+        } else if (!speechThread.isAlive()) {
+            speechThread.start();
+        }
+    }
+
+    public class SpeechRunnable implements Runnable {
+        public void run() {
+            while (isSpeechLoop) {
+                if (speechTextList.size() > 0 && isStop && !Constant.IN_CALL) {
+                    if (SettingConfig.getLoopCall(BaseApplication.appContext)) {
+                        if (loopIndex >= speechTextList.size()) {
+                            loopIndex = 0;
+                        }
+                        speakSpeech = speechTextList.get(loopIndex);
+
+                        Log.d(TAG, "speakSpeech: " + speakSpeech + ", speak loopIndex: " + loopIndex + ", speech size: " + speechTextList.size());
+                        speak(speakSpeech);
+
+                        loopIndex++;
+                    } else {
+                        loopIndex = 0;
+                        speakSpeech = speechTextList.get(loopIndex);
+                        Log.d(TAG, "speakSpeech: " + speakSpeech + ", speak loopIndex: " + loopIndex + ", speech size: " + speechTextList.size());
+                        speak(speakSpeech);
+
+                        speechTextList.remove(speakSpeech);
+                    }
+                }
+
+                try {
+                    Thread.sleep(500);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+
+    public interface TtsCallback {
+        void onInit(boolean success);
+    }
+}

+ 87 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/TimeTransition.kt

@@ -0,0 +1,87 @@
+package com.wdkl.ncs.android.component.nursehome.util
+
+import java.text.ParseException
+import java.text.SimpleDateFormat
+import java.util.*
+
+
+object TimeTransition {
+
+    fun stampToDate(s:Long):String{
+//        return TimeStampToTime(s,"yyyy-MM-dd HH:mm:ss")
+        return getDateTime(s,"yyyy-MM-dd")
+    }
+
+    /**
+     * 时间戳转时间 不带时区
+     */
+    fun stampToTime(s:Long):String{
+        return TimeStampToTime(s,"HH:mm:ss")
+    }
+
+    fun stampToDateTime(s:Long):String{
+        return TimeStampToTime(s,"MM-dd HH:mm:ss")
+    }
+
+    /**
+     * 时间戳转时间 不带时区
+     */
+    fun TimeStampToTime(s:Long, timestamp:String):String{
+        val res: String
+        val simpleDateFormat = SimpleDateFormat(timestamp)
+        val lt = s
+        val date = Date(lt)
+        res = simpleDateFormat.format(date)
+        return res
+}
+
+    /**
+     * 获取当前的时间 带时区
+     */
+    fun getDateTime(format: String): String {
+        val date = Date(System.currentTimeMillis())
+        val sdf = SimpleDateFormat(format)
+        //sdf.timeZone = TimeZone.getTimeZone("GMT+8")
+        return sdf.format(date)
+    }
+
+    /**
+     * 时间戳转时间字符串
+     */
+    fun getDateTime(timeMillis: Long, format: String): String {
+        if (timeMillis > 0) {
+            val date = Date(timeMillis)
+            val sdf = SimpleDateFormat(format)
+            //sdf.timeZone = TimeZone.getTimeZone("GMT+8")
+            return sdf.format(date)
+        }
+        return "null"
+    }
+
+    /**
+     * 时间转时间戳
+     */
+    fun dateToStamp(s: String): Long {
+        return dateToStamp(s, "yyyy-MM-dd HH:mm:ss")
+    }
+
+    /**
+     * 将时间转换为时间戳
+     */
+    fun dateToStamp(s: String, pattern: String): Long {
+        val simpleDateFormat = SimpleDateFormat(pattern)
+        var date: Date? = null
+        try {
+            //simpleDateFormat.timeZone = TimeZone.getTimeZone("GMT+8")
+            date = simpleDateFormat.parse(s)
+
+            return date!!.time
+        } catch (e: ParseException) {
+            e.printStackTrace()
+        }
+
+        return 0
+    }
+
+
+}

+ 102 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/UpdateTipsDialogHelper.java

@@ -0,0 +1,102 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.Intent;
+import android.os.CountDownTimer;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.Button;
+
+import com.wdkl.ncs.android.component.nursehome.R;
+import com.wdkl.ncs.android.component.nursehome.activity.AppUpdateActivity;
+import com.wdkl.ncs.android.lib.base.BaseApplication;
+import com.wdkl.ncs.android.middleware.common.Constant;
+
+public class UpdateTipsDialogHelper {
+
+    private static AlertDialog dialog;
+
+    public static void showDialog(final Activity activity) {
+        if (dialog != null && dialog.isShowing()) {
+            return;
+        }
+
+        View contentView = LayoutInflater.from(activity).inflate(R.layout.update_tips_dialog, null);
+        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+        builder.setView(contentView);
+        Button buttonCancel = contentView.findViewById(R.id.cancel_button);
+        final Button buttonConfirm = contentView.findViewById(R.id.confirm_button);
+        final CountDownTimer timer = new CountDownTimer(15000, 1000) {
+
+            @Override
+            public void onTick(long millisUntilFinished) {
+                String text = BaseApplication.appContext.getString(R.string.confirm_down_time, millisUntilFinished/1000);
+                buttonConfirm.setText(text);
+            }
+
+            @Override
+            public void onFinish() {
+                Intent intent = new Intent();
+                intent.setClass(activity, AppUpdateActivity.class);
+                activity.startActivity(intent);
+
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        };
+
+        buttonCancel.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+//                Constants.Companion.setApp_updating(false);
+                Constant.APP_UPDATING =false;
+                if (timer != null) {
+                    timer.cancel();
+                }
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        buttonConfirm.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                if (timer != null) {
+                    timer.cancel();
+                }
+
+                Intent intent = new Intent();
+                intent.setClass(activity, AppUpdateActivity.class);
+                activity.startActivity(intent);
+
+                if (dialog != null) {
+                    dialog.dismiss();
+                }
+            }
+        });
+
+        dialog = builder.create();
+        dialog.setCanceledOnTouchOutside(false);
+        dialog.setCancelable(false);
+        dialog.show();
+        timer.start();
+
+        //设置dialog宽高及位置
+        try {
+            Window window = dialog.getWindow();
+            WindowManager.LayoutParams lp = window.getAttributes();
+            lp.width = 600;
+            lp.height = 320;
+            lp.gravity = Gravity.CENTER;
+            window.setAttributes(lp);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+}

+ 73 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/Util.kt

@@ -0,0 +1,73 @@
+package com.wdkl.ncs.android.component.nursehome.util
+
+import android.annotation.SuppressLint
+import android.app.KeyguardManager
+import android.content.Context
+import android.content.Context.KEYGUARD_SERVICE
+import android.os.PowerManager
+import android.util.DisplayMetrics
+import android.view.WindowManager
+import com.wdkl.ncs.android.component.nursehome.settingconfig.SettingConfig
+import com.wdkl.ncs.android.lib.base.BaseApplication
+
+
+object Util {
+
+    /**
+     * 亮屏并解锁
+     */
+    @SuppressLint("InvalidWakeLockTag")
+    fun wakeUpAndUnlock(): PowerManager.WakeLock? {
+        val pm = BaseApplication.appContext.getSystemService(Context.POWER_SERVICE) as PowerManager
+        var wakeLock: PowerManager.WakeLock? = null
+
+        val screenOn = pm.isInteractive
+        if (!screenOn) { //如果是熄灭状态
+            wakeLock = pm.newWakeLock(PowerManager.ACQUIRE_CAUSES_WAKEUP or PowerManager.SCREEN_DIM_WAKE_LOCK, "TAG")
+            wakeLock.acquire(10000)//亮屏
+        }
+
+        // 屏幕解锁
+        val keyguardManager = BaseApplication.appContext.getSystemService(KEYGUARD_SERVICE) as KeyguardManager
+        val keyguardLock = keyguardManager.newKeyguardLock("unLock")
+        // 屏幕锁定
+        keyguardLock.reenableKeyguard()
+        keyguardLock.disableKeyguard() // 解锁
+        return wakeLock
+    }
+
+    @SuppressLint("InvalidWakeLockTag")
+    fun getCpuWakeLock(context: Context): PowerManager.WakeLock? {
+        val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+        val cpuWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                context.javaClass.canonicalName)
+        return cpuWakeLock
+    }
+
+    fun appendSpace(para: String): String {
+        if (SettingConfig.getVoiceNumeric(BaseApplication.appContext)) {
+            val length = para.length
+            val value = CharArray(length shl 1)
+            var i = 0
+            var j = 0
+            while (i < length) {
+                value[j] = para[i]
+                value[1 + j] = ' '
+                ++i
+                j = i shl 1
+            }
+            return String(value)
+        } else {
+            return para
+        }
+    }
+
+
+
+    fun getPixelsFromDp(context: Context, size: Int): Int {
+        val metrics = DisplayMetrics()
+        val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
+        wm.getDefaultDisplay().getMetrics(metrics)
+        return size * metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT
+    }
+}

+ 194 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/VoiceManagerUtil.java

@@ -0,0 +1,194 @@
+package com.wdkl.ncs.android.component.nursehome.util;
+
+import android.content.Context;
+import android.media.AudioManager;
+
+/**
+ * 类名称:VoiceManagerUtil <br>
+ * 类描述:声音控制工具类 <br>
+ * 创建人:Waderson Shll (TEL:15675117662)<br>
+ * 创建时间:2018-03-15 <br>
+ * 特别提醒:如有需要该类可任意创建与调用;在未通知本人的情况下该类禁止任何修改!<br>
+ */
+public class VoiceManagerUtil {
+    /**
+     * 获取提示音音量最大值
+     *
+     * @param context
+     */
+    public static int getAlarmMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM);
+    }
+
+    /**
+     * 获取提示音音量当前值
+     *
+     * @param context
+     */
+    public static int getAlarmNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM);
+    }
+
+    /**
+     * 获取多媒体音量最大值
+     *
+     * @param context
+     */
+    public static int getMusicMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+    }
+
+    /**
+     * 获取多媒体音量当前值
+     *
+     * @param context
+     */
+    public static int getMusicNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+    }
+
+    /**
+     * 获取铃声音量最大值
+     *
+     * @param context
+     */
+    public static int getRingMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
+    }
+
+    /**
+     * 获取铃声音量当前值
+     *
+     * @param context
+     */
+    public static int getRingNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
+    }
+
+    /**
+     * 获取系统音量最大值
+     *
+     * @param context
+     */
+    public static int getSystemMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM);
+    }
+
+    /**
+     * 获取系统音量当前值
+     *
+     * @param context
+     */
+    public static int getSystemNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM);
+    }
+
+    /**
+     * 获取通话音量最大值
+     *
+     * @param context
+     */
+    public static int getCallMax(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
+    }
+
+    /**
+     * 获取通话音量当前值
+     *
+     * @param context
+     */
+    public static int getCallNow(Context context) {
+        AudioManager mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        return mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
+    }
+
+    /**
+     * 设置提示音音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setAlarmVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_ALARM, (int) (getAlarmMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置多媒体音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setMusicVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, (int) (getMusicMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置铃声音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setRingVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_RING, (int) (getRingMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置系统音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setSystemVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, (int) (getSystemMax(context) * vPercent), 0);
+    }
+
+    /**
+     * 设置通话音量
+     *
+     * @param context
+     * @param percent (百分比;只能0--100之间)
+     */
+    public static void setCallVoice(Context context, int percent) {
+        float vPercent=((float)percent)/100f;
+        vPercent = vPercent < 0 ? 0 : vPercent;
+        vPercent = vPercent > 1 ? 1 : vPercent;
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setStreamVolume(AudioManager.STREAM_VOICE_CALL, (int) (getCallMax(context) * vPercent), 0);
+    }
+
+    public static void switchAudioMode(Context context, boolean speakerOn) {
+        AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
+        audioManager.setSpeakerphoneOn(speakerOn);
+        if (speakerOn) {
+            audioManager.setMode(AudioManager.MODE_NORMAL);
+        } else {
+            audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+        }
+    }
+
+}

+ 0 - 0
android_host/src/main/java/com/wdkl/ncs/android/component/nursehome/util/WarningDialogHelper.java


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است