EdgexAgent/device-ble-go/pkg/mqttbus/config.go
2025-07-10 20:40:32 +08:00

139 lines
4.0 KiB
Go

// -*- Mode: Go; indent-tabs-mode: t -*-
//
// Copyright (C) 2019-2023 IOTech Ltd
//
// SPDX-License-Identifier: Apache-2.0
package mqttbus
import (
"fmt"
"net/url"
"github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/interfaces"
"github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/secret"
"github.com/edgexfoundry/go-mod-bootstrap/v4/bootstrap/startup"
"github.com/edgexfoundry/go-mod-bootstrap/v4/config"
"github.com/edgexfoundry/go-mod-core-contracts/v4/errors"
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
"github.com/labstack/gommon/log"
)
type ServiceConfig struct {
MQTTBrokerInfo MQTTBrokerInfo
}
// UpdateFromRaw updates the service's full configuration from raw data received from
// the Service Provider.
func (sw *ServiceConfig) UpdateFromRaw(rawConfig interface{}) bool {
configuration, ok := rawConfig.(*ServiceConfig)
if !ok {
return false //errors.New("unable to cast raw config to type 'ServiceConfig'")
}
*sw = *configuration
return true
}
func (s *ServiceConfig) GetCredentials(secretProvider interfaces.SecretProvider, secretName string) (config.Credentials, error) {
credentials := config.Credentials{}
timer := startup.NewTimer(s.MQTTBrokerInfo.CredentialsRetryTime, s.MQTTBrokerInfo.CredentialsRetryWait)
var secretData map[string]string
var err error
for timer.HasNotElapsed() {
secretData, err = secretProvider.GetSecret(secretName, secret.UsernameKey, secret.PasswordKey)
if err == nil {
break
}
log.Warnf(
"无法从SecretProvider获取MQTT证书 '%s': %s. 重试中,剩余时间: %s",
secretName,
err.Error(),
timer.RemainingAsString())
timer.SleepForInterval()
}
if err != nil {
return credentials, err
}
credentials.Username = secretData[secret.UsernameKey]
credentials.Password = secretData[secret.PasswordKey]
return credentials, nil
}
type MQTTBrokerInfo struct {
Schema string
Host string
Port int
Qos int
KeepAlive int
ClientId string
CredentialsRetryTime int
CredentialsRetryWait int
ConnEstablishingRetry int
ConnRetryWaitTime int
AuthMode string
CredentialsName string
IncomingTopic string
ResponseTopic string
Writable WritableInfo
}
// Validate ensures your custom configuration has proper values.
func (info *MQTTBrokerInfo) Validate() errors.EdgeX {
if info.Writable.ResponseFetchInterval == 0 {
return errors.NewCommonEdgeX(errors.KindContractInvalid, "MQTTBrokerInfo.Writable.ResponseFetchInterval configuration setting can not be blank", nil)
}
return nil
}
type WritableInfo struct {
// ResponseFetchInterval specifies the retry interval(milliseconds) to fetch the command response from the MQTT broker
ResponseFetchInterval int
}
func fetchCommandTopic(protocols map[string]models.ProtocolProperties) (string, errors.EdgeX) {
properties, ok := protocols[Protocol]
if !ok {
return "", errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("'%s' protocol properties is not defined", Protocol), nil)
}
commandTopic, ok := properties[CommandTopic]
if !ok {
return "", errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("'%s' not found in the '%s' protocol properties", CommandTopic, Protocol), nil)
}
commandTopicString, ok := commandTopic.(string)
if !ok {
return "", errors.NewCommonEdgeX(errors.KindContractInvalid, fmt.Sprintf("cannot convert '%v' to string type", CommandTopic), nil)
}
return commandTopicString, nil
}
func (s *ServiceConfig) SetCredentials(uri *url.URL, secretProvider interfaces.SecretProvider, category string, authMode string, secretName string) error {
switch authMode {
case AuthModeUsernamePassword:
credentials, err := s.GetCredentials(secretProvider, secretName)
if err != nil {
return fmt.Errorf("获取%s MQTT证书失败 '%s': %w", category, secretName, err)
}
uri.User = url.UserPassword(credentials.Username, credentials.Password)
case AuthModeNone:
return nil
default:
return fmt.Errorf("MQTT %s 连接认证模式 '%s' 不支持", category, authMode)
}
return nil
}