初始
This commit is contained in:
51
third/ys7/struct.go
Normal file
51
third/ys7/struct.go
Normal file
@ -0,0 +1,51 @@
|
||||
package ys7
|
||||
|
||||
const OK = "200"
|
||||
|
||||
//type Public struct {
|
||||
// Code string `json:"code"`
|
||||
// Msg string `json:"msg"`
|
||||
//}
|
||||
|
||||
type TP struct {
|
||||
Public
|
||||
Data struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
ExpireTime int64 `json:"expireTime"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
type HelMet struct {
|
||||
Public
|
||||
RequestId string `json:"requestId"`
|
||||
Data []struct {
|
||||
Id string `json:"id"`
|
||||
Height string `json:"height"`
|
||||
TargetList []struct {
|
||||
BodyRect struct {
|
||||
VmodelHF string `json:"vmodel_h_f"`
|
||||
VmodelWF string `json:"vmodel_w_f"`
|
||||
VmodelXF string `json:"vmodel_x_f"`
|
||||
VmodelYF string `json:"vmodel_y_f"`
|
||||
} `json:"body_rect"`
|
||||
AlarmFlg int `json:"alarm_flg"`
|
||||
UniformType int `json:"uniform_type"`
|
||||
ID int `json:"ID"`
|
||||
HelmetType int `json:"helmet_type"`
|
||||
HeadRect struct {
|
||||
VmodelHF string `json:"vmodel_h_f"`
|
||||
VmodelWF string `json:"vmodel_w_f"`
|
||||
VmodelXF string `json:"vmodel_x_f"`
|
||||
VmodelYF string `json:"vmodel_y_f"`
|
||||
} `json:"head_rect"`
|
||||
ColorType int `json:"color_type"`
|
||||
} `json:"target_list"`
|
||||
Width string `json:"width"`
|
||||
RuleInfo []interface{} `json:"rule_info"`
|
||||
RuleList [][]struct {
|
||||
Y string `json:"y"`
|
||||
X string `json:"x"`
|
||||
} `json:"rule_list"`
|
||||
ErrorCode int `json:"errorCode"`
|
||||
} `json:"data"`
|
||||
}
|
558
third/ys7/ys7.go
Normal file
558
third/ys7/ys7.go
Normal file
@ -0,0 +1,558 @@
|
||||
package ys7
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
|
||||
)
|
||||
|
||||
var accessToken = "at.ddhhz6ea49jorccubhg3elqs19nvmxta-1754nu5ce8-017egq8-fmymwvvhv"
|
||||
|
||||
const (
|
||||
Ok = "200"
|
||||
Online = 1
|
||||
)
|
||||
|
||||
// 改变 accessToken
|
||||
func SetAccessToken(token string) {
|
||||
accessToken = token
|
||||
}
|
||||
|
||||
// 传入 serial 返回 Devicemap 中的设备信息
|
||||
func GetDevice(serial string) (Ys7Device, error) {
|
||||
device, ok := deviceMap[serial]
|
||||
if ok {
|
||||
return device, nil
|
||||
}
|
||||
return Ys7Device{}, fmt.Errorf("设备不存在")
|
||||
}
|
||||
|
||||
var deviceMap = make(map[string]Ys7Device)
|
||||
|
||||
/*当前包的入口方法*/
|
||||
func InitYs7() {
|
||||
/*获取一次token*/
|
||||
getAccessToken()
|
||||
/*获取一次设备列表*/
|
||||
getDeviceList(0, 50) // 可以提前获取数据库中的记录进行缓存,比对当前设备是否在数据库中已经存在,不存在则自动入库
|
||||
}
|
||||
|
||||
func GetAccessToken() string {
|
||||
return accessToken
|
||||
}
|
||||
|
||||
/*获取设备表*/
|
||||
func GetDeviceMap() map[string]Ys7Device {
|
||||
return deviceMap
|
||||
}
|
||||
|
||||
type TokenRes struct {
|
||||
Public
|
||||
Data struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
ExpireTime int64 `json:"expireTime"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
func getAccessToken() {
|
||||
// ctx := gctx.New()
|
||||
// appKey := g.Cfg().MustGet(ctx, "ys7.appKey").String()
|
||||
// appSecret := g.Cfg().MustGet(ctx, "ys7.appSecret").String()
|
||||
|
||||
appKey := "3acf9f1a43dc4209841e0893003db0a2"
|
||||
appSecret := "4bbf3e9394f55d3af6e3af27b2d3db36"
|
||||
|
||||
url := "https://open.ys7.com/api/lapp/token/get"
|
||||
dt := struct {
|
||||
AppKey string `json:"appKey"`
|
||||
AppSecret string `json:"appSecret"`
|
||||
}{AppKey: appKey, AppSecret: appSecret}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
} else {
|
||||
res := TokenRes{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
} else {
|
||||
accessToken = res.Data.AccessToken
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type DeviceListRes struct {
|
||||
Public
|
||||
Page struct {
|
||||
Total int `json:"total"`
|
||||
Page int `json:"page"`
|
||||
Size int `json:"size"`
|
||||
} `json:"page"`
|
||||
Data []Ys7Device `json:"data"`
|
||||
}
|
||||
|
||||
func delayRequest(page, pageSize int) {
|
||||
time.Sleep(time.Second * 5)
|
||||
getDeviceList(page, pageSize)
|
||||
}
|
||||
|
||||
func getDeviceList(page, pageSize int) {
|
||||
url := "https://open.ys7.com/api/lapp/device/list"
|
||||
dt := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
PageStart int `json:"pageStart"`
|
||||
PageSize int `json:"pageSize"`
|
||||
}{AccessToken: accessToken, PageSize: pageSize, PageStart: page}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
delayRequest(page, pageSize)
|
||||
} else {
|
||||
res := DeviceListRes{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
delayRequest(page, pageSize)
|
||||
} else {
|
||||
if res.Code == Ok {
|
||||
for _, datum := range res.Data {
|
||||
deviceMap[datum.DeviceSerial] = datum
|
||||
//marshal, err := json.Marshal(datum)
|
||||
//if err != nil {
|
||||
// return
|
||||
//}
|
||||
//fmt.Println(string(marshal))
|
||||
//if datum.Online() {
|
||||
// capRes, err := datum.Capture()
|
||||
// if err != nil {
|
||||
// fmt.Println("抓图识别")
|
||||
// } else {
|
||||
// SavePicture(capRes.Data.PicUrl, "static/"+gmd5.MustEncryptString(capRes.Data.PicUrl)+".jpg")
|
||||
// }
|
||||
//}
|
||||
}
|
||||
if (page+1)*pageSize < res.Page.Total {
|
||||
getDeviceList(page+1, pageSize)
|
||||
}
|
||||
} else {
|
||||
delayRequest(page, pageSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type Ys7Device struct {
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
DeviceName string `json:"deviceName"`
|
||||
DeviceType string `json:"deviceType"`
|
||||
Status int `json:"status"`
|
||||
Defence int `json:"defence"`
|
||||
DeviceVersion string `json:"deviceVersion"`
|
||||
}
|
||||
type Public struct {
|
||||
Code string `json:"code"`
|
||||
Msg string `json:"msg"`
|
||||
}
|
||||
|
||||
func (receiver *Ys7Device) Online() bool {
|
||||
if receiver.Status == Online {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func Post(url string, data interface{}) (res []byte, err error) {
|
||||
response, err := g.Client().Header(map[string]string{"Content-Type": "application/x-www-form-urlencoded"}).Post(gctx.New(), url, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.ReadAll(), nil
|
||||
}
|
||||
|
||||
/*开始云台控制*/
|
||||
func (receiver *Ys7Device) PTZStart(direction int) (res *Public, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/ptz/start"
|
||||
dt := struct {
|
||||
ChannelNo int `json:"channelNo"`
|
||||
Direction int `json:"direction"`
|
||||
Speed int `json:"speed"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}{
|
||||
AccessToken: accessToken, DeviceSerial: receiver.DeviceSerial, ChannelNo: 1, Speed: 1, Direction: direction,
|
||||
}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
res = &Public{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/*停止云台控制*/
|
||||
func (receiver *Ys7Device) PTZEnd(direction int) (res *Public, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/ptz/stop"
|
||||
dt := struct {
|
||||
ChannelNo int `json:"channelNo"`
|
||||
Direction int `json:"direction"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}{
|
||||
AccessToken: accessToken, DeviceSerial: receiver.DeviceSerial, ChannelNo: 1, Direction: direction,
|
||||
}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
res = &Public{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
type PresetAddRes struct {
|
||||
Public
|
||||
Data struct {
|
||||
Index int `json:"index"` // 预置点序号,C6设备是1-12,该参数需要开发者自行保存
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
/*添加预制点*/
|
||||
func (receiver *Ys7Device) AddPreset() (res *PresetAddRes, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/preset/add"
|
||||
dt := struct {
|
||||
ChannelNo int `json:"channelNo"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}{
|
||||
AccessToken: accessToken, DeviceSerial: receiver.DeviceSerial, ChannelNo: 1,
|
||||
}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
res = &PresetAddRes{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/*调用预制点*/
|
||||
func (receiver *Ys7Device) MovePreset(index int) (res *Public, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/preset/move"
|
||||
dt := struct {
|
||||
ChannelNo int `json:"channelNo"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
Index int `json:"index"`
|
||||
}{ChannelNo: 1, DeviceSerial: receiver.DeviceSerial, AccessToken: accessToken, Index: index}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
res = &Public{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/*清除预制点*/
|
||||
func (receiver *Ys7Device) ClearPreset(index int) (res *Public, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/preset/clear"
|
||||
dt := struct {
|
||||
ChannelNo int `json:"channelNo"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
Index int `json:"index"`
|
||||
}{ChannelNo: 1, DeviceSerial: receiver.DeviceSerial, AccessToken: accessToken, Index: index}
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
res = &Public{}
|
||||
err = json.Unmarshal(post, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 开启设备视频加密
|
||||
func (r *Ys7Device) OpenEncrypt() error {
|
||||
url := "https://open.ys7.com/api/lapp/device/encrypt/on"
|
||||
dt := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
}{
|
||||
AccessToken: accessToken,
|
||||
DeviceSerial: r.DeviceSerial,
|
||||
}
|
||||
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gjson.New(string(post)).Get("code").Int() != 200 {
|
||||
return fmt.Errorf("%s", gjson.New(string(post)).Get("msg").String())
|
||||
}
|
||||
|
||||
// 更新数据库
|
||||
_, err = dao.Ys7Devices.Ctx(context.Background()).
|
||||
Where(dao.Ys7Devices.Columns().DeviceSerial, r.DeviceSerial).
|
||||
Update(g.Map{
|
||||
"VideoEncrypted": 1,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 关闭设备视频加密
|
||||
func (r *Ys7Device) CloseEncrypt() error {
|
||||
url := "https://open.ys7.com/api/lapp/device/encrypt/off"
|
||||
dt := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
}{
|
||||
AccessToken: accessToken,
|
||||
DeviceSerial: r.DeviceSerial,
|
||||
}
|
||||
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if gjson.New(string(post)).Get("code").Int() != 200 {
|
||||
return fmt.Errorf("%s", gjson.New(string(post)).Get("msg").String())
|
||||
}
|
||||
|
||||
_, err = dao.Ys7Devices.Ctx(context.Background()).
|
||||
Where(dao.Ys7Devices.Columns().DeviceSerial, r.DeviceSerial).
|
||||
Update(g.Map{
|
||||
"VideoEncrypted": 0,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetLiveAddress 获取播放地址
|
||||
func (r *Ys7Device) GetLiveAddress() (string, error) {
|
||||
url := "https://open.ys7.com/api/lapp/v2/live/address/get"
|
||||
dt := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
ChannelNo int `json:"channelNo"`
|
||||
}{
|
||||
AccessToken: accessToken,
|
||||
DeviceSerial: r.DeviceSerial,
|
||||
ChannelNo: 1,
|
||||
}
|
||||
|
||||
post, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
Body := string(post)
|
||||
println(Body)
|
||||
if gjson.New(Body).Get("code").Int() != 200 {
|
||||
return "", fmt.Errorf("获取播放地址失败: %s", gjson.New(Body).Get("msg").String())
|
||||
}
|
||||
|
||||
return gjson.New(Body).Get("data.url").String(), nil
|
||||
}
|
||||
|
||||
/*抓图结果返回*/
|
||||
type CapRes struct {
|
||||
Public
|
||||
Data struct {
|
||||
PicUrl string `json:"picUrl"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
/*抓拍图片*/
|
||||
func (receiver *Ys7Device) Capture() (cap *CapRes, err error) {
|
||||
url := "https://open.ys7.com/api/lapp/device/capture"
|
||||
dt := struct {
|
||||
DeviceSerial string `json:"deviceSerial"`
|
||||
ChannelNo int `json:"channelNo"`
|
||||
AccessToken string `json:"accessToken"`
|
||||
}{DeviceSerial: receiver.DeviceSerial, ChannelNo: 1, AccessToken: accessToken}
|
||||
res, err := Post(url, dt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cap = &CapRes{}
|
||||
err = json.Unmarshal(res, &cap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// cap.Data.PicUrl = string(TransHtmlJson([]byte(cap.Data.PicUrl)))
|
||||
return cap, nil
|
||||
}
|
||||
|
||||
// download file会将url下载到本地文件,它会在下载时写入,而不是将整个文件加载到内存中。
|
||||
|
||||
func SavePicture(url, dst string) (err error) {
|
||||
// Get the data
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
// Create the file
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
// Write the body to file
|
||||
_, err = io.Copy(out, resp.Body)
|
||||
return err
|
||||
}
|
||||
|
||||
//var appKey = ""
|
||||
//var secret = ""
|
||||
//var token = ""
|
||||
//
|
||||
//// InitYs7 安全帽 absolutePath绝对路径
|
||||
//func InitYs7(absolutePath string) (flag bool, num int, err error) {
|
||||
// getConfig()
|
||||
// GetAccesstoken()
|
||||
// imageData, err := os.ReadFile(absolutePath)
|
||||
// if err != nil {
|
||||
// err = errors.New("读取图片文件失败")
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// // 将图片数据转换为Base64字符串
|
||||
// base64String := base64.StdEncoding.EncodeToString(imageData)
|
||||
// flag, num, err = HelmetCheck(base64String, absolutePath)
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//func getConfig() {
|
||||
// appKey = g.Cfg().MustGet(gctx.New(), "ys7.key").String()
|
||||
// secret = g.Cfg().MustGet(gctx.New(), "ys7.secret").String()
|
||||
//}
|
||||
//
|
||||
//func GetAccesstoken() {
|
||||
// key := "ys7"
|
||||
// //从缓存捞取key
|
||||
// ctx := gctx.New()
|
||||
// get := commonService.Cache().Get(ctx, key)
|
||||
// if get != nil && get.String() != "" {
|
||||
// token = get.String()
|
||||
// } else {
|
||||
// getConfig()
|
||||
// url := "https://open.ys7.com/api/lapp/token/get"
|
||||
// dt := struct {
|
||||
// AppKey string `json:"appKey"`
|
||||
// AppSecret string `json:"appSecret"`
|
||||
// }{appKey, secret}
|
||||
// err, s := post(url, dt)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// tp := TP{}
|
||||
// err = json.Unmarshal(s, &tp)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// if tp.Code == OK {
|
||||
// token = tp.Data.AccessToken
|
||||
// //将token存储到redis中,tiken默认时间为秒,实际计算为7天,(这里少100秒,防止token过期还存在redis中)
|
||||
// commonService.Cache().Set(ctx, key, tp.Data.AccessToken, time.Duration(tp.Data.ExpireTime-100)*time.Second)
|
||||
// token = tp.Data.AccessToken
|
||||
// }
|
||||
// }
|
||||
//
|
||||
//}
|
||||
//
|
||||
//func post(uri string, data interface{}) (error, []byte) {
|
||||
// response, err := g.Client().ContentType("application/x-www-form-urlencoded").Post(gctx.New(), uri, data)
|
||||
// if err != nil {
|
||||
// return err, nil
|
||||
// }
|
||||
// return nil, response.ReadAll()
|
||||
//}
|
||||
//
|
||||
//// HelmetCheck 图片中标记安全帽
|
||||
//func HelmetCheck(image string, absolutePath string) (flag bool, num int, err error) {
|
||||
// flag = false
|
||||
// num = 0
|
||||
// url := "https://open.ys7.com/api/lapp/intelligence/target/analysis"
|
||||
// dt := struct {
|
||||
// AccessToken string `json:"accessToken"`
|
||||
// DataType int `json:"dataType"`
|
||||
// Image string `json:"image"`
|
||||
// ServiceType string `json:"serviceType"`
|
||||
// }{token, 1, image, "helmet"}
|
||||
// err, s := post(url, dt)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// tp := HelMet{}
|
||||
// err = json.Unmarshal(s, &tp)
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// if tp.Code == OK && len(tp.Data) > 0 {
|
||||
// for _, data := range tp.Data {
|
||||
// height, _ := strconv.ParseFloat(data.Height, 64)
|
||||
// width, _ := strconv.ParseFloat(data.Width, 64)
|
||||
// if len(tp.Data) <= 0 {
|
||||
// continue
|
||||
// }
|
||||
// for _, dataTwo := range data.TargetList {
|
||||
// HeadRect := dataTwo.HeadRect
|
||||
// helmetType := dataTwo.HelmetType
|
||||
// if helmetType == 2 || helmetType == 0 {
|
||||
// flag = true
|
||||
// num = num + 1
|
||||
// vmodel_h_f, _ := strconv.ParseFloat(HeadRect.VmodelHF, 64)
|
||||
// vmodel_w_f, _ := strconv.ParseFloat(HeadRect.VmodelWF, 64)
|
||||
// vmodel_x_f, _ := strconv.ParseFloat(HeadRect.VmodelXF, 64)
|
||||
// vmodel_y_f, _ := strconv.ParseFloat(HeadRect.VmodelYF, 64)
|
||||
//
|
||||
// vmodel_h_f = vmodel_h_f * height
|
||||
// vmodel_w_f = vmodel_w_f * width
|
||||
// vmodel_x_f = vmodel_x_f * width
|
||||
// vmodel_y_f = vmodel_y_f * height
|
||||
// coryCommon.Test_draw_rect_text(absolutePath,
|
||||
// vmodel_x_f, vmodel_y_f, vmodel_w_f, vmodel_h_f)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
//}
|
338
third/ys7/ys72.go
Normal file
338
third/ys7/ys72.go
Normal file
@ -0,0 +1,338 @@
|
||||
package ys7
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/model/do"
|
||||
"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
|
||||
)
|
||||
|
||||
type Ys72 struct {
|
||||
FnLogin func() (string, error) // 登录回调
|
||||
Devices map[string]Ys7Device // 设备列表
|
||||
Total int // 总页数 和 当前页数
|
||||
}
|
||||
|
||||
var Ys72Instance = NewYs72()
|
||||
|
||||
// NewYs72 初始化
|
||||
func NewYs72() *Ys72 {
|
||||
ys7 := &Ys72{
|
||||
FnLogin: DefaultLogin,
|
||||
Devices: make(map[string]Ys7Device),
|
||||
Total: 999, // 第一次获取设备列表时,会刷新其实际值
|
||||
}
|
||||
|
||||
// 刷新 ys7.go 中的 AccessToken
|
||||
_ = ys7.GetAccessToken()
|
||||
|
||||
// 初始化设备列表
|
||||
//if err := ys7.Init(); err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
// 定时任务更新设备列表
|
||||
go func() {
|
||||
for range time.Tick(3 * time.Minute) {
|
||||
if err := ys7.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := ys7.GetAllDeviceList(); err != nil {
|
||||
log.Println("更新设备列表失败:", err)
|
||||
}
|
||||
|
||||
// 获取设备截图并存入 Redis
|
||||
ys7.CaptureAllDevice()
|
||||
}
|
||||
}()
|
||||
|
||||
return ys7
|
||||
}
|
||||
|
||||
// Init 第一次初始化时从数据库获取设备列表存入 Devices
|
||||
func (ys *Ys72) Init() error {
|
||||
device := []entity.Ys7Devices{}
|
||||
|
||||
// 获取设备列表
|
||||
err := dao.Ys7Devices.Ctx(context.Background()).Scan(&device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将设备列表存入 Devices
|
||||
for _, v := range device {
|
||||
ys.Devices[v.DeviceSerial] = Ys7Device{
|
||||
DeviceSerial: v.DeviceSerial,
|
||||
DeviceName: v.DeviceName,
|
||||
DeviceType: v.DeviceType,
|
||||
Status: v.Status,
|
||||
Defence: int(v.Defence),
|
||||
DeviceVersion: v.DeviceVersion,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 遍历 ys.Devices 调用 Capture 获取设备截图并存入Redis
|
||||
func (ys *Ys72) CaptureAllDevice() {
|
||||
for _, device := range ys.Devices {
|
||||
// 获取设备截图
|
||||
resp, err := device.Capture()
|
||||
if err != nil {
|
||||
log.Println("获取设备截图失败:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// 存入 Redis
|
||||
ctx := context.Background()
|
||||
g.Redis().Set(ctx, "ys7:capture:"+device.DeviceSerial, resp.Data.PicUrl)
|
||||
// 两小时后过期
|
||||
g.Redis().Expire(ctx, "ys7:capture:"+device.DeviceSerial, 2*60*60)
|
||||
}
|
||||
}
|
||||
|
||||
// 由 Redis 管理 AccessToken 的生命周期,如果获取失败则重新刷新
|
||||
func (ys *Ys72) GetAccessToken() string {
|
||||
ctx := context.Background()
|
||||
// 从 Redis 获取 AccessToken
|
||||
accessToken, err := g.Redis().Get(ctx, "ys7:accessToken")
|
||||
|
||||
// 兼容原本获取 AccessToken 的逻辑
|
||||
SetAccessToken(accessToken.String())
|
||||
|
||||
if err == nil && accessToken.String() != "" {
|
||||
return accessToken.String()
|
||||
}
|
||||
|
||||
// 未获取到 AccessToken 则重新登录
|
||||
if accessToken.String() == "" {
|
||||
// 如果登录失败则递归重试
|
||||
if err := ys.login(); err != nil {
|
||||
return ys.GetAccessToken()
|
||||
}
|
||||
|
||||
accessToken, err = g.Redis().Get(ctx, "ys7:accessToken")
|
||||
if err != nil {
|
||||
return accessToken.String()
|
||||
}
|
||||
}
|
||||
|
||||
return accessToken.String()
|
||||
}
|
||||
|
||||
// 传入 deviceSerial 获取设备信息
|
||||
func (ys *Ys72) GetDevice(deviceSerial string) (Ys7Device, error) {
|
||||
if device, ok := ys.Devices[deviceSerial]; ok {
|
||||
return device, nil
|
||||
}
|
||||
|
||||
return Ys7Device{}, fmt.Errorf("设备不存在: %s", deviceSerial)
|
||||
}
|
||||
|
||||
// 获取单页设备列表并存入 Devices
|
||||
func (ys *Ys72) getDeviceList(page int, deviceMapping map[string]Ys7Device) error {
|
||||
accessToken := ys.GetAccessToken()
|
||||
|
||||
req := struct {
|
||||
AccessToken string `json:"accessToken"`
|
||||
PageStart int `json:"pageStart"`
|
||||
PageSize int `json:"pageSize"`
|
||||
}{AccessToken: accessToken, PageSize: 50, PageStart: page}
|
||||
|
||||
resp, err := Post("https://open.ys7.com/api/lapp/device/list", req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
body := string(resp)
|
||||
|
||||
// 解析返回数据
|
||||
if gjson.Get(body, "code").Int() != 200 {
|
||||
return fmt.Errorf("获取设备列表失败: %s", gjson.Get(body, "msg").String())
|
||||
}
|
||||
|
||||
// 解析设备列表
|
||||
gjson.Get(body, "data").ForEach(func(_, value gjson.Result) bool {
|
||||
deviceSerial := value.Get("deviceSerial").String() // 设备序列号
|
||||
deviceName := value.Get("deviceName").String() // 设备名称
|
||||
deviceType := value.Get("deviceType").String() // 设备类型
|
||||
deviceStatus := int(value.Get("status").Int()) // 设备状态 1:在线 2:离线
|
||||
defence := int(value.Get("defence").Int()) // 是否布撤防 0:未布防 1:布防 不用管
|
||||
deviceVersion := value.Get("deviceVersion").String() // 设备版本
|
||||
|
||||
deviceMapping[deviceSerial] = Ys7Device{
|
||||
DeviceSerial: deviceSerial,
|
||||
DeviceName: deviceName,
|
||||
DeviceType: deviceType,
|
||||
Status: deviceStatus,
|
||||
Defence: defence,
|
||||
DeviceVersion: deviceVersion,
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
ys.Total = int(gjson.Get(body, "page.total").Int())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 依次调用 getDeviceList 获取所有设备列表
|
||||
func (ys *Ys72) GetAllDeviceList() error {
|
||||
// 创建一个设备map
|
||||
deviceMapping := make(map[string]Ys7Device)
|
||||
|
||||
// 遍历页码获取所有设备列表
|
||||
for page := 0; page <= ys.Total; page++ {
|
||||
if err := ys.getDeviceList(page, deviceMapping); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
newDevices := []do.Ys7Devices{} // 新设备列表
|
||||
updateDevices := []do.Ys7Devices{} // 更新设备列表
|
||||
|
||||
// 遍历 deviceMapping 对比 ys.Devices 筛选出增量或更新设备列表
|
||||
for deviceSerial, device := range deviceMapping {
|
||||
// 如果设备不存在则为新增设备
|
||||
if _, ok := ys.Devices[deviceSerial]; !ok {
|
||||
newDevices = append(newDevices, do.Ys7Devices{
|
||||
DeviceSerial: device.DeviceSerial,
|
||||
DeviceName: device.DeviceName,
|
||||
DeviceType: device.DeviceType,
|
||||
Status: device.Status,
|
||||
Defence: device.Defence,
|
||||
DeviceVersion: device.DeviceVersion,
|
||||
})
|
||||
} else {
|
||||
// 如果设备存在则对比设备状态
|
||||
if ok, newDevice := ys.CompareDevice(ys.Devices[deviceSerial], device); !ok {
|
||||
// 如果设备状态不同则更新设备
|
||||
updateDevices = append(updateDevices, do.Ys7Devices{
|
||||
DeviceSerial: newDevice.DeviceSerial,
|
||||
DeviceName: newDevice.DeviceName,
|
||||
DeviceType: newDevice.DeviceType,
|
||||
Status: newDevice.Status,
|
||||
Defence: newDevice.Defence,
|
||||
DeviceVersion: newDevice.DeviceVersion,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 新旧状态替换
|
||||
ys.Devices = deviceMapping
|
||||
|
||||
// 新设备列表入库
|
||||
if len(newDevices) > 0 {
|
||||
_, err := dao.Ys7Devices.Ctx(context.Background()).Data(newDevices).Batch(20).Insert()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 更新设备列表
|
||||
if len(updateDevices) > 0 {
|
||||
for _, device := range updateDevices {
|
||||
_, err := dao.Ys7Devices.Ctx(context.Background()).Data(device).
|
||||
Where(dao.Ys7Devices.Columns().DeviceSerial, device.DeviceSerial).Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// _, err := dao.Ys7Devices.Ctx(context.Background()).Data(updateDevices).Batch(20).Update()
|
||||
// if err != nil {
|
||||
// log.Println("更新错误:", err)
|
||||
// return err
|
||||
// }
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 登录并将 AccessToken 存入 Redis 由 Redis 管理其有效期
|
||||
// 当获取失败则重新登录后刷新周期
|
||||
func (ys *Ys72) login() error {
|
||||
accessToken, err := ys.FnLogin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
g.Redis().Set(ctx, "ys7:accessToken", accessToken)
|
||||
// 设置 key 将在 5 天后过期
|
||||
g.Redis().Expire(ctx, "ys7:accessToken", 5*24*60*60)
|
||||
return nil
|
||||
}
|
||||
|
||||
// CompareDevice 对比传递的两个设备结构体是否相同
|
||||
// 如果不同则返回 false 并构造出新的设备结构体
|
||||
func (ys *Ys72) CompareDevice(old, new Ys7Device) (bool, Ys7Device) {
|
||||
// 对比old 和 new 结构体的所有字段,是否相同
|
||||
if old == new {
|
||||
return true, Ys7Device{}
|
||||
}
|
||||
|
||||
// 构造出新的ys7Device
|
||||
return false, Ys7Device{
|
||||
DeviceSerial: new.DeviceSerial,
|
||||
DeviceName: new.DeviceName,
|
||||
DeviceType: new.DeviceType,
|
||||
Status: new.Status,
|
||||
Defence: new.Defence,
|
||||
DeviceVersion: new.DeviceVersion,
|
||||
}
|
||||
}
|
||||
|
||||
type defalutFn func() (string, error)
|
||||
|
||||
var DefaultLogin = defalutFn(func() (string, error) {
|
||||
appKey := "3acf9f1a43dc4209841e0893003db0a2"
|
||||
appSecret := "4bbf3e9394f55d3af6e3af27b2d3db36"
|
||||
|
||||
req := struct {
|
||||
AppKey string `json:"appKey"`
|
||||
AppSecret string `json:"appSecret"`
|
||||
}{AppKey: appKey, AppSecret: appSecret}
|
||||
|
||||
// 登录
|
||||
resp, err := Post("https://open.ys7.com/api/lapp/token/get", req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
body := string(resp)
|
||||
|
||||
// 解析返回数据
|
||||
if gjson.Get(body, "code").Int() != 200 {
|
||||
return "", fmt.Errorf("登录失败: %s", gjson.Get(body, "msg").String())
|
||||
}
|
||||
|
||||
// 返回 AccessToken
|
||||
return gjson.Get(body, "data.accessToken").String(), nil
|
||||
})
|
||||
|
||||
func StartAI(device Ys7Device) {
|
||||
capture, err := device.Capture()
|
||||
if err != nil {
|
||||
fmt.Println("定时快照错误!", err)
|
||||
} else {
|
||||
get, err := g.Client().Get(gctx.New(), capture.Data.PicUrl)
|
||||
if err != nil {
|
||||
} else {
|
||||
os.WriteFile("", get.ReadAll(), 0o666)
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user