EdgexAgent/device-ble-go/internal/driver/driver.go

272 lines
7.7 KiB
Go
Raw Normal View History

2025-07-10 20:40:32 +08:00
// -*- Mode: Go; indent-tabs-mode: t -*-
//
// Copyright (C) 2018 Canonical Ltd
// Copyright (C) 2018-2019 IOTech Ltd
// Copyright (C) 2021 Jiangxing Intelligence Ltd
// Copyright (C) 2022 HCL Technologies Ltd
//
// SPDX-License-Identifier: Apache-2.0
// Package driver this package provides an UART implementation of
// ProtocolDriver interface.
//
// CONTRIBUTORS COMPANY
//===============================================================
// 1. Sathya Durai HCL Technologies
// 2. Sudhamani Bijivemula HCL Technologies
// 3. Vediyappan Villali HCL Technologies
// 4. Vijay Annamalaisamy HCL Technologies
//
//
package driver
import (
"device-ble/cmd/config"
internalif "device-ble/internal/interfaces"
"log"
"device-ble/pkg/ble"
"device-ble/pkg/dataparse"
"device-ble/pkg/mqttbus"
"device-ble/pkg/uart"
errorDefault "errors"
"fmt"
"sync"
"time"
"github.com/spf13/cast"
edgexif "github.com/edgexfoundry/device-sdk-go/v4/pkg/interfaces"
dsModels "github.com/edgexfoundry/device-sdk-go/v4/pkg/models"
"github.com/edgexfoundry/go-mod-core-contracts/v4/clients/logger"
"github.com/edgexfoundry/go-mod-core-contracts/v4/models"
"github.com/edgexfoundry/go-mod-messaging/v4/pkg/types"
"github.com/tarm/serial"
)
// Driver BLE代理服务驱动程序协调各组件初始化和生命周期管理。
type Driver struct {
// EdgeX SDK相关
sdk edgexif.DeviceServiceSDK
logger logger.LoggingClient
asyncCh chan<- *dsModels.AsyncValues
deviceCh chan<- []dsModels.DiscoveredDevice
// 核心组件
BleController internalif.BLEController
MessageBusClient internalif.MessageBusClient
// 业务服务
CommandService *CommandService
AgentService *AgentService
// 内部状态
commandResponses sync.Map
}
// Initialize 初始化设备服务
/*
Initialize 方法执行时
设备配置文件 devices.yaml尚未加载设备实例还未添加到 EdgeX 只能访问服务级别的配置不能访问具体的设备配置
*/
func (d *Driver) Initialize(sdk edgexif.DeviceServiceSDK) error {
d.sdk = sdk
d.logger = sdk.LoggingClient()
d.asyncCh = sdk.AsyncValuesChannel()
d.deviceCh = sdk.DiscoveredDeviceChannel()
return nil
}
// HandleUpAgentCallback 处理上行透明代理数据回调。
func (d *Driver) HandleUpAgentCallback(data string) {
if d.AgentService != nil {
d.AgentService.HandleAgentData(data)
}
}
// HandleUpCommandCallback 处理上行命令回调。
func (d *Driver) HandleUpCommandCallback(cmd string) {
if d.CommandService != nil {
d.CommandService.HandleCommand(cmd)
}
}
// Start 启动设备服务。
func (d *Driver) Start() error {
return nil
}
// agentDown 处理蓝牙透明代理下行数据。
func (d *Driver) agentDown(topic string, envelope types.MessageEnvelope) error {
if err := dataparse.SendToBlE(d.BleController, envelope); err != nil {
d.logger.Infof("【透明代理(↓)】下行数据发送失败 ❌, err: %v", err) // 记录成功日志
}
d.logger.Infof("【透明代理(↓)】下行数据发送成功 ✔, err: %v") // 记录成功日志
return nil
}
// Discover 触发协议特定的设备发现。
func (s *Driver) Discover() error {
return fmt.Errorf("Discover function is yet to be implemented!")
}
// ValidateDevice 校验设备协议属性。
func (s *Driver) ValidateDevice(device models.Device) error {
protocol, ok := device.Protocols["UART"]
if !ok {
return errorDefault.New("Missing 'UART' protocols")
}
deviceLocation, ok := protocol["deviceLocation"]
if !ok {
return errorDefault.New("Missing 'deviceLocation' information")
} else if deviceLocation == "" {
return errorDefault.New("deviceLocation must not empty")
}
baudRate, ok := protocol["baudRate"]
if !ok {
return errorDefault.New("Missing 'baudRate' information")
} else if baudRate == "" {
return errorDefault.New("baudRate must not empty")
}
return nil
}
// Stop 停止设备服务,释放资源。
func (d *Driver) Stop(force bool) error {
if d.logger != nil {
d.logger.Infof("正在停止BLE代理服务 (force=%v)", force)
}
// 关闭MessageBus客户端
if d.MessageBusClient != nil {
if closer, ok := d.MessageBusClient.(interface{ Disconnect() error }); ok {
err := closer.Disconnect()
if err != nil {
d.logger.Errorf("MessageBus客户端关闭失败: %v", err)
} else {
d.logger.Debug("MessageBus客户端已断开连接")
}
} else {
d.logger.Debug("MessageBus客户端不支持关闭操作")
}
}
// 关闭BLE控制器和串口
if d.BleController != nil {
if closer, ok := d.BleController.(interface{ Close() error }); ok {
err := closer.Close()
if err != nil {
d.logger.Errorf("BLE控制器关闭失败: %v", err)
} else {
d.logger.Debug("BLE控制器已关闭")
}
} else {
d.logger.Debug("BLE控制器不支持关闭操作")
}
}
if d.logger != nil {
d.logger.Info("BLE代理服务已停止")
}
return nil
}
// AddDevice 添加设备回调函数。
func (d *Driver) AddDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error {
d.logger.Debugf("新设备已添加: %s", deviceName)
// 获取 UART 配置信息
// 通过结构体字段访问 Protocols
var deviceLocation string
var baudRate int
for i, protocol := range protocols {
deviceLocation = fmt.Sprintf("%v", protocol["deviceLocation"])
baudRate, _ = cast.ToIntE(protocol["baudRate"])
d.logger.Debugf("Driver.HandleReadCommands(): protocol = %v, device location = %v, baud rate = %v timeout=%v", i, deviceLocation, baudRate)
}
serialPort, err := uart.NewSerialPort(serial.Config{
Name: deviceLocation,
Baud: baudRate,
ReadTimeout: time.Duration(10) * time.Millisecond,
}, d.logger)
if err != nil {
log.Fatal("创建串口实例失败:", err)
}
// 初始化串口队列注册Driver回调
serialQueue := uart.NewSerialQueue(
serialPort,
d.logger,
func(cmd string) { d.HandleUpCommandCallback(cmd) },
func(data string) { d.HandleUpAgentCallback(data) },
5,
)
// 初始化BLE控制器
bleController := ble.NewBLEController(serialPort, serialQueue, d.logger)
// 初始化BLE设备为外围设备模式
if err := bleController.InitializeAsPeripheral(); err != nil {
log.Fatal("BLE设备初始化失败:", err)
}
// 加载自定义MQTT配置
cfg, err := config.LoadConfig("./res/configuration.yaml")
if err != nil {
log.Fatal("MessageBusClient 获取自定义配置失败:", err)
}
d.logger.Debugf("自定义Mqtt服务配置: %v\n", cfg)
// 初始化消息总线
mqttClient, err := mqttbus.NewEdgexMessageBusClient(cfg, d.logger)
if err != nil {
log.Fatal("MessageBusClient 创建失败:", err)
}
// 初始化业务服务
commandService := &CommandService{
Logger: d.logger,
MessageBusClient: mqttClient,
BleController: bleController,
}
agentService := &AgentService{
Logger: d.logger,
MessageBusClient: mqttClient,
}
// 注入依赖到Driver
d.BleController = bleController
d.MessageBusClient = mqttClient
d.CommandService = commandService
d.AgentService = agentService
if d.BleController == nil || d.MessageBusClient == nil {
return fmt.Errorf("依赖未注入")
}
if err := d.MessageBusClient.Subscribe(TopicBLEDown, d.agentDown); err != nil { // 转发下行数据
d.logger.Errorf("【透明代理(↓)】 订阅下行总线失败 err: %v", err)
}
return nil
}
// UpdateDevice 更新设备回调函数。
func (d *Driver) UpdateDevice(deviceName string, protocols map[string]models.ProtocolProperties, adminState models.AdminState) error {
d.logger.Debugf("设备 %s 已更新", deviceName)
return nil
}
// RemoveDevice 移除设备回调函数。
func (d *Driver) RemoveDevice(deviceName string, protocols map[string]models.ProtocolProperties) error {
d.logger.Debugf("设备 %s 已移除", deviceName)
return nil
}