|
@@ -9,10 +9,8 @@ import android.content.pm.PackageManager
|
|
|
import android.media.AudioAttributes
|
|
|
import android.media.AudioManager
|
|
|
import android.media.SoundPool
|
|
|
-import android.os.Build
|
|
|
-import android.os.CountDownTimer
|
|
|
-import android.os.Handler
|
|
|
-import android.os.Looper
|
|
|
+import android.os.*
|
|
|
+import android.provider.Settings
|
|
|
import android.text.TextUtils
|
|
|
import android.util.Log
|
|
|
import android.view.View
|
|
@@ -21,7 +19,6 @@ import androidx.annotation.RequiresApi
|
|
|
import com.alibaba.fastjson.JSON
|
|
|
import com.enation.javashop.net.engine.plugin.permission.RxPermissions
|
|
|
import com.google.common.base.Strings
|
|
|
-import com.szeasco.facesdk.helper.GpioHelper
|
|
|
import com.wdkl.ncs.entraceguard.adapter.NumAdapter
|
|
|
import com.wdkl.ncs.entraceguard.contracts.MainActivityContract
|
|
|
import com.wdkl.ncs.entraceguard.di.DaggerApplicationComponent
|
|
@@ -34,9 +31,7 @@ import com.wdkl.ncs.entraceguard.tcp.channel.EntraceGuardUtil
|
|
|
import com.wdkl.ncs.entraceguard.tcp.dto.TcpModel
|
|
|
import com.wdkl.ncs.entraceguard.tcp.enums.TcpAction
|
|
|
import com.wdkl.ncs.entraceguard.tcp.enums.TcpType
|
|
|
-import com.wdkl.ncs.entraceguard.utils.AudioRouteUtils
|
|
|
-import com.wdkl.ncs.entraceguard.utils.LocaleMangerUtils
|
|
|
-import com.wdkl.ncs.entraceguard.utils.SettingConfig
|
|
|
+import com.wdkl.ncs.entraceguard.utils.*
|
|
|
import com.wdkl.ncs.janus.client.CallSessionCallback
|
|
|
import com.wdkl.ncs.janus.client.JanusClient
|
|
|
import com.wdkl.ncs.janus.client.VideoRoomCallback
|
|
@@ -64,11 +59,11 @@ import org.greenrobot.eventbus.ThreadMode
|
|
|
import org.linphone.core.*
|
|
|
import org.linphone.mediastream.Version
|
|
|
import org.webrtc.SurfaceViewRenderer
|
|
|
-import java.io.File
|
|
|
-import java.io.IOException
|
|
|
+import java.io.*
|
|
|
import java.math.BigInteger
|
|
|
import java.util.*
|
|
|
|
|
|
+
|
|
|
class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(), MainActivityContract.View, CallSessionCallback /*IUserState, CallSession.CallSessionCallback*/ {
|
|
|
val TAG = MainActivity::class.java.getSimpleName()
|
|
|
|
|
@@ -82,7 +77,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
.build()
|
|
|
}
|
|
|
|
|
|
- private var gpioHelper: GpioHelper? = null
|
|
|
+
|
|
|
private var interactionVO: InteractionVO? = null
|
|
|
private var tid: String? = ""
|
|
|
|
|
@@ -104,12 +99,15 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
//sip
|
|
|
private val START_SIPPHONE_LOGS = " ==== Device information dump ===="
|
|
|
private var sipHandler: Handler? = null
|
|
|
- private var sipTimer: Timer? = null
|
|
|
+ private var sipTimer: Timer? =null
|
|
|
|
|
|
private var mCore: Core? = null
|
|
|
private var mCoreListener: CoreListenerStub? = null
|
|
|
private var mAccountCreator: AccountCreator? = null
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
override fun getLayId(): Int {
|
|
|
return R.layout.activity_main
|
|
|
}
|
|
@@ -124,25 +122,26 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
@RequiresApi(Build.VERSION_CODES.N)
|
|
|
override fun init() {
|
|
|
//猫瞳默认已经给了权限
|
|
|
- /*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.BLUETOOTH,
|
|
|
- Manifest.permission.RECORD_AUDIO
|
|
|
- )
|
|
|
+ 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.BLUETOOTH,
|
|
|
+ Manifest.permission.RECORD_AUDIO
|
|
|
+ )
|
|
|
).subscribe {
|
|
|
if (it) {
|
|
|
permissionGrant()
|
|
|
} else {
|
|
|
- showMessage("请重新授权!")
|
|
|
+ showMessage(R.string.str_accredit)
|
|
|
}
|
|
|
- }.joinManager(disposableManager)*/
|
|
|
+ }.joinManager(disposableManager)
|
|
|
+
|
|
|
|
|
|
|
|
|
- permissionGrant()
|
|
|
+// permissionGrant()
|
|
|
}
|
|
|
|
|
|
@RequiresApi(Build.VERSION_CODES.N)
|
|
@@ -154,14 +153,12 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
tv_voice_type.text = "RTC"
|
|
|
}
|
|
|
|
|
|
- Constants.imei = Build.SERIAL
|
|
|
+ Constants.imei = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
|
|
|
passSoundID = mSoundPool.load(this, R.raw.pass, 1)
|
|
|
strangerSoundID = mSoundPool.load(this, R.raw.not_allow, 1)
|
|
|
- // 门禁SDK
|
|
|
- gpioHelper = GpioHelper.getInstance()
|
|
|
|
|
|
if(!NetHelper.getInstance().netAvailable){
|
|
|
- showTipView(R.drawable.net_inavailable,R.string.no_network, true, 5000)
|
|
|
+ showTipView(R.drawable.net_inavailable, R.string.no_network, true, 5000)
|
|
|
//exitApp(5000)
|
|
|
}else {
|
|
|
//获取tcp服务器信息
|
|
@@ -192,10 +189,10 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
//主监听器,根据事件调用界面
|
|
|
mCoreListener = object : CoreListenerStub() {
|
|
|
override fun onCallStateChanged(
|
|
|
- core: Core,
|
|
|
- call: Call,
|
|
|
- state: Call.State,
|
|
|
- message: String
|
|
|
+ core: Core,
|
|
|
+ call: Call,
|
|
|
+ state: Call.State,
|
|
|
+ message: String
|
|
|
) {
|
|
|
if (!SettingConfig.getSipEnabled(BaseApplication.appContext)) {
|
|
|
return
|
|
@@ -217,10 +214,10 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}
|
|
|
|
|
|
override fun onRegistrationStateChanged(
|
|
|
- core: Core,
|
|
|
- cfg: ProxyConfig,
|
|
|
- state: RegistrationState,
|
|
|
- message: String
|
|
|
+ core: Core,
|
|
|
+ cfg: ProxyConfig,
|
|
|
+ state: RegistrationState,
|
|
|
+ message: String
|
|
|
) {
|
|
|
if (!SettingConfig.getSipEnabled(BaseApplication.appContext)) {
|
|
|
return
|
|
@@ -300,7 +297,6 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
override fun initDevice(deviceDO: DeviceDO) {
|
|
|
responseCountDownTimer.cancel()
|
|
|
-
|
|
|
Log.i("设备信息:", JSON.toJSONString(deviceDO))
|
|
|
if (!Strings.isNullOrEmpty(deviceDO.sipId)&&deviceDO.status.equals(1)) {
|
|
|
Constants.sipId = deviceDO.sipId
|
|
@@ -350,7 +346,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
TcpClient.getInstance().sendMsg(EntraceGuardUtil.startVisit(Constants.deviceId).toJson())
|
|
|
}else{
|
|
|
- showTipView(R.drawable.unregister,R.string.device_unregister, true, 3000)
|
|
|
+ showTipView(R.drawable.unregister, R.string.device_unregister, true, 3000)
|
|
|
//exitApp(3000)
|
|
|
}
|
|
|
}
|
|
@@ -384,6 +380,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
interactionVO = JSON.parseObject(tcpModel.data.toString(), InteractionVO::class.java)
|
|
|
|
|
|
RingPlayHelper.playRingTone(this, R.raw.alice, true)
|
|
|
+ GpioController.writeGpioValue3(1)
|
|
|
|
|
|
if (SettingConfig.getSipEnabled(activity)) {
|
|
|
//发起sip视频请求
|
|
@@ -391,6 +388,16 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
val addressToCall = mCore!!.interpretUrl(interactionVO!!.toSipId)
|
|
|
val params = mCore!!.createCallParams(null)
|
|
|
params?.isVideoEnabled = true
|
|
|
+// val videoDevices = mCore!!.videoDevicesList
|
|
|
+//
|
|
|
+// // 选择第一个摄像头(可以根据需要选择其他摄像头)
|
|
|
+// val selectedDevice = videoDevices.getOrNull(2)
|
|
|
+// Log.d(TAG, ">>>>>>>>>>> selectedDevice: 2" )
|
|
|
+//
|
|
|
+// // 设置摄像头
|
|
|
+// if (selectedDevice != null) {
|
|
|
+// mCore!!.videoDevice = selectedDevice
|
|
|
+// }
|
|
|
|
|
|
if (addressToCall != null) {
|
|
|
mCore!!.inviteAddressWithParams(addressToCall, params!!)
|
|
@@ -400,20 +407,25 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- TcpAction.EntraceGuardAction.FAILED ->{ //护士主机不在线
|
|
|
+ TcpAction.EntraceGuardAction.FAILED -> { //护士主机不在线
|
|
|
//取消响应计时
|
|
|
responseCountDownTimer.cancel()
|
|
|
- showTipView(R.drawable.host_offline,R.string.call_failed, false, 3000)
|
|
|
+ showTipView(R.drawable.host_offline, R.string.call_failed, false, 3000)
|
|
|
//exitApp(3000)
|
|
|
+ GpioController.writeGpioValue3(0)
|
|
|
+ GpioController.writeGpioValue5(1)
|
|
|
}
|
|
|
|
|
|
|
|
|
TcpAction.EntraceGuardAction.UNLOCKDOOR -> { //开门指令
|
|
|
//停止等待音乐,停止倒计时
|
|
|
cancelCountDownTimer()
|
|
|
+
|
|
|
// 通过,亮起绿色灯光,并开门
|
|
|
- gpioHelper!!.setPassStatus(true)
|
|
|
- gpioHelper!!.setWhiteLedStatus(true)
|
|
|
+ GpioController.writeGpioValue3(0)
|
|
|
+ GpioController.writeGpioValue4(1)
|
|
|
+ GpioController.writeGpioValue6(1)
|
|
|
+
|
|
|
//结束通话
|
|
|
if (SettingConfig.getSipEnabled(activity)) {
|
|
|
sipCallTerminate()
|
|
@@ -422,7 +434,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
janusClient!!.disConnect()
|
|
|
}
|
|
|
|
|
|
- showTipView(R.drawable.allow_in,R.string.door_opened, false, 10000)
|
|
|
+ showTipView(R.drawable.allow_in, R.string.door_opened, false, 10000)
|
|
|
play(passSoundID!!)
|
|
|
|
|
|
//10秒后退出程序,调起门禁默认应用
|
|
@@ -430,9 +442,11 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
}
|
|
|
|
|
|
- TcpAction.EntraceGuardAction.REJECT ->{
|
|
|
+ TcpAction.EntraceGuardAction.REJECT -> {
|
|
|
//停止等待音乐,停止倒计时
|
|
|
cancelCountDownTimer()
|
|
|
+ GpioController.writeGpioValue3(0)
|
|
|
+ GpioController.writeGpioValue5(1)
|
|
|
|
|
|
if (SettingConfig.getSipEnabled(activity)) {
|
|
|
sipCallTerminate()
|
|
@@ -441,7 +455,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
janusClient!!.disConnect()
|
|
|
}
|
|
|
|
|
|
- showTipView(R.drawable.busyline,R.string.call_busy, false, 3000)
|
|
|
+ showTipView(R.drawable.busyline, R.string.call_busy, false, 3000)
|
|
|
play(strangerSoundID!!)
|
|
|
|
|
|
//3秒后退出程序
|
|
@@ -450,8 +464,10 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}
|
|
|
TcpAction.EntraceGuardAction.LOCKDOOR -> {
|
|
|
// 陌生人,亮起红外灯光
|
|
|
- gpioHelper!!.setPassStatus(false)
|
|
|
play(strangerSoundID!!)
|
|
|
+ GpioController.writeGpioValue3(0)
|
|
|
+ GpioController.writeGpioValue5(1)
|
|
|
+
|
|
|
}
|
|
|
|
|
|
TcpAction.EntraceGuardAction.OPENSPEAKER -> { //打开音频
|
|
@@ -493,7 +509,10 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}
|
|
|
|
|
|
play(strangerSoundID!!)
|
|
|
- showTipView(R.drawable.not_allow,R.string.not_allowed, false, 3000)
|
|
|
+ GpioController.writeGpioValue3(0)
|
|
|
+ GpioController.writeGpioValue5(1)
|
|
|
+
|
|
|
+ showTipView(R.drawable.not_allow, R.string.not_allowed, false, 3000)
|
|
|
|
|
|
//3秒后退出程序
|
|
|
//exitApp(3000)
|
|
@@ -512,20 +531,20 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
}
|
|
|
}
|
|
|
- Constants.TIME->{
|
|
|
+ Constants.TIME -> {
|
|
|
var tcpModel = messageEvent.getMessage() as TcpModel
|
|
|
- if(tcpModel.type.equals(TcpType.TIME)&&tcpModel.action.equals(TcpAction.TimeAction.SYNC)){
|
|
|
+ if (tcpModel.type.equals(TcpType.TIME) && tcpModel.action.equals(TcpAction.TimeAction.SYNC)) {
|
|
|
var time = 0L
|
|
|
var timeZone = "Asia/Shanghai"
|
|
|
- if(canPaseJson(tcpModel.data.toString())){
|
|
|
+ if (canPaseJson(tcpModel.data.toString())) {
|
|
|
var json = JSON.parseObject(tcpModel.data.toString())
|
|
|
- time=json.getLong("time")*1000+200
|
|
|
- timeZone=json.getString("time_zone")
|
|
|
- }else {
|
|
|
- time = tcpModel.data.toString().toLong()*1000+200
|
|
|
+ time = json.getLong("time") * 1000 + 200
|
|
|
+ timeZone = json.getString("time_zone")
|
|
|
+ } else {
|
|
|
+ time = tcpModel.data.toString().toLong() * 1000 + 200
|
|
|
}
|
|
|
(this.getSystemService(Context.ALARM_SERVICE) as AlarmManager).setTime(time)
|
|
|
- (this.getSystemService(Context.ALARM_SERVICE) as AlarmManager).setTimeZone(timeZone)
|
|
|
+// (this.getSystemService(Context.ALARM_SERVICE) as AlarmManager).setTimeZone(timeZone)
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -550,12 +569,9 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
private fun exitApp(delay: Long) {
|
|
|
if (delay > 0) {
|
|
|
handler.postDelayed({
|
|
|
- //关闭灯光,闭合继电器
|
|
|
- gpioHelper!!.ledDismiss(false);
|
|
|
-
|
|
|
try {
|
|
|
val packageManager: PackageManager = packageManager
|
|
|
- val intent: Intent = packageManager.getLaunchIntentForPackage("com.rlapk")
|
|
|
+ val intent: Intent = packageManager.getLaunchIntentForPackage("org.zg.app")
|
|
|
startActivity(intent)
|
|
|
} catch (e: Exception) {
|
|
|
e.printStackTrace()
|
|
@@ -565,11 +581,11 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}, delay)
|
|
|
} else {
|
|
|
//关闭灯光,闭合继电器
|
|
|
- gpioHelper!!.ledDismiss(false);
|
|
|
+
|
|
|
|
|
|
try {
|
|
|
val packageManager: PackageManager = packageManager
|
|
|
- val intent: Intent = packageManager.getLaunchIntentForPackage("com.rlapk")
|
|
|
+ val intent: Intent = packageManager.getLaunchIntentForPackage("org.zg.app")
|
|
|
startActivity(intent)
|
|
|
} catch (e: Exception) {
|
|
|
e.printStackTrace()
|
|
@@ -607,7 +623,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
//呼叫超时,返回到主界面
|
|
|
callFinish()
|
|
|
|
|
|
- showTipView(R.drawable.no_reponse,R.string.call_no_response, false, 3000)
|
|
|
+ showTipView(R.drawable.no_reponse, R.string.call_no_response, false, 3000)
|
|
|
//exitApp(3000)
|
|
|
}
|
|
|
}
|
|
@@ -626,7 +642,7 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
}
|
|
|
override fun onFinish() {
|
|
|
- showTipView(R.drawable.no_reponse,R.string.call_no_response, true, 3000)
|
|
|
+ showTipView(R.drawable.no_reponse, R.string.call_no_response, true, 3000)
|
|
|
//exitApp(3000)
|
|
|
}
|
|
|
}
|
|
@@ -720,7 +736,6 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
} else {
|
|
|
//保存配置
|
|
|
CommonUtils.setUrl(BaseApplication.appContext, url)
|
|
|
-
|
|
|
Toast.makeText(activity, R.string.str_save, Toast.LENGTH_SHORT).show()
|
|
|
}
|
|
|
}
|
|
@@ -767,6 +782,10 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
override fun didCreateLocalVideoTrack() {
|
|
|
runOnUiThread {
|
|
|
if (localSurfaceView == null) {
|
|
@@ -823,18 +842,18 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
|
|
|
if (enable) {
|
|
|
audioManager.setStreamVolume(
|
|
|
- AudioManager.MODE_IN_COMMUNICATION,
|
|
|
- audioManager.getStreamMaxVolume(AudioManager.MODE_IN_COMMUNICATION),
|
|
|
- AudioManager.FX_KEY_CLICK
|
|
|
+ AudioManager.MODE_IN_COMMUNICATION,
|
|
|
+ audioManager.getStreamMaxVolume(AudioManager.MODE_IN_COMMUNICATION),
|
|
|
+ AudioManager.FX_KEY_CLICK
|
|
|
)
|
|
|
audioManager.setSpeakerphoneOn(true)
|
|
|
|
|
|
AudioRouteUtils.routeAudioToSpeaker(mCore!!)
|
|
|
} else {
|
|
|
audioManager.setStreamVolume(
|
|
|
- AudioManager.STREAM_MUSIC,
|
|
|
- audioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
|
|
|
- AudioManager.FX_KEY_CLICK
|
|
|
+ AudioManager.STREAM_MUSIC,
|
|
|
+ audioManager.getStreamVolume(AudioManager.STREAM_MUSIC),
|
|
|
+ AudioManager.FX_KEY_CLICK
|
|
|
)
|
|
|
audioManager.setSpeakerphoneOn(false)
|
|
|
|
|
@@ -885,6 +904,28 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
Log.i("sipCall", ">>>>>>>>>>>>>>>>>2 " + pt.getMimeType() + " = " + pt.enabled())
|
|
|
}
|
|
|
mCore?.setAudioPayloadTypes(payloads)
|
|
|
+
|
|
|
+ val videoCodecs = mCore!!.videoPayloadTypes
|
|
|
+ if (videoCodecs != null) {
|
|
|
+ val h264Codecs = videoCodecs.filter { it.mimeType == "H264" }
|
|
|
+ // 将 h264Codecs 转换为数组
|
|
|
+ val h264CodecsArray = h264Codecs.toTypedArray()
|
|
|
+ if (h264CodecsArray.isNotEmpty()) {
|
|
|
+ mCore?.setVideoPayloadTypes(h264CodecsArray)
|
|
|
+ Log.i("sipCall", "Set video payload types to H264 codecs.")
|
|
|
+ } else {
|
|
|
+ Log.w("sipCall", "No H264 codecs found.")
|
|
|
+ }
|
|
|
+// for (i in videoCodecs.indices) {
|
|
|
+// val pt = videoCodecs[i]
|
|
|
+// if (pt.mimeType == "H264") {
|
|
|
+// mCore?.setVideoPayloadTypes(videoCodecs)
|
|
|
+// }
|
|
|
+// Log.i("sipCall", ">>>>>>>>>>>>>>>>>2 " + pt.getMimeType() + " = " + pt.enabled())
|
|
|
+// }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
}
|
|
|
|
|
|
private fun dumpDeviceInformation() {
|
|
@@ -910,8 +951,8 @@ class MainActivity : BaseActivity<MainActivityPresenter, ActivityMainBinding>(),
|
|
|
}
|
|
|
if (info != null) {
|
|
|
Log.i(TAG,
|
|
|
- "[Service] sipphone version is " +
|
|
|
- info.versionName + " (" + info.versionCode + ")"
|
|
|
+ "[Service] sipphone version is " +
|
|
|
+ info.versionName + " (" + info.versionCode + ")"
|
|
|
)
|
|
|
} else {
|
|
|
Log.i(TAG, "[Service] sipphone version is unknown")
|