Working video receiver
This commit is contained in:
parent
9d2db3672c
commit
51308a2395
@ -35,12 +35,64 @@ type CertificateConnectRequest struct {
|
||||
EvidenceSupport string `json:"EV"`
|
||||
}
|
||||
|
||||
type CertificateConnectClientRequest struct {
|
||||
UK string `json:"UK"`
|
||||
}
|
||||
|
||||
type CertificateConnectResponse struct {
|
||||
ErrorCode uint `json:"ERRORCODE"`
|
||||
ErrorCause string `json:"ERRORCAUSE"`
|
||||
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
|
||||
|
||||
const (
|
||||
@ -54,6 +106,24 @@ const (
|
||||
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) {
|
||||
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
|
||||
|
||||
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")
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user