259 lines
6.1 KiB
Go
259 lines
6.1 KiB
Go
package iot
|
||
|
||
import (
|
||
"crypto/tls"
|
||
"encoding/json"
|
||
"errors"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
"net/url"
|
||
"os"
|
||
"reflect"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
var (
|
||
baseURL = "https://api2.hik-cloud.com"
|
||
clientID = ""
|
||
clientSecret = ""
|
||
scope = ""
|
||
)
|
||
|
||
func init() {
|
||
baseURL = os.Getenv("IOT_URL")
|
||
if baseURL == "" {
|
||
baseURL = "https://api2.hik-cloud.com"
|
||
}
|
||
clientID = os.Getenv("IOT_CLIENTID")
|
||
if clientID == "" {
|
||
clientID = "164edfd71b744dd88c945dbd5ae30a9a"
|
||
}
|
||
clientSecret = os.Getenv("IOT_CLIENTSECRET")
|
||
if clientSecret == "" {
|
||
clientSecret = "2f580d932d7d46029a2091ece681035c"
|
||
}
|
||
scope = os.Getenv("IOT_SCOPE")
|
||
if scope == "" {
|
||
scope = "yy"
|
||
}
|
||
}
|
||
|
||
// 基础云眸http请求 公共方法
|
||
func hikvisionRequest(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, baseURL+url, reqbody)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
token, err := hikvisionOauth()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req.Header.Add("authorization", fmt.Sprintf(" bearer %s", *token))
|
||
|
||
switch strings.ToLower(method) {
|
||
case "post":
|
||
req.Header.Add("Content-Type", "application/json")
|
||
case "delete":
|
||
if body != nil {
|
||
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
|
||
}
|
||
|
||
return respBody, nil
|
||
}
|
||
|
||
var token string
|
||
var expired time.Time
|
||
|
||
// 客户端认证获取access_token,公共方法
|
||
func hikvisionOauth() (*string, error) {
|
||
|
||
if expired.After(time.Now()) {
|
||
return &token, nil
|
||
}
|
||
|
||
params := struct {
|
||
client_id string
|
||
client_secret string
|
||
grant_type string
|
||
scope string
|
||
}{
|
||
client_id: clientID,
|
||
client_secret: clientSecret,
|
||
grant_type: "client_credentials",
|
||
scope: scope,
|
||
}
|
||
|
||
resp, err := hikvisionIOTRequestUrlencoded("POST", `/oauth/token`, params, false)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
result := &struct {
|
||
AccessToken string `json:"access_token"`
|
||
TokenType string `json:"token_type"`
|
||
ExpiresIn int `json:"expires_in"`
|
||
Scope string `json:"scope"`
|
||
}{}
|
||
|
||
if err := json.Unmarshal(resp, &result); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
token = result.AccessToken
|
||
expired = time.Now().Add(time.Duration(result.ExpiresIn) * time.Second)
|
||
|
||
return &token, nil
|
||
}
|
||
|
||
// iot 使用form请求 application/x-www-form-urlencoded,公共方法
|
||
//
|
||
// 传入的结构体内的字段名称必须与文档一致
|
||
func hikvisionIOTRequestUrlencoded(method string, url string, body interface{}, auth bool) ([]byte, error) {
|
||
|
||
reader, err := hikvisioninspectStruct(body)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
req, err := http.NewRequest(method, baseURL+url, strings.NewReader(reader.Encode()))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
req.Header.Add("Accept", "*/*")
|
||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||
if auth {
|
||
token, err := hikvisionOauth()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req.Header.Add("authorization", fmt.Sprintf(" bearer %s", *token))
|
||
}
|
||
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
|
||
}
|
||
|
||
return respBody, nil
|
||
}
|
||
|
||
func hikvisionRequestUrlencoded(method string, url string, body interface{}, auth bool) ([]byte, error) {
|
||
|
||
reader, err := hikvisioninspectStruct(body)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
req, err := http.NewRequest(method, url, strings.NewReader(reader.Encode()))
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
req.Header.Add("Accept", "*/*")
|
||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||
if auth {
|
||
token, err := hikvisionOauth()
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
req.Header.Add("authorization", fmt.Sprintf(" bearer %s", *token))
|
||
}
|
||
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
|
||
}
|
||
|
||
return respBody, nil
|
||
}
|
||
|
||
// 解析结构体数据,写入到url.values中
|
||
func hikvisioninspectStruct(u interface{}) (url.Values, error) {
|
||
values := url.Values{}
|
||
|
||
typev := reflect.TypeOf(u)
|
||
|
||
if typev.Kind() != reflect.Struct {
|
||
return nil, errors.New("typev.Kind() is not a reflect.Struct")
|
||
}
|
||
|
||
for i := 0; i < typev.NumField(); i++ {
|
||
v := reflect.ValueOf(u)
|
||
field := v.FieldByName(typev.Field(i).Name)
|
||
// typev := reflect.TypeOf(u).FieldByName()
|
||
switch field.Kind() {
|
||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||
values.Add(typev.Field(i).Name, fmt.Sprintf("%d", field.Int()))
|
||
// fmt.Printf("field:%s type:%s value:%d\n", typev.Field(i).Name, field.Type().Name(), field.Int())
|
||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||
values.Add(typev.Field(i).Name, fmt.Sprintf("%d", field.Uint()))
|
||
// fmt.Printf("field:%s type:%s value:%d\n", typev.Field(i).Name, field.Type().Name(), field.Uint())
|
||
case reflect.Bool:
|
||
values.Add(typev.Field(i).Name, fmt.Sprintf("%v", field.Bool()))
|
||
// fmt.Printf("field:%s type:%s value:%t\n", typev.Field(i).Name, field.Type().Name(), field.Bool())
|
||
case reflect.String:
|
||
values.Add(typev.Field(i).Name, field.String())
|
||
// fmt.Printf("field:%s type:%s value:%q\n", typev.Field(i).Name, field.Type().Name(), field.String())
|
||
// default:
|
||
// fmt.Printf("field:%s unhandled kind:%s\n", typev.Field(i).Name, field.Kind())
|
||
}
|
||
}
|
||
return values, nil
|
||
}
|