Working video receiver
This commit is contained in:
parent
9d2db3672c
commit
51308a2395
@ -35,12 +35,64 @@ type CertificateConnectRequest struct {
|
|||||||
EvidenceSupport string `json:"EV"`
|
EvidenceSupport string `json:"EV"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CertificateConnectClientRequest struct {
|
||||||
|
UK string `json:"UK"`
|
||||||
|
}
|
||||||
|
|
||||||
type CertificateConnectResponse struct {
|
type CertificateConnectResponse struct {
|
||||||
ErrorCode uint `json:"ERRORCODE"`
|
ErrorCode uint `json:"ERRORCODE"`
|
||||||
ErrorCause string `json:"ERRORCAUSE"`
|
ErrorCause string `json:"ERRORCAUSE"`
|
||||||
CommandMask uint `json:"MASKCMD"`
|
CommandMask uint `json:"MASKCMD"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CertificateConnectClientResponse struct {
|
||||||
|
S0 string `json:"S0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateVerificationRequest struct {
|
||||||
|
S0 string `json:"S0"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateVerificationResponse struct {
|
||||||
|
ErrorCode uint `json:"ERRORCODE"`
|
||||||
|
ErrorCause string `json:"ERRORCAUSE"`
|
||||||
|
ReturnFlag bool `json:"RETURN"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateLoginRequest struct {
|
||||||
|
ClientID uint `json:"CID,omitempty"`
|
||||||
|
MAC string `json:"MAC,omitempty"`
|
||||||
|
User string `json:"USER"`
|
||||||
|
Password string `json:"PASSWD"`
|
||||||
|
PlayDevID uint `json:"PLAYDEVID"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateLoginResponse struct {
|
||||||
|
SerialNumber string `json:"DSNO"`
|
||||||
|
DeviceName string `json:"DEVNAME"`
|
||||||
|
ChannelsNumber uint `json:"CHANNEL"`
|
||||||
|
UID string `json:"UID"`
|
||||||
|
AlarmInputNumber uint `json:"ALARMIN"`
|
||||||
|
AlarmOutputNumber uint `json:"ALARMOUT"`
|
||||||
|
DeviceType string `json:"TYPE"`
|
||||||
|
DeviceClass DeviceType `json:"DEVCLASS"`
|
||||||
|
CurrentVersion string `json:"PRO"`
|
||||||
|
LicensePlate string `json:"CARNUM"`
|
||||||
|
UserLever UserAccessLevel `json:"LEVEL"`
|
||||||
|
CompanyName string `json:"CPN"`
|
||||||
|
CustomerName string `json:"CNAME"`
|
||||||
|
AudioChannelsNumber uint `json:"ACHN"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateCreateStreamRequest struct {
|
||||||
|
StreamName string `json:"STREAMNAME"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CertificateCreateStreamResponse struct {
|
||||||
|
ErrorCode uint `json:"ERRORCODE"`
|
||||||
|
ErrorCause string `json:"ERRORCAUSE"`
|
||||||
|
}
|
||||||
|
|
||||||
type CommandMaskParameters uint
|
type CommandMaskParameters uint
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -54,6 +106,24 @@ const (
|
|||||||
CommandMaskAll = 0b1111111
|
CommandMaskAll = 0b1111111
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type DeviceType uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
DeviceTypeDVR DeviceType = 1 + iota
|
||||||
|
DeviceTypeIPC
|
||||||
|
DeviceTypeNVR
|
||||||
|
DeviceTypeMIPC
|
||||||
|
DeviceTypeMDVR
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserAccessLevel uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
UserAccessLevelSuperAdmin UserAccessLevel = iota
|
||||||
|
UserAccessLevelAdministrator
|
||||||
|
UserAccessLeverUser
|
||||||
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
func (e *Package) RequestConnect(session string, serial string, numOfCams int) {
|
func (e *Package) RequestConnect(session string, serial string, numOfCams int) {
|
||||||
e.Payload = map[string]any{
|
e.Payload = map[string]any{
|
||||||
|
279
cmd/dev-client/main.go
Normal file
279
cmd/dev-client/main.go
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"gitea.unprism.ru/KRBL/n9m/v2"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
var mainPack *n9m.SmartPackage
|
||||||
|
var videoPack *n9m.SmartPackage
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
conn, err := net.Dial("tcp", "10.100.100.99:9006")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var pack = n9m.Package{}
|
||||||
|
|
||||||
|
pack.Payload.Module = "CERTIFICATE"
|
||||||
|
pack.Payload.Operation = "CONNECT"
|
||||||
|
pack.SetParameters(n9m.CertificateConnectClientRequest{})
|
||||||
|
conn.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
handle(conn, &mainPack)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSpecialPackages(_ *n9m.SmartPackage, pack n9m.Package) error {
|
||||||
|
switch pack.SSRC {
|
||||||
|
case n9m.SpecialPayloadTypeGPS:
|
||||||
|
fmt.Printf("%+v\n", pack.GPS)
|
||||||
|
return nil
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unhandled special operation: %d", pack.SSRC)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCertificateConnect(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.CertificateConnectClientResponse
|
||||||
|
|
||||||
|
if err = pack.GetResponseAs(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("failed to get response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = n9m.CertificateVerificationRequest{
|
||||||
|
S0: GenerateVerifyKey(params.S0),
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.Payload.Operation = "VERIFY"
|
||||||
|
pack.SetParameters(response)
|
||||||
|
|
||||||
|
sPack.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleVerify(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.CertificateVerificationResponse
|
||||||
|
|
||||||
|
if err = pack.GetResponseAs(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("failed to get response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.ErrorCode == 0 {
|
||||||
|
fmt.Println("ШАЛОСТЬ УДАЛАСЬ!")
|
||||||
|
} else {
|
||||||
|
fmt.Println("шалость НЕ удалась(((")
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = n9m.CertificateLoginRequest{
|
||||||
|
ClientID: 0,
|
||||||
|
MAC: "",
|
||||||
|
User: "admin",
|
||||||
|
Password: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.Payload.Operation = "LOGIN"
|
||||||
|
pack.SetParameters(request)
|
||||||
|
|
||||||
|
sPack.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleLogin(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.CertificateLoginResponse
|
||||||
|
|
||||||
|
if err = pack.GetResponseAs(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("failed to get response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.Dial("tcp", "10.100.100.99:9006")
|
||||||
|
|
||||||
|
var request = n9m.CertificateCreateStreamRequest{
|
||||||
|
StreamName: "KRBL",
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.Payload.Operation = "CREATESTREAM"
|
||||||
|
pack.SetParameters(request)
|
||||||
|
|
||||||
|
conn.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
go handle(conn, &videoPack)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCreateStream(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.CertificateCreateStreamResponse
|
||||||
|
|
||||||
|
if err = pack.GetResponseAs(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("failed to get response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.ErrorCode != 0 {
|
||||||
|
fmt.Println("Create stream error:", params.ErrorCode, params.ErrorCause)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = n9m.MediaStreamModelRequestLiveVideoRequest{
|
||||||
|
StreamName: "KRBL",
|
||||||
|
StreamType: 2,
|
||||||
|
Channel: 1,
|
||||||
|
AudioValid: 1,
|
||||||
|
FrameMode: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
pack.Payload.Module = "MEDIASTREAMMODEL"
|
||||||
|
pack.Payload.Operation = "REQUESTALIVEVIDEO"
|
||||||
|
pack.SetParameters(request)
|
||||||
|
|
||||||
|
mainPack.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleRequestLiveVideo(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.MediaStreamModelRequestLiveVideoResponse
|
||||||
|
|
||||||
|
if err = pack.GetResponseAs(¶ms); err != nil {
|
||||||
|
return fmt.Errorf("failed to get response: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if params.ErrorCode != 0 {
|
||||||
|
fmt.Println("Request live stream error:", params.ErrorCode, params.ErrorCause)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleKeepAlive(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
serial := sPack.Storage["serial"]
|
||||||
|
fmt.Println(serial, "still alive!")
|
||||||
|
|
||||||
|
pack.SetResponse(nil)
|
||||||
|
sPack.Write(pack.PackPackage())
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleGetConfig(sPack *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
serial := sPack.Storage["serial"]
|
||||||
|
|
||||||
|
os.WriteFile(fmt.Sprintf("./%s.json", serial), pack.RawPayload, 0644)
|
||||||
|
|
||||||
|
var request n9m.ConfigModelSetRequest
|
||||||
|
|
||||||
|
if err = pack.GetParametersAs(&request); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleUselessAlarms(sPack *n9m.SmartPackage, pack n9m.Package, response n9m.SendAlarmInfoResponse) (err error) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleVideoLossAlarm(sPack *n9m.SmartPackage, pack n9m.Package, response n9m.SendAlarmInfoResponse) (err error) {
|
||||||
|
fmt.Println("Video loss alarm!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleCameraCoveredAlarm(sPack *n9m.SmartPackage, pack n9m.Package, response n9m.SendAlarmInfoResponse) (err error) {
|
||||||
|
fmt.Println("Camera covered alarm!")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSPI(_ *n9m.SmartPackage, pack n9m.Package) (err error) {
|
||||||
|
var params n9m.SpiParameters
|
||||||
|
|
||||||
|
if err = pack.GetParametersAs(¶ms); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%+v\n", params)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSmartPackage(conn net.Conn) (pack *n9m.SmartPackage) {
|
||||||
|
pack = n9m.NewSmartPackage(conn)
|
||||||
|
|
||||||
|
pack.AddPayloadHandler(n9m.PayloadTypeSpecial, handleSpecialPackages)
|
||||||
|
|
||||||
|
pack.AddJSONHandler("CERTIFICATE", "CONNECT", handleCertificateConnect)
|
||||||
|
pack.AddJSONHandler("CERTIFICATE", "VERIFY", handleVerify)
|
||||||
|
pack.AddJSONHandler("CERTIFICATE", "LOGIN", handleLogin)
|
||||||
|
pack.AddJSONHandler("CERTIFICATE", "CREATESTREAM", handleCreateStream)
|
||||||
|
pack.AddJSONHandler("CERTIFICATE", "KEEPALIVE", handleKeepAlive)
|
||||||
|
pack.AddJSONHandler("MEDIASTREAMMODEL", "REQUESTALIVEVIDEO", handleRequestLiveVideo)
|
||||||
|
pack.AddJSONHandler("CONFIGMODEL", "GET", handleGetConfig)
|
||||||
|
pack.AddJSONHandler("DEVEMM", "SPI", handleSPI)
|
||||||
|
|
||||||
|
pack.AddAlarmHandler(n9m.AlarmTypeMotionDetection, handleUselessAlarms)
|
||||||
|
|
||||||
|
pack.AddAlarmHandler(n9m.AlarmTypeVideoLoss, handleVideoLossAlarm)
|
||||||
|
pack.AddAlarmHandler(n9m.AlarmTypeCameraCovered, handleCameraCoveredAlarm)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
go func() {
|
||||||
|
pack := packS
|
||||||
|
pack.Payload.Module = "EVEM"
|
||||||
|
pack.Payload.Operation = "GALARMING"
|
||||||
|
|
||||||
|
ticker := time.NewTicker(5 * time.Second)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
for range ticker.C {
|
||||||
|
fmt.Println("Sent!")
|
||||||
|
if _, err := conn.Write(pack.PackPackage()); err != nil {
|
||||||
|
fmt.Println("Failed to send GALARMING:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
*/
|
||||||
|
|
||||||
|
func isNetConnClosedErr(err error) bool {
|
||||||
|
switch {
|
||||||
|
case
|
||||||
|
errors.Is(err, net.ErrClosed),
|
||||||
|
errors.Is(err, io.EOF),
|
||||||
|
errors.Is(err, syscall.EPIPE):
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handle(conn net.Conn, pack **n9m.SmartPackage) {
|
||||||
|
if pack != nil {
|
||||||
|
*pack = createSmartPackage(conn)
|
||||||
|
} else {
|
||||||
|
tmp := createSmartPackage(conn)
|
||||||
|
pack = &tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for {
|
||||||
|
if err = (*pack).Handle(); err != nil {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
|
||||||
|
if isNetConnClosedErr(err) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
cmd/dev-client/utils.go
Normal file
15
cmd/dev-client/utils.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/hmac"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GenerateVerifyKey(key string) string {
|
||||||
|
mac := hmac.New(md5.New, []byte(key))
|
||||||
|
|
||||||
|
mac.Write([]byte(key))
|
||||||
|
|
||||||
|
return hex.EncodeToString(mac.Sum(nil))
|
||||||
|
}
|
9
cmd/dev-client/utils_test.go
Normal file
9
cmd/dev-client/utils_test.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestGenerateVerifyKey(t *testing.T) {
|
||||||
|
if GenerateVerifyKey("45792d55-0844-4053-848a-64fd0685fb32") != "fae5f19b8452c7bd03dc4f3471966c42" {
|
||||||
|
t.Error()
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,32 @@
|
|||||||
package n9m
|
package n9m
|
||||||
|
|
||||||
|
type StreamType uint
|
||||||
|
|
||||||
|
const (
|
||||||
|
StreamTypeSub StreamType = iota
|
||||||
|
StreamTypeMain
|
||||||
|
StreamTypeMobile
|
||||||
|
)
|
||||||
|
|
||||||
|
type MediaStreamModelRequestLiveVideoRequest struct {
|
||||||
|
SSRC uint `json:"SSRC,omitempty"`
|
||||||
|
StreamName string `json:"STREAMNAME"`
|
||||||
|
StreamType StreamType `json:"STREAMTYPE"`
|
||||||
|
Channel uint `json:"CHANNEL"`
|
||||||
|
AudioValid uint `json:"AUDIOVALID"`
|
||||||
|
Destination string `json:"IPANDPORT,omitempty"`
|
||||||
|
FrameCount uint `json:"FRAMECOUNT,omitempty"`
|
||||||
|
FrameMode uint `json:"FRAMEMODE"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MediaStreamModelRequestLiveVideoResponse struct {
|
||||||
|
SSRC uint `json:"SSRC"`
|
||||||
|
StreamName string `json:"STREAMNAME"`
|
||||||
|
StreamType StreamType `json:"STREAMTYPE"`
|
||||||
|
ErrorCode uint `json:"ERRORCODE"`
|
||||||
|
ErrorCause string `json:"ERRORCAUSE"`
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
var ip string = os.Getenv("SERVER_IP")
|
var ip string = os.Getenv("SERVER_IP")
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user