云台控制
This commit is contained in:
@@ -548,6 +548,8 @@ class HomeMenuFragment : Fragment() {
|
|||||||
val intent = Intent(requireContext(), LiveVideoActivity::class.java)
|
val intent = Intent(requireContext(), LiveVideoActivity::class.java)
|
||||||
intent.putExtra("device_id", device.deviceId)
|
intent.putExtra("device_id", device.deviceId)
|
||||||
intent.putExtra("device_name", device.name)
|
intent.putExtra("device_name", device.name)
|
||||||
|
intent.putExtra("deviceNo", device.deviceNo)
|
||||||
|
intent.putExtra("light", device.light)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
} else {
|
} else {
|
||||||
showDefenseDialog(
|
showDefenseDialog(
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import android.content.res.Configuration
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.view.GestureDetector
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -22,6 +24,9 @@ import com.shuyu.gsyvideoplayer.listener.GSYSampleCallBack
|
|||||||
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
import com.shuyu.gsyvideoplayer.utils.OrientationUtils
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import android.os.Handler
|
||||||
|
import android.os.Looper
|
||||||
|
import com.ckkj.defense_device.view.MyGSYVideoPlayerLive
|
||||||
|
|
||||||
class LiveVideoActivity : BaseActivity() {
|
class LiveVideoActivity : BaseActivity() {
|
||||||
private lateinit var binding: LiveVideoActivityBinding
|
private lateinit var binding: LiveVideoActivityBinding
|
||||||
@@ -30,6 +35,7 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
private var isLightOn = false
|
private var isLightOn = false
|
||||||
private var isConsoleVisible = false
|
private var isConsoleVisible = false
|
||||||
private var deviceId: String? = null
|
private var deviceId: String? = null
|
||||||
|
private var deviceNo: String? = null
|
||||||
private var alarmList: MutableList<DeviceAlarmBean> = mutableListOf()
|
private var alarmList: MutableList<DeviceAlarmBean> = mutableListOf()
|
||||||
private var alarmAdapter: AlarmLogHorizontalAdapter? = null
|
private var alarmAdapter: AlarmLogHorizontalAdapter? = null
|
||||||
private var currentPage = 1
|
private var currentPage = 1
|
||||||
@@ -39,6 +45,8 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
private var isLoading = false
|
private var isLoading = false
|
||||||
|
|
||||||
private var orientationUtils: OrientationUtils? = null
|
private var orientationUtils: OrientationUtils? = null
|
||||||
|
private val ptzHandler = Handler(Looper.getMainLooper())
|
||||||
|
private var currentPtzDirection: String? = null
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -54,6 +62,8 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
|
|
||||||
deviceId = intent.getStringExtra("device_id")
|
deviceId = intent.getStringExtra("device_id")
|
||||||
val deviceName = intent.getStringExtra("device_name")
|
val deviceName = intent.getStringExtra("device_name")
|
||||||
|
deviceNo = intent.getStringExtra("deviceNo")
|
||||||
|
val light = intent.getStringExtra("light")
|
||||||
if (!deviceName.isNullOrEmpty()) {
|
if (!deviceName.isNullOrEmpty()) {
|
||||||
binding.tvTitle.text = deviceName
|
binding.tvTitle.text = deviceName
|
||||||
}
|
}
|
||||||
@@ -112,6 +122,21 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
hidePlayerControls()
|
hidePlayerControls()
|
||||||
binding.exoPlayContextId.startPlayLogic()
|
binding.exoPlayContextId.startPlayLogic()
|
||||||
binding.exoPlayContextId.fullscreenButton.setOnClickListener {
|
binding.exoPlayContextId.fullscreenButton.setOnClickListener {
|
||||||
|
binding.exoPlayContextId.onPtzControlListener =
|
||||||
|
object : MyGSYVideoPlayerLive.OnPtzControlListener {
|
||||||
|
override fun onStartPtz(direction: String) {
|
||||||
|
val no = deviceNo ?: return
|
||||||
|
startPtz(deviceNo = no, direction = direction)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopPtz() {
|
||||||
|
stopCurrentPtz()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onShoot() {
|
||||||
|
deviceNo?.let { shoot(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
orientationUtils?.resolveByClick()
|
orientationUtils?.resolveByClick()
|
||||||
binding.exoPlayContextId.startWindowFullscreen(this, true, true)
|
binding.exoPlayContextId.startWindowFullscreen(this, true, true)
|
||||||
}
|
}
|
||||||
@@ -237,6 +262,114 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
binding.ivVoice.setImageResource(R.mipmap.voice)
|
binding.ivVoice.setImageResource(R.mipmap.voice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.ivUp.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(
|
||||||
|
view = v,
|
||||||
|
event = event,
|
||||||
|
direction = "up",
|
||||||
|
action = { deviceNo }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivDown.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(
|
||||||
|
view = v,
|
||||||
|
event = event,
|
||||||
|
direction = "down",
|
||||||
|
action = { deviceNo }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivLeft.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(
|
||||||
|
view = v,
|
||||||
|
event = event,
|
||||||
|
direction = "left",
|
||||||
|
action = { deviceNo }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivRight.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(
|
||||||
|
view = v,
|
||||||
|
event = event,
|
||||||
|
direction = "right",
|
||||||
|
action = { deviceNo }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handlePtzTouch(
|
||||||
|
view: View,
|
||||||
|
event: MotionEvent,
|
||||||
|
direction: String,
|
||||||
|
action: () -> String?
|
||||||
|
): Boolean {
|
||||||
|
when (event.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
view.isPressed = true
|
||||||
|
val deviceNo = action()
|
||||||
|
if (!deviceNo.isNullOrEmpty()) {
|
||||||
|
startPtz(deviceNo = deviceNo, direction = direction)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
view.isPressed = false
|
||||||
|
stopCurrentPtz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startPtz(deviceNo: String, direction: String) {
|
||||||
|
stopCurrentPtz()
|
||||||
|
|
||||||
|
currentPtzDirection = direction
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
val response = when (direction) {
|
||||||
|
"up" -> RetrofitNetwork.getNetworkService().ptzUp(deviceNo)
|
||||||
|
"down" -> RetrofitNetwork.getNetworkService().ptzDown(deviceNo)
|
||||||
|
"left" -> RetrofitNetwork.getNetworkService().ptzLeft(deviceNo)
|
||||||
|
"right" -> RetrofitNetwork.getNetworkService().ptzRight(deviceNo)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
Log.d("LV", "PTZ $direction start response: ${response?.code}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("LV", "PTZ $direction start failed", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shoot(deviceNo: String) {
|
||||||
|
Log.d("LV", "btnCapture click, deviceNo=$deviceNo, duration=0")
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
val response = RetrofitNetwork.getNetworkService().ptzShoot(
|
||||||
|
deviceNo = deviceNo,
|
||||||
|
duration = "0"
|
||||||
|
)
|
||||||
|
Log.d("LV", "PTZ shoot response: code=${response.code}, msg=${response.msg}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("LV", "PTZ shoot failed", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun stopCurrentPtz() {
|
||||||
|
val direction = currentPtzDirection ?: return
|
||||||
|
currentPtzDirection = null
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
try {
|
||||||
|
val response = RetrofitNetwork.getNetworkService().ptzStop(deviceNo ?: return@launch)
|
||||||
|
Log.d("LV", "PTZ $direction stop response: ${response.code}")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("LV", "PTZ $direction stop failed", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAlarmList(page: Int = 1) {
|
private fun fetchAlarmList(page: Int = 1) {
|
||||||
@@ -284,6 +417,7 @@ class LiveVideoActivity : BaseActivity() {
|
|||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
ptzHandler.removeCallbacksAndMessages(null)
|
||||||
orientationUtils?.releaseListener()
|
orientationUtils?.releaseListener()
|
||||||
binding.exoPlayContextId.release()
|
binding.exoPlayContextId.release()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,5 +271,62 @@ interface ApiService {
|
|||||||
@POST("/app/joinTheFamily")
|
@POST("/app/joinTheFamily")
|
||||||
suspend fun joinTheFamily(@Body request: JoinTheFamilyBean): GetCodeBean<Any>
|
suspend fun joinTheFamily(@Body request: JoinTheFamilyBean): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ向上控制
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/up")
|
||||||
|
suspend fun ptzUp(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
@Query("speed") speed: String = "5",
|
||||||
|
@Query("duration") duration: String = "0"
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ向下控制
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/down")
|
||||||
|
suspend fun ptzDown(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
@Query("speed") speed: String = "5",
|
||||||
|
@Query("duration") duration: String = "0"
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ向左控制
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/left")
|
||||||
|
suspend fun ptzLeft(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
@Query("speed") speed: String = "5",
|
||||||
|
@Query("duration") duration: String = "0"
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ向右控制
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/right")
|
||||||
|
suspend fun ptzRight(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
@Query("speed") speed: String = "5",
|
||||||
|
@Query("duration") duration: String = "0"
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ停止控制
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/stop")
|
||||||
|
suspend fun ptzStop(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PTZ控制水枪喷水
|
||||||
|
*/
|
||||||
|
@POST("/app/ptz/{deviceNo}/shoot")
|
||||||
|
suspend fun ptzShoot(
|
||||||
|
@retrofit2.http.Path("deviceNo") deviceNo: String,
|
||||||
|
@Query("duration") duration: String,
|
||||||
|
): GetCodeBean<Any>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.ckkj.defense_device.view
|
package com.ckkj.defense_device.view
|
||||||
|
|
||||||
|
import android.util.Log
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
|
import android.view.MotionEvent
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.ckkj.defense_device.R
|
import com.ckkj.defense_device.R
|
||||||
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
import com.shuyu.gsyvideoplayer.video.StandardGSYVideoPlayer
|
||||||
@@ -12,6 +14,18 @@ class MyGSYVideoPlayerLive @JvmOverloads constructor(
|
|||||||
context: Context, attrs: AttributeSet? = null
|
context: Context, attrs: AttributeSet? = null
|
||||||
) : StandardGSYVideoPlayer(context, attrs) {
|
) : StandardGSYVideoPlayer(context, attrs) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "MyGSYVideoPlayerLive"
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OnPtzControlListener {
|
||||||
|
fun onStartPtz(direction: String)
|
||||||
|
fun onStopPtz()
|
||||||
|
fun onShoot()
|
||||||
|
}
|
||||||
|
|
||||||
|
var onPtzControlListener: OnPtzControlListener? = null
|
||||||
|
|
||||||
override fun init(context: Context) {
|
override fun init(context: Context) {
|
||||||
super.init(context)
|
super.init(context)
|
||||||
startButton.visibility = View.GONE
|
startButton.visibility = View.GONE
|
||||||
@@ -76,10 +90,54 @@ class MyGSYVideoPlayerLive @JvmOverloads constructor(
|
|||||||
|
|
||||||
overlay.findViewById<View>(R.id.btnCapture)
|
overlay.findViewById<View>(R.id.btnCapture)
|
||||||
?.setOnClickListener {
|
?.setOnClickListener {
|
||||||
|
Log.d("MyGSYVideoPlayerLive", "btnCapture clicked, onShoot invoked")
|
||||||
|
onPtzControlListener?.onShoot()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
player.initPtzControls(overlay)
|
||||||
|
|
||||||
return player
|
return player
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun initPtzControls(overlay: View) {
|
||||||
|
val ptzListener = onPtzControlListener
|
||||||
|
|
||||||
|
overlay.findViewById<View>(R.id.ivUp)?.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(v, event, "up", ptzListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay.findViewById<View>(R.id.ivDown)?.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(v, event, "down", ptzListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay.findViewById<View>(R.id.ivLeft)?.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(v, event, "left", ptzListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
overlay.findViewById<View>(R.id.ivRight)?.setOnTouchListener { v, event ->
|
||||||
|
handlePtzTouch(v, event, "right", ptzListener)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handlePtzTouch(
|
||||||
|
view: View,
|
||||||
|
event: MotionEvent,
|
||||||
|
direction: String,
|
||||||
|
listener: OnPtzControlListener?
|
||||||
|
): Boolean {
|
||||||
|
when (event.action) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
Log.d(TAG, "全屏PTZ长按开始 direction=$direction")
|
||||||
|
view.isPressed = true
|
||||||
|
listener?.onStartPtz(direction)
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
Log.d(TAG, "全屏PTZ长按结束 direction=$direction")
|
||||||
|
view.isPressed = false
|
||||||
|
listener?.onStopPtz()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user