#12 支持设备发放服务

This commit is contained in:
ctlove0523 2022-02-11 20:47:39 +08:00
parent ba6b05c8b9
commit 8e4302495e
6 changed files with 138 additions and 65 deletions

View File

@ -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)
~~~

View File

@ -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()))

View File

@ -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 {

View File

@ -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,

View File

@ -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
View File

@ -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, "_")
}