Newer
Older
Endoscope / app / src / main / java / com / casic / endoscope / view / MainActivity.kt
package com.casic.endoscope.view

import android.annotation.SuppressLint
import android.graphics.PixelFormat
import android.os.Bundle
import android.os.Handler
import android.os.Message
import android.util.Log
import android.view.KeyEvent
import android.view.MotionEvent
import android.view.SurfaceHolder
import android.view.View
import androidx.lifecycle.lifecycleScope
import com.casic.endoscope.adapter.CameraPointAdapter
import com.casic.endoscope.bean.CameraPointBean
import com.casic.endoscope.databinding.ActivityMainBinding
import com.casic.endoscope.extensions.createImageFileDir
import com.casic.endoscope.extensions.createVideoFileDir
import com.casic.endoscope.extensions.getChannel
import com.casic.endoscope.extensions.toTime
import com.casic.endoscope.utils.DataBaseManager
import com.casic.endoscope.utils.ProjectConstant
import com.casic.endoscope.utils.hk.MessageCodeHub
import com.casic.endoscope.utils.hk.SDKGuider
import com.casic.endoscope.widgets.AddCameraPointDialog
import com.gyf.immersionbar.ImmersionBar
import com.hikvision.netsdk.HCNetSDK
import com.hikvision.netsdk.NET_DVR_JPEGPARA
import com.hikvision.netsdk.NET_DVR_PREVIEWINFO
import com.hikvision.netsdk.PTZCommand
import com.pengxh.kt.lite.base.KotlinBaseActivity
import com.pengxh.kt.lite.extensions.getStatusBarHeight
import com.pengxh.kt.lite.extensions.navigatePageTo
import com.pengxh.kt.lite.extensions.show
import com.pengxh.kt.lite.utils.WeakReferenceHandler
import com.pengxh.kt.lite.widget.SteeringWheelView
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.Timer
import java.util.TimerTask

@SuppressLint("all")
class MainActivity : KotlinBaseActivity<ActivityMainBinding>(), SurfaceHolder.Callback,
    Handler.Callback {

    private val kTag = "MainActivity"
    private val hkSDK by lazy { HCNetSDK.getInstance() }
    private val timeFormat by lazy { SimpleDateFormat("yyyyMMddHHmmss", Locale.CHINA) }
    private val selectedSpeed = 7
    private val messageCode = 2024021901
    private var clickTime = 0L
    private var previewHandle = -1
    private var selectChannel = -1
    private var returnUserId = -1
    private var aChannelNum = 0
    private var startAChannel = 0
    private var dChannelNum = 0
    private var startDChannel = 0
    private var isPreviewSuccess = false

    //手指是否已经从方向控制盘抬起
    private var isActionUp = true

    //焦距按钮是否已松开
    private var isScaleButtonUp = true
    private var timer: Timer? = null
    private var timerTask: TimerTask? = null
    private var seconds = 0L
    private var dataBeans: MutableList<CameraPointBean> = ArrayList()
    private var selectedItems: MutableList<CameraPointBean> = ArrayList()
    private lateinit var weakReferenceHandler: WeakReferenceHandler
    private lateinit var dataAdapter: CameraPointAdapter

    override fun initViewBinding(): ActivityMainBinding {
        return ActivityMainBinding.inflate(layoutInflater)
    }

    override fun initOnCreate(savedInstanceState: Bundle?) {
        weakReferenceHandler = WeakReferenceHandler(this)

        dataBeans = DataBaseManager.get.loadAllCameraPoint()

        //显示数据
        weakReferenceHandler.sendEmptyMessage(messageCode)
    }

    override fun handleMessage(msg: Message): Boolean {
        if (msg.what == messageCode) {
            //绑定数据
            dataAdapter = CameraPointAdapter(this, dataBeans)
            binding.recyclerView.adapter = dataAdapter
            dataAdapter.setOnItemCheckedListener(object : CameraPointAdapter.OnItemCheckedListener {
                override fun onItemChecked(position: Int, items: ArrayList<CameraPointBean>) {
                    selectedItems = items
                }
            })
        }
        return true
    }

    override fun initEvent() {
        binding.openAlbumButton.setOnClickListener {
            if (isPreviewSuccess) {
                "设备预览画面中,无法切换".show(this)
                return@setOnClickListener
            }
            navigatePageTo<AlbumActivity>()
        }

        //单张拍照
        binding.imageButton.setOnClickListener {
            if (isPreviewSuccess) {
                val strJpeg = NET_DVR_JPEGPARA()
                strJpeg.wPicQuality = 1
                strJpeg.wPicSize = 2

                val imagePath = "/${createImageFileDir()}/${timeFormat.format(Date())}.png"
                hkSDK.NET_DVR_CaptureJPEGPicture(
                    returnUserId, selectChannel, strJpeg, imagePath
                )

                if (MessageCodeHub.getErrorCode() == 0) {
                    "画面抓取成功".show(this@MainActivity)
                }
            } else {
                "摄像头预览未打开,无法拍照".show(this)
            }
        }

        //视频录制
        binding.videoButton.setOnClickListener {
            if (isPreviewSuccess) {
                val videoPath = "/${createVideoFileDir()}/${timeFormat.format(Date())}.mp4"
                hkSDK.NET_DVR_SaveRealData(returnUserId, videoPath)
                binding.videoStateView.visibility = View.VISIBLE
            } else {
                "摄像头预览未打开,无法录制视频".show(this)
            }
        }

        binding.videoButton.setOnLongClickListener {
            //停止视频抓取
            hkSDK.NET_DVR_StopSaveRealData(returnUserId)
            binding.videoStateView.visibility = View.INVISIBLE
            "视频录制成功".show(this@MainActivity)
            true
        }

        //连续拍照
        binding.multipleImageButton.setOnClickListener {
            if (dataBeans.isEmpty()) {
                "请先设置连续拍照步骤".show(this)
                return@setOnClickListener
            }
            if (isPreviewSuccess) {

            } else {
                "摄像头预览未打开,无法拍照".show(this)
            }
        }

        binding.addButton.setOnClickListener {
            val step = if (dataBeans.isEmpty()) {
                0
            } else {
                dataBeans.last().step
            }
            AddCameraPointDialog.Builder()
                .setContext(this)
                .setLastStep(step)
                .setNegativeButton("取消")
                .setPositiveButton("添加")
                .setOnDialogButtonClickListener(object :
                    AddCameraPointDialog.OnDialogButtonClickListener {
                    override fun onConfirmClick(step: Int, hAngle: Int, vAngle: Int) {
                        DataBaseManager.get.cacheCameraPoint(step, hAngle, vAngle)
                        dataBeans = DataBaseManager.get.loadAllCameraPoint()
                        dataAdapter.setRefreshData(dataBeans)
                    }

                    override fun onCancelClick() {

                    }
                }).build().show()
        }

        binding.deleteButton.setOnClickListener {
            if (selectedItems.isEmpty()) {
                "请先选择要删除的步骤".show(this)
                return@setOnClickListener
            }
            DataBaseManager.get.deleteCameraPoints(selectedItems)
            dataBeans = DataBaseManager.get.loadAllCameraPoint()
            dataAdapter.setRefreshData(dataBeans)
            selectedItems.clear()
        }

        binding.steeringWheelView.setOnWheelTouchListener(object :
            SteeringWheelView.OnWheelTouchListener {
            override fun onCenterClicked() {
                if (!isPreviewSuccess) {
                    val deviceItem = SDKGuider.sdkGuider.devManageGuider.DeviceItem()
                    deviceItem.szDevName = ""
                    deviceItem.devNetInfo = SDKGuider.sdkGuider.devManageGuider.DevNetInfo(
                        ProjectConstant.HK_NET_IP,
                        ProjectConstant.HK_NET_PORT,
                        ProjectConstant.HK_NET_USERNAME,
                        ProjectConstant.HK_NET_PASSWORD
                    )
                    if (deviceItem.szDevName.isEmpty()) {
                        deviceItem.szDevName = deviceItem.devNetInfo.szIp
                    }
                    val loginV40Jna = SDKGuider.sdkGuider.devManageGuider.login_v40_jna(
                        deviceItem.szDevName, deviceItem.devNetInfo
                    )
                    if (loginV40Jna) {
                        //配置设备通道
                        try {
                            val deviceInfo = SDKGuider.sdkGuider.devManageGuider.devList[0]
                            returnUserId = deviceInfo.szUserId

                            aChannelNum =
                                deviceInfo.deviceInfoV40_jna.struDeviceV30.byChanNum.toInt()
                            startAChannel =
                                deviceInfo.deviceInfoV40_jna.struDeviceV30.byStartChan.toInt()

                            dChannelNum = deviceInfo.deviceInfoV40_jna.struDeviceV30.byIPChanNum +
                                    deviceInfo.deviceInfoV40_jna.struDeviceV30.byHighDChanNum * 256
                            startDChannel =
                                deviceInfo.deviceInfoV40_jna.struDeviceV30.byStartChan.toInt()

                            var iAnalogStartChan = startAChannel
                            var iDigitalStartChan = startDChannel

                            val channelList = ArrayList<String>()

                            for (i in 0 until aChannelNum) {
                                channelList.add("ACamera_$iAnalogStartChan")
                                iAnalogStartChan++
                            }

                            for (i in 0 until dChannelNum) {
                                channelList.add("DCamera_$iDigitalStartChan")
                                iDigitalStartChan++
                            }
                            selectChannel = Integer.valueOf(channelList[0].getChannel())

                            val streamList = ArrayList<String>()
                            streamList.add("main_stream")
                            streamList.add("sub_stream")
                            streamList.add("third_stream")

                            //开始预览
                            if (previewHandle != -1) {
                                SDKGuider.sdkGuider.devPreviewGuider.RealPlay_Stop_jni(previewHandle)
                            }
                            val strutPlayInfo = NET_DVR_PREVIEWINFO()
                            strutPlayInfo.lChannel = selectChannel
                            strutPlayInfo.dwStreamType = 1
                            strutPlayInfo.bBlocked = 1
                            strutPlayInfo.hHwnd = binding.surfaceView.holder
                            previewHandle = SDKGuider.sdkGuider.devPreviewGuider.RealPlay_V40_jni(
                                returnUserId, strutPlayInfo, null
                            )
                            if (previewHandle < 0) {
                                Log.d(kTag, "initEvent: Err:${MessageCodeHub.getErrorCode()}")
                                return
                            }
                            isPreviewSuccess = true
                            "预览开启成功".show(this@MainActivity)
                            //开始计时
                            timer = Timer()
                            timerTask = object : TimerTask() {
                                override fun run() {
                                    seconds++
                                    lifecycleScope.launch(Dispatchers.Main) {
                                        binding.runningTimeView.text = seconds.toTime()
                                    }
                                }
                            }
                            timer?.schedule(timerTask, 0, 1000)
                        } catch (e: IndexOutOfBoundsException) {
                            e.printStackTrace()
                            "设备未正常连接,无法开启预览".show(this@MainActivity)
                        }
                    }
                } else {
                    if (!SDKGuider.sdkGuider.devPreviewGuider.RealPlay_Stop_jni(previewHandle)) {
                        return
                    }
                    previewHandle = -1
                    isPreviewSuccess = false
                    "预览关闭成功".show(this@MainActivity)
                    //停止计时
                    timerTask?.cancel()
                    timer?.cancel()
                }
            }

            override fun onLeftTurn() {
                if (isPreviewSuccess && isActionUp) {
                    hkSDK.NET_DVR_PTZControlWithSpeed(
                        previewHandle, PTZCommand.PAN_LEFT, 0, selectedSpeed
                    )
                    isActionUp = false
                }
            }

            override fun onTopTurn() {
                if (isPreviewSuccess && isActionUp) {
                    hkSDK.NET_DVR_PTZControlWithSpeed(
                        previewHandle, PTZCommand.TILT_UP, 0, selectedSpeed
                    )
                    isActionUp = false
                }
            }

            override fun onRightTurn() {
                if (isPreviewSuccess && isActionUp) {
                    hkSDK.NET_DVR_PTZControlWithSpeed(
                        previewHandle, PTZCommand.PAN_RIGHT, 0, selectedSpeed
                    )
                    isActionUp = false
                }
            }

            override fun onBottomTurn() {
                if (isPreviewSuccess && isActionUp) {
                    hkSDK.NET_DVR_PTZControlWithSpeed(
                        previewHandle, PTZCommand.TILT_DOWN, 0, selectedSpeed
                    )
                    isActionUp = false
                }
            }

            override fun onActionTurnUp(dir: SteeringWheelView.Direction) {
                when (dir) {
                    SteeringWheelView.Direction.LEFT -> {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.PAN_LEFT, 1)
                        isActionUp = true
                    }

                    SteeringWheelView.Direction.TOP -> {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.TILT_UP, 1)
                        isActionUp = true
                    }

                    SteeringWheelView.Direction.RIGHT -> {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.PAN_RIGHT, 1)
                        isActionUp = true
                    }

                    SteeringWheelView.Direction.BOTTOM -> {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.TILT_DOWN, 1)
                        isActionUp = true
                    }
                }
            }
        })

        binding.upScaleButton.setOnTouchListener { _, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    if (isPreviewSuccess && isScaleButtonUp) {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.ZOOM_IN, 0)
                        isScaleButtonUp = false
                    }
                }

                MotionEvent.ACTION_UP -> {
                    isScaleButtonUp = true
                    hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.ZOOM_IN, 1)
                }
            }
            false
        }

        binding.downScaleButton.setOnTouchListener { _, event ->
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    if (isPreviewSuccess && isScaleButtonUp) {
                        hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.ZOOM_OUT, 0)
                        isScaleButtonUp = false
                    }
                }

                MotionEvent.ACTION_UP -> {
                    isScaleButtonUp = true
                    hkSDK.NET_DVR_PTZControl(previewHandle, PTZCommand.ZOOM_OUT, 1)
                }
            }
            false
        }
    }


    override fun observeRequestState() {

    }

    override fun surfaceCreated(holder: SurfaceHolder) {
        binding.surfaceView.holder.setFormat(PixelFormat.TRANSLUCENT)
        if (-1 == previewHandle) {
            return
        }
        val surface = holder.surface
        if (surface.isValid) {
            if (-1 == SDKGuider.sdkGuider.devPreviewGuider.RealPlaySurfaceChanged_jni(
                    previewHandle, 0, holder
                )
            ) {
                Log.d(kTag, "surfaceCreated: ${MessageCodeHub.getErrorCode()}")
            }
        }
    }

    override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {

    }

    override fun surfaceDestroyed(holder: SurfaceHolder) {
        if (-1 == previewHandle) {
            return
        }
        if (holder.surface.isValid) {
            if (-1 == SDKGuider.sdkGuider.devPreviewGuider.RealPlaySurfaceChanged_jni(
                    previewHandle, 0, null
                )
            ) {
                Log.d(kTag, "surfaceDestroyed: ${MessageCodeHub.getErrorCode()}")
            }
        }
    }

    override fun setupTopBarLayout() {
        ImmersionBar.with(this).statusBarDarkFont(false).init()
        //根据不同设备状态栏高度设置statusBarView高度
        val statusBarHeight = getStatusBarHeight()
        binding.rootView.setPadding(0, statusBarHeight, 0, 0)
        binding.rootView.requestLayout()
    }

    override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (System.currentTimeMillis() - clickTime > 2000) {
                "再按一次退出应用".show(this)
                clickTime = System.currentTimeMillis()
                return true
            } else {
                super.onKeyDown(keyCode, event)
            }
        }
        return super.onKeyDown(keyCode, event)
    }
}