98 lines
3.2 KiB
Go
98 lines
3.2 KiB
Go
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
|
|
|
|
comm transport.Communicator
|
|
}
|
|
|
|
// NewGeneralDeviceService 创建一个通用设备服务
|
|
func NewGeneralDeviceService(deviceRepo repository.DeviceRepository, logger *logs.Logger, comm transport.Communicator) *GeneralDeviceService {
|
|
return &GeneralDeviceService{
|
|
deviceRepo: deviceRepo,
|
|
logger: logger,
|
|
comm: comm,
|
|
}
|
|
}
|
|
|
|
func (g *GeneralDeviceService) Switch(device models.Device, action DeviceAction) error {
|
|
|
|
// 校验设备参数及生成指令
|
|
if *device.ParentID == 0 {
|
|
return fmt.Errorf("设备 %v(id=%v) 的上级区域主控(id=%v) ID不合理, 无法执行指令", device.Name, device.ID, *device.ParentID)
|
|
}
|
|
|
|
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(*device.ParentID)
|
|
if err != nil {
|
|
return fmt.Errorf("获取区域主控(id=%v)信息失败: %v", *device.ParentID, 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)
|
|
|
|
}
|