// -*- 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 }