HappyOnvif - ONVIF协议摄像机接入平台

平台功能:在平台上录入相机后台设置的onvif信息,对外提供webapi接口,如获取播放地址,ptz控制,预置点控制等功能

开发环境:NetCore 6.0 + Sqlite

 

一、相机管理

1. 添加相机

2. 控制面板
2.1 获取播放地址,并播放rtsp流
2.2 PTZ控制
2.3 预置点管理(获取,前往,添加,删除)

2.4 语音对讲(语音广播,开始对讲,结束对讲)需要支持onvif backchannel

 rtsp转webrtc程序,用于html页面播放rtsp地址流

二、日志信息

三、 Swagger

 四、程序结构

 五、部分接口代码

using HappyOnvif.Utility;
using HappyOnvif.Utilty;
using HappyOnvif.Utilty.db;
using HappyOnvif.Utilty.db.model;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

namespace HappyOnvif.Controllers
{
    [Route("api/onvif/[action]")]
    [ApiController]
    public class OnvifController : ControllerBase
    {
        /// <summary>
        /// 获取webrtc服务ip
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public ResponseExtend getwebrtcip()
        {
            var result = new ResponseExtend<string>();

            try
            {
                result.data = Program.Rtsp2Webrtc_ServiceIp;
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/getwebrtcip 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }
        /// <summary>
        /// 设备初始化
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public ResponseExtend init([FromBody] Camera model)
        {
            string ip = model.Ip;

            var result = new ResponseExtend<bool>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null == onvif)
                {
                    onvif = new OnvifWsdl();

                    bool status = onvif.Init(ip, model.HttpPort, model.RtspPort, model.Name, model.Pwd);
                    if (status)
                    {
                        DataMgr.AddOnvif(ip, onvif);
                    } 
                    result.data = status;
                }
                else
                {
                    result.data = true;
                } 
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/init 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }

        /// <summary>
        /// 获取播放地址
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        [HttpGet]
        public ResponseExtend geturi(string ip = "192.168.0.13")
        {
            var result = new ResponseExtend<string>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null != onvif)
                { 
                    result.data = JsonConvert.SerializeObject(onvif.GetUri());
                }
                else
                {
                    result.code = 10001;
                    result.msg = "设备尚未初始化";
                }

            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/geturi 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }

        /// <summary>
        /// 获取预置点
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        [HttpGet]
        public ResponseExtend getpresets(string ip = "192.168.0.13")
        {
            var result = new ResponseExtend<string>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null != onvif)
                {
                    // 获取预置点
                    onvif.PTZControl(ECommandType.GetPreset);

                    result.data = JsonConvert.SerializeObject(onvif.Presets); 
                }
                else
                {
                    result.code = 10001;
                    result.msg = "设备尚未初始化";
                } 
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/gettpresets 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }

        /// <summary>
        /// ptz控制
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="cmd">0:停止;1:上;2:左上;3:右上;4:下;5:左下;6:右下;7:左;8:右;9:聚焦+;10:聚焦-;11:变倍+;12:变倍-;13:光圈开;14:光圈关;15:调用预置位;16:前往预置点;17:设置预置位;18:删除预置位</param>
        /// <param name="presetname"></param>
        /// <param name="presettoken">通过gettpresets获取到value</param>
        /// <param name="speed">步长 0-10</param>
        /// <returns></returns>
        [HttpGet]
        public ResponseExtend ptz(string ip = "192.168.0.13", int cmd = 0, int speed = 5, string presetname = "", string presettoken = "")
        {
            var result = new ResponseExtend<string>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null != onvif)
                {
                    result.data = onvif.PTZControl((ECommandType)cmd, speed, presetname, presettoken);
                }
                else
                {
                    result.code = 10001;
                    result.msg = "设备尚未初始化";
                }
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/ptz 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }

        /// <summary>
        /// 获取websocket信息
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public string wsinfo()
        {
            Dictionary<string, string> dicResult = new Dictionary<string, string>();
            dicResult["ServerIp"] = Program.Rtsp2Webrtc_ServiceIp;
            dicResult["WebSocketPort"] = Program.WebSocketPort.ToString();
            return JsonConvert.SerializeObject(dicResult);
        }

        /// <summary>
        /// 播放音频文件
        /// </summary>
        /// <param name="ip"></param> 
        /// <param name="type">音频类型(1:1.g711a;2:2.g711a;3:3.g711a)</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResponseExtend> playmediafile(string ip, int type)
        {
            var result = new ResponseExtend<string>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null != onvif)
                {
                    string filePath = AppDomain.CurrentDomain.BaseDirectory + "g77a//";
                    switch (type)
                    {
                        case 1:
                            filePath += "1.g711a";
                            break;
                        case 2:
                            filePath += "2.g711a";
                            break;
                        case 3:
                            filePath += "3.g711a";
                            break;
                        default:
                            break;
                    }

                    string rtspUrl = $"rtsp://{ip}:{onvif.RtspPort}";
                    string rtpmap = await onvif.Session.InitVoice(rtspUrl, onvif.Name, onvif.Pwd);
                    result.data = onvif.Session.Status ? "初始化成功,rtpmap=" + rtpmap : "初始化失败:" + onvif.Session.Errmsg;

                    if (!onvif.Session.Status || 0 != onvif.Session.VoiceStatus)
                    {
                        result.code = 10001;
                        result.msg = "状态错误";
                    }
                    else 
                    {
                        onvif.Session.VoiceStatus = 1;

                        byte[] audio = System.IO.File.ReadAllBytes(filePath);// out1_8k.g711a  css.pcm left.g711a  

                        ThreadPool.QueueUserWorkItem(async p => {
                            string note = "";
                            try
                            {
                                await onvif.Session.PlayAudio_G711A(audio, 25, 8000, onvif.Session.Ssrc2, onvif.Session.Channel);
                                note = "播放结束";
                                onvif.Session.VoiceStatus = 0; 
                            }
                            catch (Exception ex)
                            {
                                note = "播放失败,errmsg:" + ex.Message;
                            }
                            finally
                            {
                                onvif.Session.Close();
                            }
                        });
                    } 
                }
                else
                {
                    result.code = 10001;
                    result.msg = "设备尚未初始化";
                }
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/media 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }

        /// <summary>
        /// 语音对讲申请
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<ResponseExtend> talk(string ip)
        {
            var result = new ResponseExtend<bool>();

            try
            {
                var onvif = DataMgr.GetOnvif(ip);

                if (null != onvif)
                { 
                    string rtspUrl = $"rtsp://{ip}:{onvif.RtspPort}";
                    string rtpmap = await onvif.Session.InitVoice(rtspUrl, onvif.Name, onvif.Pwd);
                    result.data = onvif.Session.Status;
                }
                else
                {
                    result.code = 10001;
                    result.msg = "设备尚未初始化";
                }
            }
            catch (Exception ex)
            {
                result.code = 10000;
                result.msg = ex.Message;
                Logger.Error($"系统调用接口/onvif/talk 发生内部错误:{ex.Message}");
            }

            FreeSqlHelper.InsterApiLog(HttpContext.Request.GetDisplayUrl(), JsonConvert.SerializeObject(result));

            return result;
        }
    }
}
posted @ 2022-10-17 17:31  CHHC  阅读(705)  评论(0编辑  收藏  举报