实现 GeneralDeviceService

This commit is contained in:
2025-09-16 17:12:27 +08:00
parent 2ac3dcda84
commit c9df4fd6f4
5 changed files with 137 additions and 14 deletions

View File

@@ -6,15 +6,15 @@ import "git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
type DeviceAction string
var (
DeviceActionStart = "start" // 启动
DeviceActionStop = "stop" // 停止
DeviceActionStart DeviceAction = "start" // 启动
DeviceActionStop DeviceAction = "stop" // 停止
)
// 指令类型
type Method string
var (
MethodPing = "ping" // ping指令
MethodSwitch Method = "switch" // 启停指令
)
// Service 抽象了一组方法用于控制设备行为

View File

@@ -1,20 +1,103 @@
package device
import (
"fmt"
"strconv"
"git.huangwc.com/pig/pig-farm-controller/internal/app/service/device/proto"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/logs"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/models"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/repository"
"git.huangwc.com/pig/pig-farm-controller/internal/infra/transport"
gproto "google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
)
type GeneralDeviceService struct {
deviceRepo repository.DeviceRepository
logger *logs.Logger
deviceID uint // 区域主控的设备ID
// regionalController 是执行命令的区域主控, 所有的指令都会发往区域主控
regionalController *models.Device
comm transport.Communicator
}
func (g *GeneralDeviceService) Switch(device models.Device, action DeviceAction) error {
//TODO implement me
panic("implement me")
// NewGeneralDeviceService 创建一个通用设备服务
func NewGeneralDeviceService(deviceID uint, deviceRepo repository.DeviceRepository, logger *logs.Logger, comm transport.Communicator) *GeneralDeviceService {
return &GeneralDeviceService{
deviceID: deviceID,
deviceRepo: deviceRepo,
logger: logger,
comm: comm,
}
}
func (g *GeneralDeviceService) Ping() error {
//TODO implement me
panic("implement me")
func (g *GeneralDeviceService) Switch(device models.Device, action DeviceAction) error {
// 校验设备参数及生成指令
if *device.ParentID != g.deviceID {
return fmt.Errorf("设备 %v(id=%v) 的上级区域主控是(id=%v), 不是当前区域主控(id=%v)下属设备, 无法执行指令", device.Name, device.ID, device.ParentID, g.deviceID)
}
if !device.SelfCheck() {
return fmt.Errorf("设备 %v(id=%v) 缺少必要信息, 无法发送指令", device.Name, device.ID)
}
deviceInfo := make(map[string]interface{})
if err := device.ParseProperties(&deviceInfo); err != nil {
return fmt.Errorf("解析设备 %v(id=%v) 配置失败: %v", device.Name, device.ID, err)
}
busNumber, err := strconv.Atoi(fmt.Sprintf("%v", deviceInfo[models.BusNumber]))
if err != nil {
return fmt.Errorf("无效的总线号: %v", err)
}
busAddress, err := strconv.Atoi(fmt.Sprintf("%v", deviceInfo[models.BusAddress]))
if err != nil {
return fmt.Errorf("无效的总线地址: %v", err)
}
relayChannel, err := strconv.Atoi(fmt.Sprintf("%v", deviceInfo[models.RelayChannel]))
if err != nil {
return fmt.Errorf("无效的继电器通道: %v", err)
}
data, err := anypb.New(&proto.Switch{
DeviceAction: string(action),
BusNumber: int32(busNumber),
BusAddress: int32(busAddress),
RelayChannel: int32(relayChannel),
})
if err != nil {
return fmt.Errorf("创建指令失败: %v", err)
}
instruction := &proto.Instruction{
Method: proto.MethodType_SWITCH,
Data: data,
}
// 获取自身LoRa设备ID, 因为可能变更, 所以每次都现获取
thisDevice, err := g.deviceRepo.FindByID(g.deviceID)
if err != nil {
return fmt.Errorf("获取区域主控(id=%v)信息失败: %v", g.deviceID, err)
}
if !thisDevice.SelfCheck() {
return fmt.Errorf("区域主控 %v(id=%v) 缺少必要信息, 无法发送指令", thisDevice.Name, thisDevice.ID)
}
thisDeviceinfo := make(map[string]interface{})
if err := thisDevice.ParseProperties(&thisDeviceinfo); err != nil {
return fmt.Errorf("解析区域主控 %v(id=%v) 配置失败: %v", device.Name, device.ID, err)
}
loraAddress := fmt.Sprintf("%v", thisDeviceinfo[models.LoRaAddress])
// 生成消息并发送
message, err := gproto.Marshal(instruction)
if err != nil {
return fmt.Errorf("序列化指令失败: %v", err)
}
return g.comm.Send(loraAddress, message)
}