#12 支持设备发放服务
This commit is contained in:
parent
ba6b05c8b9
commit
8e4302495e
47
README.md
47
README.md
|
@ -21,11 +21,11 @@ huaweicloud-iot-device-sdk-go提供设备接入华为云IoT物联网平台的Go
|
|||
* [设备日志收集](#设备日志收集)
|
||||
|
||||
* [HTTP协议上报消息和属性](#HTTP协议上报消息和属性)
|
||||
|
||||
* [支持设备发放服务](#使用设备发放服务)
|
||||
|
||||
## 版本说明
|
||||
|
||||
当前稳定版本:v2.0.0
|
||||
当前稳定版本:v1.0.1
|
||||
|
||||
|
||||
|
||||
|
@ -658,6 +658,49 @@ type HttpDevice interface {
|
|||
|
||||
|
||||
|
||||
### 使用设备发放服务
|
||||
|
||||
有两种方法可以使用设备发放服务动态获取设备连接平台的地址
|
||||
|
||||
方法1:通过设备发放服务获取设备连接平台的地址,然后创建设备
|
||||
|
||||
~~~golang
|
||||
id := "device_id"
|
||||
pwd := "your device password"
|
||||
|
||||
bootstrapClient, err := iot.NewBootstrapClient(id, pwd)
|
||||
if err != nil {
|
||||
fmt.Printf("create bs client failed")
|
||||
return
|
||||
}
|
||||
|
||||
server := bootstrapClient.Boot()
|
||||
if len(server) == 0 {
|
||||
fmt.Println("get server address failed")
|
||||
return
|
||||
}
|
||||
|
||||
device := iot.CreateIotDevice(id, pwd, server)
|
||||
device.Init()
|
||||
~~~
|
||||
|
||||
方法2:在创建设备时启动设备发放服务
|
||||
|
||||
~~~go
|
||||
id := "device_id"
|
||||
pwd := "your device password"
|
||||
config := iot.DeviceConfig{
|
||||
Id: id,
|
||||
Password: pwd,
|
||||
UseBootstrap: true,
|
||||
}
|
||||
device := iot.CreateIotDeviceWitConfig(config)
|
||||
initRes := device.Init()
|
||||
fmt.Println(initRes)
|
||||
|
||||
time.Sleep(1 * time.Minute)
|
||||
~~~
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ type DeviceConfig struct {
|
|||
ServerCaPath string
|
||||
CertFilePath string
|
||||
CertKeyFilePath string
|
||||
UseBootstrap bool // 使用设备引导功能开关,true-使用,false-不使用
|
||||
}
|
||||
|
||||
type BaseDevice interface {
|
||||
|
@ -152,6 +153,7 @@ type baseIotDevice struct {
|
|||
devicePropertyLogCollector DevicePropertyLogCollector
|
||||
deviceMessageLogCollector DeviceMessageLogCollector
|
||||
deviceCommandLogCollector DeviceCommandLogCollector
|
||||
useBootstrap bool
|
||||
}
|
||||
|
||||
func (device *baseIotDevice) DisConnect() {
|
||||
|
@ -168,9 +170,24 @@ func (device *baseIotDevice) IsConnected() bool {
|
|||
}
|
||||
|
||||
func (device *baseIotDevice) Init() bool {
|
||||
|
||||
options := mqtt.NewClientOptions()
|
||||
options.AddBroker(device.Servers)
|
||||
if device.useBootstrap {
|
||||
bootstracpClient, err := NewBootstrapClient(device.Id, device.Password)
|
||||
if err != nil {
|
||||
fmt.Printf("create bootstrap client failed,err %s\n", err)
|
||||
return false
|
||||
}
|
||||
|
||||
serverAddress := bootstracpClient.Boot()
|
||||
if len(serverAddress) == 0 {
|
||||
fmt.Println("get server address from bootstrap server failed")
|
||||
return false
|
||||
}
|
||||
options.AddBroker(serverAddress)
|
||||
} else {
|
||||
options.AddBroker(device.Servers)
|
||||
}
|
||||
|
||||
options.SetClientID(assembleClientId(device))
|
||||
options.SetUsername(device.Id)
|
||||
options.SetPassword(hmacSha256(device.Password, timeStamp()))
|
||||
|
|
102
bootstrap.go
102
bootstrap.go
|
@ -7,51 +7,48 @@ import (
|
|||
"fmt"
|
||||
mqtt "github.com/eclipse/paho.mqtt.golang"
|
||||
"github.com/golang/glog"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type BootstrapClientConfig struct {
|
||||
id string // 设备Id,平台又称为deviceId
|
||||
password string // 设备密码
|
||||
server string // 设备发放平台地址:tls://iot-bs.cn-north-4.myhuaweicloud.com:8883
|
||||
caPath string // 设备发放平台CA证书
|
||||
}
|
||||
|
||||
func NewBootstrapClientConfig() *BootstrapClientConfig {
|
||||
return &BootstrapClientConfig{}
|
||||
}
|
||||
|
||||
func (conf *BootstrapClientConfig) WithId(id string) *BootstrapClientConfig {
|
||||
conf.id = id
|
||||
return conf
|
||||
}
|
||||
|
||||
func (conf *BootstrapClientConfig) WithPassword(password string) *BootstrapClientConfig {
|
||||
conf.password = password
|
||||
return conf
|
||||
}
|
||||
|
||||
func (conf *BootstrapClientConfig) WithServer(server string) *BootstrapClientConfig {
|
||||
conf.server = server
|
||||
return conf
|
||||
}
|
||||
|
||||
func (conf *BootstrapClientConfig) WithCaPath(caPath string) *BootstrapClientConfig {
|
||||
conf.caPath = caPath
|
||||
return conf
|
||||
}
|
||||
const (
|
||||
bsServer = "tls://iot-bs.cn-north-4.myhuaweicloud.com:8883"
|
||||
bsServerCa = "-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIETjCCAzagAwIBAgINAe5fIh38YjvUMzqFVzANBgkqhkiG9w0BAQsFADBMMSAw\n" +
|
||||
"HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFs\n" +
|
||||
"U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xODExMjEwMDAwMDBaFw0yODEx\n" +
|
||||
"MjEwMDAwMDBaMFAxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52\n" +
|
||||
"LXNhMSYwJAYDVQQDEx1HbG9iYWxTaWduIFJTQSBPViBTU0wgQ0EgMjAxODCCASIw\n" +
|
||||
"DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKdaydUMGCEAI9WXD+uu3Vxoa2uP\n" +
|
||||
"UGATeoHLl+6OimGUSyZ59gSnKvuk2la77qCk8HuKf1UfR5NhDW5xUTolJAgvjOH3\n" +
|
||||
"idaSz6+zpz8w7bXfIa7+9UQX/dhj2S/TgVprX9NHsKzyqzskeU8fxy7quRU6fBhM\n" +
|
||||
"abO1IFkJXinDY+YuRluqlJBJDrnw9UqhCS98NE3QvADFBlV5Bs6i0BDxSEPouVq1\n" +
|
||||
"lVW9MdIbPYa+oewNEtssmSStR8JvA+Z6cLVwzM0nLKWMjsIYPJLJLnNvBhBWk0Cq\n" +
|
||||
"o8VS++XFBdZpaFwGue5RieGKDkFNm5KQConpFmvv73W+eka440eKHRwup08CAwEA\n" +
|
||||
"AaOCASkwggElMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMB0G\n" +
|
||||
"A1UdDgQWBBT473/yzXhnqN5vjySNiPGHAwKz6zAfBgNVHSMEGDAWgBSP8Et/qC5F\n" +
|
||||
"JK5NUPpjmove4t0bvDA+BggrBgEFBQcBAQQyMDAwLgYIKwYBBQUHMAGGImh0dHA6\n" +
|
||||
"Ly9vY3NwMi5nbG9iYWxzaWduLmNvbS9yb290cjMwNgYDVR0fBC8wLTAroCmgJ4Yl\n" +
|
||||
"aHR0cDovL2NybC5nbG9iYWxzaWduLmNvbS9yb290LXIzLmNybDBHBgNVHSAEQDA+\n" +
|
||||
"MDwGBFUdIAAwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuZ2xvYmFsc2lnbi5j\n" +
|
||||
"b20vcmVwb3NpdG9yeS8wDQYJKoZIhvcNAQELBQADggEBAJmQyC1fQorUC2bbmANz\n" +
|
||||
"EdSIhlIoU4r7rd/9c446ZwTbw1MUcBQJfMPg+NccmBqixD7b6QDjynCy8SIwIVbb\n" +
|
||||
"0615XoFYC20UgDX1b10d65pHBf9ZjQCxQNqQmJYaumxtf4z1s4DfjGRzNpZ5eWl0\n" +
|
||||
"6r/4ngGPoJVpjemEuunl1Ig423g7mNA2eymw0lIYkN5SQwCuaifIFJ6GlazhgDEw\n" +
|
||||
"fpolu4usBCOmmQDo8dIm7A9+O4orkjgTHY+GzYZSR+Y0fFukAj6KYXwidlNalFMz\n" +
|
||||
"hriSqHKvoflShx8xpfywgVcvzfTO3PYkz6fiNJBonf6q8amaEsybwMbDqKWwIX7eSPY=\n" +
|
||||
"-----END CERTIFICATE-----"
|
||||
)
|
||||
|
||||
type BootstrapClient interface {
|
||||
Boot() string
|
||||
Close()
|
||||
}
|
||||
|
||||
func NewBootstrapClient(conf *BootstrapClientConfig) (BootstrapClient, error) {
|
||||
func NewBootstrapClient(id, password string) (BootstrapClient, error) {
|
||||
client := &bsClient{
|
||||
conf: conf,
|
||||
id: id,
|
||||
password: password,
|
||||
iotdaServer: newResult(),
|
||||
}
|
||||
|
||||
|
@ -64,27 +61,24 @@ func NewBootstrapClient(conf *BootstrapClientConfig) (BootstrapClient, error) {
|
|||
}
|
||||
|
||||
type bsClient struct {
|
||||
conf *BootstrapClientConfig
|
||||
id string
|
||||
password string
|
||||
client mqtt.Client // 使用的MQTT客户端
|
||||
iotdaServer *Result // 设备接入平台地址
|
||||
}
|
||||
|
||||
func (bs *bsClient) init() (bool, error) {
|
||||
options := mqtt.NewClientOptions()
|
||||
options.AddBroker(bs.conf.server)
|
||||
options.SetClientID(createClientId(bs.conf.id))
|
||||
options.SetUsername(bs.conf.id)
|
||||
options.SetPassword(hmacSha256(bs.conf.password, timeStamp()))
|
||||
options.AddBroker(bsServer)
|
||||
options.SetClientID(CreateMqttClientId(bs.id))
|
||||
options.SetUsername(bs.id)
|
||||
options.SetPassword(hmacSha256(bs.password, timeStamp()))
|
||||
options.SetKeepAlive(250 * time.Second)
|
||||
options.SetAutoReconnect(true)
|
||||
options.SetConnectRetry(true)
|
||||
options.SetConnectTimeout(2 * time.Second)
|
||||
|
||||
ca, err := ioutil.ReadFile(bs.conf.caPath)
|
||||
if err != nil {
|
||||
glog.Error("load server ca failed\n")
|
||||
return false, err
|
||||
}
|
||||
ca := []byte(bsServerCa)
|
||||
serverCaPool := x509.NewCertPool()
|
||||
serverCaPool.AppendCertsFromPEM(ca)
|
||||
|
||||
|
@ -98,11 +92,11 @@ func (bs *bsClient) init() (bool, error) {
|
|||
|
||||
bs.client = mqtt.NewClient(options)
|
||||
if token := bs.client.Connect(); token.Wait() && token.Error() != nil {
|
||||
glog.Warningf("device %s create bootstrap client failed,error = %v", bs.conf.id, token.Error())
|
||||
glog.Warningf("device %s create bootstrap client failed,error = %v", bs.id, token.Error())
|
||||
return false, token.Error()
|
||||
}
|
||||
|
||||
downTopic := fmt.Sprintf("$oc/devices/%s/sys/bootstrap/down", bs.conf.id)
|
||||
downTopic := fmt.Sprintf("$oc/devices/%s/sys/bootstrap/down", bs.id)
|
||||
subRes := bs.client.Subscribe(downTopic, 0, func(client mqtt.Client, message mqtt.Message) {
|
||||
go func() {
|
||||
fmt.Println("get message from bs server")
|
||||
|
@ -127,7 +121,7 @@ func (bs *bsClient) init() (bool, error) {
|
|||
}
|
||||
|
||||
func (bs *bsClient) Boot() string {
|
||||
upTopic := fmt.Sprintf("$oc/devices/%s/sys/bootstrap/up", bs.conf.id)
|
||||
upTopic := fmt.Sprintf("$oc/devices/%s/sys/bootstrap/up", bs.id)
|
||||
pubRes := bs.client.Publish(upTopic, 0, false, "")
|
||||
if pubRes.Wait() && pubRes.Error() != nil {
|
||||
fmt.Println(pubRes.Error())
|
||||
|
@ -146,22 +140,10 @@ type serverResponse struct {
|
|||
Address string `json:"address"`
|
||||
}
|
||||
|
||||
func createClientId(deviceId string) string {
|
||||
segments := make([]string, 4)
|
||||
segments[0] = deviceId
|
||||
segments[1] = "0"
|
||||
segments[2] = "0"
|
||||
segments[3] = timeStamp()
|
||||
|
||||
return strings.Join(segments, "_")
|
||||
}
|
||||
|
||||
type Result struct {
|
||||
Flag chan int
|
||||
|
||||
err error
|
||||
mErr sync.RWMutex
|
||||
|
||||
res string
|
||||
mRes sync.RWMutex
|
||||
}
|
||||
|
@ -172,13 +154,11 @@ func (b *Result) Value() string {
|
|||
return b.res
|
||||
}
|
||||
|
||||
// Wait implements the Token Wait method.
|
||||
func (b *Result) Wait() bool {
|
||||
<-b.Flag
|
||||
return true
|
||||
}
|
||||
|
||||
// WaitTimeout implements the Token WaitTimeout method.
|
||||
func (b *Result) WaitTimeout(d time.Duration) bool {
|
||||
timer := time.NewTimer(d)
|
||||
select {
|
||||
|
|
|
@ -518,6 +518,7 @@ func CreateIotDeviceWitConfig(config DeviceConfig) Device {
|
|||
device.CertFilePath = config.CertFilePath
|
||||
device.CertKeyFilePath = config.CertKeyFilePath
|
||||
|
||||
device.useBootstrap = config.UseBootstrap
|
||||
|
||||
result := &iotDevice{
|
||||
base: device,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
iot "github.com/ctlove0523/huaweicloud-iot-device-sdk-go"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
id := "611d13360ad1ed028658e089_zhou_sdk"
|
||||
pwd := "12345678901234567890"
|
||||
config := iot.DeviceConfig{
|
||||
Id: id,
|
||||
Password: pwd,
|
||||
UseBootstrap: true,
|
||||
}
|
||||
device := iot.CreateIotDeviceWitConfig(config)
|
||||
initRes := device.Init()
|
||||
fmt.Println(initRes)
|
||||
|
||||
time.Sleep(1 * time.Minute)
|
||||
}
|
10
util.go
10
util.go
|
@ -61,3 +61,13 @@ func smartFileName(filename string) string {
|
|||
|
||||
return filename
|
||||
}
|
||||
|
||||
func CreateMqttClientId(deviceId string) string {
|
||||
segments := make([]string, 4)
|
||||
segments[0] = deviceId
|
||||
segments[1] = "0"
|
||||
segments[2] = "0"
|
||||
segments[3] = timeStamp()
|
||||
|
||||
return strings.Join(segments, "_")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue