|
@@ -0,0 +1,268 @@
|
|
|
+package AiotSwitchSDK
|
|
|
+
|
|
|
+import (
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "github.com/nats-io/nats.go"
|
|
|
+ "github.com/vmihailenco/msgpack/v5"
|
|
|
+ "io/ioutil"
|
|
|
+ "os"
|
|
|
+ "path/filepath"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+type Switch struct {
|
|
|
+}
|
|
|
+
|
|
|
+// 协议基础信息
|
|
|
+
|
|
|
+var SwitchName string // 连接地址
|
|
|
+var SwitchConnect string // 连接地址
|
|
|
+var SwitchDescribe string // 协议描述
|
|
|
+
|
|
|
+// 参数配置模版
|
|
|
+var SwitchConfig = map[string]map[string]string{}
|
|
|
+var ns *nats.Conn
|
|
|
+
|
|
|
+var funPullHandleStruct func(T_topic string, T_data []byte) error
|
|
|
+
|
|
|
+/*
|
|
|
+name:服务名称 默认 程序名
|
|
|
+nats: NATS 地址 默认 nats://127.0.0.1:6503
|
|
|
+funPH: 平台-> Switch网关方法
|
|
|
+*/
|
|
|
+func AiotSwitchInit(name, nats string, funPH func(T_topic string, T_data []byte) error) {
|
|
|
+ funPullHandleStruct = nil
|
|
|
+ if len(name) == 0 {
|
|
|
+ name = filepath.Base(os.Args[0]) // 程序名
|
|
|
+ }
|
|
|
+ SwitchName = name
|
|
|
+
|
|
|
+ if len(nats) == 0 {
|
|
|
+ nats = "nats://127.0.0.1:6503" // 程序名
|
|
|
+ }
|
|
|
+ funPullHandleStruct = funPH
|
|
|
+ initNats(nats)
|
|
|
+ initConfig(SwitchName)
|
|
|
+ funPullHandle(SwitchName)
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化 NATS 服务
|
|
|
+func (s *Switch) initNats(url string) {
|
|
|
+ var err error
|
|
|
+ // 连接Nats服务器
|
|
|
+ ns, err = nats.Connect(url, nats.MaxReconnects(10), nats.ReconnectWait(10*time.Second),
|
|
|
+ nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
|
|
|
+ // handle disconnect error event
|
|
|
+ fmt.Println("natsS.DisconnectErrHandler 断开 ", err)
|
|
|
+ }),
|
|
|
+ nats.ReconnectHandler(func(nc *nats.Conn) {
|
|
|
+ // handle reconnect event
|
|
|
+ fmt.Println("natsS.ReconnectHandler, 已经重新连接 ", err)
|
|
|
+ }))
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("natsS 连接失败!", err)
|
|
|
+ panic(any("natsS 连接失败!" + url))
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("nats 连接失败!", err)
|
|
|
+ panic(any(err))
|
|
|
+ }
|
|
|
+ fmt.Println("nats OK!")
|
|
|
+}
|
|
|
+func initNats(url string) {
|
|
|
+ var err error
|
|
|
+ // 连接Nats服务器
|
|
|
+ ns, err = nats.Connect(url, nats.MaxReconnects(10), nats.ReconnectWait(10*time.Second),
|
|
|
+ nats.DisconnectErrHandler(func(nc *nats.Conn, err error) {
|
|
|
+ // handle disconnect error event
|
|
|
+ fmt.Println("natsS.DisconnectErrHandler 断开 ", err)
|
|
|
+ }),
|
|
|
+ nats.ReconnectHandler(func(nc *nats.Conn) {
|
|
|
+ // handle reconnect event
|
|
|
+ fmt.Println("natsS.ReconnectHandler, 已经重新连接 ", err)
|
|
|
+ }))
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("natsS 连接失败!", err)
|
|
|
+ panic(any("natsS 连接失败!" + url))
|
|
|
+ }
|
|
|
+
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("nats 连接失败!", err)
|
|
|
+ panic(any(err))
|
|
|
+ }
|
|
|
+ fmt.Println("nats OK!")
|
|
|
+}
|
|
|
+
|
|
|
+// 配置文件
|
|
|
+func initConfig(name string) {
|
|
|
+ Configjson := "./" + name + "json"
|
|
|
+ _, err := os.Stat(Configjson) // 用你的文件路径替换"/path/to/your/file"
|
|
|
+ if os.IsNotExist(err) {
|
|
|
+ fmt.Println("文件不存在")
|
|
|
+ jsonData, err := json.Marshal(SwitchConfig)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ }
|
|
|
+ err = ioutil.WriteFile(Configjson, jsonData, 0644)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error unmarshalling JSON:", err)
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ fmt.Println("文件存在")
|
|
|
+ jsonData, err := ioutil.ReadFile(Configjson)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ }
|
|
|
+ err = json.Unmarshal(jsonData, &SwitchConfig)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Error unmarshalling JSON:", err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // nats 注册 服务
|
|
|
+ type Struct struct {
|
|
|
+ T_name string
|
|
|
+ T_SwitchConfig map[string]map[string]string
|
|
|
+ }
|
|
|
+ b, _ := msgpack.Marshal(&Struct{T_name: SwitchName, T_SwitchConfig: SwitchConfig})
|
|
|
+
|
|
|
+ // 请求-响应, 向 test3 发布一个 `help me` 请求数据,设置超时间3秒,如果有多个响应,只接收第一个收到的消息
|
|
|
+ ns.Request("/Switch/Init", b, 3*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ panic(any("nats 注册失败!"))
|
|
|
+ }
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 设备->平台 设备状态 1 在线 2 离线
|
|
|
+func AiotSwitchState(T_sn, T_password string, T_State int, T_Reason string) error {
|
|
|
+
|
|
|
+ type Struct struct {
|
|
|
+ T_sn string
|
|
|
+ T_password string
|
|
|
+ T_State int
|
|
|
+ T_Reason string
|
|
|
+ }
|
|
|
+ b, _ := msgpack.Marshal(&Struct{T_sn: T_sn, T_password: T_password, T_State: T_State, T_Reason: T_Reason})
|
|
|
+
|
|
|
+ // 请求-响应, 向 test3 发布一个 `help me` 请求数据,设置超时间3秒,如果有多个响应,只接收第一个收到的消息
|
|
|
+ msg, err := ns.Request("/Switch/State", b, 3*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return errors.New("通讯异常")
|
|
|
+ }
|
|
|
+ if len(msg.Data) != 0 {
|
|
|
+ return errors.New(string(msg.Data))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// 设备->平台 验证
|
|
|
+func AiotSwitchVerify(T_sn, T_password string) error {
|
|
|
+
|
|
|
+ type Struct struct {
|
|
|
+ T_sn string
|
|
|
+ T_password string
|
|
|
+ }
|
|
|
+ b, _ := msgpack.Marshal(&Struct{T_sn: T_sn, T_password: T_password})
|
|
|
+
|
|
|
+ // 请求-响应, 向 test3 发布一个 `help me` 请求数据,设置超时间3秒,如果有多个响应,只接收第一个收到的消息
|
|
|
+ msg, err := ns.Request("/Switch/Verify", b, 3*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return errors.New("通讯异常")
|
|
|
+ }
|
|
|
+ if len(msg.Data) != 0 {
|
|
|
+ return errors.New(string(msg.Data))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 设备->平台 添加设备
|
|
|
+func AiotSwitchAdd(T_ProductID, T_ProductKey, T_sn, T_password string) error {
|
|
|
+ type Struct struct {
|
|
|
+ T_ProductID string
|
|
|
+ T_ProductKey string
|
|
|
+ T_sn string
|
|
|
+ T_password string
|
|
|
+ }
|
|
|
+ b, _ := msgpack.Marshal(&Struct{T_sn: T_sn, T_password: T_password, T_ProductID: T_ProductID, T_ProductKey: T_ProductKey})
|
|
|
+
|
|
|
+ // 请求-响应, 向 test3 发布一个 `help me` 请求数据,设置超时间3秒,如果有多个响应,只接收第一个收到的消息
|
|
|
+ msg, err := ns.Request("/Switch/Add", b, 3*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return errors.New("通讯异常")
|
|
|
+ }
|
|
|
+ if len(msg.Data) != 0 {
|
|
|
+ return errors.New(string(msg.Data))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 设备->平台
|
|
|
+func AiotSwitchPush(T_sn, T_password, T_topic string, T_data []byte) error {
|
|
|
+
|
|
|
+ type Struct struct {
|
|
|
+ T_sn string
|
|
|
+ T_password string
|
|
|
+ T_topic string
|
|
|
+ T_data []byte
|
|
|
+ }
|
|
|
+ b, _ := msgpack.Marshal(&Struct{T_sn: T_sn, T_password: T_password, T_topic: T_topic, T_data: T_data})
|
|
|
+
|
|
|
+ // 请求-响应, 向 test3 发布一个 `help me` 请求数据,设置超时间3秒,如果有多个响应,只接收第一个收到的消息
|
|
|
+ msg, err := ns.Request("/Switch/Pull", b, 3*time.Second)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println(err)
|
|
|
+ return errors.New("通讯异常")
|
|
|
+ }
|
|
|
+ if len(msg.Data) != 0 {
|
|
|
+ return errors.New(string(msg.Data))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// 平台->设备
|
|
|
+func funPullHandle(T_name string) {
|
|
|
+ ns.Subscribe("/Switch/"+T_name, func(m *nats.Msg) {
|
|
|
+ go func(m *nats.Msg) {
|
|
|
+ type Struct struct {
|
|
|
+ T_topic string
|
|
|
+ T_data []byte
|
|
|
+ }
|
|
|
+ var date_r Struct
|
|
|
+ err := msgpack.Unmarshal(m.Data, &date_r)
|
|
|
+ if err != nil {
|
|
|
+ fmt.Println("Nats:", err)
|
|
|
+ ns.Publish(m.Reply, []byte("Unmarshal 错误!"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 防止 没有给方法报错
|
|
|
+ if funPullHandleStruct != nil {
|
|
|
+ err = funPullHandleStruct(date_r.T_topic, date_r.T_data)
|
|
|
+ if err != nil {
|
|
|
+ ns.Publish(m.Reply, []byte(err.Error()))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ns.Publish(m.Reply, []byte(""))
|
|
|
+
|
|
|
+ }(m)
|
|
|
+
|
|
|
+ })
|
|
|
+
|
|
|
+}
|