zhangcan128 há 1 ano atrás
pai
commit
062f354376
49 ficheiros alterados com 2751 adições e 7 exclusões
  1. 4 0
      api/v1/enter.go
  2. 8 0
      api/v1/isapi/enter.go
  3. 75 0
      api/v1/isapi/fieldDetection.go
  4. 74 0
      api/v1/isapi/lineDetection.go
  5. 72 0
      api/v1/isapi/regionEntrance.go
  6. 62 0
      api/v1/isapi/system.go
  7. 4 4
      config.yaml
  8. 45 0
      eventServer/email.go
  9. 50 0
      eventServer/eventNotificationAlert.go
  10. 168 0
      eventServer/eventServer.go
  11. 275 0
      gatewayServer/c2s.go
  12. 13 0
      gatewayServer/ending.go
  13. 172 0
      gatewayServer/gatewayProtocol.go
  14. 76 0
      gatewayServer/gatewayServer.go
  15. 13 0
      initialize/router.go
  16. 279 0
      isapi/client.go
  17. 88 0
      isapi/digest.go
  18. 52 0
      isapi/http.go
  19. 1 0
      isapi/isapi_common.go
  20. 32 0
      isapi/isapi_event_channelCap.go
  21. 33 0
      isapi/isapi_event_httphost.go
  22. 102 0
      isapi/isapi_event_notification.go
  23. 33 0
      isapi/isapi_event_schedule.go
  24. 58 0
      isapi/isapi_event_tamperDetection.go
  25. 26 0
      isapi/isapi_smart_calibration.go
  26. 68 0
      isapi/isapi_smart_fieldDetection.go
  27. 59 0
      isapi/isapi_smart_lineDetection.go
  28. 53 0
      isapi/isapi_smart_regionEntrance.go
  29. 33 0
      isapi/isapi_smart_regionExiting.go
  30. 328 0
      isapi/isapi_system_deviceCap.go
  31. 39 0
      isapi/isapi_system_deviceInfo.go
  32. 5 0
      isapi/isapi_system_email.go
  33. 42 0
      isapi/isapi_system_motionDetection.go
  34. 47 0
      isapi/isapi_system_time.go
  35. 45 0
      isapi/operation.go
  36. 9 0
      isapi/response.go
  37. 69 0
      isapi/sip.go
  38. 1 0
      main.go
  39. 8 0
      model/app/response/cameras.go
  40. 11 0
      model/app/response/event.go
  41. 13 0
      model/app/response/gateway.go
  42. 10 0
      model/isapi/sip.go
  43. 5 1
      router/enter.go
  44. 5 0
      router/isapi/enter.go
  45. 46 0
      router/isapi/isapi.go
  46. 1 2
      service/app/gateway.go
  47. 4 0
      service/enter.go
  48. 5 0
      service/isapi/enter.go
  49. 30 0
      service/isapi/sipServer.go

+ 4 - 0
api/v1/enter.go

@@ -1,11 +1,15 @@
 package v1
 
 import (
+	"lc-fangdaosha/api/v1/app"
+	"lc-fangdaosha/api/v1/isapi"
 	"lc-fangdaosha/api/v1/system"
 )
 
 type ApiGroup struct {
 	SystemApiGroup system.ApiGroup
+	AppApiGroup    app.ApiGroup
+	IsApiGroup     isapi.ApiGroup
 }
 
 var ApiGroupApp = new(ApiGroup)

+ 8 - 0
api/v1/isapi/enter.go

@@ -0,0 +1,8 @@
+package isapi
+
+type ApiGroup struct {
+	SystemApi
+	FieldDetectionApi
+	LineDetectionApi
+	RegionEntranceApi
+}

+ 75 - 0
api/v1/isapi/fieldDetection.go

@@ -0,0 +1,75 @@
+package isapi
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"lc-fangdaosha/isapi"
+)
+
+//区域入侵
+
+type FieldDetectionApi struct {
+}
+
+// GetFieldDetectionCap 获取单个通道区域入侵规则参数配置能力
+func (api FieldDetectionApi) GetFieldDetectionCap(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetFieldDetectionCap, nil, c)
+
+}
+
+// GetSizeFd 获取监测目标的尺寸
+func (api FieldDetectionApi) GetSizeFd(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetFieldDetectionCal, nil, c)
+}
+
+// PutSizeFd 配置监测目标的尺寸
+func (api FieldDetectionApi) PutSizeFd(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutFieldDetectionCal, all, c)
+}
+
+// GetFieldDetection 获取单个通道区域入侵侦测规则
+func (api FieldDetectionApi) GetFieldDetection(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetFieldDetection, nil, c)
+}
+
+// PutFieldDetection 配置单个通道区域入侵侦测规则
+func (api FieldDetectionApi) PutFieldDetection(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+		return
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutRegionEntrance, all, c)
+}

+ 74 - 0
api/v1/isapi/lineDetection.go

@@ -0,0 +1,74 @@
+package isapi
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"lc-fangdaosha/isapi"
+)
+
+// 越界侦测
+
+type LineDetectionApi struct {
+}
+
+// GetLineDetectionCap  获取越界侦测能力
+func (api *LineDetectionApi) GetLineDetectionCap(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetLineDetectionCap, nil, c)
+}
+
+// GetSizeLd  获取越界侦测目标的尺寸
+func (api *LineDetectionApi) GetSizeLd(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetLineDetectionCal, nil, c)
+}
+
+// PutSizeLd 配置越界侦测目标尺寸
+func (api *LineDetectionApi) PutSizeLd(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutLineDetectionCal, all, c)
+}
+
+// GetLineDetection 获取越界侦测能力
+func (api *LineDetectionApi) GetLineDetection(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetLineDetection, nil, c)
+}
+
+// PutLineDetection 配置越界侦测能力
+func (api *LineDetectionApi) PutLineDetection(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutLineDetection, all, c)
+}

+ 72 - 0
api/v1/isapi/regionEntrance.go

@@ -0,0 +1,72 @@
+package isapi
+
+import (
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"lc-fangdaosha/isapi"
+)
+
+// 进入区域
+
+type RegionEntranceApi struct{}
+
+// GetRegionEntranceCap  获取单个通道进入区域侦测规则参数配置能力
+func (api RegionEntranceApi) GetRegionEntranceCap(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("GetHost err:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetRegionEntranceCap, nil, c)
+}
+
+// GetSizeRe 获取侦测目标的尺寸
+func (api RegionEntranceApi) GetSizeRe(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("GetHost err:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetRegionEntranceCal, nil, c)
+}
+
+// PutSizeRe 配置侦测目标的尺寸
+func (api RegionEntranceApi) PutSizeRe(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutRegionEntranceCal, all, c)
+}
+
+// GetRegionEntrance 获取单个通道进入区域侦测规则
+func (api RegionEntranceApi) GetRegionEntrance(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取host失败:%s", err.Error())
+		return
+	}
+	isapi.TouChuan(host, isapi.GetRegionEntrance, nil, c)
+}
+
+// PutRegionEntrance 配置单个通道进入区域侦测规则
+func (api RegionEntranceApi) PutRegionEntrance(c *gin.Context) {
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+		return
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutFieldDetection, all, c)
+}

+ 62 - 0
api/v1/isapi/system.go

@@ -0,0 +1,62 @@
+package isapi
+
+import (
+	"errors"
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"lc-fangdaosha/gatewayServer"
+	"lc-fangdaosha/isapi"
+	"strings"
+)
+
+type SystemApi struct {
+}
+
+// GetInfo 获取设备信息
+func (i SystemApi) GetInfo(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.GetDeviceInfo, nil, c)
+}
+
+// GetCap 获取设备能力集
+func (i SystemApi) GetCap(c *gin.Context) {
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.GetSystemCap, nil, c)
+}
+
+// PutEmail 配置邮箱
+func (i SystemApi) PutEmail(c *gin.Context) {
+	defer c.Request.Body.Close()
+	all, err := ioutil.ReadAll(c.Request.Body)
+	if err != nil {
+		logrus.Errorf("读取数据失败:%e\n", err)
+	}
+	host, err := GetHost(c)
+	if err != nil {
+		logrus.Errorf("获取设备连接失败:%e\n", err)
+		return
+	}
+	isapi.TouChuan(host, isapi.PutEmail, all, c)
+}
+
+// GetHost 获取设备连接的host
+func GetHost(c *gin.Context) (string, error) {
+	devId := c.Query("devId")
+	if devId == "" {
+		return "", errors.New("设备Id为空")
+	}
+	conn, ok := gatewayServer.ConnMap[devId]
+	if !ok {
+		return "", errors.New("获取设备Id对应连接失败")
+	}
+	return strings.Split(conn.RemoteAddr().String(), ":")[0] + ":8848", nil
+}

+ 4 - 4
config.yaml

@@ -1,7 +1,7 @@
 #系统/后台相关
 system:
   env: public
-  addr: 8889
+  addr: 9000
   db-type: mysql
   oss-type: local
   use-multipoint: false
@@ -15,7 +15,7 @@ jwt:
   buffer-time: 1d
   issuer: qmPlus
 captcha:
-  key-long: 6     #验证码长度
+  key-long: 4    #验证码长度
   img-width: 240  #宽
   img-height: 80  #高
   open-captcha: 0 #开启验证码 1关闭,0开启
@@ -25,9 +25,9 @@ mysql:
   path: 127.0.0.1
   port: "3306"
   config: charset=utf8mb4&parseTime=True&loc=Local
-  db-name: lcfns
+  db-name: lcfds
   username: root
-  password: root
+  password: 123456
   prefix: ""
   singular: false
   engine: ""

+ 45 - 0
eventServer/email.go

@@ -0,0 +1,45 @@
+package eventServer
+
+import (
+	"fmt"
+	"github.com/sirupsen/logrus"
+	mail "github.com/xhit/go-simple-mail/v2"
+	"lc-fangdaosha/global"
+	"lc-fangdaosha/utils"
+)
+
+func SendAlarmEmail(cameraMac string, msg string, file *mail.File) {
+	var html = `
+<!DOCTYPE html>
+<html>
+<head><title>报警通知</title></head>
+<body>
+<h5>%s</h5>
+<h5><a href="http://192.168.110.165:9000/user/userUnbindEmail?id=%d&email=%s">不再接收龙弛防防盗砂报警邮箱通知!</a></h5>
+</body>
+</html>
+`
+	//查出所有相关email
+	var emails []UserEmails
+	//SELECT e.email FROM camera c JOIN gateway g ON c.gid = g.id LEFT JOIN sys_user_email e ON g.uid = e.uid WHERE c.mac_address = 'e0:ca:3c:6a:26:8c';
+	err := global.Db.Select("g.uid,e.email").
+		Table("camera c JOIN gateway g ON c.gid = g.id LEFT JOIN sys_user_email e ON g.uid = e.uid").
+		Where("c.mac_address = ?", cameraMac).
+		Scan(&emails).Error
+	if err != nil {
+		logrus.Error(err)
+		return
+	}
+	for _, v := range emails {
+		body := fmt.Sprintf(html, msg, v.Uid, v.Email)
+		utils.EmailPicture(v.Email,
+			"防盗砂通知",
+			body,
+			file)
+	}
+}
+
+type UserEmails struct {
+	Uid   uint   `json:"uid"`
+	Email string `json:"email"`
+}

+ 50 - 0
eventServer/eventNotificationAlert.go

@@ -0,0 +1,50 @@
+package eventServer
+
+// 事件警报通知
+type EventNotificationAlert struct {
+	IpAddress           string `xml:"ipAddress"`
+	PortNo              string `xml:"portNo"`
+	Protocol            string `xml:"protocol"`
+	MacAddress          string `xml:"macAddress"`
+	ChannelID           string `xml:"channelID"`
+	DateTime            string `xml:"dateTime"`
+	ActivePostCount     string `xml:"activePostCount"`
+	EventType           string `xml:"eventType"`
+	EventState          string `xml:"eventState"`
+	EventDescription    string `xml:"eventDescription"`
+	DetectionRegionList struct {
+		DetectionRegionEntry []struct {
+			RegionID              string `xml:"regionID"`
+			SensitivityLevel      string `xml:"sensitivityLevel"`
+			RegionCoordinatesList struct {
+				RegionCoordinates []struct {
+					PositionX string `xml:"positionX"`
+					PositionY string `xml:"positionY"`
+				} `xml:"RegionCoordinates"`
+			} `xml:"RegionCoordinatesList"`
+			DetectionTarget string `xml:"detectionTarget"`
+			TargetRect      struct {
+				X      string `xml:"X"`
+				Y      string `xml:"Y"`
+				Width  string `xml:"width"`
+				Height string `xml:"height"`
+			} `xml:"TargetRect"`
+		} `xml:"DetectionRegionEntry"`
+	} `xml:"DetectionRegionList"`
+	ChannelName               string `xml:"channelName"`
+	DetectionPictureTransType string `xml:"detectionPictureTransType"`
+	DetectionPicturesNumber   string `xml:"detectionPicturesNumber"`
+	IsDataRetransmission      string `xml:"isDataRetransmission"`
+	DurationList              struct {
+		Duration []struct {
+			RelationEvent string `xml:"relationEvent"`
+		} `xml:"Duration"`
+	} `xml:"DurationList"`
+}
+
+var sMap = map[string]string{
+	"shelteralarm":   "遮盖报警",
+	"regionEntrance": "进入区域",
+	"fielddetection": "区域入侵",
+	"linedetection":  "越界侦测",
+}

+ 168 - 0
eventServer/eventServer.go

@@ -0,0 +1,168 @@
+package eventServer
+
+import (
+	"encoding/xml"
+	"fmt"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"net/http"
+	"strings"
+	"time"
+)
+
+// MQDEvent (MQTT Data Event) 用于mqtt传输事件
+type MQDEvent struct {
+	EventCode string `json:"eventCode"`
+	EId       int    `json:"eId"`
+	Ip        string `json:"ip"`
+	Type      string `json:"type"`
+	StartTime string `json:"startTime"`
+	Name      string `json:"name"`
+	Data      []byte `json:"data"`
+}
+
+func StartEventServer() {
+	http.HandleFunc("/event", handler)
+	logrus.Fatal("事件监听服务启动失败", http.ListenAndServe(":8850", nil))
+}
+
+func handler(w http.ResponseWriter, r *http.Request) {
+	go func() {
+		//监听主机应答固定,直接先应答
+		w.WriteHeader(200)
+		w.Header().Add("Date", time.Now().String())
+		w.Header().Add("Connection", "close")
+	}()
+	//logRequest(r)
+	contentType := r.Header.Get("Content-Type")
+	if strings.Contains(contentType, "application/xml") {
+		bytes, err := ioutil.ReadAll(r.Body)
+		if err != nil {
+			logrus.Error("事件处理-读取错误:", err)
+			return
+		}
+		var event EventNotificationAlert
+		err = xml.Unmarshal(bytes, &event)
+		if err != nil {
+			logrus.Error("事件处理-解析错误:", err)
+			return
+		}
+		//处理事件 todo 邮箱
+		handleEvent_(event)
+	} else if strings.Contains(contentType, "multipart/form-data") {
+		fmt.Println("multipart/form-data 事件")
+		//handleMultipart(r)
+	} else {
+		logrus.WithField("Content-Type", contentType).Error("该Content-Type没有写处理逻辑")
+		return
+	}
+}
+
+////TODO 限制事件重复触发,一段时间内不重复发送邮件,但保持报警状态
+//
+//var eventService = service.ServiceGroupApp.AppServiceGroup.EventService
+//
+//// 处理多文件事件
+//func handleMultipart(r *http.Request) {
+//	// todo  远程联动-ip音柱
+//	multipartReader := multipart.NewReader(r.Body, "boundary")
+//	var msg string //邮件消息
+//	// 循环读取每个 part
+//	var eventAlert EventNotificationAlert
+//	for {
+//		part, err := multipartReader.NextPart()
+//		//defer part.Close()
+//		if err == io.EOF {
+//			break
+//		}
+//		if err != nil {
+//			log.Println("Failed to read part:", err)
+//			continue
+//		}
+//		// 检查 part 的 Content-Disposition
+//		formName := part.FormName()
+//		fmt.Println("formName", formName)
+//		if formName != "intrusionImage" {
+//			//不含图片的xml部分数据
+//			xmlData, err := ioutil.ReadAll(part)
+//			if err != nil {
+//				return
+//			}
+//			xml.Unmarshal(xmlData, &eventAlert)
+//			//event.Ip = eventAlert.IpAddress
+//			//event.Type = eventAlert.EventType
+//			//event.StartTime = eventAlert.DateTime
+//			msg = handleEvent_(eventAlert)
+//			continue
+//		}
+//		fmt.Printf("eventAlert:%+v\n", eventAlert)
+//		//处理图片部分数据
+//		contentType := part.Header.Get("Content-Type")
+//		eventCode := part.Header.Get("Content-ID")
+//		picName := timeFmt(eventAlert.DateTime) + ".jpeg"
+//		//event.Name = picName
+//		data, _ := ioutil.ReadAll(part)
+//		f := &mail.File{
+//			Name:     picName,
+//			MimeType: contentType,
+//			Data:     data,
+//			Inline:   true,
+//		}
+//		picture := &app.Picture{
+//			Name: picName,
+//			Time: time.Now(),
+//			Mime: contentType,
+//			Size: len(data),
+//		}
+//		pictureData := &app.PictureData{
+//			Data: data,
+//		}
+//		event := &app.Event{
+//			EventCode:  eventCode,
+//			MacAddress: eventAlert.MacAddress,
+//			EventType:  eventAlert.EventType,
+//		}
+//		//保存图片
+//		go eventService.Save(event, picture, pictureData)
+//		//邮件通知
+//		SendAlarmEmail(eventAlert.MacAddress, msg, f)
+//		//utils.EmailPicture("1104038181@qq.com",
+//		//	"防溺水通知",
+//		//	"",
+//		//	f)
+//	}
+//}
+
+func handleEvent_(event EventNotificationAlert) string {
+	var eType string
+	if event.EventType == "duration" {
+		eType = event.DurationList.Duration[0].RelationEvent
+	} else {
+		eType = event.EventType
+	}
+	return fmt.Sprintf("事件类型:%s,时间:%s", sMap[eType], timeFmt(event.DateTime))
+}
+
+func timeFmt(str string) string {
+	s := strings.Split(str, "T")
+	t := s[0]
+	s1 := strings.Split(s[1], ".")
+	s2 := strings.Split(s1[0], "+")
+	return t + " " + s2[0]
+}
+
+func logRequest(req *http.Request) {
+	// 打印请求行
+	fmt.Printf("%s %s %s\n", req.Method, req.URL.Path, req.Proto)
+
+	// 打印请求头
+	for name, headers := range req.Header {
+		for _, h := range headers {
+			fmt.Printf("%v: %v\n", name, h)
+		}
+	}
+
+	// 打印请求体
+	body, _ := ioutil.ReadAll(req.Body)
+	fmt.Printf("%s\n", body)
+}

+ 275 - 0
gatewayServer/c2s.go

@@ -0,0 +1,275 @@
+package gatewayServer
+
+import (
+	"encoding/xml"
+	"fmt"
+	"github.com/sirupsen/logrus"
+	"lc-fangdaosha/global"
+	"lc-fangdaosha/isapi"
+	appModel "lc-fangdaosha/model/app"
+	"lc-fangdaosha/service"
+	appService "lc-fangdaosha/service/app"
+	is "lc-fangdaosha/service/isapi"
+	"net"
+	"strings"
+)
+
+// ParseAndResponse 分析和响应
+func ParseAndResponse(adu AppDataUnit, c net.Conn) {
+	switch adu.CmdCode {
+	case CmdCodeHeartbeatC2S:
+		c2s4002(adu, c)
+	case CmdCodeGetParamC2S:
+		c2s4003(adu)
+	case CmdCodeSetParameterC2S:
+		c2s4004(adu)
+	case CmdCodeRegisterC2S:
+		c2s4001(adu, c)
+	case CmdCodeUpdateC2S:
+		//更新固件
+	default:
+		fmt.Println(adu.String())
+	}
+
+}
+
+// c2s4000 请求管理服务器响应
+func c2s4000(adu AppDataUnit, c net.Conn) {
+	unit := AppDataUnit{
+		CmdCode: CmdCodeServerS2C,
+		SubCode: 0,
+		DevId:   adu.DevId,
+		Data:    ipAddress,
+	}
+	unit.Debug()
+	_, err := c.Write(Pack(unit))
+	if err != nil {
+		logrus.Errorf("写入数据错误 %e\n", err)
+	}
+	logrus.Info(adu.DevId, "请求管理服务器成功")
+}
+
+// c2s4001 注册登录响应
+func c2s4001(adu AppDataUnit, c net.Conn) {
+	a := AppDataUnit{
+		CmdCode: CmdCodeRegisterS2C,
+		SubCode: 0,
+		DevId:   adu.DevId,
+	}
+	a.Data = "0"
+	a.Debug()
+	_, err := c.Write(Pack(a))
+	if err != nil {
+		logrus.Errorf("写入数据错误 %e\n", err)
+	}
+	ConnMap[adu.DevId] = c
+	//1. 网关登录后检查是否已经注册到数据库,没有就要保存至数据库
+	gs := service.ServiceGroupApp.AppServiceGroup.GatewayService
+	gw, err := gs.CreateIfNotExist(adu.DevId)
+	if err != nil {
+		if err == appService.ExistError {
+			logrus.Infof("网关[%s]登录成功", adu.DevId)
+		} else {
+			//如果错误不是"已注册",退出
+			logrus.WithField("网关注册失败", adu.DevId).Error(err)
+			return
+		}
+	}
+	//2. 获取网关上摄像头和ip音柱的信息,保存至数据库
+	var cs = service.ServiceGroupApp.AppServiceGroup.CameraService
+	baseUrl := strings.Split(c.RemoteAddr().String(), ":")[0] + ":8848"
+	resp, err := isapi.Com(baseUrl, isapi.GetDeviceInfo, nil)
+	if err != nil {
+		logrus.Error(err)
+		return
+	}
+	var info isapi.DeviceInfo
+	xml.Unmarshal(resp, &info)
+	//创建camera记录并绑定gateway_id
+	err = cs.CreateIfNotExist(info, gw.ID)
+	if err != nil {
+		logrus.WithField("摄像头注册失败", info.SerialNumber).Error(err)
+	}
+	//3.检查摄像头是否配置
+	camera, err := cs.GetCameraByDeviceId(info.SerialNumber)
+	if err != nil {
+		logrus.Error(err)
+		return
+	}
+	//已配置不执行下面
+	if &camera != nil && camera.IsRegisted == 1 {
+		return
+	}
+	//配置摄像头-事件监听服务器
+	setServer(baseUrl)
+	//配置摄像头-sip服务器
+	setSIP(baseUrl, camera.ID, cs)
+}
+
+// c2s4002 心跳响应
+func c2s4002(adu AppDataUnit, c net.Conn) {
+	//todo 心跳处理
+	a := AppDataUnit{
+		CmdCode: CmdCodeHeartbeatS2C,
+		SubCode: 0,
+		DevId:   adu.DevId,
+	}
+	a.Debug()
+	_, err := c.Write(Pack(a))
+	if err != nil {
+		logrus.Errorf("写入数据错误 %e\n", err)
+	}
+}
+
+// c2s4003 查询参数响应
+func c2s4003(adu AppDataUnit) {
+	logrus.Infof("参数响应%s,devId:%s,CmdCode=%X,SubCode=%X\n", adu.Data, adu.DevId, adu.CmdCode, adu.SubCode)
+}
+
+// c2s4004 设置参数响应
+func c2s4004(adu AppDataUnit) {
+	logrus.Infof("配置参数-响应码%s,devId:%s,CmdCode=%X,SubCode=%X\n", adu.Data, adu.DevId, adu.CmdCode, adu.SubCode)
+}
+
+// setServer 设置事件监听服务器
+func setServer(host string) uint {
+	marshal, err := xml.Marshal(global.Config.HttpHostNotificationList)
+	fmt.Println("host:", string(marshal))
+	if err != nil {
+		logrus.Errorf("事件主机配置文件解析错误: %e\n", err)
+		return 0
+	}
+	bytes, err := isapi.Com(host, isapi.SetHosts, marshal)
+	if err != nil {
+		logrus.Error("配置监听主机错误", err)
+	}
+	var resp isapi.ResponseStatus
+	err = xml.Unmarshal(bytes, &resp)
+	if err != nil || (resp.StatusCode != 0 && resp.StatusCode != 1) {
+		logrus.Errorf("配置监听服务器响应 err:%s,StatusCode:%d,StatusString:%s", err.Error(), resp.StatusCode, resp.StatusString)
+		return 0
+	}
+	logrus.Info("配置监听主机响应", string(bytes))
+	return 1
+}
+
+// setSIP 设置sip服务器
+func setSIP(host string, cid uint, cs appService.CameraService) uint {
+	//1. 准备数据
+	var sipstr = `
+<?xml version: "1.0" encoding="utf-8"?><SIPServerList xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
+<SIPServer>
+<id>1</id>
+<localPort>5060</localPort>
+<streamID>1</streamID>
+<Standard>
+<registerStatus>false</registerStatus>
+<enabled>false</enabled>
+<registrar/>
+<registrarPort>5060</registrarPort>
+<proxy/>
+<proxyPort>5060</proxyPort>
+<displayName/>
+<userName/>
+<authID/>
+<password/>
+<expires>0</expires>
+</Standard>
+<GB28181>
+<registerStatus>true</registerStatus>
+<enabled>true</enabled>
+<registrar>106.52.134.22</registrar>
+<registrarPort>5060</registrarPort>
+<serverId>34020000002000000001</serverId>
+<serverDomain>3402000000</serverDomain>
+<userName>34020000002000000%03d</userName>
+<authID>34020000001320000%03d</authID>
+<password>kk176@lc</password>
+<expires>3600</expires>
+<liveTime>1</liveTime>
+<heartbeatTime>15</heartbeatTime>
+<heartbeatCount>3</heartbeatCount>
+<transportType>UDP</transportType>
+<registerInterval>60</registerInterval>
+<protocolVersion>GB/T28181-2016</protocolVersion>
+<platformNo>1</platformNo>
+<localPort>5060</localPort>
+<unidirectionEnabled>false</unidirectionEnabled>
+<voiceBroadcastEnabled>false</voiceBroadcastEnabled>
+</GB28181>
+</SIPServer>
+</SIPServerList>`
+	var sipInfo = `
+<?xml version: "1.0" encoding="UTF-8"?>
+<SIPInfo xmlns="http://www.hikvision.com/ver20/XMLSchema" version="2.0">
+<videoID>34020000001320000001</videoID>
+<AlarmInList>
+</AlarmInList>
+<VideoInputList>
+<VideoInput>
+<id>1</id>
+<videoInputID>34020000001320000001</videoInputID>
+</VideoInput>
+</VideoInputList>
+<AudioOutputList>
+<AudioOutput>
+<id>1</id>
+<audioOutputID/>
+</AudioOutput>
+</AudioOutputList>
+</SIPInfo>`
+	//获取自增ID,以51为起始值
+	id, err := is.GetSipUserID()
+	if err != nil {
+		logrus.Error("事务错误", err)
+	}
+	//2. 配置SIP
+	s := fmt.Sprintf(sipstr, id, id)
+	bytes, err := isapi.Com(host, isapi.SetSIP, []byte(s))
+	if err != nil {
+		logrus.Error("配置SIP错误", err)
+		return 0
+	}
+	var resp isapi.ResponseStatus
+	err = xml.Unmarshal(bytes, &resp)
+	if err != nil {
+		logrus.Errorf("配置SIP服务器err:%s", err.Error())
+		return 0
+	}
+	//失败记录失败原因
+	if resp.StatusCode != 0 && resp.StatusCode != 1 {
+		logrus.Infof("配置SIP服务器响应 StatusCode:%d,StatusString:%s", resp.StatusCode, resp.StatusString)
+		return 0
+	}
+	//3. 配置SIPInfo
+	com, err := isapi.Com(host, isapi.SetSIPInfo, []byte(sipInfo))
+	if err != nil {
+		logrus.Error("配置SIPInfo错误", err)
+		return 0
+	}
+	var resp1 isapi.ResponseStatus
+	err = xml.Unmarshal(com, &resp1)
+	if err != nil {
+		logrus.Errorf("配置配置SIPInfo err:%s", err.Error())
+		return 0
+	}
+	//记录失败原因
+	if resp.StatusCode != 0 && resp.StatusCode != 1 {
+		logrus.Infof("配置SIPInfo-响应 StatusCode:%d,StatusString:%s", resp.StatusCode, resp.StatusString)
+		return 0
+	}
+	//成功保存数据库
+	streamId := fmt.Sprintf("34020000002000000%03d@34020000001320000001", id)
+	streamUrl := global.Config.Hikvision.StreamBaseUrl + streamId
+	var camera = appModel.Camera{
+		StreamId:   streamId,
+		StreamUrl:  streamUrl,
+		IsRegisted: 1,
+	}
+	camera.ID = cid
+	err = cs.UpdateCamera(camera)
+	if err != nil {
+		logrus.Error(err)
+	}
+	return 1
+}

+ 13 - 0
gatewayServer/ending.go

@@ -0,0 +1,13 @@
+package gatewayServer
+
+import "encoding/binary"
+
+func Bin2UInt16(buf []byte, order binary.ByteOrder) uint16 {
+	return order.Uint16(buf)
+}
+
+func Uint16ToBin(i uint16, order binary.ByteOrder) []byte {
+	buf := make([]byte, 2)
+	order.PutUint16(buf, i)
+	return buf
+}

+ 172 - 0
gatewayServer/gatewayProtocol.go

@@ -0,0 +1,172 @@
+package gatewayServer
+
+import (
+	"bytes"
+	"encoding/binary"
+	"encoding/hex"
+	"fmt"
+	"strings"
+)
+
+type CmdCode uint16
+
+/*设备->服务端:命令码0x4xxx开头;
+  服务端->设备:命令码0x8xxx开头;
+*/
+
+const (
+	CmdCodeServerC2S    CmdCode = 0x4000 //获取管理服务器请求
+	CmdCodeServerS2C    CmdCode = 0x8000 //获取管理服务器应答
+	CmdCodeRegisterC2S  CmdCode = 0x4001 //设备注册登录请求
+	CmdCodeRegisterS2C  CmdCode = 0x8001 //设备注册登陆应答
+	CmdCodeHeartbeatC2S CmdCode = 0x4002 //设备心跳请求
+	CmdCodeHeartbeatS2C CmdCode = 0x8002 //设备心跳应答
+	CmdCodeGetParamS2C  CmdCode = 0x8003 //获取设备配置参数请求
+	CmdCodeGetParamC2S  CmdCode = 0x4003 //获取设备配置参数应答
+	CmdCodeUpdateS2C    CmdCode = 0x8101 //开始设备升级请求
+	CmdCodeUpdateC2S    CmdCode = 0x4101 //设备升级应答
+
+	CmdCodeSetParameterS2C CmdCode = 0x8004 //配置设备参数请求
+	CmdCodeSetParameterC2S CmdCode = 0x4004 //配置设备参数应答
+	SubCodeWAN             CmdCode = 0x0001 //WAN口参数配置
+	SubCodeLAN             CmdCode = 0x0002 //LAN口参数配置
+	SubCodeWiFi            CmdCode = 0x0003 //WiFi参数配置
+	SubCodeDetection       CmdCode = 0x0004 //在线探测参数配置
+	SubCodePPTP            CmdCode = 0x1001 //PPTP参数配置
+	SubCodeL2TP            CmdCode = 0x1002 //L2TP参数配置
+	SubCodeSerialPort      CmdCode = 0x2001 //串口应用配置
+	SubCodeFlowRate        CmdCode = 0x2002 //流量统计配置
+	SubCodeInfo            CmdCode = 0x3001 //系统基本信息配置
+	SubCodeTime            CmdCode = 0x3002 //时间设置
+	SubCodeRecover         CmdCode = 0x3003 //恢复出厂设置
+	SubCodeReboot          CmdCode = 0x3004 //重启
+	SubCodePortTrans       CmdCode = 0x5001 //端口转发
+)
+
+type AppDataUnit struct {
+	Start          []byte
+	Length         uint16
+	identification string
+	CmdCode        CmdCode
+	SubCode        CmdCode
+	DevId          string
+	Data           string
+	CheckCode      []byte
+}
+
+func (adu AppDataUnit) String() string {
+	return fmt.Sprintf(`
+    报头标识:%s
+	数据长度:%X
+	包标识:%s
+	命令码:%4X
+	子命令码:%04X
+	设备ID:%s
+	DATA:%s
+	CRC:%X
+    `, adu.Start, adu.Length, adu.identification, adu.CmdCode, adu.SubCode, adu.DevId, adu.Data, adu.CheckCode)
+}
+
+func (adu AppDataUnit) Debug() {
+	if !openDebug {
+		return
+	}
+	if adu.Start == nil {
+		fmt.Println(UnPack(Pack(adu)))
+	} else {
+		fmt.Println(adu)
+	}
+}
+
+func UnPack(data []byte) AppDataUnit {
+	//todo 校验数据
+	var res = AppDataUnit{
+		Start:          data[:2],
+		Length:         Bin2UInt16(data[2:4], binary.BigEndian),
+		identification: hex.EncodeToString(data[4:36]),
+		CmdCode:        CmdCode(Bin2UInt16(data[36:38], binary.BigEndian)),
+		SubCode:        CmdCode(Bin2UInt16(data[38:40], binary.BigEndian)),
+		DevId:          strings.Trim(string(data[40:52]), string(byte(0))),
+		CheckCode:      data[len(data)-2:],
+	}
+	if res.Length-54 > 0 {
+		res.Data = string(data[52 : len(data)-2])
+	} else {
+		res.Data = ""
+	}
+	return res
+}
+
+func Pack(adu AppDataUnit) []byte {
+	//devId不够12位补ascii空值
+	for i := 0; i < 12-len(adu.DevId); i++ {
+		adu.DevId = adu.DevId + string(byte(0))
+	}
+	var buf []byte
+	writer := bytes.NewBuffer(buf)
+	writer.Write([]byte("@@"))                                                                                           //起始
+	writer.Write(Uint16ToBin(uint16(54+len(adu.Data)), binary.BigEndian))                                                //长度
+	writer.Write([]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}) //包标识
+	writer.Write(Uint16ToBin(uint16(adu.CmdCode), binary.BigEndian))                                                     //命令码
+	writer.Write(Uint16ToBin(uint16(adu.SubCode), binary.BigEndian))                                                     //子命令码
+	writer.Write([]byte(adu.DevId))                                                                                      //设备ID
+	writer.Write([]byte(adu.Data))                                                                                       //数据内容
+	writer.Write(CRC16(writer.Bytes(), len(writer.Bytes())))                                                             //校验
+	return writer.Bytes()
+}
+
+func CRC16(data []byte, dataLen int) []byte {
+	var uchCRCHi byte = 0xFF
+	var uchCRCLo byte = 0xFF
+	var uIndex uint16
+
+	for i := 0; i < int(dataLen); i++ {
+		uIndex = uint16(uchCRCLo) ^ uint16(data[i])
+		uchCRCLo = uchCRCHi ^ auchCRCHi[uIndex]
+		uchCRCHi = auchCRCLo[uIndex]
+	}
+	crc := (uint16(uchCRCHi) << 8) | uint16(uchCRCLo)
+	return Uint16ToBin(crc, binary.BigEndian)
+}
+
+var auchCRCHi = []byte{
+	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
+	0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
+	0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
+	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
+	0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
+	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
+	0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
+	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
+	0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+	0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
+	0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+	0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
+	0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
+	0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
+	0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
+	0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
+	0x40,
+}
+
+var auchCRCLo = []byte{
+	0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4,
+	0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
+	0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD,
+	0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
+	0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7,
+	0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
+	0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE,
+	0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
+	0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2,
+	0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
+	0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB,
+	0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
+	0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91,
+	0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
+	0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88,
+	0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
+	0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80,
+	0x40,
+}

+ 76 - 0
gatewayServer/gatewayServer.go

@@ -0,0 +1,76 @@
+package gatewayServer
+
+import (
+	"fmt"
+	"io"
+	"lc-fangdaosha/global"
+	"log"
+	"net"
+	"sync/atomic"
+)
+
+var ipAddress = global.Config.Foreign.GatewayServer
+var ConnMap = make(map[string]net.Conn, 50)
+var openDebug bool = false
+
+func GatewayServe() {
+	listen, err := net.Listen("tcp", ipAddress)
+	if err != nil {
+		log.Fatalln("服务启动失败 ", err)
+	}
+	for {
+		accept, err := listen.Accept()
+		if err != nil {
+			log.Fatalln("获取连接失败 ", err)
+		}
+		go handleConn(accept)
+	}
+}
+
+var n int32
+
+func handleConn(c net.Conn) {
+	defer func() {
+		atomic.AddInt32(&n, -1)
+	}()
+	atomic.AddInt32(&n, 1)
+	fmt.Printf("连接数 %d\n", atomic.LoadInt32(&n))
+	fmt.Printf("当前连接 %s\n", c.RemoteAddr())
+	//var filterChan = make(chan []byte, 32)
+	var dataChan = make(chan []byte, 32)
+	readData := func() {
+		for {
+			var buf = make([]byte, 1024)
+			n, err := c.Read(buf)
+			if err != nil {
+				if err == io.EOF {
+					log.Println("已到达文件结束")
+					break
+				}
+				log.Println("读数据失败", err)
+				break
+			}
+			if n == 0 {
+				log.Println("未读取到数据")
+				break
+			}
+			dataChan <- buf[:n]
+		}
+	}
+	//filterData := func() {
+	//
+	//}
+	handleData := func() {
+		for {
+			v, ok := <-dataChan
+			if !ok {
+				return
+			}
+			adu := UnPack(v)
+			c.RemoteAddr()
+			ParseAndResponse(adu, c)
+		}
+	}
+	go readData()
+	go handleData()
+}

+ 13 - 0
initialize/router.go

@@ -12,6 +12,8 @@ import (
 func Routers() *gin.Engine {
 	Router := gin.Default()
 	systemRouter := router.RouterGroupApp.System
+	isApiRouter := router.RouterGroupApp.IsApi
+	appRouterGroup := router.RouterGroupApp.AppGroup
 	//Router.StaticFS(global.Config.Local.StorePath, http.Dir(global.Config.Local.StorePath))
 
 	//docs.SwaggerInfo.BasePath = global.Config.System.RouterPrefix
@@ -47,6 +49,17 @@ func Routers() *gin.Engine {
 		//systemRouter.InitAuthorityBtnRouterRouter(PrivateGroup)
 		//systemRouter.InitChatGptRouter(PrivateGroup)
 	}
+	//isapi
+	{
+		isApiRouter.InitInfoRouter(PrivateGroup) //isapi
+	}
+	//应用层
+	{
+		appRouterGroup.GatewayRouter.InitGatewayRouter(PrivateGroup) //网关
+		appRouterGroup.CameraRouter.InitCameraRouter(PrivateGroup)   //摄像机
+		appRouterGroup.EventRouter.InitInfoRouter(PrivateGroup)      //事件
+		appRouterGroup.PictureRouter.InitInfoRouter(PrivateGroup)    //图片
+	}
 	logrus.Info("router register success")
 	return Router
 }

+ 279 - 0
isapi/client.go

@@ -0,0 +1,279 @@
+package isapi
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"github.com/sirupsen/logrus"
+	"io/ioutil"
+	"lc-fangdaosha/model/common/response"
+	"net/http"
+	"net/url"
+	"strings"
+)
+
+const (
+	contentTypeXML  = `application/xml; charset="UTF-8"`
+	contentTypeJSON = `application/json; charset="UTF-8"`
+	contentTypeHTML = `text/html`
+)
+
+type Client struct {
+	Client  *http.Client
+	BaseURL string
+}
+
+// NewClient 获取新的连接
+func NewClient(host, username, password string) (*Client, error) {
+	u, err := url.Parse("http://" + host)
+	if err != nil {
+		return nil, err
+	}
+	return &Client{
+		Client: &http.Client{
+			Transport: NewAuthTransport(username, password),
+		},
+		BaseURL: u.String(),
+	}, nil
+}
+
+// TouChuan 透传
+func TouChuan(host string, o Operation, data []byte, c *gin.Context) ([]byte, error) {
+	info, err := Com(host, o, data)
+	if err != nil {
+		return nil, fmt.Errorf("TouChuan错误: %e", err)
+	}
+	if err != nil {
+		response.FailWithMessage(err.Error(), c)
+		logrus.Errorf("%s error: %e", o, err)
+		return nil, err
+	}
+	c.Data(200, `application/xml; charset="UTF-8"`, info)
+	return info, nil
+}
+
+// Com 透传
+func Com(host string, o Operation, data []byte) ([]byte, error) {
+	c, err := NewClient(host, "admin", "kk176@lc")
+	if err != nil {
+		return nil, err
+	}
+	switch o {
+	case GetDeviceInfo:
+		return c.GetDeviceInfo()
+	case GetSystemCap:
+		return c.GetSystemCap()
+	case GetChanCap:
+		return c.GetOneChanEventCap()
+	//越界侦测
+	case GetLineDetectionCap:
+		return c.GetLineDetectionCap()
+	case GetLineDetectionCal:
+		return c.GetSizeLd()
+	case PutLineDetectionCal:
+		return c.PutSizeLd(data)
+	case GetLineDetection:
+		return c.GetLineDetection()
+	case PutLineDetection:
+		return c.PutLineDetection(data)
+	//区域入侵
+	case GetFieldDetectionCap:
+		return c.GetFieldDetectionCap()
+	case GetFieldDetectionCal:
+		return c.GetSizeFd()
+	case PutFieldDetectionCal:
+		return c.PutSizeFd(data)
+	case GetFieldDetection:
+		return c.GetFieldDetection()
+	case PutFieldDetection:
+		return c.PutFieldDetection(data)
+	//进入区域
+	case GetRegionEntranceCap:
+		return c.GetRegionEntranceCap()
+	case GetRegionEntranceCal:
+		return c.GetSizeRe()
+	case PutRegionEntranceCal:
+		return c.PutSizeRe(data)
+	case GetRegionEntrance:
+		return c.GetRegionEntrance()
+	case PutRegionEntrance:
+		return c.PutRegionEntrance(data)
+		//离开区域
+	case SetHosts:
+		return c.PutHost(data)
+	case SetSIP:
+		return c.PutSip(data)
+	case SetSIPInfo:
+		return c.PutSipInfo(data)
+	case PutEmail:
+		return c.PutEmail(data)
+	}
+	return nil, errors.New("未定义操作")
+}
+
+func (c *Client) Do(r *http.Request) ([]byte, error) {
+	resp, err := c.Client.Do(r)
+	if err != nil {
+		return nil, err
+	}
+	defer resp.Body.Close()
+	body, err := ioutil.ReadAll(resp.Body)
+	if err != nil {
+		return nil, err
+	}
+	return body, nil
+}
+
+func (c *Client) CommonGet(path string) (resp []byte, err error) {
+	u, err := url.Parse(c.BaseURL + path)
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.Get(u)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+func (c *Client) CommonPut(data []byte, path string) (resp []byte, err error) {
+	u, err := url.Parse(c.BaseURL + path)
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.PutXML(u, data)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+func (c *Client) CommonDel(data []byte, path string) (resp []byte, err error) {
+	u, err := url.Parse(c.BaseURL + path)
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.DeleteXML(u, data)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+func (c *Client) Get(u *url.URL) ([]byte, error) {
+	req, err := http.NewRequest("GET", u.String(), nil)
+	if err != nil {
+		return nil, err
+	}
+	return c.Do(req)
+}
+
+func (c *Client) put(u *url.URL, contentType string, data []byte) ([]byte, error) {
+	b := bytes.NewBuffer(data)
+	req, err := http.NewRequest("PUT", u.String(), b)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", contentType)
+	return c.Do(req)
+}
+
+func (c *Client) PutXML(u *url.URL, data []byte) ([]byte, error) {
+	return c.put(u, contentTypeXML, data)
+}
+
+func (c *Client) PutJSON(u *url.URL, data []byte) ([]byte, error) {
+	return c.put(u, contentTypeJSON, data)
+}
+
+func (c *Client) post(u *url.URL, contentType string, data []byte) ([]byte, error) {
+	b := bytes.NewBuffer(data)
+	req, err := http.NewRequest("POST", u.String(), b)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", contentType)
+	return c.Do(req)
+}
+
+func (c *Client) PostXML(u *url.URL, data []byte) ([]byte, error) {
+	return c.post(u, contentTypeXML, data)
+}
+
+func (c *Client) PostJSON(u *url.URL, data []byte) ([]byte, error) {
+	return c.post(u, contentTypeJSON, data)
+}
+
+func (c *Client) delete(u *url.URL, contentType string, data []byte) ([]byte, error) {
+	b := bytes.NewBuffer(data)
+	req, err := http.NewRequest("DELETE", u.String(), b)
+	if err != nil {
+		return nil, err
+	}
+	req.Header.Set("Content-Type", contentType)
+	return c.Do(req)
+}
+
+func (c *Client) DeleteXML(u *url.URL, data []byte) ([]byte, error) {
+	return c.delete(u, contentTypeXML, data)
+}
+
+func (c *Client) DeleteJSON(u *url.URL, data []byte) ([]byte, error) {
+	return c.delete(u, contentTypeJSON, data)
+}
+
+func DoModFacePicRecord(url, json, faceimage, boundary string) {
+	var bodyParam = "--" + boundary + "\r\n" +
+		"Content-Disposition: form-data; name=\"FaceDataRecord\";\r\n" +
+		"Content-Type: text/json\r\n" +
+		"Content-Length: " + fmt.Sprintf("%d", len(json)) + "\r\n\r\n" +
+		json + "\r\n" +
+		"--" + boundary + "\r\n" +
+		"Content-Disposition: form-data; name=\"FaceImage\";\r\n" +
+		"Content-Type: image/jpeg\r\n" +
+		"Content-Length: " + fmt.Sprintf("%d", len(faceimage)) + "\r\n\r\n" +
+		faceimage +
+		"\r\n--" + boundary + "--\r\n"
+	req, err := http.NewRequest("PUT", url, strings.NewReader(bodyParam))
+	if err != nil {
+		logrus.Error(err)
+	}
+	req.SetBasicAuth("", "")
+
+	req.Header.Add("Accept", "text/html, application/xhtml+xml")
+	req.Header.Add("Accept-Language", "zh-CN")
+	req.Header.Add("Content-Type", "multipart/form-data; boundary="+boundary)
+	req.Header.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)")
+	req.Header.Add("Accept-Encoding", "gzip, deflate")
+	req.Header.Add("Connection", "Keep-Alive")
+	req.Header.Add("Cache-Control", "no-cache")
+
+}
+
+func DoPostStorageCloud(url, json, faceimage, boundary string) {
+	var bodyParam = "--" + boundary + "\r\n" +
+		"Content-Disposition: form-data; name=\"FaceDataRecord\";\r\n" +
+		"Content-Type: text/json\r\n" +
+		"Content-Length: " + fmt.Sprintf("%d", len(json)) + "\r\n\r\n" +
+		json + "\r\n" +
+		"--" + boundary + "\r\n" +
+		"Content-Disposition: form-data; name=\"FaceImage\";\r\n" +
+		"Content-Type: image/jpeg\r\n" +
+		"Content-Length: " + fmt.Sprintf("%d", len(faceimage)) + "\r\n\r\n" +
+		faceimage +
+		"\r\n--" + boundary + "--\r\n"
+	req, err := http.NewRequest("POST", url, strings.NewReader(bodyParam))
+	if err != nil {
+		logrus.Error(err)
+	}
+	req.SetBasicAuth("", "")
+
+	req.Header.Add("Accept", "text/html, application/xhtml+xml")
+	req.Header.Add("Accept-Language", "zh-CN")
+	req.Header.Add("Content-Type", "multipart/form-data; boundary="+boundary)
+	req.Header.Add("User-Agent", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)")
+	req.Header.Add("Accept-Encoding", "gzip, deflate")
+	req.Header.Add("Connection", "Keep-Alive")
+	req.Header.Add("Cache-Control", "no-cache")
+}

+ 88 - 0
isapi/digest.go

@@ -0,0 +1,88 @@
+package isapi
+
+import (
+	"crypto/md5"
+	"encoding/json"
+	"fmt"
+	"log"
+	"strings"
+)
+
+// Challenge WWW-Authorization头部的值
+type Challenge struct {
+	Realm     string
+	Domain    string
+	Nonce     string
+	Opaque    string
+	Stale     string
+	Algorithm string
+	Qop       string
+}
+
+// Response 作为Authorization头部的值
+type Response struct {
+	Username string
+	Realm    string
+	Nonce    string
+	URI      string
+	Qop      string
+	Cnonce   string
+	Nc       string
+	Response string
+}
+
+func MD5(s string) string {
+	return fmt.Sprintf("%x", md5.Sum([]byte(s)))
+}
+
+// NewChallenge 根据WWW-Authorization的值生成Challenge
+func NewChallenge(header string) *Challenge {
+	var m = make(map[string]string, 5)
+	str := header[7:]
+	split := strings.Split(str, ",")
+	for _, v := range split {
+		s := strings.Split(v, "=")
+		k := strings.Trim(s[0], " ")
+		m[k] = strings.Trim(s[1], "\"")
+	}
+
+	// Marshall digest
+	b, err := json.Marshal(m)
+	if err != nil {
+		log.Fatalln("Error:", err)
+	}
+
+	// Unmarshall into struct
+	challenge := Challenge{}
+	if err := json.Unmarshal(b, &challenge); err != nil {
+		log.Fatalln("Error:", err)
+	}
+	return &challenge
+}
+
+// Authorize 生成 Response  #客户端需要对服务端认证时cnonce应是变化的#
+func (c *Challenge) Authorize(username, password, method, uri string) *Response {
+	// MD5(<username>:<realm>:<password>)
+	a1 := MD5(fmt.Sprintf("%s:%s:%s", username, c.Realm, password))
+
+	// MD5(<request-method>:<uri>)
+	a2 := MD5(fmt.Sprintf("%s:%s", method, uri))
+
+	// MD5(MD5(A1):<auth>:<nc>:<cnonce>:<qop>:MD5(A2))
+	response := MD5(fmt.Sprintf("%s:%s:%s:%s:%s:%s", a1, c.Nonce, "00000001", "0a4f113b", c.Qop, a2))
+	return &Response{
+		Username: username,
+		Realm:    c.Realm,
+		Nonce:    c.Nonce,
+		URI:      uri,
+		Qop:      c.Qop,
+		Cnonce:   "0a4f113b",
+		Nc:       "00000001",
+		Response: response,
+	}
+}
+
+// 生成字符串作为Authorization的值
+func (r *Response) String() string {
+	return fmt.Sprintf(`Digest username="%s", realm="%s", nonce="%s", uri="%s", qop=%s, nc=%s, cnonce="%s", response="%s"`, r.Username, r.Realm, r.Nonce, r.URI, r.Qop, r.Nc, r.Cnonce, r.Response)
+}

+ 52 - 0
isapi/http.go

@@ -0,0 +1,52 @@
+package isapi
+
+import (
+	"bytes"
+	"io/ioutil"
+	"net/http"
+)
+
+// AuthTransport 实现接口http.RoundTripper,自定义RoundTripper处理认证
+type AuthTransport struct {
+	Username  string
+	Password  string
+	Transport http.RoundTripper
+}
+
+func NewAuthTransport(username, password string) *AuthTransport {
+	t := &AuthTransport{
+		Username: username,
+		Password: password,
+	}
+	t.Transport = http.DefaultTransport
+	return t
+}
+
+func (t *AuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
+	req2 := new(http.Request)
+	*req2 = *req
+	//复制header
+	req2.Header = make(http.Header)
+	for k, s := range req.Header {
+		req2.Header[k] = s
+	}
+	// 复制body
+	if req.Body != nil {
+		buf, _ := ioutil.ReadAll(req.Body)
+		req.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
+		req2.Body = ioutil.NopCloser(bytes.NewBuffer(buf))
+	}
+	//
+	resp, err := t.Transport.RoundTrip(req)
+	if err != nil || resp.StatusCode != 401 {
+		return resp, err
+	}
+	//↓未认证逻辑-----------
+	authChal := resp.Header.Get("WWW-Authenticate")
+	c := NewChallenge(authChal)
+	authResp := c.Authorize(t.Username, t.Password, req.Method, req.URL.Path)
+	resp.Body.Close()
+	//todo nonce并未重用,可以优化
+	req2.Header.Set("Authorization", authResp.String())
+	return t.Transport.RoundTrip(req2)
+}

+ 1 - 0
isapi/isapi_common.go

@@ -0,0 +1 @@
+package isapi

+ 32 - 0
isapi/isapi_event_channelCap.go

@@ -0,0 +1,32 @@
+package isapi
+
+import (
+	"encoding/xml"
+)
+
+type ChannelEventCapList struct {
+	XMLName         xml.Name          `xml:"ChannelEventCapList"`
+	Text            string            `xml:",chardata"`
+	Version         string            `xml:"version,attr"`
+	Xmlns           string            `xml:"xmlns,attr"`
+	ChannelEventCap []ChannelEventCap `xml:"ChannelEventCap"`
+}
+
+type ChannelEventCap struct {
+	Text      string `xml:",chardata"`
+	EventType struct {
+		Text string `xml:",chardata"`
+		Opt  string `xml:"opt,attr"`
+	} `xml:"eventType"`
+	ChannelID string `xml:"channelID"`
+	ID        string `xml:"id"`
+}
+
+func (c *Client) GetAllChanEventCap() ([]byte, error) {
+
+	return c.CommonGet("/ISAPI/Event/channels/capabilities")
+}
+
+func (c *Client) GetOneChanEventCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Event/channels/1/capabilities")
+}

+ 33 - 0
isapi/isapi_event_httphost.go

@@ -0,0 +1,33 @@
+package isapi
+
+type eventType string
+
+const (
+	shelterAlarm   eventType = "shelteralarm"   //遮盖报警
+	fieldAlarm     eventType = "fielddetection" //区域入侵
+	lineAlarm      eventType = "linedetection"  //越界侦测
+	regionEntrance eventType = "regionEntrance" //进入区域侦测
+	regionExiting  eventType = "regionExiting"  //离开区域侦测
+)
+
+//todo 边缘端启动时配置一次, 提供主动配置配置接口
+
+// GetHostCap 获取监听主机参数能力
+func (c *Client) GetHostCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Event/notification/httpHosts/capabilities")
+}
+
+// PutHost 配置单个监听主机参数
+func (c *Client) PutHost(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Event/notification/httpHosts")
+}
+
+// DelHost 删除单个监听主机参数
+func (c *Client) DelHost() ([]byte, error) {
+	return c.CommonDel(nil, "/ISAPI/Event/notification/httpHosts/1")
+}
+
+// GetHost 获取单个监听主机参数
+func (c *Client) GetHost() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Event/notification/httpHosts/1")
+}

+ 102 - 0
isapi/isapi_event_notification.go

@@ -0,0 +1,102 @@
+package isapi
+
+import (
+	"encoding/xml"
+	"net/url"
+)
+
+type HttpHostNotification struct {
+	ID                       string `xml:"id"`
+	URL                      string `xml:"url"`
+	ProtocolType             string `xml:"protocolType"`
+	ParameterFormatType      string `xml:"parameterFormatType"`
+	AddressingFormatType     string `xml:"addressingFormatType"`
+	IpAddress                string `xml:"ipAddress"`
+	PortNo                   string `xml:"portNo"`
+	UserName                 string `xml:"userName"`
+	HttpAuthenticationMethod string `xml:"httpAuthenticationMethod"`
+	HttpBroken               string `xml:"httpBroken"`
+}
+
+// GetOneHost 获取单个监听主机参数
+func (c *Client) GetOneHost(hostID string) (resp []byte, err error) {
+	u, err := url.Parse("/ISAPI/Event/notification/httpHosts/" + hostID + "?security=1&iv=1")
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.Get(u)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+// PutOneHost 配置单个监听主机参数
+func (c *Client) PutOneHost(hostID string, data []byte) (resp []byte, err error) {
+	u, err := url.Parse("/ISAPI/Event/notification/httpHosts/" + hostID + "?security=1&iv=1")
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.PutXML(u, data)
+	return resp, err
+}
+
+// HttpHostNotificationCap 获取监听主机参数能力
+type HttpHostNotificationCap struct {
+	HostNumber string `xml:"hostNumber"`
+	UrlLen     struct {
+		Min string `xml:"min,attr"`
+		Max string `xml:"max,attr"`
+	} `xml:"urlLen"`
+	ProtocolType struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"protocolType"`
+	ParameterFormatType struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"parameterFormatType"`
+	AddressingFormatType struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"addressingFormatType"`
+	IpAddress struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"ipAddress"`
+	PortNo struct {
+		Min string `xml:"min,attr"`
+		Max string `xml:"max,attr"`
+	} `xml:"portNo"`
+	UserNameLen struct {
+		Min string `xml:"min,attr"`
+		Max string `xml:"max,attr"`
+	} `xml:"userNameLen"`
+	PasswordLen struct {
+		Min string `xml:"min,attr"`
+		Max string `xml:"max,attr"`
+	} `xml:"passwordLen"`
+	HttpAuthenticationMethod struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"httpAuthenticationMethod"`
+	UploadImagesDataType struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"uploadImagesDataType"`
+	HttpBroken struct {
+		Opt string `xml:"opt,attr"`
+		Def string `xml:"def,attr"`
+	} `xml:"httpBroken"`
+}
+
+// GetParamHost 获取监听主机参数能力
+func (c *Client) GetParamHost() (resp *HttpHostNotification, err error) {
+	u, err := url.Parse("/ISAPI/Event/notification/httpHosts/capabilities")
+	if err != nil {
+		return nil, err
+	}
+	get, err := c.Get(u)
+	if err != nil {
+		return nil, err
+	}
+	err = xml.Unmarshal(get, &resp)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}

+ 33 - 0
isapi/isapi_event_schedule.go

@@ -0,0 +1,33 @@
+package isapi
+
+// Schedule 获取指定通道视频遮盖单个通道布防时间
+type Schedule struct {
+	ID                  string `xml:"id"`
+	EventType           string `xml:"eventType"`
+	VideoInputChannelID string `xml:"videoInputChannelID"`
+	TimeBlockList       []struct {
+		TimeBlock struct {
+			DayOfWeek string `xml:"dayOfWeek"`
+			TimeRange struct {
+				BeginTime string `xml:"beginTime"`
+				EndTime   string `xml:"endTime"`
+			} `xml:"TimeRange"`
+		} `xml:"TimeBlock"`
+	} `xml:"TimeBlockList"`
+	HolidayBlockList []struct {
+		TimeBlock struct {
+			TimeRange struct {
+				BeginTime string `xml:"beginTime"`
+				EndTime   string `xml:"endTime"`
+			} `xml:"TimeRange"`
+		} `xml:"TimeBlock"`
+	} `xml:"HolidayBlockList"`
+}
+
+func (c *Client) GetSchedule() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Event/schedules/tamperDetections/tamperdetection_video1")
+}
+
+func (c *Client) PutSchedule(data []byte) (resp []byte, err error) {
+	return c.CommonPut(data, "/ISAPI/Event/schedules/tamperDetections/tamperdetection_video1")
+}

+ 58 - 0
isapi/isapi_event_tamperDetection.go

@@ -0,0 +1,58 @@
+package isapi
+
+import (
+	"net/url"
+)
+
+type RegionCoordinates struct {
+	PositionX string `xml:"positionX"`
+	PositionY string `xml:"positionY"`
+}
+
+// TamperDetectionRegionList 配置指定通道视频遮盖所有区域参数
+type TamperDetectionRegionList struct {
+	TamperDetectionRegion []struct {
+		ID                    string `xml:"id"`
+		Enabled               bool   `xml:"enabled"`
+		SensitivityLevel      int    `xml:"sensitivityLevel"`
+		RegionCoordinatesList struct {
+			RegionCoordinates []RegionCoordinates `xml:"RegionCoordinates"`
+		} `xml:"RegionCoordinatesList"`
+	} `xml:"TamperDetectionRegion"`
+}
+
+// TamperDetection 获取指定通道视频遮盖参数
+type TamperDetection struct {
+	Enabled              string `xml:"enabled"`
+	NormalizedScreenSize struct {
+		NormalizedScreenWidth  string `xml:"normalizedScreenWidth"`
+		NormalizedScreenHeight string `xml:"normalizedScreenHeight"`
+	} `xml:"normalizedScreenSize"`
+	TampersensitivityLevel    string `xml:"tampersensitivityLevel"`
+	TamperDetectionRegionList TamperDetectionRegionList
+}
+
+// GetTamperDetection 获取指定通道视频遮盖参数
+func (c *Client) GetTamperDetection() ([]byte, error) {
+	return c.CommonGet("/ISAPI/System/Video/inputs/channels/1/tamperDetection")
+}
+
+// PutTamperDetection 配置指定通道视频遮盖参数
+func (c *Client) PutTamperDetection(data []byte) (resp []byte, err error) {
+	return c.CommonPut(data, "/ISAPI/System/Video/inputs/channels/1/tamperDetection")
+}
+
+// DelTamperDetection 清除指定通道视频遮盖参数
+func (c *Client) DelTamperDetection() (resp []byte, err error) {
+	u, err := url.Parse(c.BaseURL + "/ISAPI/System/Video/inputs/channels1/tamperDetection/regions")
+	if err != nil {
+		return nil, err
+	}
+	var data = TamperDetection{}
+	data.TamperDetectionRegionList.TamperDetectionRegion = nil
+	resp, err = c.DeleteXML(u, nil)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}

+ 26 - 0
isapi/isapi_smart_calibration.go

@@ -0,0 +1,26 @@
+package isapi
+
+// SmartCalibrationList 配置最大、最小尺寸
+type SmartCalibrationList struct {
+	SmartCalibration []struct {
+		ID         string `xml:"ID"`
+		FilterSize struct {
+			MinTargetSize struct {
+				RegionCoordinatesList struct {
+					RegionCoordinates []struct {
+						PositionX string `xml:"positionX"`
+						PositionY string `xml:"positionY"`
+					} `xml:"RegionCoordinates"`
+				} `xml:"RegionCoordinatesList"`
+			} `xml:"MinTargetSize"`
+			MaxTargetSize struct {
+				RegionCoordinatesList struct {
+					RegionCoordinates []struct {
+						PositionX string `xml:"positionX"`
+						PositionY string `xml:"positionY"`
+					} `xml:"RegionCoordinates"`
+				} `xml:"RegionCoordinatesList"`
+			} `xml:"MaxTargetSize"`
+		} `xml:"FilterSize"`
+	} `xml:"SmartCalibration"`
+}

+ 68 - 0
isapi/isapi_smart_fieldDetection.go

@@ -0,0 +1,68 @@
+package isapi
+
+import (
+	"encoding/xml"
+)
+
+//能力
+//http://192.168.110.165/ISAPI/Smart/FieldDetection/1/capabilities
+//http://192.168.110.165/ISAPI/Smart/channels/1/calibrations/capabilities
+
+// FieldDetection 区域入侵
+type FieldDetection struct {
+	XMLName              xml.Name `xml:"FieldDetection"`
+	Xmlns                string   `xml:"xmlns,attr"`
+	Version              string   `xml:"version,attr"`
+	ID                   string   `xml:"id"`
+	Enabled              string   `xml:"enabled"`
+	StartTriggerTime     string   `xml:"startTriggerTime"`
+	EndTriggerTime       string   `xml:"endTriggerTime"`
+	NormalizedScreenSize struct {
+		NormalizedScreenWidth  string `xml:"normalizedScreenWidth"`
+		NormalizedScreenHeight string `xml:"normalizedScreenHeight"`
+	} `xml:"normalizedScreenSize"`
+	FieldDetectionRegionList struct {
+		Size                 string `xml:"size,attr"`
+		FieldDetectionRegion []struct {
+			ID               string `xml:"id"`
+			Enabled          string `xml:"enabled"`
+			SensitivityLevel string `xml:"sensitivityLevel"`
+			TimeThreshold    string `xml:"timeThreshold"`
+			DetectionTarget  string `xml:"detectionTarget"`
+			AlarmConfidence  struct {
+				Opt string `xml:"opt,attr"`
+			} `xml:"alarmConfidence"`
+			RegionCoordinatesList struct {
+				RegionCoordinates []struct {
+					PositionX string `xml:"positionX"`
+					PositionY string `xml:"positionY"`
+				} `xml:"RegionCoordinates"`
+			} `xml:"RegionCoordinatesList"`
+		} `xml:"FieldDetectionRegion"`
+	} `xml:"FieldDetectionRegionList"`
+	IsSupportMultiScene           string `xml:"isSupportMultiScene"`
+	IsSupportHumanMisinfoFilter   string `xml:"isSupportHumanMisinfoFilter"`
+	IsSupportVehicleMisinfoFilter string `xml:"isSupportVehicleMisinfoFilter"`
+}
+
+func (c *Client) GetFieldDetectionCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/FieldDetection/1/capabilities")
+}
+
+func (c *Client) GetSizeFd() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/channels/1/calibrations/FieldDetection")
+}
+
+func (c *Client) PutSizeFd(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/channels/1/calibrations/FieldDetection")
+}
+
+// PutFieldDetection 设置区域入侵报警区域
+func (c *Client) PutFieldDetection(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/FieldDetection/1")
+}
+
+// GetFieldDetection 获取报警区域
+func (c *Client) GetFieldDetection() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/FieldDetection/1")
+}

+ 59 - 0
isapi/isapi_smart_lineDetection.go

@@ -0,0 +1,59 @@
+package isapi
+
+//能力
+//http://192.168.110.165/ISAPI/Smart/LineDetection/1/capabilities
+//http://192.168.110.165/ISAPI/Smart/channels/1/calibrations/capabilities
+
+// LineDetection 越界侦测
+type LineDetection struct {
+	ID                   string `xml:"id"`
+	Enabled              string `xml:"enabled"`
+	NormalizedScreenSize struct {
+		NormalizedScreenWidth  string `xml:"normalizedScreenWidth"`
+		NormalizedScreenHeight string `xml:"normalizedScreenHeight"`
+	} `xml:"normalizedScreenSize"`
+	LineItemList struct {
+		Size     string `xml:"size,attr"`
+		LineItem []struct {
+			ID                   string `xml:"id"`
+			Enabled              string `xml:"enabled"`
+			SensitivityLevel     string `xml:"sensitivityLevel"`
+			DirectionSensitivity string `xml:"directionSensitivity"`
+			DetectionTarget      string `xml:"detectionTarget"`
+			AlarmConfidence      struct {
+				Text string `xml:",chardata"`
+				Opt  string `xml:"opt,attr"`
+			} `xml:"alarmConfidence"`
+			CoordinatesList struct {
+				Coordinates []struct {
+					PositionX string `xml:"positionX"`
+					PositionY string `xml:"positionY"`
+				} `xml:"Coordinates"`
+			} `xml:"CoordinatesList"`
+		} `xml:"LineItem"`
+	} `xml:"LineItemList"`
+	IsSupportMultiScene string `xml:"isSupportMultiScene"`
+	RecogRuleType       string `xml:"recogRuleType"`
+}
+
+func (c *Client) GetLineDetectionCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/LineDetection/1/capabilities")
+}
+
+func (c *Client) GetSizeLd() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/channels/1/calibrations/linedetection")
+}
+
+func (c *Client) PutSizeLd(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/channels/1/calibrations/linedetection")
+}
+
+// GetLineDetection 获取单个通道越界侦测规则
+func (c *Client) GetLineDetection() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/LineDetection/1")
+}
+
+// PutLineDetection 配置单个通道越界侦测规则
+func (c *Client) PutLineDetection(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/LineDetection/1")
+}

+ 53 - 0
isapi/isapi_smart_regionEntrance.go

@@ -0,0 +1,53 @@
+package isapi
+
+// RegionEntrance 进入区域
+type RegionEntrance struct {
+	ID                   string `xml:"id"`
+	Enabled              string `xml:"enabled"`
+	NormalizedScreenSize struct {
+		NormalizedScreenWidth  string `xml:"normalizedScreenWidth"`
+		NormalizedScreenHeight string `xml:"normalizedScreenHeight"`
+	} `xml:"normalizedScreenSize"`
+	RegionEntranceRegionList struct {
+		Size                 string `xml:"size,attr"`
+		RegionEntranceRegion []struct {
+			ID               string `xml:"id"`
+			SensitivityLevel string `xml:"sensitivityLevel"`
+			DetectionTarget  string `xml:"detectionTarget"`
+			AlarmConfidence  struct {
+				Text string `xml:",chardata"`
+				Opt  string `xml:"opt,attr"`
+			} `xml:"alarmConfidence"`
+			RegionCoordinatesList struct {
+				Text  string `xml:",chardata"`
+				Xmlns string `xml:"xmlns,attr"`
+			} `xml:"RegionCoordinatesList"`
+		} `xml:"RegionEntranceRegion"`
+	} `xml:"RegionEntranceRegionList"`
+	IsSupportMultiScene           string `xml:"isSupportMultiScene"`
+	IsSupportHumanMisinfoFilter   string `xml:"isSupportHumanMisinfoFilter"`
+	IsSupportVehicleMisinfoFilter string `xml:"isSupportVehicleMisinfoFilter"`
+	IsSupportTargetMultiSelect    string `xml:"isSupportTargetMultiSelect"`
+}
+
+func (c *Client) GetRegionEntranceCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/regionEntrance/1/capabilities")
+}
+
+func (c *Client) GetSizeRe() (resp []byte, err error) {
+	return c.CommonGet("/ISAPI/Smart/channels/1/calibrations/regionEntrance")
+}
+
+func (c *Client) PutSizeRe(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/channels/1/calibrations/regionEntrance")
+}
+
+// GetRegionEntrance 获取区域侦测参数
+func (c *Client) GetRegionEntrance() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/regionEntrance/1")
+}
+
+// PutRegionEntrance 配置区域侦测参数
+func (c *Client) PutRegionEntrance(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/regionEntrance/1")
+}

+ 33 - 0
isapi/isapi_smart_regionExiting.go

@@ -0,0 +1,33 @@
+package isapi
+
+type RegionExiting struct {
+	ID                   string `xml:"id"`
+	Enabled              string `xml:"enabled"`
+	NormalizedScreenSize struct {
+		NormalizedScreenWidth  string `xml:"normalizedScreenWidth"`
+		NormalizedScreenHeight string `xml:"normalizedScreenHeight"`
+	} `xml:"normalizedScreenSize"`
+	RegionExitingRegionList struct {
+		Size                string `xml:"size,attr"`
+		RegionExitingRegion []struct {
+			ID                    string `xml:"id"`
+			SensitivityLevel      string `xml:"sensitivityLevel"`
+			RegionCoordinatesList string `xml:"RegionCoordinatesList"`
+			DetectionTarget       string `xml:"detectionTarget"`
+			AlarmConfidence       struct {
+				Opt string `xml:"opt,attr"`
+			} `xml:"alarmConfidence"`
+		} `xml:"RegionExitingRegion"`
+	} `xml:"RegionExitingRegionList"`
+	IsSupportMultiScene           string `xml:"isSupportMultiScene"`
+	IsSupportHumanMisinfoFilter   string `xml:"isSupportHumanMisinfoFilter"`
+	IsSupportVehicleMisinfoFilter string `xml:"isSupportVehicleMisinfoFilter"`
+	IsSupportTargetMultiSelect    string `xml:"isSupportTargetMultiSelect"`
+}
+
+func (c *Client) GetRegionExiting() ([]byte, error) {
+	return c.CommonGet("/ISAPI/Smart/regionExiting/1")
+}
+func (c *Client) PutRegionExiting(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/Smart/regionExiting/1")
+}

+ 328 - 0
isapi/isapi_system_deviceCap.go

@@ -0,0 +1,328 @@
+package isapi
+
+import (
+	"encoding/xml"
+)
+
+// DeviceCap 获取系统能力
+type DeviceCap struct {
+	XMLName xml.Name `xml:"DeviceCap"`
+	Text    string   `xml:",chardata"`
+	Version string   `xml:"version,attr"`
+	Xmlns   string   `xml:"xmlns,attr"`
+	SysCap  struct {
+		IsSupportDst string `xml:"isSupportDst"`
+		NetworkCap   struct {
+			IsSupportWireless string `xml:"isSupportWireless"`
+			IsSupportPPPoE    string `xml:"isSupportPPPoE"`
+			IsSupportBond     string `xml:"isSupportBond"`
+			IsSupport8021x    string `xml:"isSupport802_1x"`
+			IsSupportNtp      string `xml:"isSupportNtp"`
+			IsSupportFtp      string `xml:"isSupportFtp"`
+			IsSupportUpnp     string `xml:"isSupportUpnp"`
+			IsSupportDdns     string `xml:"isSupportDdns"`
+			IsSupportHttps    string `xml:"isSupportHttps"`
+			SnmpCap           struct {
+				IsSupport string `xml:"isSupport"`
+			} `xml:"SnmpCap"`
+			IsSupportExtNetCfg                string `xml:"isSupportExtNetCfg"`
+			IsSupportIPFilter                 string `xml:"isSupportIPFilter"`
+			IsSupportEZVIZ                    string `xml:"isSupportEZVIZ"`
+			IsSupportEhome                    string `xml:"isSupportEhome"`
+			IsSupportWirelessDial             string `xml:"isSupportWirelessDial"`
+			IsSupportWirelessServer           string `xml:"isSupportWirelessServer"`
+			IsSupportWPS                      string `xml:"isSupportWPS"`
+			IsWirelessMutexWithWirelessServer string `xml:"isWirelessMutexWithWirelessServer"`
+			IsSupportMACFilter                string `xml:"isSupportMACFilter"`
+			IsSupportRFIDData                 string `xml:"isSupportRFIDData"`
+			IsSupportwifiProbeSSID            string `xml:"isSupportwifiProbeSSID"`
+			IsSupportWifiProbe                string `xml:"isSupportWifiProbe"`
+			VerificationCode                  struct {
+				Min string `xml:"min,attr"`
+				Max string `xml:"max,attr"`
+			} `xml:"verificationCode"`
+			VerificationCodeModification struct {
+				VerificationCodeType struct {
+					Opt string `xml:"opt,attr"`
+				} `xml:"verificationCodeType"`
+				IsSupportDeclarationURL   string `xml:"isSupportDeclarationURL"`
+				IsSupportPrivacyPolicyURL string `xml:"isSupportPrivacyPolicyURL"`
+				VerificationCodeModify    struct {
+					Opt string `xml:"opt,attr"`
+				} `xml:"verificationCodeModify"`
+			} `xml:"VerificationCodeModification"`
+			IsSupportIntegrate       string `xml:"isSupportIntegrate"`
+			IsSupportPlatformAccess  string `xml:"isSupportPlatformAccess"`
+			IsSupportGetLinkSocketIP string `xml:"isSupportGetLinkSocketIP"`
+			IsSupportWebSocket       string `xml:"isSupportWebSocket"`
+			IsSupportWebSocketS      string `xml:"isSupportWebSocketS"`
+			IsSupportVideoImgDB      string `xml:"isSupportVideoImgDB"`
+			IsSupportDynamicHostName string `xml:"isSupportDynamicHostName"`
+			IsSupportEmailEncrypt    string `xml:"isSupportEmailEncrypt"`
+			IsSupportEZVIZUnbind     string `xml:"isSupportEZVIZUnbind"`
+		} `xml:"NetworkCap"`
+		IOCap struct {
+			IsSupportStrobeLamp string `xml:"isSupportStrobeLamp"`
+		} `xml:"IOCap"`
+		SerialCap struct {
+			Rs485PortNums      string `xml:"rs485PortNums"`
+			SupportRS232Config string `xml:"supportRS232Config"`
+			Rs422PortNums      string `xml:"rs422PortNums"`
+			Rs232PortNums      string `xml:"rs232PortNums"`
+		} `xml:"SerialCap"`
+		VideoCap struct {
+			VideoInputPortNums              string `xml:"videoInputPortNums"`
+			VideoOutputPortNums             string `xml:"videoOutputPortNums"`
+			IsSupportHeatmap                string `xml:"isSupportHeatmap"`
+			IsSupportCounting               string `xml:"isSupportCounting"`
+			IsSupportPicture                string `xml:"isSupportPicture"`
+			IsSupportPrivacyMask            string `xml:"isSupportPrivacyMask"`
+			IsSupportBinocularPreviewSwitch string `xml:"isSupportBinocularPreviewSwitch"`
+			IsSupportCalibCheck             string `xml:"isSupportCalibCheck"`
+			IsSupportPIP                    string `xml:"isSupportPIP"`
+			IsSupportVideoOutputMode        string `xml:"isSupportVideoOutputMode"`
+		} `xml:"VideoCap"`
+		AudioCap struct {
+			AudioInputNums  string `xml:"audioInputNums"`
+			AudioOutputNums string `xml:"audioOutputNums"`
+		} `xml:"AudioCap"`
+		IsSupportExternalDevice string `xml:"isSupportExternalDevice"`
+		IsSupportSubscribeEvent string `xml:"isSupportSubscribeEvent"`
+		IsSupportDiagnosedData  string `xml:"isSupportDiagnosedData"`
+		IsSupportMetadata       string `xml:"isSupportMetadata"`
+	} `xml:"SysCap"`
+	VoicetalkNums     string `xml:"voicetalkNums"`
+	IsSupportSnapshot string `xml:"isSupportSnapshot"`
+	SecurityCap       struct {
+		SupportUserNums           string `xml:"supportUserNums"`
+		UserBondIpNums            string `xml:"userBondIpNums"`
+		UserBondMacNums           string `xml:"userBondMacNums"`
+		IsSupCertificate          string `xml:"isSupCertificate"`
+		IssupIllegalLoginLock     string `xml:"issupIllegalLoginLock"`
+		IsSupportOnlineUser       string `xml:"isSupportOnlineUser"`
+		IsSupportAnonymous        string `xml:"isSupportAnonymous"`
+		IsSupportStreamEncryption string `xml:"isSupportStreamEncryption"`
+		SecurityVersion           struct {
+			Opt string `xml:"opt,attr"`
+		} `xml:"securityVersion"`
+		KeyIterateNum                   string `xml:"keyIterateNum"`
+		IsSupportUserCheck              string `xml:"isSupportUserCheck"`
+		IsSupportSecurityQuestionConfig string `xml:"isSupportSecurityQuestionConfig"`
+		SupportSecurityNode             struct {
+			Opt string `xml:"opt,attr"`
+		} `xml:"supportSecurityNode"`
+		SecurityLimits struct {
+			LoginPasswordLenLimit struct {
+				Min string `xml:"min,attr"`
+				Max string `xml:"max,attr"`
+			} `xml:"LoginPasswordLenLimit"`
+			SecurityAnswerLenLimit struct {
+				Min string `xml:"min,attr"`
+				Max string `xml:"max,attr"`
+			} `xml:"SecurityAnswerLenLimit"`
+		} `xml:"SecurityLimits"`
+		RSAKeyLength struct {
+			Opt string `xml:"opt,attr"`
+			Def string `xml:"def,attr"`
+		} `xml:"RSAKeyLength"`
+		IsSupportONVIFUserManagement       string `xml:"isSupportONVIFUserManagement"`
+		IsSupportGB35114Certificate        string `xml:"isSupportGB35114Certificate"`
+		IsSupportSIPCertificatesManagement string `xml:"isSupportSIPCertificatesManagement"`
+		WebCertificateCap                  struct {
+			CertificateType struct {
+				Opt string `xml:"opt,attr"`
+			} `xml:"CertificateType"`
+			SecurityAlgorithm struct {
+				AlgorithmType struct {
+					Opt string `xml:"opt,attr"`
+				} `xml:"algorithmType"`
+			} `xml:"SecurityAlgorithm"`
+		} `xml:"WebCertificateCap"`
+		IsSupportConfigFileImport string `xml:"isSupportConfigFileImport"`
+		IsSupportConfigFileExport string `xml:"isSupportConfigFileExport"`
+		CfgFileSecretKeyLenLimit  struct {
+			Min string `xml:"min,attr"`
+			Max string `xml:"max,attr"`
+		} `xml:"cfgFileSecretKeyLenLimit"`
+		IsIrreversible                        string `xml:"isIrreversible"`
+		Salt                                  string `xml:"salt"`
+		IsSupportOnvifInfo                    string `xml:"isSupportOnvifInfo"`
+		IsSupportDeviceCertificatesManagement string `xml:"isSupportDeviceCertificatesManagement"`
+		IsSupportDeviceSelfSignCertExport     string `xml:"isSupportDeviceSelfSignCertExport"`
+		IsSupportSecurityEmail                string `xml:"isSupportSecurityEmail"`
+		MaxIllegalLoginTimes                  struct {
+			Min string `xml:"min,attr"`
+			Max string `xml:"max,attr"`
+			Def string `xml:"def,attr"`
+		} `xml:"maxIllegalLoginTimes"`
+		SecurityAdvanced struct {
+			NoOperationEnabled string `xml:"noOperationEnabled"`
+			NoOperationTime    struct {
+				Min string `xml:"min,attr"`
+				Max string `xml:"max,attr"`
+				Def string `xml:"def,attr"`
+			} `xml:"noOperationTime"`
+		} `xml:"SecurityAdvanced"`
+		LoginLinkNum struct {
+			MaxLinkNum struct {
+				Min string `xml:"min,attr"`
+				Max string `xml:"max,attr"`
+				Def string `xml:"def,attr"`
+			} `xml:"maxLinkNum"`
+		} `xml:"LoginLinkNum"`
+		IsSupportCertificateCustomID string `xml:"isSupportCertificateCustomID"`
+		IsSupportEncryptCertificate  string `xml:"isSupportEncryptCertificate"`
+		MaxIllegalLoginLockTime      struct {
+			Min string `xml:"min,attr"`
+			Max string `xml:"max,attr"`
+			Def string `xml:"def,attr"`
+		} `xml:"maxIllegalLoginLockTime"`
+		IsSupportSoftwareLicense string `xml:"isSupportSoftwareLicense"`
+	} `xml:"SecurityCap"`
+	EventCap struct {
+		IsSupportHDFull                 string `xml:"isSupportHDFull"`
+		IsSupportHDError                string `xml:"isSupportHDError"`
+		IsSupportNicBroken              string `xml:"isSupportNicBroken"`
+		IsSupportIpConflict             string `xml:"isSupportIpConflict"`
+		IsSupportIllAccess              string `xml:"isSupportIllAccess"`
+		IsSupportViException            string `xml:"isSupportViException"`
+		IsSupportViMismatch             string `xml:"isSupportViMismatch"`
+		IsSupportRecordException        string `xml:"isSupportRecordException"`
+		IsSupportTriggerFocus           string `xml:"isSupportTriggerFocus"`
+		IsSupportMotionDetection        string `xml:"isSupportMotionDetection"`
+		IsSupportVideoLoss              string `xml:"isSupportVideoLoss"`
+		IsSupportTamperDetection        string `xml:"isSupportTamperDetection"`
+		IsSupportStudentsStoodUp        string `xml:"isSupportStudentsStoodUp"`
+		IsSupportFramesPeopleCounting   string `xml:"isSupportFramesPeopleCounting"`
+		IsSupportPersonQueueDetection   string `xml:"isSupportPersonQueueDetection"`
+		IsSupportFaceContrast           string `xml:"isSupportFaceContrast"`
+		IsSupportFaceLib                string `xml:"isSupportFaceLib"`
+		IsSupportFaceSnap               string `xml:"isSupportFaceSnap"`
+		IsSupportPersonDensityDetection string `xml:"isSupportPersonDensityDetection"`
+		IsSupportTeacherBehaviorDetect  string `xml:"isSupportTeacherBehaviorDetect"`
+		IsSupportCityManagement         string `xml:"isSupportCityManagement"`
+		IsSupportMixedTargetDetection   string `xml:"isSupportMixedTargetDetection"`
+		IsSupportFaceSnapModeling       string `xml:"isSupportFaceSnapModeling"`
+		IsSupportIntersectionAnalysis   string `xml:"isSupportIntersectionAnalysis"`
+		IsSupportLuma                   string `xml:"isSupportLuma"`
+		IsSupportChroma                 string `xml:"isSupportChroma"`
+		IsSupportSnow                   string `xml:"isSupportSnow"`
+		IsSupportStreak                 string `xml:"isSupportStreak"`
+		IsSupportFreeze                 string `xml:"isSupportFreeze"`
+		IsSupportSigLose                string `xml:"isSupportSigLose"`
+		IsSupportClarity                string `xml:"isSupportClarity"`
+		IsSupportJitter                 string `xml:"isSupportJitter"`
+		IsSupportBlock                  string `xml:"isSupportBlock"`
+		IsSupportFlowers                string `xml:"isSupportFlowers"`
+		IsSupportNoise                  string `xml:"isSupportNoise"`
+		IsSupportGhost                  string `xml:"isSupportGhost"`
+		IsSupportPurple                 string `xml:"isSupportPurple"`
+		IsSupportICR                    string `xml:"isSupportICR"`
+		IsSupportProtectiveFilm         string `xml:"isSupportProtectiveFilm"`
+	} `xml:"EventCap"`
+	RacmCap struct {
+		NasNums           string `xml:"nasNums"`
+		PictureSearchType struct {
+			Opt string `xml:"opt,attr"`
+		} `xml:"pictureSearchType"`
+		RecordSearchType struct {
+			Opt string `xml:"opt,attr"`
+		} `xml:"recordSearchType"`
+		SecurityLog struct {
+			IsSupportSecurityLog   string `xml:"isSupportSecurityLog"`
+			IsSupportLogServer     string `xml:"isSupportLogServer"`
+			IsSupportLogServerTest string `xml:"isSupportLogServerTest"`
+			SecurityLogTypeList    struct {
+				SecurityLogType []struct {
+					PrimaryType   string `xml:"primaryType"`
+					SecondaryType struct {
+						Opt string `xml:"opt,attr"`
+					} `xml:"secondaryType"`
+				} `xml:"SecurityLogType"`
+			} `xml:"SecurityLogTypeList"`
+		} `xml:"SecurityLog"`
+		IsSupportRacmChannelsCap struct {
+			Opt string `xml:"opt,attr"`
+		} `xml:"isSupportRacmChannelsCap"`
+	} `xml:"RacmCap"`
+	SmartCap struct {
+		IsSupportROI                  string `xml:"isSupportROI"`
+		IsSupportAudioDetection       string `xml:"isSupportAudioDetection"`
+		IsSupportFaceDetect           string `xml:"isSupportFaceDetect"`
+		IsSupportLineDetection        string `xml:"isSupportLineDetection"`
+		IsSupportFieldDetection       string `xml:"isSupportFieldDetection"`
+		IsSupportRegionEntrance       string `xml:"isSupportRegionEntrance"`
+		IsSupportRegionExiting        string `xml:"isSupportRegionExiting"`
+		IsSupportLoitering            string `xml:"isSupportLoitering"`
+		IsSupportGroup                string `xml:"isSupportGroup"`
+		IsSupportRapidMove            string `xml:"isSupportRapidMove"`
+		IsSupportParking              string `xml:"isSupportParking"`
+		IsSupportUnattendedBaggage    string `xml:"isSupportUnattendedBaggage"`
+		IsSupportAttendedBaggage      string `xml:"isSupportAttendedBaggage"`
+		IsSupportSmartCalibration     string `xml:"isSupportSmartCalibration"`
+		IsSupportIntelliTrace         string `xml:"isSupportIntelliTrace"`
+		IsSupportPeopleDetection      string `xml:"isSupportPeopleDetection"`
+		IsSupportDefocusDetection     string `xml:"isSupportDefocusDetection"`
+		IsSupportSceneChangeDetection string `xml:"isSupportSceneChangeDetection"`
+		IsSupportStorageDetection     string `xml:"isSupportStorageDetection"`
+		IsSupportChannelResource      string `xml:"isSupportChannelResource"`
+	} `xml:"SmartCap"`
+	WLAlarmCap struct {
+		IsSupportTeleControl string `xml:"isSupportTeleControl"`
+		IsSupportPIR         string `xml:"isSupportPIR"`
+		IsSupportWLSensors   string `xml:"isSupportWLSensors"`
+		IsSupportCallHelp    string `xml:"isSupportCallHelp"`
+		WLSensorsNum         string `xml:"WLSensorsNum"`
+	} `xml:"WLAlarmCap"`
+	IsSupportGIS              string `xml:"isSupportGIS"`
+	IsSupportCompass          string `xml:"isSupportCompass"`
+	IsSupportRoadInfoOverlays string `xml:"isSupportRoadInfoOverlays"`
+	TestCap                   struct {
+		IsSupportFTPTest   string `xml:"isSupportFTPTest"`
+		IsSupportPingTest  string `xml:"isSupportPingTest"`
+		IsSupportNTPTest   string `xml:"isSupportNTPTest"`
+		IsSupportNASTest   string `xml:"isSupportNASTest"`
+		IsSupportEmailTest string `xml:"isSupportEmailTest"`
+	} `xml:"TestCap"`
+	PanoramaCap struct {
+		IsSupportGeneratePanorama   string `xml:"isSupportGeneratePanorama"`
+		IsSupportPanoramaPosition3D string `xml:"isSupportPanoramaPosition3D"`
+		IsSupportPreset             string `xml:"isSupportPreset"`
+	} `xml:"PanoramaCap"`
+	IsSupportFaceCaptureStatistics string `xml:"isSupportFaceCaptureStatistics"`
+	IsSupportElectronicsEnlarge    string `xml:"isSupportElectronicsEnlarge"`
+	IsSupportTraffic               string `xml:"isSupportTraffic"`
+	IsSupportFirmwareVersionInfo   string `xml:"isSupportFirmwareVersionInfo"`
+	IsSupportLaserSpotManual       string `xml:"isSupportLaserSpotManual"`
+	IsSupportSetupCalibration      string `xml:"isSupportSetupCalibration"`
+	IsSupportPicInfoOverlap        string `xml:"isSupportPicInfoOverlap"`
+	IsOnlySupportAnalogChannel     string `xml:"isOnlySupportAnalogChannel"`
+	IsSupportChannelEventCap       string `xml:"isSupportChannelEventCap"`
+	IsSupportChannelEventListCap   string `xml:"isSupportChannelEventListCap"`
+	VCAResourceChannelsCap         struct {
+		ChannelsList struct {
+			ChannelsID string `xml:"channelsID"`
+		} `xml:"ChannelsList"`
+	} `xml:"VCAResourceChannelsCap"`
+	SupportSnapshotChannel struct {
+		Opt string `xml:"opt,attr"`
+	} `xml:"supportSnapshotChannel"`
+	IsSupportGPSCalibratation     string `xml:"isSupportGPSCalibratation"`
+	IsSupportGPSLabelTracking     string `xml:"isSupportGPSLabelTracking"`
+	IsSupportCalibrationStream    string `xml:"isSupportCalibrationStream"`
+	IsSupportActiveMulticast      string `xml:"isSupportActiveMulticast"`
+	IsSupportChannelFullEventCap  string `xml:"isSupportChannelFullEventCap"`
+	IsSupportAUXInfoCap           string `xml:"isSupportAUXInfoCap"`
+	IsSupportVehicleMonitor       string `xml:"isSupportVehicleMonitor"`
+	IsSupportManualVehicleMonitor string `xml:"isSupportManualVehicleMonitor"`
+	IsSupportSnapshotAsync        string `xml:"isSupportSnapshotAsync"`
+	IsSupportAutoMaintenance      string `xml:"isSupportAutoMaintenance"`
+	IsSupportSIMCardStatus        string `xml:"isSupportSIMCardStatus"`
+	IsSupportISUPHttpPassthrough  string `xml:"isSupportISUPHttpPassthrough"`
+	IsSupportTOFShelterAlarm      string `xml:"isSupportTOFShelterAlarm"`
+	IsSupportT1Test               string `xml:"isSupportT1Test"`
+}
+
+func (c *Client) GetSystemCap() ([]byte, error) {
+	return c.CommonGet("/ISAPI/System/capabilities")
+}

+ 39 - 0
isapi/isapi_system_deviceInfo.go

@@ -0,0 +1,39 @@
+package isapi
+
+import (
+	"encoding/xml"
+)
+
+// DeviceInfo 设备信息
+type DeviceInfo struct {
+	XMLName              xml.Name `xml:"DeviceInfo,omitempty"`
+	XMLVersion           string   `xml:"version,attr"`
+	XMLNamespace         string   `xml:"xmlns,attr"`
+	DeviceName           string   `xml:"deviceName,omitempty" json:"deviceName,omitempty"`
+	DeviceID             string   `xml:"deviceID,omitempty" json:"deviceID,omitempty"`
+	DeviceDescription    string   `xml:"deviceDescription,omitempty" json:"deviceDescription,omitempty"`
+	DeviceLocation       string   `xml:"deviceLocation,omitempty" json:"deviceLocation,omitempty"`
+	SystemContact        string   `xml:"systemContact,omitempty" json:"systemContact,omitempty"` //生产商
+	Model                string   `xml:"model,omitempty" json:"model,omitempty"`
+	SerialNumber         string   `xml:"serialNumber,omitempty" json:"serialNumber,omitempty"`
+	MacAddress           string   `xml:"macAddress,omitempty" json:"macAddress,omitempty"`
+	FirmwareVersion      string   `xml:"firmwareVersion,omitempty" json:"firmwareVersion,omitempty"`
+	FirmwareReleasedDate string   `xml:"firmwareReleasedDate,omitempty" json:"firmwareReleasedDate,omitempty"`
+	EncoderVersion       string   `xml:"encoderVersion,omitempty" json:"encoderVersion,omitempty"`
+	EncoderReleasedDate  string   `xml:"encoderReleasedDate,omitempty" json:"encoderReleasedDate,omitempty"`
+	BootVersion          string   `xml:"bootVersion,omitempty" json:"bootVersion,omitempty"`
+	BootReleasedDate     string   `xml:"bootReleasedDate,omitempty" json:"bootReleasedDate,omitempty"`
+	HardwareVersion      string   `xml:"hardwareVersion,omitempty" json:"hardwareVersion,omitempty"`
+	DeviceType           string   `xml:"deviceType,omitempty" json:"deviceType,omitempty"`
+	TelecontrolID        string   `xml:"telecontrolID,omitempty" json:"telecontrolID,omitempty"`
+	SupportBeep          string   `xml:"supportBeep,omitempty" json:"supportBeep,omitempty"`
+	SupportVideoLoss     string   `xml:"supportVideoLoss" json:"supportVideoLoss"`
+	FirmwareVersionInfo  string   `xml:"firmwareVersionInfo" json:"firmwareVersionInfo"`
+	Manufacturer         string   `xml:"manufacturer" json:"manufacturer"`
+	SubSerialNumber      string   `xml:"subSerialNumber" json:"subSerialNumber"`
+	OEMCode              string   `xml:"OEMCode" json:"OEMCode"`
+}
+
+func (c *Client) GetDeviceInfo() ([]byte, error) {
+	return c.CommonGet("/ISAPI/System/deviceInfo")
+}

+ 5 - 0
isapi/isapi_system_email.go

@@ -0,0 +1,5 @@
+package isapi
+
+func (c *Client) PutEmail(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/System/Network/mailing/1")
+}

+ 42 - 0
isapi/isapi_system_motionDetection.go

@@ -0,0 +1,42 @@
+package isapi
+
+type MotionDetection struct {
+	Enabled          string `xml:"enabled"`
+	EnableHighlight  string `xml:"enableHighlight"`
+	SamplingInterval string `xml:"samplingInterval"`
+	StartTriggerTime string `xml:"startTriggerTime"`
+	EndTriggerTime   string `xml:"endTriggerTime"`
+	RegionType       string `xml:"regionType"`
+	Grid             struct {
+		RowGranularity    string `xml:"rowGranularity"`
+		ColumnGranularity string `xml:"columnGranularity"`
+	} `xml:"Grid"`
+	MotionDetectionLayout struct {
+		SensitivityLevel string `xml:"sensitivityLevel"`
+		Layout           struct {
+			GridMap    string `xml:"gridMap"`
+			RegionList struct {
+				Text   string `xml:",chardata"`
+				Size   string `xml:"size,attr"`
+				Region struct {
+					ID                    string `xml:"id"`
+					RegionCoordinatesList struct {
+						RegionCoordinates []struct {
+							PositionX string `xml:"positionX"`
+							PositionY string `xml:"positionY"`
+						} `xml:"RegionCoordinates"`
+					} `xml:"RegionCoordinatesList"`
+				} `xml:"Region"`
+			} `xml:"RegionList"`
+		} `xml:"layout"`
+		TargetType string `xml:"targetType"`
+	} `xml:"MotionDetectionLayout"`
+}
+
+func (c *Client) GetMotionDetection() ([]byte, error) {
+	return c.CommonGet("/ISAPI/System/Video/inputs/channels/1/motionDetection")
+}
+
+func (c *Client) PutMotionDetection(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/System/Video/inputs/channels/1/motionDetection")
+}

+ 47 - 0
isapi/isapi_system_time.go

@@ -0,0 +1,47 @@
+package isapi
+
+import (
+	"encoding/xml"
+	"net/url"
+)
+
+// Time
+type Time struct {
+	XMLName      xml.Name `xml:"Time,omitempty"`
+	XMLVersion   string   `xml:"version,attr"`
+	XMLNamespace string   `xml:"xmlns,attr"`
+	TimeMode     string   `xml:"timeMode,omitempty" json:"timeMode,omitempty"` //校时方式,[NTP#NTP校时,manual#手动校时,satellite#卫星校时,platform#平台校时,NONE#不允校时或无校时源,GB28181#GB28181校时,PTP#PTP校时]
+	LocalTime    string   `xml:"localTime,omitempty" json:"localTime,omitempty"`
+	TimeZone     string   `xml:"timeZone,omitempty" json:"timeZone,omitempty"` //CST为时区名称,-8:00:00为(UTC时间-本地时间)
+}
+
+// GetTime 获取时间信息
+func (c *Client) GetTime() (resp *Time, err error) {
+	path := "/ISAPI/System/time"
+	u, err := url.Parse(c.BaseURL + path)
+	if err != nil {
+		return nil, err
+	}
+	body, err := c.Get(u)
+	if err != nil {
+		return nil, err
+	}
+	err = xml.Unmarshal(body, &resp)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}
+
+// PutTime 更新时间
+func (c *Client) PutTime(data []byte) (resp []byte, err error) {
+	u, err := url.Parse(c.BaseURL + "/ISAPI/System/time")
+	if err != nil {
+		return nil, err
+	}
+	resp, err = c.PutXML(u, data)
+	if err != nil {
+		return nil, err
+	}
+	return resp, nil
+}

+ 45 - 0
isapi/operation.go

@@ -0,0 +1,45 @@
+package isapi
+
+// Operation 操作相关主题
+type Operation string
+
+const (
+	GetDeviceInfo Operation = "GetDeviceInfo" //获取摄像头信息
+	GetSystemCap  Operation = "GetSystemCap"  //获取系统能力
+	GetChanCap    Operation = "GetChanCap"    //获取指定通道摄像头能力
+	PutEmail      Operation = "PutEmail"
+
+	SetHosts   Operation = "SetHosts" //配置事件监听服务器
+	SetSIP     Operation = "SetSIP"   //配置sip服务器
+	SetSIPInfo Operation = "SetSIPInfo"
+
+	GetTamperDetection Operation = "GetTamperDetection" //获取指定通道视频遮盖检测规则
+	PutTamperDetection Operation = "PutTamperDetection" //配置指定通道视频遮盖检测规则
+
+	GetMotionDetection Operation = "GetMotionDetection" //获取移动侦测参数
+	PutMotionDetection Operation = "PutMotionDetection" //配置移动侦测参数
+
+	GetLineDetectionCap Operation = "GetLineDetectionCap" //获取单个通道越界规则参数配置能力
+	GetLineDetectionCal Operation = "GetLineDetectionCal" //获取监测目标最大和最小尺寸
+	PutLineDetectionCal Operation = "PutLineDetectionCal" //配置监测目标最大和最小尺寸
+	GetLineDetection    Operation = "GetLineDetection"    //获取越界侦测参数
+	PutLineDetection    Operation = "PutLineDetection"    //配置越界侦测参数
+
+	GetFieldDetectionCap Operation = "GetFieldDetectionCap" //获取单个通道区域入侵规则参数配置能力
+	GetFieldDetectionCal Operation = "GetFieldDetectionCal" //获取监测目标最大和最小尺寸
+	PutFieldDetectionCal Operation = "PutFieldDetectionCal" //配置监测目标最大和最小尺寸
+	GetFieldDetection    Operation = "GetFieldDetection"    //获取区域入侵侦测参数
+	PutFieldDetection    Operation = "PutFieldDetection"    //配置区域入侵侦测参数
+
+	GetRegionEntranceCap Operation = "GetRegionEntranceCap" //获取单个通道进入区域规则参数配置能力
+	GetRegionEntranceCal Operation = "GetRegionEntranceCal" //获取监测目标最大和最小尺寸
+	PutRegionEntranceCal Operation = "PutRegionEntranceCal" //配置监测目标最大和最小尺寸
+	GetRegionEntrance    Operation = "GetRegionEntrance"    //获取进入区域侦测参数
+	PutRegionEntrance    Operation = "PutRegionEntrance"    //配置进入区域侦测参数
+
+	GetRegionExitingCap Operation = "GetRegionExitingCap" //获取单个通道离开区域规则参数配置能力
+	GetRegionExitingCal Operation = "GetRegionExitingCal" //获取监测目标最大和最小尺寸
+	PutRegionExitingCal Operation = "PutRegionExitingCal" //配置监测目标最大和最小尺寸
+	GetRegionExiting    Operation = "GetRegionExiting"    //获取离开区域侦测参数
+	PutRegionExiting    Operation = "PutRegionExiting"    //配置离开区域侦测参数
+)

+ 9 - 0
isapi/response.go

@@ -0,0 +1,9 @@
+package isapi
+
+type ResponseStatus struct {
+	ResponseUrl   string `xml:"responseUrl"`
+	StatusCode    int    `xml:"statusCode"`
+	StatusString  string `xml:"statusString"`
+	SubStatusCode string `xml:"subStatusCode"`
+	Description   string `xml:"description"`
+}

+ 69 - 0
isapi/sip.go

@@ -0,0 +1,69 @@
+package isapi
+
+type SIPServerList struct {
+	SIPServer []struct {
+		ID        string `xml:"id" yaml:"ID"`
+		LocalPort string `xml:"localPort" yaml:"localPort"`
+		StreamID  string `xml:"streamID" yaml:"streamID"`
+		Standard  struct {
+			RegisterStatus string `xml:"registerStatus" yaml:"registerStatus"`
+			Enabled        string `xml:"enabled" yaml:"enabled"`
+			Registrar      string `xml:"registrar" yaml:"registrar"`
+			RegistrarPort  string `xml:"registrarPort" yaml:"registrarPort"`
+			Proxy          string `xml:"proxy" yaml:"proxy"`
+			ProxyPort      string `xml:"proxyPort" yaml:"proxyPort"`
+			DisplayName    string `xml:"displayName" yaml:"displayName"`
+			UserName       string `xml:"userName" yaml:"userName"`
+			AuthID         string `xml:"authID" yaml:"authID"`
+			Password       string `xml:"password" yaml:"password"`
+			Expires        string `xml:"expires" yaml:"expires"`
+		} `xml:"Standard" yaml:"Standard"`
+		GB28181 struct {
+			RegisterStatus        string `xml:"registerStatus" yaml:"registerStatus"`
+			Enabled               string `xml:"enabled" yaml:"enabled"`
+			Registrar             string `xml:"registrar" yaml:"registrar"`
+			RegistrarPort         string `xml:"registrarPort" yaml:"registrarPort"`
+			ServerId              string `xml:"serverId" yaml:"serverId"`
+			ServerDomain          string `xml:"serverDomain" yaml:"serverDomain"`
+			UserName              string `xml:"userName" yaml:"userName"`
+			AuthID                string `xml:"authID" yaml:"authID"`
+			Expires               string `xml:"expires" yaml:"expires"`
+			Password              string `xml:"password" yaml:"password"`
+			LiveTime              string `xml:"liveTime" yaml:"liveTime"`
+			HeartbeatTime         string `xml:"heartbeatTime" yaml:"heartbeatTime"`
+			HeartbeatCount        string `xml:"heartbeatCount" yaml:"heartbeatCount"`
+			TransportType         string `xml:"transportType" yaml:"transportType"`
+			RegisterInterval      string `xml:"registerInterval" yaml:"registerInterval"`
+			ProtocolVersion       string `xml:"protocolVersion" yaml:"protocolVersion"`
+			PlatformNo            string `xml:"platformNo" yaml:"platformNo"`
+			LocalPort             string `xml:"localPort" yaml:"localPort"`
+			UnidirectionEnabled   string `xml:"unidirectionEnabled" yaml:"unidirectionEnabled"`
+			VoiceBroadcastEnabled string `xml:"voiceBroadcastEnabled" yaml:"voiceBroadcastEnabled"`
+		} `xml:"GB28181" yaml:"GB28181"`
+	} `xml:"SIPServer"`
+}
+
+func (c *Client) PutSip(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/System/Network/SIP")
+}
+
+func (c *Client) PutSipInfo(data []byte) ([]byte, error) {
+	return c.CommonPut(data, "/ISAPI/System/Network/SIP/1/SIPInfo")
+}
+
+type SIPInfo struct {
+	VideoID        string   `xml:"videoID"`
+	AlarmInList    []string `xml:"AlarmInList"`
+	VideoInputList []struct {
+		VideoInput struct {
+			ID           string `xml:"id"`
+			VideoInputID string `xml:"videoInputID"`
+		} `xml:"VideoInput"`
+	} `xml:"VideoInputList"`
+	AudioOutputList []struct {
+		AudioOutput struct {
+			ID            string `xml:"id"`
+			AudioOutputID string `xml:"audioOutputID"`
+		} `xml:"AudioOutput"`
+	} `xml:"AudioOutputList"`
+}

+ 1 - 0
main.go

@@ -21,6 +21,7 @@ func main() {
 	//initialize.Redis()
 	global.Db = initialize.Gorm() //初始化数据库orm
 	if global.Db != nil {
+		//initialize.RegisterTables() //初始化表
 		// 程序结束前关闭数据库链接
 		db, _ := global.Db.DB()
 		defer db.Close()

+ 8 - 0
model/app/response/cameras.go

@@ -0,0 +1,8 @@
+package response
+
+type Camera struct {
+	CameraName string `json:"cameraName" gorm:"column:camera_name"`
+	CameraSn   string `json:"cameraSn" gorm:"column:camera_sn"`
+	StreamId   string `json:"streamId" gorm:"column:stream_id"`
+	StreamUrl  string `json:"streamUrl" gorm:"column:stream_url"`
+}

+ 11 - 0
model/app/response/event.go

@@ -0,0 +1,11 @@
+package response
+
+type Event struct {
+	Id          int    `json:"id"`
+	GatewayName string `json:"gatewayName"`
+	EventType   string `json:"eventType"`
+	EventCode   string `json:"eventCode"`
+	StartTime   string `json:"startTime"`
+	HandleTime  string `json:"handleTime"`
+	PictureUrl  string `json:"pictureUrl"`
+}

+ 13 - 0
model/app/response/gateway.go

@@ -0,0 +1,13 @@
+package response
+
+type Gateways struct {
+	ID          int    `json:"id" gorm:"column:id"`
+	GatewayName string `json:"gatewayName" gorm:"column:gateway_name"`
+	Osn         string `json:"osn" gorm:"column:osn"`
+	Description string `json:"description" gorm:"column:description"`
+	CameraName  string `json:"cameraName" gorm:"column:camera_name"`
+	CameraSn    string `json:"cameraSn" gorm:"column:camera_sn"`
+	StreamId    string `json:"streamId" gorm:"column:stream_id"`
+	StreamUrl   string `json:"streamUrl" gorm:"column:stream_url"`
+	Status      int    `json:"ipcastState" gorm:"column:ipcast_state"`
+}

+ 10 - 0
model/isapi/sip.go

@@ -0,0 +1,10 @@
+package isapi
+
+type SipId struct {
+	Id     int `json:"id" xml:"id" gorm:"column:id;"`
+	UserId int `json:"userId" xml:"userId" gorm:"column:user_id;comment:用户id"`
+}
+
+func (SipId) TableName() string {
+	return "sip"
+}

+ 5 - 1
router/enter.go

@@ -1,11 +1,15 @@
 package router
 
 import (
+	"lc-fangdaosha/router/app"
+	"lc-fangdaosha/router/isapi"
 	"lc-fangdaosha/router/system"
 )
 
 type RouterGroup struct {
-	System system.RouterGroup
+	System   system.RouterGroup
+	AppGroup app.RouterGroup
+	IsApi    isapi.RouterGroup
 }
 
 var RouterGroupApp = new(RouterGroup)

+ 5 - 0
router/isapi/enter.go

@@ -0,0 +1,5 @@
+package isapi
+
+type RouterGroup struct {
+	IsApiRouter
+}

+ 46 - 0
router/isapi/isapi.go

@@ -0,0 +1,46 @@
+package isapi
+
+import (
+	"github.com/gin-gonic/gin"
+	v1 "lc-fangdaosha/api/v1"
+	"lc-fangdaosha/middleware"
+)
+
+type IsApiRouter struct {
+}
+
+// InitInfoRouter 初始化isapi路由
+func (i *IsApiRouter) InitInfoRouter(Router *gin.RouterGroup) {
+	var is = v1.ApiGroupApp.IsApiGroup
+
+	//摄像头系统相关
+	sys := Router.Group("/ISAPI/System/")
+	{
+		sys.GET("deviceInfo", is.GetInfo)         //获取设备信息
+		sys.GET("capabilities", is.GetCap)        //获取设备能力集
+		sys.PUT("Network/mailing/1", is.PutEmail) //设置邮件通知
+	}
+	//摄像头智能事件
+	smart := Router.Group("/ISAPI/Smart/").Use(middleware.OperationRecord())
+	smartNoRecord := Router.Group("/ISAPI/Smart/")
+	{
+		//区域入侵
+		smartNoRecord.GET("FieldDetection/1/capabilities", is.GetFieldDetection)  //获取单个通道区域入侵能力集
+		smartNoRecord.GET("channels/1/calibrations/FieldDetection", is.GetSizeFd) //获取区域入侵尺寸
+		smart.PUT("channels/1/calibrations/FieldDetection", is.PutSizeFd)         //设置区域入侵尺寸
+		smartNoRecord.GET("FieldDetection/1", is.GetFieldDetection)               //获取单个通道区域入侵规则
+		smart.PUT("FieldDetection/1", is.PutFieldDetection)                       //设置单个通道区域入侵规则
+		//越界侦测
+		smartNoRecord.GET("LineDetection/1/capabilities", is.GetLineDetectionCap) //获取越界侦测能力集
+		smartNoRecord.GET("channels/1/calibrations/linedetection", is.GetSizeLd)  //获取越界侦测尺寸
+		smart.PUT("channels/1/calibrations/linedetection", is.PutSizeLd)          //配置越界侦测的尺寸
+		smartNoRecord.GET("LineDetection/1", is.GetLineDetection)                 //获取越界侦测
+		smart.PUT("LineDetection/1", is.PutLineDetection)                         //设置越界侦测
+		//进入区域
+		smartNoRecord.GET("regionEntrance/1/capabilities", is.GetRegionEntranceCap) //获取单个通道进入区域能力集
+		smartNoRecord.GET("channels/1/calibrations/regionEntrance", is.GetSizeRe)   //获取侦测目标的尺寸
+		smart.PUT("channels/1/calibrations/regionEntrance", is.PutSizeRe)
+		smartNoRecord.GET("regionEntrance/1", is.GetRegionEntrance) //获取单个通道进入区域侦测规则
+		smart.PUT("regionEntrance/1", is.PutRegionEntrance)         //配置单个通道进入区域侦测规则
+	}
+}

+ 1 - 2
service/app/gateway.go

@@ -130,7 +130,6 @@ func (gs *GatewayService) DevIds(id uint) (devs app.Devices) {
 	//查询网关及关联设备的id
 	global.Db.Select("g.id AS gid,g.osn,c.id AS cid,RIGHT(c.sn,9) AS csn,i.id AS iid").
 		Table("gateway g LEFT JOIN camera c ON g.id = c.gid").
-		Where("g.id = ?", id).
-		Find(&devs)
+		Where("g.id = ?", id).Find(&devs)
 	return
 }

+ 4 - 0
service/enter.go

@@ -1,12 +1,16 @@
 package service
 
 import (
+	"lc-fangdaosha/service/app"
+	"lc-fangdaosha/service/isapi"
 	"lc-fangdaosha/service/system"
 )
 
 type ServiceGroup struct {
 	SystemServiceGroup system.ServiceGroup
+	AppServiceGroup    app.ServiceGroup
 	//ExampleServiceGroup example.ServiceGroup
+	IsApiServiceGroup isapi.ServiceGroup
 }
 
 var ServiceGroupApp = new(ServiceGroup)

+ 5 - 0
service/isapi/enter.go

@@ -0,0 +1,5 @@
+package isapi
+
+type ServiceGroup struct {
+	IsApiService
+}

+ 30 - 0
service/isapi/sipServer.go

@@ -0,0 +1,30 @@
+package isapi
+
+import (
+	"fmt"
+	"gorm.io/gorm"
+	"lc-fangdaosha/global"
+	"lc-fangdaosha/model/isapi"
+)
+
+type IsApiService struct {
+}
+
+// GetSipUserID 获取Sip用户ID
+func GetSipUserID() (int, error) {
+	var is isapi.SipId
+	var is2 isapi.SipId
+	erro := global.Db.Debug().Transaction(func(tx *gorm.DB) error {
+		err := tx.Select("id, user_id").Model(&is).First(&is).Debug().Error
+		if err != nil {
+			return err
+		}
+		err = tx.Model(&is2).Where("id = ?", is.Id).Update("user_id", is.UserId+1).Debug().Error
+		if err != nil {
+			return err
+		}
+		fmt.Println("user_id ", is.UserId)
+		return nil
+	})
+	return is.UserId, erro
+}