NestJs 七牛云,百度智能云连接海康摄像头示例

之前在做摄像头调试,用nestjs 写的一些测试案例,不完善

qiniu.controller.ts

import { Body, Controller, Post, Get, Query } from '@nestjs/common';
import { QiniuService } from './qiniu.service';

@Controller('qiniu')
export class QiniuController {
    constructor(private qiniuService: QiniuService) { }

    @Post('/ptz')
    // cmd: left(向左), right(向右), up(向上), down(向下), leftup(左上), 
    // rightup(右上), leftdown(左下), rightdown(右下), 
    // zoomin(放大), zoomout(缩小),stop(停止PTZ操作)
    ptzControll(@Body() { cmd, speed = 5 }) {
        return this.qiniuService.ptzControll(cmd, speed)
    }
}

qiniu.service.ts

import { Injectable } from '@nestjs/common';
import axios from 'axios';

import { HmacSHA1, enc } from 'crypto-js'

@Injectable()
export class QiniuService {
    // key
    private ACCESS_KEY = '自己的accesskey'
    private SECRET_KEY = '自己的secretkey'

    private namespaceId = 'bas-test'
    private deviceId = '31011500991320032187'
    private host = 'qvs.qiniuapi.com'

    // 生成鉴权字符串
    getAuthorization(method = 'POST', url = '', body = '') {

        console.log(method, url, body)

        const data = method + " " + url + "\nHost: " + this.host + "\nContent-Type: " + "application/json" + "\n\n" + body

        const encodedSign = enc.Base64url.stringify((HmacSHA1(data, this.SECRET_KEY)));

        const authorization = 'Qiniu ' + this.ACCESS_KEY + ':' + encodedSign

        return authorization
    }

    async ptzControll(cmd = 'left', speed = 2) {

        const body = {
            cmd,
            speed,
            chId: '',
        }

        const url = `/v1/namespaces/${this.namespaceId}/devices/${this.deviceId}/ptz`

        const austr = this.getAuthorization('POST', url, JSON.stringify(body))

        const info = { success: false, msg: '', data: {} }

        try {
            const { data } = await axios({
                method: 'POST',
                headers: {
                    'authorization': austr,
                    'content-type': 'application/json'
                },
                data: body,
                url: `http://${this.host}${url}`,
            })
            info.success = true
            info.data = data
            info.msg = '成功'

        } catch (err) {

            info.success = false
            info.data = err
            info.msg = '失败!'
        }
        return info;
    }
}

baidu.controller.ts

import { Body, Controller, Get, HttpCode, Post, Query } from '@nestjs/common';
import { BaiduService } from './baidu.service';

@Controller('baidu')
export class BaiduController {
    constructor(private baiduService: BaiduService) { }

    @Get('list')
    getAllDevices(@Query() { pageNo = 1, pageSize = 10 }) {
        return this.baiduService.getAllDevices(pageNo, pageSize)
    }

    @Get('channel')
    getChannel(@Query('deviceId') deviceId) {
        return this.baiduService.getChannel(deviceId)
    }

    @Get('play')
    getPlayUrl(@Query('channelId') channelId) {
        return this.baiduService.getPlayUrl(channelId)
    }

    @Post('au')
    getAu(@Body() { method, url, requestHeader, query, x_bce_date }) {
        return this.baiduService.getAuthorization(method, url, query, x_bce_date, requestHeader)
    }

    @Post('ptz')
    @HttpCode(200)
    ptzControl(@Body() { channelId, cmd, speed }) {
        return this.baiduService.ptzControl(channelId, cmd, speed)
    }

    @Post('fi')
    @HttpCode(200)
    fiControl(@Body() { channelId, cmd, speed }) {
        return this.baiduService.fiControl(channelId, cmd, speed)
    }

    @Get('space')
    getSpace(@Query('id') id) {
        return this.baiduService.getSpaceInfo(id)
    }

    @Get('video')
    videoList(@Query() {start,end}) {
        return this.baiduService.videoList(start,end)
    }
}

baidu.service.ts

import { Injectable } from '@nestjs/common';
import axios from 'axios';
import { HmacSHA256, enc } from 'crypto-js'
import * as dayjs from 'dayjs'

const utc = require('dayjs/plugin/utc')
dayjs.extend(utc)

@Injectable()
export class BaiduService {
    private AK = '自己的Accesskey'
    private SK = '自己的SecretKey'

    private host = 'evs.bj.baidubce.com'
    private spaceId = '1006122'

    // url 编码
    UriEncodeExceptSlash(str) {
        const result = encodeURIComponent(str).replace(/%2F/g, '/')
        return result
    }
    // query-string 解析
    getCanonicalQueryString(str) {
        if (!str) return ''
        const list = str.split('&')
        if (!list.length) return ''
        // 键值对编码
        const keyVArr = list.map(v => {
            const arr = v.split('=')
            if (!arr[1]) return encodeURIComponent(v) + '='
            const key = arr[0]
            const value = arr[1]
            return encodeURIComponent(key) + '=' + encodeURIComponent(value)
        })
        // 根据ASII码排序
        const sortArr = keyVArr.sort((a: string, b: string) => {
            let as1 = a.charCodeAt(0)
            let as2 = b.charCodeAt(0)

            return as1 - as2
        })
        // & 拼接
        return sortArr.join('&')
    }

    getAuthorization(httpMethod = 'POST', CanonicalURI = '', CanonicalQueryString = '', x_bce_date, requestHeader) {
        // 签名有效期 单位为 s 
        const expirationPeriodInSeconds = 1800
        // 前缀字符串
        const authStringPrefix = `bce-auth-v1/${this.AK}/${x_bce_date}/${expirationPeriodInSeconds}`
        // 字符编码
        CanonicalURI = this.UriEncodeExceptSlash(CanonicalURI)
        // 字符处理
        CanonicalQueryString = this.getCanonicalQueryString(CanonicalQueryString)
        // 每项header编码
        const headerArr: string[] = []

        for (let key in requestHeader) {
            const headerName = key.toLowerCase().trim()
            const headerVal = encodeURIComponent(requestHeader[key].trim())
            headerArr.push(headerName + ':' + headerVal)
        }

        const resArr = headerArr.sort((a, b) => {
            // 字典序排序
            return a.charCodeAt(0) - b.charCodeAt(0)
        })
        const CanonicalHeaders = resArr.join('\n')
        // 验证请求头数组
        const signedArr = resArr.map(v => {
            return v.split(':')[0].trim()
        })
        // 认证字符串
        const signedHeaders = signedArr.join(';')
        // console.log('signedHeaders: ' + signedHeaders)

        const CanonicalRequest = httpMethod + "\n" + CanonicalURI + "\n" + CanonicalQueryString + "\n" + CanonicalHeaders
        // console.log('CanonicalRequest: ' + CanonicalRequest)

        // 派生签名密钥
        const SigningKey = enc.Hex.stringify(HmacSHA256(authStringPrefix, this.SK))
        // console.log(SigningKey)
        // 签名
        const Signature = enc.Hex.stringify(HmacSHA256(CanonicalRequest, SigningKey))
        // console.log('Signature:' + Signature)

        // 认证字符串
        let authorization = `bce-auth-v1/${this.AK}/${x_bce_date}/${expirationPeriodInSeconds}/${signedHeaders}/${Signature}`
        return authorization
    }

    // 获取所有摄像机
    async getAllDevices(pageNo, pageSize) {
        let URI = `/v1/device`

        let query = `spaceId=${this.spaceId}&pageNo=${pageNo}&pageSize=${pageSize}`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return data
    }

    // 获取频道
    async getChannel(deviceId) {
        let URI = `/v1/device/channel`

        let query = `deviceId=${deviceId}`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return data
    }

    // 获取GB28181设备通道播流链接
    async getPlayUrl(channelId) {
        if (!channelId) return ''

        let URI = `/v1/device/channel/${channelId}/signedUrl`

        let query = `protocol=webrtc`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: playUrl } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return {
            success: true,
            data: playUrl,
            msg: 'OK'
        }
    }

    // ptz 控制
    async ptzControl(channelId, ptzCommand, speed) {

        let URI = `/v1/device/channel/${channelId}`

        let query = `ptz&ptzCommand=${ptzCommand}&speed=${speed}`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: result } = await axios({
            method: 'PUT',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('PUT', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return {
            success: true,
            msg: result
        }
    }
    // 光圈与变焦
    async fiControl(channelId, fiCommand, speed) {
        let URI = `/v1/device/channel/${channelId}`

        let query = `fi&fiCommand=${fiCommand}&speed=${speed}`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: result } = await axios({
            method: 'PUT',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('PUT', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return {
            success: true,
            msg: result
        }
    }
    // 查询空间
    async getSpaceInfo(spaceId) {
        if (!spaceId) return ''

        let URI = `/v1/space/${spaceId}`
        let query = ``

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: res } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return res
    }

    async videoList(start='2023-09-18',end='2023-09-18') {
        // @ts-ignore
        const begin = parseInt(new Date(start + ' 09:00').getTime() / 1000)
        // @ts-ignore
        const endTime = parseInt(new Date(end + ' 18:00').getTime() / 1000)

        let URI = `/v1/device/channel/1059306/localRecording`
        let query = `begin=${begin}&end=${endTime}&isSync=true`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: res } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return res
    }

    async cloudVideoList() {
        // @ts-ignore
        const begin = parseInt(new Date('2023-08-02 17:00').getTime() / 1000)
        // @ts-ignore
        const end = parseInt(new Date('2023-08-06 19:00').getTime() / 1000)
        
        let URI = `/v1/device/channel/1059306/recording`
        let query = `begin=${begin}&end=${end}&pageNo=1&pageSize=10`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: res } = await axios({
            method: 'GET',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('GET', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            }
        })
        return res
    }

    async download(key) {
        let URI = `/v1/device/channel/1059306/localRecording`
        let query = `download`

        // 生成签名的时间
        // @ts-ignore
        const x_bce_date = dayjs().utc().format()

        const requestHeader = {
            'host': this.host,
            'content-type': 'application/json;charset=utf-8',
            'x-bce-date': x_bce_date
        }

        const { data: res } = await axios({
            method: 'POST',
            url: `http://${this.host}${URI}?${query}`,
            headers: {
                'authorization': this.getAuthorization('POST', URI, query, x_bce_date, requestHeader),
                ...requestHeader,
            },
            data: {
                downloadKey: key
            }
        })
        return res
    }

}

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值