Files
monibuca/plugin/gb28181/pkg/message.go

216 lines
5.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package gb28181
import (
"bytes"
"encoding/xml"
"fmt"
"io"
"strconv"
"strings"
"time"
"golang.org/x/net/html/charset"
"golang.org/x/text/encoding/simplifiedchinese"
"golang.org/x/text/transform"
)
const (
// CatalogXML 获取设备列表xml样式
CatalogXML = `<?xml version="1.0" encoding="%s"?>
<Query>
<CmdType>Catalog</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
</Query>
`
// RecordInfoXML 获取录像文件列表xml样式
RecordInfoXML = `<?xml version="1.0"?>
<Query>
<CmdType>RecordInfo</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
<StartTime>%s</StartTime>
<EndTime>%s</EndTime>
<Secrecy>0</Secrecy>
<Type>all</Type>
</Query>
`
// DeviceInfoXML 查询设备详情xml样式
DeviceInfoXML = `<?xml version="1.0" encoding="%s"?>
<Query>
<CmdType>DeviceInfo</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
</Query>
`
// DeviceStatusXML 查询设备详情xml样式
DeviceStatusXML = `<?xml version="1.0" encoding="%s"?>
<Query>
<CmdType>DeviceStatus</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
</Query>
`
// DevicePositionXML 订阅设备位置
DevicePositionXML = `<?xml version="1.0"?>
<Query>
<CmdType>MobilePosition</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
<Interval>%d</Interval>
</Query>
`
// PresetQueryXML 查询预置位指令
PresetQueryXML = `<?xml version="1.0"?>
<Query>
<CmdType>PresetQuery</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
</Query>
`
AlarmResponseXML = `<?xml version="1.0"?><Response>
<CmdType>Alarm</CmdType>
<SN>17430</SN>
<DeviceID>%s</DeviceID>
</Response>
`
KeepAliveXML = `<?xml version="1.0"?>
<Notify>
<CmdType>Keepalive</CmdType>
<SN>%d</SN>
<DeviceID>%s</DeviceID>
<Status>OK</Status>
</Notify>
`
)
func intTotime(t int64) time.Time {
tstr := strconv.FormatInt(t, 10)
if len(tstr) == 10 {
return time.Unix(t, 0)
}
if len(tstr) == 13 {
return time.UnixMilli(t)
}
return time.Now()
}
func toGB2312(s string) []byte {
reader := transform.NewReader(strings.NewReader(s), simplifiedchinese.GBK.NewEncoder())
d, _ := io.ReadAll(reader)
return d
}
// BuildDeviceInfoXML 获取设备详情指令
func BuildDeviceInfoXML(sn int, id string, charset string) []byte {
return toGB2312(fmt.Sprintf(DeviceInfoXML, charset, sn, id))
}
// BuildDeviceStatusXML 获取设备详情指令
func BuildDeviceStatusXML(sn int, id string, charset string) []byte {
return toGB2312(fmt.Sprintf(DeviceStatusXML, charset, sn, id))
}
// BuildCatalogXML 获取NVR下设备列表指令
func BuildCatalogXML(charset string, sn int, id string) []byte {
return toGB2312(fmt.Sprintf(CatalogXML, charset, sn, id))
}
// BuildRecordInfoXML 获取录像文件列表指令
func BuildRecordInfoXML(sn int, id string, start, end int64) []byte {
return toGB2312(fmt.Sprintf(RecordInfoXML, sn, id, intTotime(start).Format("2006-01-02T15:04:05"), intTotime(end).Format("2006-01-02T15:04:05")))
}
// BuildDevicePositionXML 订阅设备位置
func BuildDevicePositionXML(sn int, id string, interval int) []byte {
return toGB2312(fmt.Sprintf(DevicePositionXML, sn, id, interval))
}
// BuildPresetQueryXML 构建预置位查询XML
func BuildPresetQueryXML(sn int, id string) []byte {
return toGB2312(fmt.Sprintf(PresetQueryXML, sn, id))
}
func BuildAlarmResponseXML(id string) []byte {
return toGB2312(fmt.Sprintf(AlarmResponseXML, id))
}
func BuildKeepAliveXML(sn int, id string) []byte {
return toGB2312(fmt.Sprintf(KeepAliveXML, sn, id))
}
type (
Message struct {
XMLName xml.Name
CmdType string
SN int // 请求序列号,一般用于对应 request 和 response
DeviceID string
Longitude string // 经度
Latitude string // 纬度
DeviceName string
Manufacturer string
Model string
Channel string
Firmware string
DeviceChannelList []DeviceChannel `xml:"DeviceList>Item"`
RecordList struct {
Num int `xml:"Num,attr"`
Item []RecordItem `xml:"Item"`
} `xml:"RecordList"`
PresetList struct {
Num int `xml:"Num,attr"`
Item []PresetItem `xml:"Item"`
} `xml:"PresetList"`
SumNum int // 录像结果的总数 SumNum录像结果会按照多条消息返回可用于判断是否全部返回
Name string // 设备/通道名称
LastTime time.Time `xml:"LastTime"` // 最后时间
// 报警相关字段
AlarmPriority string `xml:"AlarmPriority"` // 报警级别
AlarmMethod string `xml:"AlarmMethod"` // 报警方式
AlarmTime string `xml:"AlarmTime"` // 报警时间
Info struct {
AlarmType string `xml:"AlarmType"` // 报警类型
} `xml:"Info"`
}
PresetItem struct {
PresetID string `xml:"PresetID"`
PresetName string `xml:"PresetName"`
}
MobilePositionNotify struct {
XMLName xml.Name `xml:"Notify"`
CmdType string `xml:"CmdType"`
SN int `xml:"SN"`
DeviceID string `xml:"DeviceID"`
Time string `xml:"Time"`
Longitude float64 `xml:"Longitude"`
Latitude float64 `xml:"Latitude"`
}
AlarmNotify struct {
XMLName xml.Name `xml:"Notify"`
CmdType string `xml:"CmdType"`
SN int `xml:"SN"`
DeviceID string `xml:"DeviceID"`
AlarmPriority string `xml:"AlarmPriority"`
AlarmTime string `xml:"AlarmTime"`
AlarmMethod string `xml:"AlarmMethod"`
Info struct {
AlarmType string `xml:"AlarmType"`
} `xml:"Info"`
}
)
func DecodeXML(v any, body []byte) error {
decoder := xml.NewDecoder(bytes.NewReader(body))
decoder.CharsetReader = charset.NewReaderLabel
err := decoder.Decode(v)
if err != nil {
decoder = xml.NewDecoder(transform.NewReader(bytes.NewReader(body), simplifiedchinese.GBK.NewDecoder()))
decoder.CharsetReader = charset.NewReaderLabel
return decoder.Decode(v)
}
return nil
}