diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..049718a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "D:/project/hikvision-sdk" + } + ] +} \ No newline at end of file diff --git a/cloud/base-cloud.go b/cloud/base-cloud.go new file mode 100644 index 0000000..7c3bb84 --- /dev/null +++ b/cloud/base-cloud.go @@ -0,0 +1,47 @@ +package cloud + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "strings" + + "myschools.me/suguo/hikvision/model" +) + +// 基础云眸http请求 +func BaseCloudHttpRequest(accesstoken *string, method string, url string, body interface{}) ([]byte, error) { + b, err := json.Marshal(body) + if err != nil { + return nil, err + } + reqbody := strings.NewReader(string(b)) + req, err := http.NewRequest(method, url, reqbody) + if err != nil { + return nil, err + } + + req.Header.Add("authorization", fmt.Sprintf(" bearer %s", *accesstoken)) + + if strings.ToLower(method) == "post" { + req.Header.Add("Content-Type", "application/json") + } + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(respBody, &result); err != nil { + return nil, err + } + return respBody, nil +} diff --git a/cloud/device-cloud.go b/cloud/device-cloud.go new file mode 100644 index 0000000..bfe3d40 --- /dev/null +++ b/cloud/device-cloud.go @@ -0,0 +1,443 @@ +package cloud + +import ( + "encoding/json" + "fmt" + + "myschools.me/suguo/hikvision/model" +) + +/* + 基础服务能力 > 设备管理 > 设备接入管理 +*/ + +const ( + ACCESS_BASE = "https://api2.hik-cloud.com/api/v1/open/basic/devices" + ACCESS_REGISTER = ACCESS_BASE + "/create" + ACCESS_DELETE = ACCESS_BASE + "/delete" + ACCESS_UPDATE = ACCESS_BASE + "/update" + ACCESS_DETAIL = ACCESS_BASE + "/get" + ACCESS_LIST = ACCESS_BASE + "/list" + ACCESS_ACCOUNT = ACCESS_BASE + "/actions/deviceCount" + ACCESS_STATUS = ACCESS_BASE + "https://api2.hik-cloud.com/api/v1/ezviz/devices/queryDeviceStatus" + ACCESS_REBOOT = ACCESS_BASE + "/actions/system/reboot" + + // 设备校时配置 + TIME_BASE = "https://api2.hik-cloud.com/api/v1/device/isapi/system/time" + TIME_NTPCFG = TIME_BASE + "/ntpServers" + TIM_NTPSERVER_CFG = TIME_BASE + "/ntpServers/config" +) + +type DeviceRegister struct { + DeviceSerial string `json:"deviceSerial"` //设备序列号 + GroupNo string `json:"groupNo"` //组编号 + ValidateCode string `json:"validateCode"` //验证码 +} + +type DeviceRegisterRes struct { + Code int `json:"code"` + Message string `json:"message"` + Data DeviceData `json:"data"` +} + +type DeviceData struct { + DeviceId string `json:"deviceId"` //设备id + DeviceName string `json:"deviceName"` //型号 + DeviceModel string `json:"deviceModel"` //设备名称 + DeviceSerial string `json:"deviceSerial"` //设备序列号 + DeviceStatus int `json:"deviceStatus"` //0-离线,1-在线 + GroupId string `json:"groupId"` //组id + IsEncrypt int `json:"isEncrypt"` //设备加密状态 0-关闭 1-开启 + + // 当使用设备接入详情接口获取的信息才会拥有版本 + DeviceVersion string `json:"deviceVersion"` +} + +// 注册设备到对应分组内。 +// +// 注册设备时首先会将设备添加到平台,然后异步同步设备通道。如果设备添加成功而同步设备通道失败,则可以先获取设备列表信息,再手动调用通道同步接口同步设备下的通道。\ +func DeivceRegister(access_token *string, req *DeviceRegister) (*DeviceRegisterRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", ACCESS_REGISTER, req) + if err != nil { + return nil, err + } + var result *DeviceRegisterRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +// 从某一分组内删除设备 +func DeivceDelete(access_token *string, deviceSerial string) (*model.BaseOperationRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", fmt.Sprintf("%s?deviceSerial=%s", ACCESS_DELETE, deviceSerial), nil) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +type DeivceUpdateReq struct { + DeviceSerial string `json:"deviceSerial"` //设备序列号 + DeviceName string `json:"deviceName"` //设备名称 +} + +// 该接口用于修改设备名称 +func DeivceUpdate(access_token *string, req *DeivceUpdateReq) (*model.BaseOperationRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", ACCESS_UPDATE, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +// 该接口用于根据设备序列号获取单个设备详细信息 +func DeivceDetail(access_token *string, deviceSerial string) (*DeviceData, error) { + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?deviceSerial=%s", ACCESS_DETAIL, deviceSerial), nil) + if err != nil { + return nil, err + } + var result *DeviceRegisterRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type DeivceListReq struct { + GroupNo string //必填 + pageNo int //必填,分页页数 >=1 + pageSize int //必填,分页记录数 1-999 +} + +type DeivceListRes struct { + Code int `json:"code"` + Message string `json:"message"` + Data DeivceListData `json:"data"` +} + +type DeivceListData struct { + PageNo int `json:"pageNo"` + PageSize int `json:"pageSize"` + Total int `json:"total"` + Rows []DeviceData `json:"rows"` +} + +// 该接口用于查询某组下设备列表信息 +func DeivceList(access_token *string, req *DeivceListReq) (*DeivceListData, error) { + url := fmt.Sprintf("%s?groupNo=%s&pageNo=%d&pageSize=%d", ACCESS_LIST, req.GroupNo, req.pageNo, req.pageSize) + resp, err := BaseCloudHttpRequest(access_token, "GET", url, nil) + if err != nil { + return nil, err + } + var result *DeivceListRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type DeivceNumRes struct { + Code int `json:"code"` + Data DeivceNumData `json:"data"` + Message string `json:"message"` +} + +type DeivceNumData struct { + TotalCount int `json:"totalCount"` +} + +// 该接口用于获取用户接入的设备总数 +func DeivceNum(access_token *string) (*int, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", ACCESS_ACCOUNT, nil) + if err != nil { + return nil, err + } + var result *DeivceNumRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data.TotalCount, nil +} + +type DeivceStatusReq struct { + Code int `json:"code"` + Message string `json:"message"` + Data DeivceStatusData `json:"data"` +} + +type DeivceStatusData struct { + PrivacyStatus int `json:"privacyStatus"` + PirStatus int `json:"pirStatus"` + AlarmSoundMode int `json:"alarmSoundMode"` + BattryStatus int `json:"battryStatus"` + LockSignal int `json:"lockSignal"` + DiskNum int `json:"diskNum"` + DiskState string `json:"diskState"` + CloudStatus int `json:"cloudStatus"` + NvrDiskNum int `json:"nvrDiskNum"` + NvrDiskState string `json:"nvrDiskState"` +} + +// 该接口用于查询设备的状态信息,目前仅支持萤石设备 /*测试未通过*/ +func DeivceStatus(access_token *string, deviceserial string) (*DeivceStatusData, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?deviceSerial=%s", ACCESS_STATUS, deviceserial), nil) + if err != nil { + return nil, err + } + var result *DeivceStatusReq + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +// 该接口用于重启设备,请谨慎操作 +func DeivceReboot(access_token *string, deviceserial string) (*model.BaseOperationRes, error) { + params := &struct { + DeviceSerial string `json:"deviceSerial"` + }{ + DeviceSerial: deviceserial, + } + + resp, err := BaseCloudHttpRequest(access_token, "POST", ACCESS_REBOOT, params) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +/* +确权流程说明 +设备接入政策进行了如下调整: +(1)设备首次激活,需要在规定的时间(72小时)内上线平台,否则,上线时需要走确权流程; +(2)设备重新注册平台,删除设备并重新添加设备超过规定时间(72小时)需要走确权流程; + +什么时候需要进行确权 +注册设备接口返回内容code=60058时,需要进行设备确权操作。 +*/ + +// 下线确认 +func DeivceOffline(access_token *string, deviceserial string) (*model.BaseOperationRes, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("https://api2.hik-cloud.com/v1/carrier/wing/endpoint/confirm/right/offlineconfirm?deviceSerial=%s", deviceserial), nil) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +// 上线线确认 +func DeivceOnline(access_token *string, deviceserial string) (*model.BaseOperationRes, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("https://api2.hik-cloud.com/v1/carrier/wing/endpoint/confirm/right/onlineconfirm?deviceSerial=%s", deviceserial), nil) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +type DeviceGetTimeModeRes struct { + Code int `json:"code"` + Message string `json:"message"` + Data DeviceGetTimeModeData `json:"data"` +} + +type DeviceGetTimeModeData struct { + TimeMode string `json:"timeMode"` +} + +// 该接口用于获取设备当前校时配置 +func DeviceGetTimeMode(access_token *string, deviceserial string) (*DeviceGetTimeModeData, error) { + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?deviceSerial=%s", TIME_BASE, deviceserial), nil) + if err != nil { + return nil, err + } + var result *DeviceGetTimeModeRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type DeviceSetTimeModeReq struct { + DeviceSerial string `json:"deviceSerial"` + TimeMode string `json:"timeMode"` +} + +// 该接口用于配置设备校时模式 +func DeviceSetTimeMode(access_token *string, req *DeviceSetTimeModeReq) (*model.BaseOperationRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", TIME_BASE, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +// 该接口用于获取设备当前NTP服务器配置 +func DeviceGetNTPCfg(access_token *string, deviceserial string) (*DeviceSetNTPCfgServer, error) { + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?deviceSerial=%s", TIME_NTPCFG, deviceserial), nil) + if err != nil { + return nil, err + } + var result *DeviceGetNTPServerRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type DeviceSetNTPCfgReq struct { + DeviceSerial string `json:"deviceSerial"` + NtpServer DeviceSetNTPCfgServer `json:"ntpServer"` +} + +type DeviceSetNTPCfgServer struct { + Id string `json:"id"` + AddressingFormatType string `json:"addressingFormatType"` + HostName string `json:"hostName"` + IpAddress string `json:"ipAddress"` + PortNo int `json:"portNo"` + SynchronizeInterval int `json:"synchronizeInterval"` +} + +// 该接口用于配置设备NTP服务器参数 +func DeviceSetNTPCfg(access_token *string, req *DeviceSetNTPCfgReq) (*model.BaseOperationRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", TIME_NTPCFG, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +type DeviceGetNTPServerRes struct { + Code int `json:"code"` + Message string `json:"message"` + Data DeviceSetNTPCfgServer `json:"data"` +} + +// 该接口用于获取设备指定NTP服务器配置 +func DeviceGetNTPServerCfg(access_token *string, deviceserial string, ntpserverid int) (*DeviceSetNTPCfgServer, error) { + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?deviceSerial=%s&ntpServerId=%d", TIM_NTPSERVER_CFG, deviceserial, ntpserverid), nil) + if err != nil { + return nil, err + } + var result *DeviceGetNTPServerRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type DeviceSetNTPServerCfgReq struct { + DeviceSerial string `json:"deviceSerial"` + NtpServerID int `json:"ntpServerId"` + NtpServer DeviceSetNTPCfgServer `json:"ntpServer"` +} + +// 该接口用于配置设备指定NTP服务器参数 +func DeviceSetNTPServerCfg(access_token *string, req DeviceSetNTPServerCfgReq) (*model.BaseOperationRes, error) { + resp, err := BaseCloudHttpRequest(access_token, "POST", TIM_NTPSERVER_CFG, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} diff --git a/cloud/group-cloud.go b/cloud/group-cloud.go new file mode 100644 index 0000000..6d32f52 --- /dev/null +++ b/cloud/group-cloud.go @@ -0,0 +1,156 @@ +package cloud + +import ( + "encoding/json" + "fmt" + + "myschools.me/suguo/hikvision/model" +) + +/* + 基础服务能力 > 设备管理 > 设备分组管理 +*/ + +const ( + /*设备分组管理*/ + GROUP_BASE = "https://api2.hik-cloud.com/api/v1/open/basic/groups" + GROUP_ADD = GROUP_BASE + "/create" + GROUP_REMOVE = GROUP_BASE + "/delete" + GROUP_UPDATE = GROUP_BASE + "/update" + GROUP_DETAIL = GROUP_BASE + "/get" + GROUP_LISTALL = GROUP_BASE + "/actions/listAll" + GROUP_CHILD_LIST = GROUP_BASE + "/actions/childrenList" +) + +type GroupAddReq struct { + GroupName string `json:"groupName"` //组名称 + GroupNo string `json:"groupNo"` //组编号 + ParentNo string `json:"parentNo"` //父节点组编号 +} + +// 该接口用于通过编号来新增组。最多支持3000个组,最多支持5层嵌套。 +func GroupAdd(access_token *string, req *GroupAddReq) (*model.BaseOperationRes, error) { + + resp, err := BaseCloudHttpRequest(access_token, "POST", GROUP_ADD, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +type GroupUpdateReq struct { + GroupName string `json:"groupName"` //组名称 + GroupNo string `json:"groupNo"` //组编号 +} + +// 该接口用于通过组编号来删除组。组下面挂有下级节点或者设备的不可以删除,需清空后进行删除。 +func GroupUpdate(access_token *string, req *GroupUpdateReq) (*model.BaseOperationRes, error) { + + resp, err := BaseCloudHttpRequest(access_token, "POST", GROUP_UPDATE, req) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +// 该接口用于通过组编号来删除组。组下面挂有下级节点或者设备的不可以删除,需清空后进行删除。 +func GroupRemove(access_token *string, groupNo string) (*model.BaseOperationRes, error) { + + resp, err := BaseCloudHttpRequest(access_token, "POST", fmt.Sprintf("%s?groupNo=%s", GROUP_REMOVE, groupNo), nil) + if err != nil { + return nil, err + } + var result *model.BaseOperationRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result, nil +} + +type GroupGetRes struct { + Code int `json:"code"` + Data Group `json:"data"` + Message string `json:"message"` +} + +type Group struct { + GroupId string `json:"groupId"` //组ID + GroupName string `json:"groupName"` //组名称 + GroupNo string `json:"groupNo"` //组编号 + ParentId string `json:"parentId"` //父ID +} + +// 该接口用于通过组编号获取组的详细信息 +func CloudGetGroup(access_token *string, groupNo string) (*Group, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?groupNo=%s", GROUP_DETAIL, groupNo), nil) + if err != nil { + return nil, err + } + var result *GroupGetRes + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return &result.Data, nil +} + +type Groups struct { + Code int `json:"code"` + Data []Group `json:"data"` + Message string `json:"message"` +} + +// 该接口用于获取所有组。 +func GroupGetAll(access_token *string) ([]Group, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", GROUP_LISTALL, nil) + if err != nil { + return nil, err + } + var result *Groups + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result.Data, nil +} + +// 该接口用于通过组编号查找某组的下级节点。如果父节点为空,则查询根节点。 +func GroupChildList(access_token *string, groupNo string) ([]Group, error) { + + resp, err := BaseCloudHttpRequest(access_token, "GET", fmt.Sprintf("%s?parentNo=%s", GROUP_CHILD_LIST, groupNo), nil) + if err != nil { + return nil, err + } + var result *Groups + if err := json.Unmarshal(resp, &result); err != nil { + return nil, err + } + if result.Code != 200 { + return nil, fmt.Errorf("result errcode:%d errmsg:%s", result.Code, result.Message) + } + return result.Data, nil +} diff --git a/cloud/oauth-cloud.go b/cloud/oauth-cloud.go new file mode 100644 index 0000000..16588d4 --- /dev/null +++ b/cloud/oauth-cloud.go @@ -0,0 +1,78 @@ +package cloud + +import ( + "crypto/tls" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strings" + "time" +) + +const ( + BASEURL = "https://api2.hik-cloud.com/oauth" +) + +type OauthRequest struct { + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + GrantType string `json:"grant_type"` + Scope string `json:"scope"` +} + +type OauthResponse struct { + AccessToken string `json:"access_token"` + TokenType string `json:"token_type"` + ExpiresIn int `json:"expires_in"` + Scope string `json:"scope"` +} + +// 客户端认证获取access_token +func HikvisionOauth(body *OauthRequest) (*OauthResponse, error) { + + params := url.Values{} + params.Add("client_id", body.ClientID) + params.Add("client_secret", body.ClientSecret) + params.Add("grant_type", body.GrantType) + params.Add("scope", body.Scope) + + req, err := http.NewRequest("POST", fmt.Sprintf(`%s/token`, BASEURL), strings.NewReader(string(params.Encode()))) + if err != nil { + return nil, err + } + + req.Header.Add("Accept", "*/*") + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + + tr := &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + } + + client := &http.Client{Transport: tr, Timeout: 10 * time.Second} + resp, err := client.Do(req) + if err != nil { + return nil, err + } + + if resp.StatusCode != 200 { + errmsg := fmt.Sprintf("http status code: %d", resp.StatusCode) + return nil, errors.New(errmsg) + } + + defer resp.Body.Close() + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + var result *OauthResponse + if err := json.Unmarshal(respBody, &result); err != nil { + return nil, err + } + + return result, nil +} diff --git a/cloud/oauth_test.go b/cloud/oauth_test.go new file mode 100644 index 0000000..b535bad --- /dev/null +++ b/cloud/oauth_test.go @@ -0,0 +1,18 @@ +package cloud + +import ( + "fmt" + "log" + "testing" +) + +func TestOauth(t *testing.T) { + serial := "AF8534579" + accesstoken := "a08a8044-3770-41f5-b5a5-048004a723ac" + result, err := DeivceReboot(&accesstoken, serial) + if err != nil { + log.Fatal(err) + } + + fmt.Println(result) +} diff --git a/hikvision.http b/hikvision.http index d9d0ed9..cca401e 100644 --- a/hikvision.http +++ b/hikvision.http @@ -1,8 +1,22 @@ @url=https://api2.hik-cloud.com/oauth -@token=a08a8044-3770-41f5-b5a5-048004a723ac +@token=authorization: bearer a08a8044-3770-41f5-b5a5-048004a723ac @token_type=bearer +### 客户端认证 POST {{url}}/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded -client_id=164edfd71b744dd88c945dbd5ae30a9a&client_secret=2f580d932d7d46029a2091ece681035c&grant_type=client_credentials&scope=yy \ No newline at end of file +client_id=164edfd71b744dd88c945dbd5ae30a9a&client_secret=2f580d932d7d46029a2091ece681035c&grant_type=client_credentials&scope=yy + +### +GET https://api2.hik-cloud.com/api/v1/open/basic/groups/actions/listAll HTTP/1.1 +{{token}} + +### +GET https://api2.hik-cloud.com/api/v1/open/basic/groups/actions/childrenList?parentNo=02 HTTP/1.1 +{{token}} + +### +GET https://api2.hik-cloud.com/api/v1/open/basic/devices/list?groupNo=1&pageNo=1&pageSize=50 HTTP/1.1 +{{token}} + diff --git a/model/base-model.go b/model/base-model.go new file mode 100644 index 0000000..4041858 --- /dev/null +++ b/model/base-model.go @@ -0,0 +1,7 @@ +package model + +// 基础操作回参 +type BaseOperationRes struct { + Code int `json:"code"` + Message string `json:"message"` +}