package service import ( "IotAdmin/common/global" "IotAdmin/core/logger" "IotAdmin/core/sdk" "IotAdmin/core/sdk/service" "IotAdmin/core/tools/utils" "IotAdmin/iot/constant" iotInterface "IotAdmin/iot/interface" iotLog "IotAdmin/iot/log" iotMeter "IotAdmin/iot/meter" iotProtocol "IotAdmin/iot/protocol" iotProtocolHandler "IotAdmin/iot/protocol/handler" "encoding/json" "errors" "strings" "gorm.io/gorm" "IotAdmin/app/iot/models" "IotAdmin/app/iot/service/dto" cDto "IotAdmin/common/dto" "IotAdmin/common/permission" ) // IotDeviceService 设备服务 type IotDeviceService struct { service.Service } // GetPage 获取设备列表 func (e *IotDeviceService) GetPage(c *dto.IotDeviceGetPageReq, p *permission.DataPermission, list *[]models.IotDevice, count *int64) error { var err error var data models.IotDevice db := e.Orm.Model(&data).Scopes( cDto.MakeCondition(c.GetNeedSearch()), cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), permission.Permission(data.TableName(), p), ) if c.Type == constant.IotDeviceTypeGateway { db.Preload("Group").Select("id,name,type,group_id,sn,cycle,status,online_status,time_online,time_offline,iot_device.created_at") } else { db = db.Where("parent_id = ?", c.ParentId).Select("id,name,type,status,sn,protocol,mode,address,bm_yz,other_config,created_at") } err = db.Find(list).Limit(-1).Offset(-1).Count(count).Error if err != nil { e.Log.Errorf("IotDeviceService GetPage error:%s \r\n", err) return err } return nil } // Get 获取设备对象 func (e *IotDeviceService) Get(d *dto.IotDeviceGetReq, p *permission.DataPermission, model *models.IotDevice) error { var data models.IotDevice err := e.Orm.Model(&data).Scopes( permission.Permission(data.TableName(), p), ).First(model, d.GetId()).Error if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { err = errors.New("查看对象不存在或无权查看") e.Log.Errorf("Service GetIotDevice error:%s \r\n", err) return err } if err != nil { e.Log.Errorf("db error:%s", err) return err } return nil } // Insert 添加设备对象 func (e *IotDeviceService) Insert(c *dto.IotDeviceInsertReq, p *permission.DataPermission) error { var err error data := &models.IotDevice{} last := &models.IotDevice{} e.Orm.Model(data).Scopes( permission.Permission(data.TableName(), p), ).Select("sn").Where("parent_id = ? AND type = ?", c.ParentId, c.Type).Order("created_at desc,id desc").Find(last) last.Type = c.Type if c.Type == constant.IotDeviceTypeMeter && last.Sn == "" { parent := &models.IotDevice{} e.Orm.Model(parent).First(parent, "id = ?", c.ParentId) if parent.Sn == "" { return errors.New("父设备编码为空") } last.Sn = parent.Sn } data.Last = last c.Generate(data) if data.Type == constant.IotDeviceTypeMeter && data.Dsn == "" { return errors.New("设备上报配置解析失败") } err = e.Orm.Create(data).Error if err != nil { e.Log.Errorf("IotDeviceService Insert error:%s \r\n", err) return err } if data.Type == constant.IotDeviceTypeGateway { err = updateDeviceMap(data.Id, constant.IotDeviceAdd) } else { err = updateDeviceMap(data.ParentId, constant.IotDeviceAdd) } if err != nil { return err } return nil } // Update 修改设备对象 func (e *IotDeviceService) Update(c *dto.IotDeviceUpdateReq, p *permission.DataPermission) error { var err error var data = models.IotDevice{} e.Orm.Scopes( permission.Permission(data.TableName(), p), ).First(&data, c.GetId()) c.Generate(&data) if data.Type == constant.IotDeviceTypeMeter && data.Dsn == "" { return errors.New("设备上报配置解析失败") } db := e.Orm.Save(&data) if err = db.Error; err != nil { e.Log.Errorf("IotDeviceService Save error:%s \r\n", err) return err } if db.RowsAffected == 0 { return errors.New("无权更新该数据") } if data.Type == constant.IotDeviceTypeGateway { err = updateDeviceMap(data.Id, constant.IotDeviceUpdate) } else { err = updateDeviceMap(data.ParentId, constant.IotDeviceUpdate) } if err != nil { return err } return nil } // Remove 删除设备 func (e *IotDeviceService) Remove(d *dto.IotDeviceDeleteReq, p *permission.DataPermission) error { var data models.IotDevice var devices = make([]models.IotDevice, 0) db := e.Orm.Model(&data).Scopes( permission.Permission(data.TableName(), p), ).Find(&devices, d.GetId()).Delete(&data, d.GetId()) if err := db.Error; err != nil { e.Log.Errorf("Service RemoveIotDevice error:%s \r\n", err) return err } if db.RowsAffected == 0 { return errors.New("无权删除该数据") } if len(devices) > 0 { var err error for _, device := range devices { if device.Type == constant.IotDeviceTypeGateway { err = updateDeviceMap(device.Id, constant.IotDeviceDelete) } else { err = updateDeviceMap(device.ParentId, constant.IotDeviceDelete) } if err != nil { return err } } } return nil } func (e *IotDeviceService) GetDeviceProtocols(list *[]string) { *list = iotProtocol.GetMeterProtocols() } func (e *IotDeviceService) GetReportProtocols(list *[]string) { *list = iotProtocol.GetPlatProtocols() } func (e *IotDeviceService) Refresh() error { err := updateDeviceMap(0, constant.IotDeviceRefresh) return err } func (e *IotDeviceService) GetDeviceConfig(d *dto.IotDeviceGetReq, p *permission.DataPermission, data *map[string]interface{}) error { device, err := getMeterById(d.Id, p, e) if err != nil { return err } var cfg interface{} sn := device.Sn if strings.Contains(sn, "_") { arr := strings.Split(sn, "_") sn = arr[0] } ok := iotMeter.IsOnline(sn) if ok { cfg, err = iotMeter.GetMeterConfig(sn, device.Protocol, device.Address) if err != nil { return err } } *data = mergeDeviceConfig(device.OtherConfig, cfg) return nil } func (e *IotDeviceService) SetDeviceConfig(d *dto.IotDeviceSetConfigReq, p *permission.DataPermission) error { device, err := getMeterById(d.Id, p, e) if err != nil { return err } if err = verifyDeviceConfig(device, d.Config); err != nil { return err } sn := device.Sn if strings.Contains(sn, "_") { arr := strings.Split(sn, "_") sn = arr[0] } ok := iotMeter.IsOnline(sn) if ok { if err = iotMeter.SetMeterConfig(sn, device.Protocol, device.Address, &d.Config); err != nil { return err } } err = e.Orm.Model(device).Update("other_config", d.Config).Error return err } func (e *IotDeviceService) GetDeviceLastData(d *dto.IotDeviceGetReq, p *permission.DataPermission, m *map[string]interface{}) error { device, err := getMeterById(d.Id, p, e) if err != nil { return err } data, err := iotLog.GetLastData(device.Sn) if err != nil { return err } *m, err = utils.ToMap(*data) return err } func getMeterById(id int, p *permission.DataPermission, e *IotDeviceService) (*models.IotDevice, error) { device := &models.IotDevice{} err := e.Orm.Model(device).Scopes( permission.Permission(device.TableName(), p), ).First(device, id).Error if err != nil { e.Log.Errorf("IotDeviceService GetDeviceConfig error:%s \r\n", err) return nil, err } if device == nil { return nil, errors.New("设备不存在或没有设备权限") } if device.Type != constant.IotDeviceTypeMeter { return nil, errors.New("设备类型不支持此操作") } return device, err } func updateDeviceMap(deviceId int, changeType int) error { q := sdk.Runtime.GetMemoryQueue("") mp := make(map[string]interface{}) mp["id"] = deviceId mp["type"] = changeType message, err := sdk.Runtime.GetStreamMessage("", global.DtuDeviceChange, mp) if err != nil { logger.Errorf("构建更新设备列表 message [%s]失败: %v", global.DtuDeviceChange, err) return err } err = q.Append(message) if err != nil { logger.Errorf("更新设备设备列表失败: %v", err) return err } return nil } func verifyDeviceConfig(device *models.IotDevice, cfgStr string) (err error) { var cfg interface{} if cfgStr == "" { return errors.New("配置不能为空") } ok := iotMeter.IsOnline(device.Sn) if ok { var handler iotInterface.MeterHandler handler, err = iotProtocolHandler.GetMeterHandler(device.Protocol) if err != nil { return err } cfg, err = handler.VerifyConfig(&cfgStr) if err != nil { return err } } else { err = json.Unmarshal([]byte(cfgStr), &cfg) if err != nil { return err } } var mp map[string]interface{} mp, err = utils.ToMap(cfg) if err != nil { return err } if strings.HasPrefix(device.Protocol, "El-") { if mp["pvRef"] == "" || mp["pvRef"] == "0" || mp["pvRef"] == 0 || mp["pvRef"] == nil { return errors.New("相基准电压[pvRef]不能为空") } if mp["lvRef"] == "" || mp["lvRef"] == "0" || mp["lvRef"] == 0 || mp["lvRef"] == nil { return errors.New("线基准电压[lvRef]不能为空") } } return err } func mergeDeviceConfig(first string, second interface{}) map[string]interface{} { sMp := make(map[string]interface{}) if second != nil { sMp, _ = utils.ToMap(second) } if first == "" { return sMp } fMp := make(map[string]interface{}) if err := json.Unmarshal([]byte(first), &fMp); err != nil { return sMp } return mergeConfigs(fMp, sMp) } func mergeConfigs(first map[string]interface{}, second map[string]interface{}) map[string]interface{} { mp := make(map[string]interface{}) for k, v := range first { mp[k] = v } for k, v := range second { mp[k] = v } return mp }