Compare commits

..

No commits in common. "v2.1.6-alpha" and "main" have entirely different histories.

30 changed files with 515 additions and 1988 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
.idea

1
README.md Normal file
View File

@ -0,0 +1 @@
# N9M

41
certificate.go Normal file
View File

@ -0,0 +1,41 @@
package n9m
func (e *Package) RequestConnect(session string, serial string, numOfCams int) {
e.Payload = map[string]any{
"MODULE": "CERTIFICATE",
"OPERATION": "CONNECT",
"PARAMETER": map[string]any{
"DSNO": serial,
"CHANNEL": numOfCams,
},
"SESSION": session,
}
}
// video server util
func (e *Package) ResponseConnect(Sid string, streamName string) {
e.Payload = map[string]any{
"MODULE": "CERTIFICATE",
"OPERATION": "CREATESTREAM",
"RESPONSE": map[string]any{
"ERRORCODE": 0,
"STREAMNAME": streamName,
},
"SESSION": Sid,
}
}
// main server util
func (e *Package) ResponseCertificateConnect(Sid string) {
e.Payload = map[string]any{
"MODULE": "CERTIFICATE",
"OPERATION": "CONNECT",
"RESPONSE": map[string]any{
"ERRORCAUSE": "",
"ERRORCODE": 0,
"MASKCMD": 5,
"PRO": "1.0.5",
},
"SESSION": Sid,
}
}

View File

@ -1,256 +0,0 @@
package main
import (
"errors"
"fmt"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/smart"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/utils"
"io"
"net"
"os"
"syscall"
)
var videoPack *smart.SmartChannelPackage
func main() {
conn, err := net.Dial("tcp", "10.100.100.99:9006")
if err != nil {
panic(err)
}
var pack = protocol.Package{}
pack.Payload.Module = "CERTIFICATE"
pack.Payload.Operation = "CONNECT"
pack.SetParameters(models.CertificateConnectClientRequest{})
conn.Write(pack.PackPackage())
handle(conn)
}
func handleSpecialPackages(_ *smart.SmartPackage, pack protocol.Package) error {
switch pack.SSRC {
case protocol.SpecialPayloadTypeGPS:
fmt.Printf("%+v\n", pack.GPS)
return nil
default:
return fmt.Errorf("unhandled special operation: %d", pack.SSRC)
}
}
func handleLivePackages(_ *smart.SmartPackage, pack protocol.Package) error {
fmt.Printf("%+v\n", pack)
return nil
}
func handleCertificateConnect(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.CertificateConnectClientResponse
if err = pack.GetResponseAs(&params); err != nil {
return fmt.Errorf("failed to get response: %w", err)
}
var response = models.CertificateVerificationRequest{
S0: utils.GenerateVerifyKey(params.S0),
}
pack.Payload.Operation = "VERIFY"
pack.SetParameters(response)
sPack.Write(pack.PackPackage())
return
}
func handleVerify(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.CertificateVerificationResponse
if err = pack.GetResponseAs(&params); err != nil {
return fmt.Errorf("failed to get response: %w", err)
}
if params.ErrorCode == 0 {
fmt.Println("ШАЛОСТЬ УДАЛАСЬ!")
} else {
fmt.Println("шалость НЕ удалась(((")
}
var request = models.CertificateLoginRequest{
ClientID: 0,
MAC: "",
User: "admin",
Password: "",
}
pack.Payload.Operation = "LOGIN"
pack.SetParameters(request)
sPack.Write(pack.PackPackage())
return
}
func handleLogin(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.CertificateLoginResponse
if err = pack.GetResponseAs(&params); err != nil {
return fmt.Errorf("failed to get response: %w", err)
}
conn, err := net.Dial("tcp", "10.100.100.99:9006")
if err != nil {
panic(err)
}
videoPack, err = smart.NewSmartChannelPackage(conn, sPack)
if err != nil {
panic(err)
}
go videoPack.Run()
videoPack.AddLiveSource(2, func(data []byte) error {
fmt.Println("Есть контакт!")
return nil
})
var request = models.MediaStreamModelRequestLiveVideoRequest{
StreamName: videoPack.GetChannelName(),
StreamType: models.StreamTypeMain,
Channel: 4,
AudioValid: 4,
FrameMode: 0,
}
pack.Payload.Module = "MEDIASTREAMMODEL"
pack.Payload.Operation = "REQUESTALIVEVIDEO"
pack.SetParameters(request)
sPack.Write(pack.PackPackage())
return
}
func handleRequestLiveVideo(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.MediaStreamModelRequestLiveVideoResponse
if err = pack.GetResponseAs(&params); 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
}
fmt.Printf("%+v\n", params)
return
}
func handleKeepAlive(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
serial := sPack.Storage["serial"]
fmt.Println(serial, "still alive!")
pack.SetResponse(nil)
sPack.Write(pack.PackPackage())
return
}
func handleGetConfig(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
serial := sPack.Storage["serial"]
os.WriteFile(fmt.Sprintf("./%s.json", serial), pack.RawPayload, 0644)
var request models.ConfigModelSetRequest
if err = pack.GetParametersAs(&request); err != nil {
fmt.Println(err)
return err
}
return
}
func handleUselessAlarms(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
return nil
}
func handleVideoLossAlarm(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
fmt.Println("Video loss alarm!")
return nil
}
func handleCameraCoveredAlarm(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
fmt.Println("Camera covered alarm!")
return nil
}
func handleSPI(_ *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.SpiParameters
if err = pack.GetParametersAs(&params); err != nil {
return
}
fmt.Printf("%+v\n", params)
return
}
func createSmartPackage(conn net.Conn) (pack *smart.SmartPackage) {
pack = smart.NewSmartPackage(conn)
pack.AddPayloadHandler(protocol.PayloadTypeLive, handleLivePackages)
pack.AddPayloadHandler(protocol.PayloadTypeSpecial, handleSpecialPackages)
pack.AddJSONHandler("CERTIFICATE", "CONNECT", handleCertificateConnect)
pack.AddJSONHandler("CERTIFICATE", "VERIFY", handleVerify)
pack.AddJSONHandler("CERTIFICATE", "LOGIN", handleLogin)
pack.AddJSONHandler("CERTIFICATE", "KEEPALIVE", handleKeepAlive)
pack.AddJSONHandler("MEDIASTREAMMODEL", "REQUESTALIVEVIDEO", handleRequestLiveVideo)
pack.AddJSONHandler("CONFIGMODEL", "GET", handleGetConfig)
pack.AddJSONHandler("DEVEMM", "SPI", handleSPI)
pack.AddAlarmHandler(protocol.AlarmTypeMotionDetection, handleUselessAlarms)
pack.AddAlarmHandler(protocol.AlarmTypeVideoLoss, handleVideoLossAlarm)
pack.AddAlarmHandler(protocol.AlarmTypeCameraCovered, handleCameraCoveredAlarm)
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 := createSmartPackage(conn)
var err error
for {
if err = pack.Handle(); err != nil {
fmt.Println("Error:", err)
if isNetConnClosedErr(err) {
return
}
}
}
}

View File

@ -1,191 +0,0 @@
package main
import (
"errors"
"fmt"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/smart"
"io"
"net"
"os"
"syscall"
)
func main() {
ln, err := net.Listen("tcp", "0.0.0.0:5556")
if err != nil {
panic(err)
}
for {
var conn net.Conn
conn, err = ln.Accept()
if err != nil {
continue
}
go handle(conn)
}
}
func handleSpecialPackages(_ *smart.SmartPackage, pack protocol.Package) error {
switch pack.SSRC {
case protocol.SpecialPayloadTypeGPS:
fmt.Printf("%+v\n", pack.GPS)
return nil
default:
return fmt.Errorf("unhandled special operation: %d", pack.SSRC)
}
}
func handleCertificateConnect(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.CertificateConnectRequest
if err = pack.GetParametersAs(&params); err != nil {
return fmt.Errorf("failed to get parameters: %w", err)
}
var response = models.CertificateConnectResponse{
ErrorCode: 0,
CommandMask: models.CommandMaskAll,
}
pack.SetResponse(response)
if _, err = sPack.Write(pack.PackPackage()); err != nil {
return fmt.Errorf("failed to write package: %w", err)
}
fmt.Println("Connected:", params.SerialNumber)
sPack.Storage["serial"] = params.SerialNumber
var request models.ConfigModelGetRequest
request.MDVR = "?"
pack.Payload.Module = "CONFIGMODEL"
pack.Payload.Operation = "GET"
pack.SetParameters(request)
sPack.Write(pack.PackPackage())
return
}
func handleKeepAlive(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
serial := sPack.Storage["serial"]
fmt.Println(serial, "still alive!")
pack.SetResponse(nil)
sPack.Write(pack.PackPackage())
return
}
func handleGetConfig(sPack *smart.SmartPackage, pack protocol.Package) (err error) {
serial := sPack.Storage["serial"]
os.WriteFile(fmt.Sprintf("./%s.json", serial), pack.RawPayload, 0644)
var request models.ConfigModelSetRequest
if err = pack.GetParametersAs(&request); err != nil {
fmt.Println(err)
return err
}
return
}
func handleUselessAlarms(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
return nil
}
func handleVideoLossAlarm(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
fmt.Println("Video loss alarm!")
return nil
}
func handleCameraCoveredAlarm(sPack *smart.SmartPackage, pack protocol.Package, response models.SendAlarmInfoResponse) (err error) {
fmt.Println("Camera covered alarm!")
return nil
}
func handleSPI(_ *smart.SmartPackage, pack protocol.Package) (err error) {
var params models.SpiParameters
if err = pack.GetParametersAs(&params); err != nil {
return
}
fmt.Printf("%+v\n", params)
return
}
func createSmartPackage(conn net.Conn) (pack *smart.SmartPackage) {
pack = smart.NewSmartPackage(conn)
pack.AddPayloadHandler(protocol.PayloadTypeSpecial, handleSpecialPackages)
pack.AddJSONHandler("CERTIFICATE", "CONNECT", handleCertificateConnect)
pack.AddJSONHandler("CERTIFICATE", "KEEPALIVE", handleKeepAlive)
pack.AddJSONHandler("CONFIGMODEL", "GET", handleGetConfig)
pack.AddJSONHandler("DEVEMM", "SPI", handleSPI)
pack.AddAlarmHandler(protocol.AlarmTypeMotionDetection, handleUselessAlarms)
pack.AddAlarmHandler(protocol.AlarmTypeVideoLoss, handleVideoLossAlarm)
pack.AddAlarmHandler(protocol.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 := createSmartPackage(conn)
var err error
for {
if err = pack.Handle(); err != nil {
fmt.Println("Error:", err)
if isNetConnClosedErr(err) {
return
}
}
}
}

View File

@ -1,10 +1,4 @@
package models
import (
"gitea.unprism.ru/KRBL/n9m/v2/pkg/parameters"
)
/*
package n9m
// request reqistration parameters (directly to register)
func (e *Package) RequestParameters(params map[string]any, serial int, session string) {
@ -32,41 +26,37 @@ func (e *Package) SetParameters(params map[string]any, serial int, session strin
}
// log.Println(e.Payload)
} // end of 'SetParameters' function
*/
type ConfigModelSetRequest struct {
MDVR parameters.Setting `json:"MDVR"`
}
type ConfigModelGetRequest struct {
MDVR interface{} `json:"MDVR"`
}
type ConfigModelSetResponse struct {
MDVR parameters.Setting `json:"MDVR"`
}
func InitialConfig() ConfigModelSetRequest {
return ConfigModelSetRequest{
MDVR: parameters.Setting{
KEYS: parameters.KEYS{
GV: 1, // GPS version
},
PGDSM: parameters.PGDSM{
PGPS: parameters.PGPS{
EN: 1, // Real-time position monitoring
MODE: 0b10, // Enable timer
TM: 10, // Time interval
// todo al1
func (e *Package) ConfigeModel(Sid string) {
e.Payload = map[string]any{
"MODULE": "CONFIGMODEL",
"OPERATION": "SET",
"PARAMETER": map[string]any{
"MDVR": map[string]any{
"KEYS": map[string]any{ // KEY parameters
"GV": 1, // GPS version
},
"PGDSM": map[string]any{ // Network monitoring status parameters
"PGPS": map[string]any{ // GPS position
"EN": 1, // Real-time position monitoring
"TM": 10, // Time interval
},
},
"PSI": map[string]any{ // Platform basic information
"CG": map[string]any{ // Call information
"AS": 0, // Automatic answer
},
},
"SUBSTRNET": map[string]any{
"SM": 1, // 0-Smooth .. 4-Clear
},
},
SUBSTRNET: parameters.SUBSTRNET{
SM: 1,
},
},
}
}
/*
// main server util
func (e *Package) ResponseConfigModelSet(Sid string) {
e.Payload = map[string]any{
"MODULE": "CONFIGMODUL", // it's not error
@ -79,5 +69,3 @@ func (e *Package) ResponseConfigModelSet(Sid string) {
"SESSION": Sid,
}
}
*/

36
devemm.go Normal file
View File

@ -0,0 +1,36 @@
package n9m
import "fmt"
// main server util
func (e *Package) RequestGeolocation(serial int, Sid string) {
e.Payload = map[string]any{
"MODULE": "DEVEMM",
"OPERATION": "GETPOS",
"PARAMETER": map[string]any{
"SERIAL": serial,
},
"SESSION": Sid,
}
}
func (e *Package) ResponseGeolocation(errorCode int, errorCause string, serial int, longitude float32, latitude float32, altitude float32, speed int, course int, time string) {
e.Payload = map[string]any{
"MODULE": "DEVEMM",
"OPERATION": "GETPOS",
"RESPONSE": map[string]any{
"ERRORCODE": errorCode,
"ERRORCAUSE": errorCause,
"SERIAL": serial,
"P": map[string]any{
"V": errorCode == 0,
"J": fmt.Sprintf("%4.6v", longitude),
"W": fmt.Sprintf("%4.6v", latitude),
"H": fmt.Sprintf("%4.6v", altitude),
"S": speed, // unit - 0.01 km/h
"C": course, // direction (angle from north)
"T": time, // yyyymmddhhmmss
},
},
}
}

18
evem.go Normal file
View File

@ -0,0 +1,18 @@
package n9m
// main server util
func (e *Package) ResponseAlarm(alarmType int64, alarmUID int64, cmdno int64, cmdtype int64, run int64, serial string, Sid string) {
e.Payload = map[string]any{
"MODULE": "EVEM",
"OPERATION": "SENDALARMINFO",
"RESPONSE": map[string]any{
"ALARMTYPE": alarmType,
"ALARMUID": alarmUID,
"CMDNO": cmdno,
"CMDTYPE": cmdtype,
"ERRORCODE": 0,
"RUN": run,
},
"SESSION": Sid,
}
}

12
go.mod
View File

@ -1,5 +1,13 @@
module gitea.unprism.ru/KRBL/n9m/v2
module gitea.unprism.ru/KRBL/n9m
go 1.21.3
require github.com/icza/bitio v1.1.0
require (
github.com/icza/bitio v1.1.0
github.com/tidwall/gjson v1.17.0
)
require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
)

7
go.sum
View File

@ -2,3 +2,10 @@ github.com/icza/bitio v1.1.0 h1:ysX4vtldjdi3Ygai5m1cWy4oLkhWTAi+SyO6HC8L9T0=
github.com/icza/bitio v1.1.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k=
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=

175
io.go Normal file
View File

@ -0,0 +1,175 @@
package n9m
import (
"bytes"
"encoding/json"
"fmt"
"log"
"github.com/icza/bitio"
"github.com/tidwall/gjson"
)
// Extract fields from JSON
func (e *Package) SaveJsonFields() {
if value, exist := e.Payload["MODULE"]; exist {
e.Json.Module = value.(string)
} else {
e.Json.Module = ""
}
if value, exist := e.Payload["KEY"]; exist {
e.Json.Key = value.(string)
} else {
e.Json.Key = ""
}
if value, exist := e.Payload["OPERATION"]; exist {
e.Json.Operation = value.(string)
} else {
e.Json.Operation = ""
}
if value, exist := e.Payload["RESPONSE"]; exist {
e.Json.Response = value.(map[string]interface{})
} else {
e.Json.Response = make(map[string]interface{})
}
if value, exist := e.Payload["PARAMETER"]; exist {
e.Json.Parameters = value.(map[string]interface{})
} else if value, exist := e.Payload["PARAMETERS"]; exist {
e.Json.Parameters = value.(map[string]interface{})
} else {
e.Json.Parameters = make(map[string]interface{})
}
}
// Read package
func (e *Package) ReadPackage() bool {
if len(e.Accum) < 12 {
return false
}
r := bitio.NewReader(bytes.NewBuffer(e.Accum))
e.Version = r.TryReadBits(2)
e.Encription = r.TryReadBits(1)
e.Mark = r.TryReadBits(1)
e.CC = r.TryReadBits(4)
e.PayloadType = r.TryReadBits(8)
e.SSRC = r.TryReadBits(16)
// log.Println(e.PayloadType)
is_special := e.Encription == 1 && e.Mark == 1
if is_special {
r.TryReadBits(8 * 4)
e.PayloadLen = r.TryReadBits(8)
r.TryReadBits(3 * 8)
if uint64(len(e.Accum)) < e.PayloadLen+12 {
return false
}
} else {
e.PayloadLen = r.TryReadBits(32)
// WTF: e.CC is useless
for i := uint64(0); i < 1; i++ {
e.CSRC[i] = r.TryReadBits(32)
}
}
numOfBytes := 0
rawbytes := []byte{}
if e.PayloadLen != 0 {
if e.PayloadLen > 1000000 {
log.Printf("%v\n", e)
log.Panicln("CORRUPTED PACKAGE")
}
rawbytes = make([]byte, e.PayloadLen)
numOfBytes, _ = r.Read(rawbytes)
}
if numOfBytes != int(e.PayloadLen) {
return false
}
e.Raw = e.Accum[:12+e.PayloadLen]
e.Accum = e.Accum[12+e.PayloadLen:]
e.RawPayload = rawbytes
var ok bool
e.GPayload = gjson.Parse(string(rawbytes))
e.Payload, ok = e.GPayload.Value().(map[string]interface{})
if !ok {
e.Payload = gjson.Parse("{}").Value().(map[string]interface{})
}
e.SaveJsonFields()
return e.PayloadLen > 0
}
func (e *Package) PackPackage() []byte {
e.SaveJsonFields()
b := &bytes.Buffer{}
w := bitio.NewWriter(b)
w.TryWriteBits(e.Version, 2)
w.TryWriteBits(e.Encription, 1)
w.TryWriteBits(e.Mark, 1)
w.TryWriteBits(e.CC, 4)
w.TryWriteBits(e.PayloadType, 8)
w.TryWriteBits(e.SSRC, 16)
conv, err := json.Marshal(e.Payload)
if err != nil {
fmt.Println(err)
return nil
}
e.PayloadLen = uint64(len(conv))
if e.PayloadLen != 0 {
e.PayloadLen++
}
w.TryWriteBits(e.PayloadLen, 32)
// WTF: e.CC is useless
for i := uint64(0); i < 1; i++ {
w.TryWriteBits(e.CSRC[i], 32)
}
if e.PayloadLen != 0 {
w.Write(conv)
w.Write([]byte{0})
}
w.Close()
return b.Bytes()
}
func (e *Package) PackRawPackage() []byte {
b := &bytes.Buffer{}
w := bitio.NewWriter(b)
w.TryWriteBits(e.Version, 2)
w.TryWriteBits(e.Encription, 1)
w.TryWriteBits(e.Mark, 1)
w.TryWriteBits(e.CC, 4)
w.TryWriteBits(e.PayloadType, 8)
w.TryWriteBits(e.SSRC, 16)
e.PayloadLen = uint64(len(e.RawPayload) + 1)
w.TryWriteBits(e.PayloadLen, 32)
// WTF: e.CC is useless
for i := uint64(0); i < 1; i++ {
w.TryWriteBits(e.CSRC[i], 32)
}
if e.PayloadLen != 0 {
w.Write(e.RawPayload)
w.Write([]byte{0})
}
w.Close()
return b.Bytes()
}

110
mediastreammodel.go Normal file
View File

@ -0,0 +1,110 @@
package n9m
import (
"fmt"
"os"
)
var ip string = os.Getenv("SERVER_IP")
func (e *Package) MediaRequestDownloadVideo(token int, serial string, session string, camNo int, date string, begin_time string, end_time string, recordID string, serverId int) {
e.Payload = map[string]any{
"MODULE": "MEDIASTREAMMODEL",
"OPERATION": "REQUESTDOWNLOADVIDEO",
"PARAMETER": map[string]any{
"PT": 3,
"SSRC": 1,
"STREAMNAME": "DOWNLOAD" + "_" + serial + "_" + fmt.Sprint(camNo) + "_" + fmt.Sprint(serverId),
"STREAMTYPE": 1, // main stream
"RECORDID": recordID,
"CHANNEL": 1 << (camNo - 1),
"STARTTIME": date + begin_time,
"ENDTIME": date + end_time,
"OFFSETFLAG": 1,
"OFFSET": 0,
"IPANDPORT": ip + ":12092",
"SERIAL": token,
"DT": 1, // high speed download
},
"SESSION": session,
}
}
// main server util
func (e *Package) MediaRequestAliveVideo(token int, camNo int64, Sid string, serial string, quality int64) {
channel := 0
if camNo == 1 {
channel = 1
} else {
channel = 1 << (camNo - 1)
}
e.Payload = map[string]any{
"MODULE": "MEDIASTREAMMODEL",
"OPERATION": "REQUESTALIVEVIDEO",
"PARAMETER": map[string]any{
"AUDIOVALID": 1,
"CHANNEL": channel,
"FRAMEMODE": 0,
"IPANDPORT": ip + ":12092",
"STREAMNAME": "LIVE" + "_" + serial + "_" + fmt.Sprint(camNo),
"STREAMTYPE": quality,
"SERIAL": token,
},
"SESSION": Sid,
}
}
// main server util
func (e *Package) MediaRequestRemotePlayback(token int, serial string, session string, camNo int, date string, begin_time string, end_time string, serverId int) {
if end_time == "" {
e.Payload = map[string]any{
"MODULE": "MEDIASTREAMMODEL",
"OPERATION": "REQUESTREMOTEPLAYBACK",
"PARAMETER": map[string]any{
"STREAMNAME": "PLAYBACK" + "_" + fmt.Sprint(serial) + "_" + fmt.Sprint(camNo) + "_" + fmt.Sprint(serverId),
"STREAMTYPE": 1, // main stream
"VIDEOTYPE": 2, // common files
"CHANNEL": 1 << (camNo - 1),
"STARTTIME": date + begin_time,
"IPANDPORT": ip + ":12092",
"SERIAL": token,
"PBST": 0,
},
"SESSION": session,
}
} else {
e.Payload = map[string]any{
"MODULE": "MEDIASTREAMMODEL",
"OPERATION": "REQUESTREMOTEPLAYBACK",
"PARAMETER": map[string]any{
"STREAMNAME": "PLAYBACK" + "_" + fmt.Sprint(serial) + "_" + fmt.Sprint(camNo) + "_" + fmt.Sprint(serverId),
"STREAMTYPE": 1, // main stream
"VIDEOTYPE": 2, // common files
"CHANNEL": 1 << (camNo - 1),
"STARTTIME": date + begin_time,
"ENDTIME": date + end_time,
"IPANDPORT": ip + ":12092",
"SERIAL": token,
"PBST": 0,
},
"SESSION": session,
}
}
}
// main server util
func (e *Package) ControlRemotePlayback(token int, serial string, session string, camNo int, date string, begin_time string, end_time string, serverId int) {
e.Payload = map[string]any{
"MODULE": "MEDIASTREAMMODEL",
"OPERATION": "CONTROLREMOTEPLAYBACK",
"PARAMETER": map[string]any{
"STREAMNAME": fmt.Sprint(serial) + "_" + fmt.Sprint(camNo) + "_" + fmt.Sprint(serverId),
"SERIAL": token,
"PALYBACKCMD": 5, // main stream
"CHANNEL": 268435455, // common files
},
"SESSION": session,
}
}

View File

@ -1,6 +1,5 @@
package parameters
package n9m
// 7.2
type RIP struct {
DEVID string // ID номер устройства
BN string // бортовой номер
@ -152,8 +151,6 @@ type SAP struct {
UN int
}
// 7.24.3
// Alarm processing parameters
type APR struct {
AR ARR
SS SS
@ -169,6 +166,13 @@ type SS struct {
EN int
}
type UAP struct {
EN int
AS int
VT int
SDT int
}
type PVLAS struct {
EN int
AS int
@ -214,8 +218,7 @@ type DNS struct {
}
type KEYS struct {
MAC string `json:"MAC,omitempty"` // MAC-адрес
GV uint `json:"GV,omitempty"` // GPS version
MAC string // MAC-адрес
}
type WIFI struct {
@ -252,10 +255,8 @@ type MCMS struct {
SP []SP // Параметры сервера
}
// 7.12.1
// Central server configuration
type SP struct {
EN int // Флаг включения
EN int // Статус сервера
CP int // Протокол подключения
NWT int // Способ подключения
CS string // Адрес сервера
@ -266,107 +267,29 @@ type SP struct {
MUPORT int // UDP-порт медиасервера
}
// 7.28
// NVR remote device parameters
type REDEV struct {
EN int // Флаг включения
LOCK int // ???
CHL int // Номер канала на устройстве
RECHL int // ???
ONLINE int // Доступно ли сейчас устройство
RETYPE int // Тип устройства
PROTYPE int // Тип протокола
IPTYPE int // Тип IP-адреса (IPv4/IPv6)
CONTYPE int // ???
SW int // Источник поступаемого сигнала
REPORT int // Порт камеры
REIP string // IP камеры
ID string // Идентификатор камеры
RENAME string // Название устройства
USER string // Имя пользователя
PWD string // Пароль
URL string // ???
CMDPORT uint // ???
}
// 7.29
// Panel emergency alarm
type UAP struct {
EN int // Флаг включения
AS int // Уровень тревоги
T int // ???
VT int // ???
UN string // Имя тревоги
UO string // Имя тривоги на экране водителя
APR APR // Параметры обработки тревоги
// AP AP // Параметры тревоги
SDT int // ???
}
// 7.30
// Network monitoring status parameters
type PGDSM struct {
PGPS PGPS `json:"PGPS,omitempty"`
PDSM PDSM `json:"PDSM,omitempty"`
}
// 7.30.1
// GPS (position) status parameter
type PGPS struct {
EN uint // Enable
MODE uint
SEP uint `json:"SEP,omitempty"`
TM uint `json:"TM,omitempty"`
NUM uint `json:"NUM,omitempty"`
}
// 7.30.2
// Device status parameter
type PDSM struct {
}
// 7.39.3.9
// Platform basic information
type PSI struct {
CG CG `json:"CG,omitempty"`
}
// 7.39.3.8
// Total record information for call
type CG struct {
ECL uint // The maximum calling time
ECML uint // The maximum calling time per month
AS uint // Terminal phonecall answering strategy
AT uint // Answer automatically when exceed time
}
type Setting struct {
KEYS KEYS `json:"KEYS,omitempty"`
RIP RIP `json:"RIP,omitempty"`
TIMEP TIMEP `json:"TIMEP,omitempty"`
ATP ATP `json:"ATP,omitempty"`
SSP SSP `json:"SSP,omitempty"`
GSP GSP `json:"GSP,omitempty"`
UMP UMP `json:"UMP,omitempty"`
ETHERNET ETHERNET `json:"ETHERNET,omitempty"`
WIFI WIFI `json:"WIFI,omitempty"`
M3G M3G `json:"M3G,omitempty"`
MCMS MCMS `json:"MCMS,omitempty"`
SUBSTRNET SUBSTRNET `json:"SUBSTRNET,omitempty"`
DOSD DOSD `json:"DOSD,omitempty"`
AR AR `json:"AR,omitempty"`
MAIN []VEC `json:"MAIN,omitempty"`
EOSD []EOSD `json:"EOSD,omitempty"`
IOP []IOP `json:"IOP,omitempty"`
SAP SAP `json:"SAP,omitempty"`
REDEV []REDEV `json:"REDEV,omitempty"`
UAP UAP `json:"UAP,omitempty"`
PGDSM PGDSM `json:"PGDSM,omitempty"`
PVLAS PVLAS `json:"PVLAS,omitempty"`
PMDAS PMDAS `json:"PMDAS,omitempty"`
VS VS `json:"VS,omitempty"`
PSI PSI `json:"PSI,omitempty"`
SWUS SWUS `json:"SWUS,omitempty"`
// DSM DSM `json:"DSM,omitempty"`
RIP RIP
VS VS
GSP GSP
TIMEP TIMEP
ETHERNET ETHERNET
KEYS KEYS
WIFI WIFI
M3G M3G
MCMS MCMS
ATP ATP
SSP SSP
SWUS SWUS
UMP UMP
SUBSTRNET SUBSTRNET
DOSD DOSD
AR AR
EOSD []EOSD
MAIN []VEC
IOP []IOP
SAP SAP
UAP UAP
PVLAS PVLAS
PMDAS PMDAS
DSM DSM
}

View File

@ -1,168 +0,0 @@
package models
type NetConnectionType uint
const (
NetConnectionWired NetConnectionType = iota
NetConnectionWireless
)
type TimeShiftSupportFlag uint8
const (
TimeShiftNotSupported TimeShiftSupportFlag = iota
TimeShiftSupported
)
type FileSystemVersionNumber uint8
const (
FileSystemVersion4 FileSystemVersionNumber = iota
FileSystemVersion5
)
type CertificateConnectRequest struct {
Net NetConnectionType `json:"NET"`
SerialNumber string `json:"DSNO"`
DeviceName string `json:"DEVNAME"`
ChannelsNumber uint `json:"CHANNEL"`
LicensePlate string `json:"CARNUM"`
DeviceNumber string `json:"AUTONO"`
VehicleNumber string `json:"AUTOCAR"`
TimeShiftSupport TimeShiftSupportFlag `json:"TSE"`
FileSystemVersion FileSystemVersionNumber `json:"FSV"`
ICCID string `json:"ICCID"`
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 (
CommandMaskAlarm = 1 << iota
CommandMaskScanningGun
CommandMaskPassengerFlow
CommandMaskFaceContrast
CommandMaskCard
CommandMaskShutdownReport
CommandMaskGPSReport
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{
"MODULE": "CERTIFICATE",
"OPERATION": "CONNECT",
"PARAMETER": map[string]any{
"DSNO": serial,
"CHANNEL": numOfCams,
},
"SESSION": session,
}
}
// video server util
func (e *Package) ResponseConnect(Sid string, streamName string) {
e.Payload = map[string]any{
"MODULE": "CERTIFICATE",
"OPERATION": "CREATESTREAM",
"RESPONSE": map[string]any{
"ERRORCODE": 0,
"STREAMNAME": streamName,
},
"SESSION": Sid,
}
}
// main server util
func (e *Package) ResponseCertificateConnect(Sid string) {
e.Payload = map[string]any{
"MODULE": "CERTIFICATE",
"OPERATION": "CONNECT",
"RESPONSE": map[string]any{
"ERRORCAUSE": "",
"ERRORCODE": 0,
"MASKCMD": 5,
"PRO": "1.0.5",
},
"SESSION": Sid,
}
}
*/

View File

@ -1,215 +0,0 @@
package models
import (
"encoding/json"
"fmt"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"strconv"
"time"
)
/*
// main server util
func (e *Package) RequestGeolocation(serial int, Sid string) {
e.Payload = map[string]any{
"MODULE": "DEVEMM",
"OPERATION": "GETPOS",
"PARAMETER": map[string]any{
"SERIAL": serial,
},
"SESSION": Sid,
}
}
func (e *Package) ResponseGeolocation(errorCode int, errorCause string, serial int, longitude float32, latitude float32, altitude float32, speed int, course int, time string) {
e.Payload = map[string]any{
"MODULE": "DEVEMM",
"OPERATION": "GETPOS",
"RESPONSE": map[string]any{
"ERRORCODE": errorCode,
"ERRORCAUSE": errorCause,
"SERIAL": serial,
"P": map[string]any{
"V": errorCode == 0,
"J": fmt.Sprintf("%4.6v", longitude),
"W": fmt.Sprintf("%4.6v", latitude),
"H": fmt.Sprintf("%4.6v", altitude),
"S": speed, // unit - 0.01 km/h
"C": course, // direction (angle from north)
"T": time, // yyyymmddhhmmss
},
},
}
}
*/
// 3.4.5.28
type SpiParameters struct {
DriveFlag uint `json:"T"`
DataMask uint `json:"M"`
Position protocol.GPSData `json:"P"`
DeviceStatus SpiDeviceStatus `json:"S"`
}
// 3.4.5.28.1
type SpiDeviceStatus struct {
Status3G uint `json:"G3"`
Status3GStrength uint `json:"G3S"`
Status4G uint `json:"G4"`
Status4GStrength uint `json:"G4S"`
WIFIStatus uint `json:"W"`
WIFIStrength uint `json:"WS"`
Voltage float64 `json:"V"`
DeviceTemperature float64 `json:"DT"`
IndoorTemperature float64 `json:"TC"`
Speed float64 `json:"S"`
KeyIgnitionState uint `json:"SW"`
RecordStatus []uint `json:"RE"`
Time time.Time `json:"T"`
StorageDeviceNumber uint `json:"STC"`
StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"`
VideoLossStatus []uint `json:"VS"`
Humidity float64 `json:"H"`
TotalMileage float64 `json:"TM"`
HardDriveHeating uint `json:"HTR"`
}
func (g *SpiDeviceStatus) MarshalJSON() ([]byte, error) {
var alias struct {
Status3G uint `json:"G3"`
Status3GStrength uint `json:"G3S"`
Status4G uint `json:"G4"`
Status4GStrength uint `json:"G4S"`
WIFIStatus uint `json:"W"`
WIFIStrength uint `json:"WS"`
Voltage uint `json:"V"`
DeviceTemperature uint `json:"DT"`
IndoorTemperature uint `json:"TC"`
Speed uint `json:"S"`
SpeedUnits uint `json:"SU"`
KeyIgnitionState uint `json:"SW"`
RecordStatus []uint `json:"RE"`
Time string `json:"T"`
StorageDeviceNumber uint `json:"STC"`
StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"`
VideoLossStatus []uint `json:"VS"`
Humidity uint `json:"H"`
TotalMileage string `json:"TM"`
HardDriveHeating uint `json:"HTR"`
}
convert := func(v float64) uint {
if v < 0 {
return uint(-v * 100)
} else {
return uint((v + 100) * 100)
}
}
alias.Status3G = g.Status3G
alias.Status3GStrength = g.Status3GStrength
alias.Status4G = g.Status4G
alias.Status4GStrength = g.Status4GStrength
alias.WIFIStatus = g.WIFIStatus
alias.WIFIStrength = g.WIFIStrength
alias.Voltage = uint(g.Voltage * 100)
alias.DeviceTemperature = convert(g.DeviceTemperature)
alias.IndoorTemperature = convert(g.IndoorTemperature)
alias.Speed = uint(g.Speed * 100)
alias.SpeedUnits = 0
alias.KeyIgnitionState = g.KeyIgnitionState
alias.RecordStatus = g.RecordStatus
alias.Time = g.Time.Format("20060102150405")
alias.StorageDeviceNumber = g.StorageDeviceNumber
alias.StorageDeviceInfo = g.StorageDeviceInfo
alias.VideoLossStatus = g.VideoLossStatus
alias.Humidity = uint(g.Humidity * 10000)
alias.TotalMileage = fmt.Sprintf("%.6f", g.TotalMileage)
alias.HardDriveHeating = g.HardDriveHeating
return json.Marshal(alias)
}
func (g *SpiDeviceStatus) UnmarshalJSON(data []byte) (err error) {
var alias struct {
Status3G uint `json:"G3"`
Status3GStrength uint `json:"G3S"`
Status4G uint `json:"G4"`
Status4GStrength uint `json:"G4S"`
WIFIStatus uint `json:"W"`
WIFIStrength uint `json:"WS"`
Voltage uint `json:"V"`
DeviceTemperature uint `json:"TD"`
IndoorTemperature uint `json:"TC"`
Speed uint `json:"S"`
SpeedUnits uint `json:"SU"`
KeyIgnitionState uint `json:"SW"`
RecordStatus []uint `json:"RE"`
Time string `json:"T"`
StorageDeviceNumber uint `json:"STC"`
StorageDeviceInfo []StorageDeviceInfo `json:"SINFO"`
VideoLossStatus []uint `json:"VS"`
Humidity uint `json:"H"`
TotalMileage string `json:"TM"`
HardDriveHeating uint `json:"HTR"`
}
if err = json.Unmarshal(data, &alias); err != nil {
return
}
convert := func(v uint) float64 {
if v < 10000 {
return -float64(v) / 100
} else {
return float64(v-10000) / 100
}
}
g.Status3G = alias.Status3G
g.Status3GStrength = alias.Status3GStrength
g.Status4G = alias.Status4G
g.Status4GStrength = alias.Status4GStrength
g.WIFIStatus = alias.WIFIStatus
g.WIFIStrength = alias.WIFIStrength
g.Voltage = float64(alias.Voltage) / 100
g.DeviceTemperature = convert(alias.DeviceTemperature)
g.IndoorTemperature = convert(alias.IndoorTemperature)
g.Speed = float64(alias.Speed) / 100.0
switch alias.SpeedUnits {
case 0:
break
case 1:
g.Speed *= 1.609
default:
return fmt.Errorf("Strange speed units")
}
g.KeyIgnitionState = alias.KeyIgnitionState
g.RecordStatus = alias.RecordStatus
g.Time, _ = time.Parse("20060102150405", alias.Time)
g.StorageDeviceNumber = alias.StorageDeviceNumber
g.StorageDeviceInfo = alias.StorageDeviceInfo
g.VideoLossStatus = alias.VideoLossStatus
g.Humidity = float64(alias.Humidity) / 10000
if g.TotalMileage, err = strconv.ParseFloat(alias.TotalMileage, 64); err != nil {
return fmt.Errorf("invalid longitude: %w", err)
}
g.HardDriveHeating = alias.HardDriveHeating
return nil
}
// 3.4.5.28.3
type StorageDeviceInfo struct {
Type uint `json:"T"`
MediaTime uint `json:"O"`
Status uint `json:"S"`
Capacity uint `json:"TS"`
FreeCapacity uint `json:"LS"`
}

View File

@ -1,136 +0,0 @@
package models
import (
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
)
// 3.4.1.3
type EventModelGetAlarmStatusInfoResponse struct {
ErrorCode uint `json:"ERRORCODE"`
ErrorCause string `json:"ERRORCAUSE"`
StorageErrors []StorageErrorStatus `json:"ST"`
AnotherStorageErrors []AnotherStorageErrorStatus `json:"VS"`
VideoLossErrors []VideoLossErrorStatus `json:"VL"`
GPSError GPSErrorStatus `json:"GFA"`
GPSAntennaError GPSAntennaErrorStatus `json:"GPSS"`
}
// 3.4.1.4.21
type StorageErrorStatus struct {
CameraCovered uint `json:"ISA"`
ChannelBind uint `json:"LHC"`
}
// 3.4.1.4.4
type AnotherStorageErrorStatus struct {
}
// 3.4.1.4.5
type VideoLossErrorStatus struct {
}
// 3.4.1.4.44
type GPSErrorStatus struct {
}
// 3.4.1.4.46
type GPSAntennaErrorStatus struct {
}
// 3.4.1.5
// Alarm upload
type SendAlarmInfoParameters struct {
AlarmType protocol.AlarmType `json:"ALARMTYPE"`
CommandType uint `json:"CMDTYPE"`
AlarmUID uint `json:"ALARMUID"`
NumberOfRestarts uint `json:"RUN"`
AlarmLevel protocol.AlarmLevel `json:"ALARMAS"`
AlarmCount uint `json:"ALARMCOUNT"`
TriggerType protocol.TriggerType `json:"TRIGGERTYPE"`
ContinueTime uint `json:"CONTINUETIME"`
CurrentTime uint `json:"CURRENTTIME"`
Language protocol.Language `json:"L"`
GPSData protocol.GPSData `json:"P"`
RealTimeUpload uint `json:"REAL"`
InstructionSerial uint `json:"CMDNO"`
}
// 3.4.1.5
// Alarm upload
type SendAlarmInfoResponse struct {
ErrorCode uint `json:"ERRORCODE"`
AlarmType protocol.AlarmType `json:"ALARMTYPE"`
ErrorCause string `json:"ERRORCAUSE"`
CommandType uint `json:"CMDTYPE"`
AlarmUID uint `json:"ALARMUID"`
NumberOfRestarts uint `json:"RUN"`
InstructionSerial uint `json:"CMDNO"`
}
// 3.4.1.5.1
type SendAlarmInfoCameraParameters struct {
SendAlarmInfoParameters
Channel uint `json:"CHANNEL"`
ChannelMask uint `json:"CHANNELMASK"`
LCH []uint `json:"LCH"`
Push uint `json:"PUSH"`
AlarmName string `json:"ALARMNAME"`
AlarmAbbreviation string `json:"SER"`
}
type EventModelGetAlarmingResponse struct {
CameraCoveredChannelMask uint `json:"VS_CH"`
CameraCoveredAlarmMask uint `json:"VS_AT"`
CameraCoveredStatusMask uint `json:"VS_AS"`
VideoLossChannelMask uint `json:"VL_CH"`
VideoLossAlarmMask uint `json:"VL_AT"`
VideoLossStatusMask uint `json:"VL_AS"`
}
// 3.4.1.3
type EventModelGetAlarmInfoStatusResponse struct {
ErrorCode uint `json:"ERRORCODE"`
ErrorCause string `json:"ERRORCAUSE"`
MotionDetectionAlarm []MotionDetectionAlarmStatus `json:"MD"`
IOAlarm []IOAlarmStatus `json:"IO"`
StorageAlarm []StorageAlarmStatus `json:"ST"`
StorageAlarmParameters []CameraCoveredAlarmStatus `json:"VS"`
VideoLossAlarm []VideoLossAlarmStatus `json:"VL"`
}
// 3.4.1.4.1
type MotionDetectionAlarmStatus struct {
Status uint `json:"ISA"`
Mask uint `json:"LCH"`
}
// 3.4.1.4.2
type IOAlarmStatus struct {
Status uint `json:"ISA"`
IONumber uint `json:"IONO"`
Mask uint `json:"LCH"`
Name string `json:"NAME"`
NameAbbreviation string `json:"NSER"`
}
// 3.4.1.4.4
type CameraCoveredAlarmStatus struct {
ChannelMask uint `json:"CH"`
AlarmMask uint `json:"AT"`
StatusMask uint `json:"AS"`
}
// 3.4.1.4.4
type VideoLossAlarmStatus struct {
Status uint `json:"ISA"`
Mask uint `json:"LCH"`
}
// 3.4.1.4.21
type StorageAlarmStatus struct {
SID any `json:"SID"`
Type uint `json:"ST"`
Error uint `json:"E"`
}

View File

@ -1,53 +0,0 @@
package models
import "gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
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"`
}
type MediaStreamCommand uint
const (
MediaStreamCommandStop MediaStreamCommand = iota
MediaStreamCommandResume
MediaStreamCommandPause
MediaStreamCommandSwitchVideoStream
MediaStreamAudioManagement
MediaStreamFrameRate
MediaStreamSendingMode
)
type MediaStreamModelControlStreamRequest struct {
PayloadType protocol.PayloadType `json:"PT"`
SSRC uint16 `json:"SSRC"`
StreamName string `json:"STREAMNAME"`
Command MediaStreamCommand `json:"CMD"`
StreamType StreamType `json:"STREAMTYPE,omitempty"`
AudioValid uint `json:"AUDIOVALID,omitempty"`
FrameMode uint `json:"FRAMEMODE,omitempty"`
}

View File

@ -1,57 +0,0 @@
package protocol
type AlarmType uint
const (
AlarmTypeVideoLoss AlarmType = iota
AlarmTypeCameraCovered
AlarmTypeMotionDetection
AlarmTypeStorageAbnormal
AlarmTypeUserDefined
AlarmTypeSentriesInspection
AlarmTypeViolation
AlarmTypeEmergency
AlarmTypeSpeedAlarm
AlarmTypeLowVoltage
AlarmTypeOutOfFence = iota + 7
AlarmTypeAccAlarm
AlarmTypePeripheralsDropped
AlarmTypeStopAnnouncement
AlarmTypeGpsAntenna
AlarmTypeDayNightSwitch
AlarmTypeProhibitDriving
AlarmTypeSerialAlarm = iota + 15
AlarmTypeFatigueAlarm
AlarmTypeTakeOutParking
AlarmTypeGestureAlarm
AlarmTypeGreenDriving
AlarmTypeIllegalIgnition
AlarmTypeIllegalShutdown
AlarmTypeCustomExternal
AlarmTypeThinkingLKJ
AlarmTypeTAX3
AlarmTypeOilAlarm
AlarmTypeBusLineOccupation
AlarmTypeForgottenAlarm
AlarmTypeSpecialCustomerFault
AlarmTypeTemperatureAbnormal
AlarmTypeTemperatureChangeAbnormal
AlarmTypeSmokeAlarm
AlarmTypeGBox
AlarmTypeLicensePlateRecognition
AlarmTypeAnotherSpeedAlarm
AlarmTypeWirelessSignalAbnormal
AlarmTypeArming
AlarmTypePhoneCall
AlarmTypeGPSFault
AlarmTypeDSMFault
AlarmTypeFireBox
)
type AlarmLevel uint
const (
AlarmLevelImportant AlarmLevel = iota
AlarmLevelGeneral
AlarmLevelEmergency
)

View File

@ -1,192 +0,0 @@
package protocol
import (
"bytes"
"encoding/binary"
"encoding/json"
"fmt"
"github.com/icza/bitio"
"log"
"time"
)
// Read package
func (e *Package) ReadPackage() bool {
if len(e.Accum) < 12 {
return false
}
r := bitio.NewReader(bytes.NewBuffer(e.Accum))
e.Version = uint8(r.TryReadBits(2))
e.EncryptionFlag = r.TryReadBool()
e.CompressFlag = r.TryReadBool()
e.CSRCCount = uint8(r.TryReadBits(4))
e.PayloadType = PayloadType(r.TryReadBits(8))
e.SSRC = SpecialPayloadType((r.TryReadBits(8) | (r.TryReadBits(8) << 8)))
if e.EncryptionFlag && e.CompressFlag {
// TODO: get snippet, that use this code
r.TryReadBits(8 * 4)
e.payloadLen = r.TryReadBits(8)
r.TryReadBits(3 * 8)
if uint64(len(e.Accum)) < e.payloadLen+12 {
return false
}
} else {
e.payloadLen = r.TryReadBits(32)
// WTF: e.CC is useless
for i := uint64(0); i < 1; i++ {
e.CSRC[i] = r.TryReadBits(32)
}
}
if e.payloadLen > 1e6 {
log.Printf("%v\n", e)
log.Panicln("CORRUPTED PACKAGE")
}
numOfBytes := 0
if e.payloadLen != 0 {
e.RawPayload = make([]byte, e.payloadLen)
numOfBytes = r.TryRead(e.RawPayload)
} else {
e.RawPayload = []byte{}
}
if numOfBytes != int(e.payloadLen) {
return false
}
e.Accum = e.Accum[12+e.payloadLen:]
switch e.PayloadType {
case PayloadTypeData:
if err := json.Unmarshal(e.RawPayload, &e.Payload); err != nil {
log.Printf("Error parsing JSON payload: %v", err)
return false
}
case PayloadTypeSpecial:
switch e.SSRC {
case SpecialPayloadTypeGPS:
e.GPS.GPSStatus = e.RawPayload[0]
e.GPS.Expand = e.RawPayload[1]
e.GPS.Real = e.RawPayload[2]
e.GPS.Longitude = float64(binary.BigEndian.Uint32(e.RawPayload[4:8])) / 1e6
e.GPS.Latitude = float64(binary.BigEndian.Uint32(e.RawPayload[8:12])) / 1e6
e.GPS.Speed = float64(binary.BigEndian.Uint32(e.RawPayload[12:16])) / 100
e.GPS.Direction = float64(binary.BigEndian.Uint32(e.RawPayload[16:20])) / 100
e.GPS.Altitude = int32(binary.BigEndian.Uint32(e.RawPayload[20:24]))
var err error
if e.GPS.Time, err = time.Parse("20060102150405", string(e.RawPayload[24:38])); err != nil {
log.Printf("Error parsing time: %v", err)
}
default:
fmt.Println("N9M parser warning: unknown special payload type", e.SSRC)
}
// default:
// fmt.Println("N9M parser warning: unknown payload type", e.PayloadType)
}
if r.TryError != nil {
log.Printf("TryError encountered: %v", r.TryError)
return false
}
return true
}
func (e *Package) PackPayload() (err error) {
e.RawPayload, err = json.Marshal(e.Payload)
e.payloadLen = uint64(len(e.RawPayload))
if e.payloadLen != 0 {
e.RawPayload = append(e.RawPayload, 0)
e.payloadLen++
}
return
}
func (e *Package) PackPackage() []byte {
var err error
if err = e.PackPayload(); err != nil {
log.Printf("Error while packing payload: %v", err)
return []byte{}
}
return e.PackRawPackage()
}
func (e *Package) PackRawPackage() []byte {
var err error
b := &bytes.Buffer{}
w := bitio.NewWriter(b)
w.TryWriteBits(uint64(e.Version), 2)
w.TryWriteBool(e.EncryptionFlag)
w.TryWriteBool(e.CompressFlag)
w.TryWriteBits(uint64(e.CSRCCount), 4)
w.TryWriteBits(uint64(e.PayloadType), 8)
w.TryWriteBits(uint64(e.SSRC), 16)
w.TryWriteBits(e.payloadLen, 32)
// WTF: e.CC is useless
for i := uint64(0); i < 1; i++ {
w.TryWriteBits(e.CSRC[i], 32)
}
if e.payloadLen != 0 {
w.TryWrite(e.RawPayload)
}
if err = w.Close(); err != nil {
log.Printf("Error while closing writer: %v", err)
return []byte{}
}
return b.Bytes()
}
func (e *Package) GetParametersAs(parameters any) error {
marshal, err := json.Marshal(e.Payload.Parameter)
if err != nil {
return err
}
return json.Unmarshal(marshal, parameters)
}
func (e *Package) SetParameters(parameters any) {
e.Payload.Response = nil
e.Payload.Parameter = parameters
}
func (e *Package) GetResponseAs(response any) error {
marshal, err := json.Marshal(e.Payload.Response)
if err != nil {
return err
}
return json.Unmarshal(marshal, response)
}
func (e *Package) SetResponse(response any) {
e.Payload.Parameter = nil
e.Payload.Response = response
}
func (e *Package) AddToAccum(data []byte) {
e.Accum = append(e.Accum, data...)
}

View File

@ -1,22 +0,0 @@
package protocol
type Language uint
const (
LanguageSimplifiedChinese Language = iota
LanguageEnglish
LanguageKorean
LanguageItalian
LanguageGerman
LanguageThai
LanguageTurkey
LanguagePortugal
LanguageSpain
LanguageRomania
LanguageGreece
LanguageFrench
LanguageRussian
LanguageDutch
LanguageHebrew
LanguageChineseTraditional
)

View File

@ -1,139 +0,0 @@
package protocol
import (
"encoding/json"
"fmt"
"strconv"
"time"
)
type PayloadType uint8
const (
PayloadTypeData PayloadType = 0
PayloadTypeLive PayloadType = 2
PayloadTypeDownload PayloadType = 3
PayloadTypePlayback PayloadType = 4
PayloadTypeCapturedPhotos PayloadType = 6
PayloadTypeParameterImport PayloadType = 10
PayloadTypeParameterExport PayloadType = 11
PayloadTypeTransmissionSubStream PayloadType = 15
PayloadTypeRecordingSubStream PayloadType = 16
PayloadTypeBlackBox PayloadType = 17
PayloadTypeSpecial PayloadType = 22
PayloadTypeMaintainData PayloadType = 30
)
type SpecialPayloadType uint16
const (
SpecialPayloadTypeHeartbeat SpecialPayloadType = iota
SpecialPayloadTypeHeartbeatWithoutBody
SpecialPayloadTypeGPS
SpecialPayloadTypeMileage
SpecialPayloadTypeEnvironmentalQuality
SpecialPayloadTypeDrivingPosture
SpecialPayloadTypeScanningGun
SpecialPayloadTypeOil
SpecialPayloadTypeGDS
SpecialPayloadTypeGPSToBWS
SpecialPayloadTypeCANBOX
SpecialPayloadTypeGSenor
SpecialPayloadTypeAckGPS
)
type Message struct {
Module string `json:"MODULE"`
Session string `json:"SESSION"`
Operation string `json:"OPERATION"`
Parameter interface{} `json:"PARAMETER,omitempty"`
Response interface{} `json:"RESPONSE,omitempty"`
}
// 3.4.5.27.1
type GPSData struct {
GPSStatus uint8
Expand uint8
Real uint8
Longitude float64
Latitude float64
Speed float64
Direction float64
Altitude int32
Time time.Time
}
func (g *GPSData) MarshalJSON() ([]byte, error) {
var alias struct {
GPSStatus uint8 `json:"V"`
Longitude string `json:"J"`
Latitude string `json:"W"`
Speed uint `json:"S"`
Direction uint `json:"C"`
Altitude int32 `json:"H"`
Time string `json:"T"`
}
alias.GPSStatus = g.GPSStatus
alias.Longitude = fmt.Sprintf("%.6f", g.Longitude)
alias.Latitude = fmt.Sprintf("%.6f", g.Latitude)
alias.Speed = uint(g.Speed * 100)
alias.Direction = uint(g.Direction * 100)
alias.Altitude = g.Altitude
alias.Time = g.Time.Format("20060102150405")
return json.Marshal(alias)
}
func (g *GPSData) UnmarshalJSON(data []byte) (err error) {
var alias struct {
GPSStatus uint8 `json:"V"`
Longitude string `json:"J"`
Latitude string `json:"W"`
Speed uint `json:"S"`
Direction uint `json:"C"`
Altitude int32 `json:"H"`
Time string `json:"T"`
}
if err = json.Unmarshal(data, &alias); err != nil {
return
}
g.GPSStatus = alias.GPSStatus
if g.Longitude, err = strconv.ParseFloat(alias.Longitude, 64); err != nil {
return fmt.Errorf("invalid longitude: %w", err)
}
if g.Latitude, err = strconv.ParseFloat(alias.Latitude, 64); err != nil {
return fmt.Errorf("invalid latitude: %w", err)
}
g.Speed = float64(alias.Speed) / 100.0
g.Direction = float64(alias.Direction) / 100.0
g.Altitude = alias.Altitude
g.Time, _ = time.Parse("20060102150405", alias.Time)
return nil
}
type Package struct {
Version uint8
EncryptionFlag bool
CompressFlag bool
CSRCCount uint8
PayloadType PayloadType
SSRC SpecialPayloadType
Reserved uint64
CSRC [16]uint64
GPS GPSData
payloadLen uint64
Payload Message
RawPayload []byte
Accum []byte
}

View File

@ -1,8 +0,0 @@
package protocol
type TriggerType uint
const (
TriggerTypeManual TriggerType = iota
TriggerTypeAutomatic
)

View File

@ -1,177 +0,0 @@
package smart
import (
"errors"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/utils"
"net"
"sync"
)
const (
charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
length = 6
)
func NewAutoSmartChannelPackage(mainSmartPackage *SmartPackage) (*SmartChannelPackage, error) {
conn, err := net.Dial(mainSmartPackage.conn.RemoteAddr().Network(), mainSmartPackage.conn.RemoteAddr().String())
if err != nil {
return nil, err
}
return NewSmartChannelPackage(conn, mainSmartPackage)
}
func NewSmartChannelPackage(conn net.Conn, mainSmartPackage *SmartPackage) (*SmartChannelPackage, error) {
pack := NewSmartPackage(conn)
pack.pack.Payload.Session = mainSmartPackage.pack.Payload.Session
channelName, err := registerChannelHandles(pack)
if err != nil {
return nil, err
}
smartChannelPackage := &SmartChannelPackage{
pack: pack,
mainPack: mainSmartPackage,
channelName: channelName,
mutex: sync.RWMutex{},
ssrc: make(map[uint16][]func([]byte) error),
}
pack.AddPayloadHandler(protocol.PayloadTypeLive, smartChannelPackage.handleLiveVideo)
return smartChannelPackage, nil
}
func (channelPack *SmartChannelPackage) Run() error {
for {
if err := channelPack.pack.Handle(); err != nil {
return err
}
}
}
func (channelPack *SmartChannelPackage) GetChannelName() string {
return channelPack.channelName
}
func (channelPack *SmartChannelPackage) AddLiveSource(ssrc uint16, source func([]byte) error) {
channelPack.mutex.Lock()
defer channelPack.mutex.Unlock()
channelPack.ssrc[ssrc] = append(channelPack.ssrc[ssrc], source)
}
func (channelPack *SmartChannelPackage) handleLiveVideo(sPack *SmartPackage, pack protocol.Package) error {
channelPack.mutex.RLock()
sources, ok := channelPack.ssrc[uint16(pack.SSRC)]
if !ok || len(sources) == 0 {
channelPack.mutex.RUnlock()
var request = models.MediaStreamModelControlStreamRequest{
PayloadType: protocol.PayloadTypeLive,
SSRC: uint16(pack.SSRC),
StreamName: channelPack.channelName,
Command: models.MediaStreamCommandStop,
}
pack.PayloadType = protocol.PayloadTypeData
pack.Payload.Module = "MEDIASTREAMMODEL"
pack.Payload.Operation = "CONTROLSTREAM"
pack.SetParameters(request)
if _, err := channelPack.mainPack.Write(pack.PackPackage()); err != nil {
panic(err)
}
return nil
}
var errorMask = map[int]bool{}
for i, source := range sources {
if err := source(pack.RawPayload); err != nil {
errorMask[i] = true
}
}
channelPack.mutex.RUnlock()
if len(errorMask) > 0 {
newSources := make([]func([]byte) error, 0, len(sources))
for i, source := range sources {
if !errorMask[i] {
newSources = append(newSources, source)
}
}
channelPack.mutex.Lock()
channelPack.ssrc[uint16(pack.SSRC)] = newSources
channelPack.mutex.Unlock()
}
return nil
}
func registerChannelHandles(pack *SmartPackage) (string, error) {
res := make(chan error, 1)
pack.AddJSONHandler("CERTIFICATE", "CREATESTREAM", func(smartPackage *SmartPackage, p protocol.Package) error {
var params models.CertificateCreateStreamResponse
if err := p.GetResponseAs(&params); err != nil {
return err
}
if params.ErrorCode != 0 {
res <- errors.New(params.ErrorCause)
} else {
res <- nil
}
return nil
})
channelName := utils.RandomString(length, charset)
var request = models.CertificateCreateStreamRequest{
StreamName: channelName,
}
pack.pack.Payload.Module = "CERTIFICATE"
pack.pack.Payload.Operation = "CREATESTREAM"
pack.pack.SetParameters(request)
pack.Write(pack.pack.PackPackage())
for {
if err := pack.Handle(); err != nil {
return "", err
}
select {
case err := <-res:
close(res)
if err != nil {
return "", err
}
pack.AddJSONHandler("CERTIFICATE", "CREATESTREAM", func(smartPackage *SmartPackage, p protocol.Package) error {
return errors.New("stream already exists")
})
return channelName, nil
default:
}
}
}

View File

@ -1,33 +0,0 @@
package smart
import (
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"net"
"sync"
)
type ProcessFunc func(*SmartPackage, protocol.Package) error
type AlarmProcessFunc func(*SmartPackage, protocol.Package, models.SendAlarmInfoResponse) error
type SmartPackage struct {
pack protocol.Package
conn net.Conn
buff []byte
payloadProcess map[protocol.PayloadType]ProcessFunc
jsonProcess map[string]ProcessFunc
alarmProcess map[protocol.AlarmType]AlarmProcessFunc
Storage map[string]interface{}
}
type SmartChannelPackage struct {
pack *SmartPackage
mainPack *SmartPackage
channelName string
mutex sync.RWMutex
ssrc map[uint16][]func([]byte) error
}

View File

@ -1,144 +0,0 @@
package smart
import (
"errors"
"fmt"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/models"
"gitea.unprism.ru/KRBL/n9m/v2/pkg/protocol"
"net"
)
type notFoundError struct {
message string
}
func (e *notFoundError) Error() string {
return fmt.Sprintf("not found %s", e.message)
}
func NewSmartPackage(conn net.Conn) *SmartPackage {
return &SmartPackage{
pack: protocol.Package{},
conn: conn,
buff: make([]byte, 1024),
payloadProcess: make(map[protocol.PayloadType]ProcessFunc),
jsonProcess: make(map[string]ProcessFunc),
alarmProcess: make(map[protocol.AlarmType]AlarmProcessFunc),
Storage: make(map[string]interface{}),
}
}
func (pack *SmartPackage) AddPayloadHandler(payloadType protocol.PayloadType, processFunc ProcessFunc) {
pack.payloadProcess[payloadType] = processFunc
}
func (pack *SmartPackage) AddJSONHandler(module, operation string, processFunc ProcessFunc) {
pack.jsonProcess[fmt.Sprintf("%s:%s", module, operation)] = processFunc
}
func (pack *SmartPackage) AddAlarmHandler(alarmType protocol.AlarmType, processFunc AlarmProcessFunc) {
pack.alarmProcess[alarmType] = processFunc
}
func (pack *SmartPackage) handleAlarm() (err error) {
if !(pack.pack.PayloadType == protocol.PayloadTypeData && pack.pack.Payload.Module == "EVEM" && pack.pack.Payload.Operation == "SENDALARMINFO") {
return fmt.Errorf("invalid payload type or operation for alarm handling")
}
var params models.SendAlarmInfoParameters
if err = pack.pack.GetParametersAs(&params); err != nil {
return fmt.Errorf("invalid payload")
}
var processFunc AlarmProcessFunc
var ok bool
if processFunc, ok = pack.alarmProcess[params.AlarmType]; !ok {
return &notFoundError{
message: fmt.Sprintf("alarm %d", params.AlarmType),
}
}
var response models.SendAlarmInfoResponse
response.ErrorCode = 0
response.AlarmType = params.AlarmType
response.CommandType = params.CommandType
response.AlarmUID = params.AlarmUID
response.NumberOfRestarts = params.NumberOfRestarts
response.InstructionSerial = params.InstructionSerial
return processFunc(pack, pack.pack, response)
}
func (pack *SmartPackage) handleJson() (err error) {
if pack.pack.PayloadType != protocol.PayloadTypeData {
return fmt.Errorf("invalid json payload type")
}
var nfErr *notFoundError
if err = pack.handleAlarm(); err == nil || errors.As(err, &nfErr) {
return
}
var processFunc ProcessFunc
var ok bool
var key = fmt.Sprintf("%s:%s", pack.pack.Payload.Module, pack.pack.Payload.Operation)
if processFunc, ok = pack.jsonProcess[key]; !ok {
return &notFoundError{
message: fmt.Sprintf("json %s", key),
}
}
return processFunc(pack, pack.pack)
}
func (pack *SmartPackage) handle() (err error) {
var nfErr *notFoundError
if err = pack.handleJson(); err == nil || errors.As(err, &nfErr) {
return
}
var processFunc ProcessFunc
var ok bool
if processFunc, ok = pack.payloadProcess[pack.pack.PayloadType]; !ok {
return &notFoundError{
message: fmt.Sprintf("payload type %d", pack.pack.PayloadType),
}
}
return processFunc(pack, pack.pack)
}
func (pack *SmartPackage) handleLoop() (err error) {
for pack.pack.ReadPackage() {
if err = pack.handle(); err != nil {
return err
}
}
return
}
func (pack *SmartPackage) Handle() (err error) {
if err = pack.handleLoop(); err != nil {
return err
}
var rn int
if rn, err = pack.conn.Read(pack.buff); err != nil {
return
}
pack.pack.AddToAccum(pack.buff[:rn])
return pack.handleLoop()
}
func (pack *SmartPackage) GetPackage() protocol.Package {
return pack.pack
}
func (pack *SmartPackage) Write(data []byte) (int, error) {
return pack.conn.Write(data)
}

View File

@ -1,23 +0,0 @@
package utils
import (
"crypto/hmac"
"crypto/md5"
"encoding/hex"
)
func generateHMAC(key string, data string) string {
mac := hmac.New(md5.New, []byte(key))
mac.Write([]byte(data))
return hex.EncodeToString(mac.Sum(nil))
}
func GenerateVerifyKey(key string) string {
return generateHMAC(key, key)
}
func GeneratePasswordHash(password string) string {
return generateHMAC("streaming", password)
}

View File

@ -1,18 +0,0 @@
package utils
import (
"math/rand"
"time"
)
// seededRand is a source of random numbers seeded with the current time.
var seededRand *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))
// randomString generates a random string of the specified length using the given charset.
func RandomString(length int, charset string) string {
b := make([]byte, length)
for i := range b {
b[i] = charset[seededRand.Intn(len(charset))]
}
return string(b)
}

32
scheme.go Normal file
View File

@ -0,0 +1,32 @@
package n9m
import "github.com/tidwall/gjson"
type PayloadJson struct {
Module string
Key string
Operation string
Parameters map[string]interface{}
Response map[string]interface{}
}
type Package struct {
Version uint64
Encription uint64
Mark uint64
CC uint64
PayloadType uint64
SSRC uint64
Reserved uint64
CSRC [16]uint64
PayloadLen uint64
GPayload gjson.Result
Payload map[string]interface{}
RawPayload []byte
Raw []byte
Accum []byte
Json PayloadJson
}

View File

@ -1,6 +1,4 @@
package models
/*
package n9m
func (e *Package) ResponseCalendar(errorCode int, errorCause string, serial int, dates []string) {
e.Payload = map[string]any{
@ -80,5 +78,3 @@ func (e *Package) RequestFileList(queryTime string, serial int, session string,
"SESSION": session,
}
}
*/

25
utils.go Normal file
View File

@ -0,0 +1,25 @@
package n9m
import (
"encoding/hex"
)
// add bytes to accum
func (e *Package) AddToAccum(data []byte) {
e.Accum = append(e.Accum, data...)
}
// why store a string and constantly change it to the same thing
// the stored string is not used
func (e *Package) GetToken() {
hexStream := "3876431502000010380000007b224b4559223a22434c49454e544c4f47494e222c22524553504f4e5345223a7b22434c49454e544944223a2237643531323030227d7d00"
e.RawPayload, _ = hex.DecodeString(hexStream)
}
// the same
func (e *Package) RequestGetTokenDop() {
hexStream := "3876431501000010360000007b224b4559223a224c4f47494e222c22504152414d223a7b224355534552223a2231222c22505744223a22313233343536227d7d0a00"
e.RawPayload, _ = hex.DecodeString(hexStream)
}