package service import ( "encoding/json" "errors" "fmt" "reflect" "rtzh_elec_temperature/conf" "rtzh_elec_temperature/datachannel" "rtzh_elec_temperature/enum" "rtzh_elec_temperature/global" "rtzh_elec_temperature/logger" "rtzh_elec_temperature/models/bo" "rtzh_elec_temperature/mqtt" "rtzh_elec_temperature/rtelec_app_public_lib/utils" "rtzh_elec_temperature/tools" "strconv" "strings" "sync" "time" "git.rtzhtech.cn/iss/public-lib/logic" "git.rtzhtech.cn/iss/public-lib/model" "github.com/astaxie/beego/orm" "github.com/spf13/cast" "github.com/wxnacy/wgo/arrays" ) //设备测点映射缓存 var deviceMappinInfo = sync.Map{} //设备测点列表缓存 var deviceMpList = sync.Map{} //创建设备时提交的数据信息 var deviceInfoData = new(sync.Map) var Device_name_id_Cache *sync.Map var Device_id_name_Cache *sync.Map var DeviceList_Cache *sync.Map //公共平台设备服务,提供设备的维护等 type DeviceService struct { BaseService DeviceId int Model DeviceInfo } type DeviceInfo struct { DeviceId int DeviceName string PageIndex int PageSize int AppId int32 ActionId string AttrName string } type CpInfo struct { Deviceid int `json:"deviceid"` Attrname string `json:"attrname"` Cpname string `json:"cpname"` Positionname string `json:"positionname"` State string `json:"state"` State_value string `json:"state_value"` Mpname string `json:"mpname"` } type ControlCommand struct { Deviceid int `json:"deviceid"` AttrName string `json:"attr_name"` Modelid int `json:"modelid"` Devicename string `json:"devicename"` } //设备列表及状态模型 type DeviceAndStateInfo struct { Deviceid int `json:"deviceid"` Devicename string `json:"devicename"` Area string `json:"area"` Working string `json:"working"` } func init() { logger.Logger.Println("初始化设备服务") go func() { ins := new(DeviceService) //启动设备离线检查进程 logger.Logger.Println("启动设备离线检查进程") ins.CheckDeviceState() }() go func() { logger.Logger.Println("启动设备添加回复处理进程") for { data, ok := <-datachannel.Service_DeviceAdd_Chanl logger.Logger.Debug(fmt.Sprintf("=======接收到中台回复的设备添加数据:%+v", data)) if ok { ins := new(DeviceService) go ins.HandleAddDevice(data, tools.IsEmpty(data["mid"])) } } }() go func() { logger.Logger.Println("启动设备删除回复处理进程") for { data, ok := <-datachannel.Service_DeviceDel_Chanl logger.Logger.Debug(fmt.Sprintf("=======接收到中台回复的设备删除数据:%+v", data)) if ok { ins := new(DeviceService) go ins.HandleDelete(data, tools.IsEmpty(data["mid"])) } } }() } //查询设备类型列表 func (c *DeviceService) SearchDeviceTypeList() (interface{}, error) { if v, h := global.GoCahce.Get("SearchDeviceTypeList"); h { return v.([]orm.Params), nil } db := orm.NewOrm() db.Using("iss") rowset := []orm.Params{} sql := "select * from dev_type order by id" _, err := db.Raw(sql).Values(&rowset) if err != nil { logger.Logger.Error(err) return nil, err } global.GoCahce.Set("SearchDeviceTypeList", rowset, -1) return rowset, err } //创建设备信息 func (t *DeviceService) CreateDevice(messageId string, field model.DevDevinfo, MpInfo []model.DevMpinfo, controlInfo []map[string]interface{}) error { var parameter = make(map[string]interface{}) parameter["token"] = RtelecManageApp().AppToken parameter["mid"] = messageId //mqtt消息中的message数据处理 var para = make(map[string]interface{}) if field.Deviceid > 0 { para["id"] = field.Deviceid } utils.MessageIds.Set(messageId, messageId) para["model_id"] = field.Modelid para["device_name"] = field.Devicename para["serial"] = field.Serial para["baudrate"] = strconv.FormatInt(int64(field.Baudrate), 10) para["stop_bit"] = strconv.FormatInt(int64(field.Stopbit), 10) para["check_bit"] = field.Checkbit para["data_bit"] = strconv.FormatInt(int64(field.Databit), 10) para["ip"] = field.IP para["port"] = strconv.FormatInt(int64(field.Port), 10) para["eid"] = field.Eid para["client_id"] = RtelecManageApp().RegAppID para["slave_id"] = strconv.FormatInt(int64(field.Slaveid), 10) para["mqtt_topic"] = field.Mqtttopic para["dev_type_id"] = field.DevTypeId para["region_id"] = field.RegionId deviceInfoData.Store("dev_"+messageId, field) //设备信息 if len(MpInfo) > 0 { deviceInfoData.Store("mp_"+messageId, MpInfo) //测点信息 } if len(controlInfo) > 0 { deviceInfoData.Store("control_"+messageId, controlInfo) //控制点及动作信息 } Message, _ := json.Marshal(para) msg, _ := new(utils.ToolsLogic).EncryptMsg(Message, []byte(conf.GlobalConfig["rtelec_manage_password"]), true) parameter["message"] = msg value, _ := json.Marshal(parameter) mqtt.PublishMessage(global.Rtelec_Topics["device_add"], string(value)) return nil } //删除中台上的设备信息 func (t *DeviceService) DeleteDeviceByMqtt(deviceId int) error { var parameter = make(map[string]interface{}) var mid = fmt.Sprintf("%d_%s", deviceId, tools.GetUid()) parameter["mid"] = mid parameter["token"] = RtelecManageApp().AppToken utils.MessageIds.Set(mid, mid) //mqtt消息中的message数据处理 var para = make(map[string]interface{}) para["id"] = deviceId Message, _ := json.Marshal(para) msg, _ := new(utils.ToolsLogic).EncryptMsg(Message, []byte(conf.GlobalConfig["rtelec_manage_password"]), true) parameter["message"] = msg value, _ := json.Marshal(parameter) mqtt.PublishMessage(global.Rtelec_Topics["device_del"], string(value)) return nil } //从订阅的mqtt消息中取得deviceid并添加设备、测点、控制点、控制点动作 func (t *DeviceService) HandleAddDevice(data map[string]interface{}, messageId string) { if message, ok := data["message"]; ok && tools.IsEmpty(message) != "" { var tempData map[string]interface{} if reflect.TypeOf(message).Kind() == reflect.String { bytes := []byte(message.(string)) err := json.Unmarshal(bytes, &tempData) if err != nil { logger.Logger.Error(err) new(utils.MsgStateManage).SetMessageStateObj(messageId, utils.MsgState{Success: false, State: true, Message: tempData["message"].(string)}) return } } if cast.ToInt(tempData["code"]) == 200 { new(utils.MsgStateManage).SetMessageStateObj(messageId, utils.MsgState{Success: true, State: true, Message: ""}) deviceId := tempData["data"].(map[string]interface{})["id"] tmpV, _ := deviceInfoData.Load("dev_" + messageId) field := tmpV.(model.DevDevinfo) dev_id := strconv.FormatFloat(deviceId.(float64), 'f', 0, 64) field.Deviceid = cast.ToInt32(dev_id) logger.Logger.Debug(fmt.Sprintf("===========添加设备到ISS库:%+v", field)) t.EditDevice(field, messageId) } else { logger.Logger.Debug(fmt.Sprintf("===========添加设备失败:%s", message.(string))) new(utils.MsgStateManage).SetMessageStateObj(messageId, utils.MsgState{Success: false, State: false, Message: tools.IsEmpty(tempData["message"])}) } } } func (t *DeviceService) EditDevice(field model.DevDevinfo, mid string) error { deviceObject := logic.NewDeviceLogic() var err error var desc = "添加" var isAdd = true exists, online := t.exists_device(field.Deviceid) if exists { isAdd = false desc = "修改" field.Online = online field.UpdateAt = time.Now().Local() err = deviceObject.ModifyDevice(&field) } else { field.Online = 1 //添加设备时默认为离线 field.Disable = 1 //默认为启用 1 启用 2禁用 field.CreateAt = time.Now().Local() field.UpdateAt = time.Now().Local() err = deviceObject.AddDevice(&field) } context, _ := json.Marshal(field) if err != nil { new(LogService).SaveLog(fmt.Sprintf("%s设备记录失败!参数值:%s,失败原因:%s", desc, string(context), err.Error())) } else { //清除缓存 global.GoCahce.Delete("devicelistall") global.GoCahce.Delete("GetAllDevice") //重新加载设备缓存 go t.LoadDefaultDeviceAttr(true) new(LogService).SaveLog(fmt.Sprintf("%s设备记录成功!参数值:%s", desc, string(context))) ////编辑测点 tmpV, ok := deviceInfoData.Load("mp_" + mid) if !ok { return nil } Mp_Field := tmpV.([]model.DevMpinfo) logger.Logger.Debug(fmt.Sprintf("================编辑测点:%+v", Mp_Field)) t.EditMpInfo(Mp_Field, field.Deviceid, isAdd) tmpV, ok = deviceInfoData.Load("control_" + mid) if !ok { return nil } controlInfo := tmpV.([]map[string]interface{}) //添加控制点及控制点动作 t.EditControlInfo(controlInfo, field.Deviceid, isAdd) } return err } //根据deviceid或mapid删除测点 func (t *DeviceService) DeleteMapByDeviceId(deviceId int32, MpId int64) error { var mpObject = logic.NewMpInfoLogic() var sqlCommandText, description = "", "" mpMap := t.GetMapInfoByDeviceId(deviceId) mpinfo := mpMap[MpId] if mpinfo == nil { return nil } description = fmt.Sprintf("MpId:%d deviceid:%d", MpId, deviceId) sqlCommandText = fmt.Sprintf("delete from dev_mpinfo where mpid=%d and deviceid=%d ", MpId, deviceId) err := mpObject.SvcCtx.DevMpinfo.Base.Exec(sqlCommandText) logdesc := fmt.Sprintf("删除设备测点,操作数据:%s", description) if err == nil { if MpId > 0 { //删除测点的历史数据 new(HistoryService).DeleteHistory(deviceId, MpId) //删除关联测点分组数据 mpMgr := new(MpinfoService) mpMgr.UserInfo = t.UserInfo mpMgr.DeleteMp(deviceId, MpId) //删除关联的测点告警配置 //FIX... //删除关联的测点优化配置 attrname := tools.IsEmpty(mpinfo["attrname"]) go new(DataoptimizeService).DeleteAttrnameOptimize("invalid", deviceId, attrname) go new(DataoptimizeService).DeleteAttrnameOptimize("deletion", deviceId, attrname) //删除关联的控制点配置 //FIX... } go new(LogService).SaveLog(fmt.Sprintf("删除测点数据记录成功,删除条件:%s", description)) new(bo.SystemLog).Success( enum.AuditType_device, enum.LogType_Delete, enum.OptEventType_System, enum.OptEventLevel_Hight, logdesc, global.SystemLogDefaultAccount, ) deviceMpList.Delete(fmt.Sprintf("MpList_%d_0", deviceId)) //清除缓存的测点列表 global.GoCahce.Delete(fmt.Sprintf("MpInfo_%d", deviceId)) //清除以模型属性缓存的测点定义 global.GoCahce.Delete(fmt.Sprintf("MapInfoByDeviceId_%d", deviceId)) //清除以测点id缓存的测点定义 return nil } else { logger.Logger.Error(err) go new(LogService).SaveLog(fmt.Sprintf("删除测点数据记录失败,删除条件:%s", description+err.Error())) new(bo.SystemLog).Fail( enum.AuditType_device, enum.LogType_Delete, enum.OptEventType_System, enum.OptEventLevel_Hight, logdesc, global.SystemLogDefaultAccount, ) return err } } //根据deviceid删除控制点及控制点动作数据记录 func (t *DeviceService) DeleteControlByDeviceId(deviceId int32, controlId int64, actionId int64) { //删除控制点动作 var mpObject = logic.NewMpInfoLogic() var sqlCommandText = "" if deviceId > 0 { sqlCommandText = fmt.Sprintf("delete from dev_cpaction where cpid in (select cpid from dev_cpinfo where deviceid=%d);", deviceId) } else if controlId > 0 { sqlCommandText = fmt.Sprintf("delete from dev_cpinfo where cpid=%d;", controlId) } else if actionId > 0 { sqlCommandText = fmt.Sprintf("delete from dev_cpaction where actid=%d;", actionId) } var err = mpObject.SvcCtx.AlarmStrategy.Base.Exec(sqlCommandText) if err == nil { sqlCommandText = "" if deviceId > 0 { sqlCommandText = fmt.Sprintf("delete from dev_cpinfo where deviceid=%d;", deviceId) } else if controlId > 0 { sqlCommandText = fmt.Sprintf("delete from dev_cpaction where cpid=%d;", controlId) } if sqlCommandText != "" { err = mpObject.SvcCtx.AlarmStrategy.Base.Exec(sqlCommandText) } } } func (t *DeviceService) exists_device(deviceId int32) (bool, int32) { l := logic.NewDeviceLogic() var online int32 = 0 type ExistsDevice struct { Deviceid int32 `json:"deviceid"` Online int32 `json:"online"` } var list []ExistsDevice sqlCommandText := fmt.Sprintf("select deviceid,online from dev_devinfo where appid=%s and deviceid=%d ", RtelecManageApp().RegAppID, deviceId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) var exists bool if err == nil { if len(list) == 0 { exists = false } else { online = list[0].Online exists = true } } else { logger.Logger.Error(err) } return exists, online } //编辑测点数据记录 func (t *DeviceService) EditMpInfo(mpData []model.DevMpinfo, DeviceId int32, isAdd bool) error { if len(mpData) == 0 { if !isAdd { //如果修改的时候测点为空则删除原来的测点 t.DeleteMapByDeviceId(DeviceId, 0) } } else { mpinfoObject := logic.NewMpInfoLogic() var oldMpid = make(map[int64]int64) if !isAdd { //如果为修改时获取原来的测点id mpinfo := t.GetMapInfoByDeviceId(DeviceId) for mpid, _ := range mpinfo { mpid := cast.ToInt64(mpid) oldMpid[mpid] = mpid } } var err error var mpid int64 = 0 appid := cast.ToInt(RtelecManageApp().RegAppID) logger.Logger.Debug(fmt.Sprintf("============%+v保存测点=================:%+v", isAdd, mpData)) for _, Record := range mpData { Record.Deviceid = DeviceId mpid = Record.Mpid if mpid == 0 { //判断模型属性是否已绑定测点 hasMp := t.DeviceMpInfo(DeviceId) if hasMp[Record.Attrname] != nil { tmpObj := hasMp[Record.Attrname] return errors.New(fmt.Sprintf("模型属性名%s已关联到测点%s", Record.Attrname, tmpObj["mpname"])) } Record.Mpid = new(utils.ToolsLogic).GetOnlyId(int64(appid)) err = mpinfoObject.AddMpInfo(&Record) } else { if _, ok := oldMpid[Record.Mpid]; ok { oldMpid[mpid] = 0 //不删除的记录 } err = mpinfoObject.ModifyMpInfo(&Record) } if err != nil { logger.Logger.Println(fmt.Sprintf("设备测点编辑:%+v", Record)) logger.Logger.Error(fmt.Sprintf("设备测点编辑错误:%+v", err)) return err } } deviceMpList.Delete(fmt.Sprintf("MpList_%d_0", DeviceId)) //清除缓存的测点列表 global.GoCahce.Delete(fmt.Sprintf("MpInfo_%d", DeviceId)) //清除以模型属性缓存的测点定义 global.GoCahce.Delete(fmt.Sprintf("MapInfoByDeviceId_%d", DeviceId)) //清除以测点id缓存的测点定义 if !isAdd && len(oldMpid) > 0 { for _, val := range oldMpid { if val > 0 { t.DeleteMapByDeviceId(0, val) } } } } return nil } //编辑控制点及控制动作数据记录 func (t *DeviceService) EditControlInfo(data []map[string]interface{}, DeviceId int32, isAddRecord bool) { if len(data) == 0 { if !isAddRecord { //如果修改的时候控制点为空则删除控制点及控制动作 t.DeleteControlByDeviceId(DeviceId, 0, 0) } } else { var control = make(map[int64]int64) var control_action = make(map[int64]int64) if !isAddRecord { control, control_action = t.GetControlByDeviceId(DeviceId) } appid := cast.ToInt(RtelecManageApp().RegAppID) for _, row := range data { var isAdd = false var ControlField = row["control"].(model.CpMpinfo) CpInfoObject := logic.NewCpInfoLogic() if ControlField.Cpid == 0 { isAdd = true ControlField.Cpid = new(utils.ToolsLogic).GetOnlyId(int64(appid)) } else { if _, ok := control[ControlField.Cpid]; ok { control[ControlField.Cpid] = 0 } } ControlField.Deviceid = DeviceId if isAdd { CpInfoObject.AddCpInfo(&ControlField) } else { CpInfoObject.ModifyCpInfo(&ControlField) } var ActionData = row["action"].([]model.DevCpaction) if len(ActionData) > 0 { ActionObject := logic.NewActInfoLogic() for _, actionRow := range ActionData { actionRow.Cpid = ControlField.Cpid isAdd = false if actionRow.Actid == 0 { isAdd = true actionRow.Actid = new(utils.ToolsLogic).GetOnlyId(int64(appid)) } else { if _, ok := control_action[actionRow.Actid]; ok { control_action[actionRow.Actid] = 0 } } if isAdd { ActionObject.AddActInfo(&actionRow) } else { ActionObject.ModifyActInfo(&actionRow) } } } } if !isAddRecord && len(control) > 0 { for _, val := range control { if val > 0 { fmt.Println("===delete control==", val) t.DeleteControlByDeviceId(0, val, 0) } } } if !isAddRecord && len(control_action) > 0 { for _, val := range control_action { if val > 0 { fmt.Println("===delete control_action==", val) t.DeleteControlByDeviceId(0, 0, val) } } } } } //根据DeviceId获取原来的测试id func (t *DeviceService) GetControlByDeviceId(deviceId int32) (map[int64]int64, map[int64]int64) { l := logic.NewCpInfoLogic() type ActionInfo struct { Cpid int64 `json:"cpid"` Actid int64 `json:"actid"` } var list []ActionInfo var sqlCommandText = fmt.Sprintf("select b.actid ,a.cpid from dev_cpinfo a inner join dev_cpaction b on a.cpid=b.cpid where a.deviceid=%d ", deviceId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) var Control = make(map[int64]int64) var controls = []int64{} var controlAction = make(map[int64]int64) var cpid int64 = 0 if err == nil && len(list) > 0 { for _, record := range list { cpid = record.Cpid controlAction[record.Actid] = record.Actid if arrays.Contains(controls, cpid) == -1 { Control[cpid] = cpid controls = append(controls, cpid) } } } else { logger.Logger.Error(err) } return Control, controlAction } //删除设备数据记录 func (t *DeviceService) HandleDelete(data map[string]interface{}, messageId string) { if message, ok := data["message"]; ok && tools.IsEmpty(message) != "" { var tempData map[string]interface{} if reflect.TypeOf(message).Kind() == reflect.String { bytes := []byte(message.(string)) err := json.Unmarshal(bytes, &tempData) if err == nil { if cast.ToInt(tempData["code"]) == 200 { //同时删除本地数据数据记录 id := strings.Split(messageId, "_") if len(id) > 1 { deviceId := cast.ToInt32(id[0]) l := logic.NewDeviceLogic() err := l.DelDevice(deviceId) if err != nil { logger.Logger.Error(err) } logdesc := fmt.Sprintf("删除设备记录(deviceId=%d)", deviceId) if err == nil { //清除缓存 global.GoCahce.Delete("devicelistall") global.GoCahce.Delete("GetAllDevice") deviceMpList.Delete(fmt.Sprintf("MpList_%d_0", deviceId)) //清除缓存的测点列表 global.GoCahce.Delete(fmt.Sprintf("MpInfo_%d", deviceId)) //清除以模型属性缓存的测点定义 global.GoCahce.Delete(fmt.Sprintf("MapInfoByDeviceId_%d", deviceId)) //清除以测点id缓存的测点定义 //重新获取数据 go t.GetComboxList() //清除监测数据记录 go new(HistoryService).DeleteHistory(deviceId, 0) go new(DataoptimizeService).DeleteOptimize("deletion", deviceId) go new(DataoptimizeService).DeleteOptimize("invaild", deviceId) //删除告警配置 //FIX:.... //删除告警记录 //FIX:.... new(LogService).SaveLog(logdesc) new(bo.SystemLog).Success( enum.AuditType_device, enum.LogType_Delete, enum.OptEventType_System, enum.OptEventLevel_Hight, logdesc, global.SystemLogDefaultAccount, ) } else { new(LogService).SaveLog(fmt.Sprintf("删除设备记录失败(deviceId=%v)", deviceId)) new(bo.SystemLog).Fail( enum.AuditType_device, enum.LogType_Delete, enum.OptEventType_System, enum.OptEventLevel_Hight, logdesc, global.SystemLogDefaultAccount, ) } } } } } } } // 默认加载设备名称与设备ID对应关系 func (t *DeviceService) LoadDefaultDeviceAttr(refresh bool) *sync.Map { if refresh || Device_name_id_Cache == nil { var list = []orm.Params{} var sqlCommandText = "select * from dev_devinfo where appid=? " db := orm.NewOrm() db.Using("iss") _, err := db.Raw(sqlCommandText, RtelecManageApp().RegAppID).Values(&list) if err == nil { Device_name_id_Cache = new(sync.Map) Device_id_name_Cache = new(sync.Map) for _, record := range list { Device_name_id_Cache.Store(tools.IsEmpty(record["devicename"]), tools.IsEmpty(record["deviceid"])) Device_id_name_Cache.Store(tools.IsEmpty(record["deviceid"]), tools.IsEmpty(record["devicename"])) } } else { logger.Logger.Error(err) logger.Logger.Println(fmt.Sprintf("Error SQL:%s Paramers:%s", sqlCommandText, RtelecManageApp().RegAppID)) } } return Device_name_id_Cache } //设备名称与设备id对应关系 func (t *DeviceService) DeviceNameByID() *sync.Map { if Device_id_name_Cache == nil { t.LoadDefaultDeviceAttr(true) } return Device_id_name_Cache } //设备名称与设备id对应关系 func (t *DeviceService) DeviceIdByDeviceName() *sync.Map { if Device_name_id_Cache == nil { t.LoadDefaultDeviceAttr(true) } return Device_name_id_Cache } //设备在线状态 1离线/2 在线 /3 超时,持续超时次数5次则离线 func (t *DeviceService) SetDeviceState(deviceId int, state int) error { db := orm.NewOrm() db.Using("iss") var sqlCommandText = "update dev_devinfo set online=? where deviceid=?" _, err := db.Raw(sqlCommandText, state, deviceId).Exec() if err != nil { logger.Logger.Error(err) logger.Logger.Println(fmt.Sprintf("Error SQL:%s Paramers:%d,%s", sqlCommandText, state, deviceId)) } return err } //查询设备记录信息 func (c *DeviceService) SearchDeviceList(params map[string]interface{}) (interface{}, int, error) { db := orm.NewOrm() db.Using("iss") sql := "select * from dev_devinfo where appid=? " sqlParamters := []interface{}{ RtelecManageApp().RegAppID, } pno := cast.ToInt(params["PageIndex"]) psize := cast.ToInt(params["PageSize"]) sqlLimit := fmt.Sprintf(" limit %d,%d", (pno-1)*psize, psize) if v, h := params["DeviceName"]; h { v2 := v.(string) if v2 != "" { sql += " and devicename like ?" sqlParamters = append(sqlParamters, "%"+v.(string)+"%") } } if v, h := params["Regionid"]; h { v2 := cast.ToInt(v) if v2 > 0 { sql += " and region_id=?" sqlParamters = append(sqlParamters, v2) } } if v, h := params["Typeid"]; h { v2 := cast.ToInt(v) if v2 > 0 { sql += " and dev_type_id=?" sqlParamters = append(sqlParamters, v2) } } if v, h := params["Modelid"]; h { v2 := cast.ToInt(v) if v2 > 0 { sql += " and modelid=?" sqlParamters = append(sqlParamters, v2) } } list := []orm.Params{} _, err := db.Raw(sql+" order by id desc "+sqlLimit, sqlParamters).Values(&list) if err != nil { logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", sql+sqlLimit, sqlParamters)) return nil, 0, err } //获取总数 totalSql := strings.Replace(sql, "*", "count(1) cnt", 1) totalRowset := []orm.Params{} _, err = db.Raw(totalSql, sqlParamters).Values(&totalRowset) if err != nil { logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%+v", totalSql, sqlParamters)) return nil, 0, err } if len(totalRowset) == 0 { return list, 0, err } cnt := cast.ToInt(totalRowset[0]["cnt"]) return list, cnt, err } //查询设备记录信息(包含设备信息、测点信息、控制点信息) func (c *DeviceService) DeviceDetail() (map[string]interface{}, error) { var result = map[string]interface{}{"device": model.DevDevinfo{}, "measure": []interface{}{}, "control": []interface{}{}} deviceObject := logic.NewDeviceLogic() var list model.DevDevinfo //设备基本信息 var sqlCommandText = fmt.Sprintf("select * from dev_devinfo where deviceid=%d and appid=%s", c.DeviceId, RtelecManageApp().RegAppID) err := deviceObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) if err == nil { result["device"] = list } measureObject := logic.NewMpInfoLogic() var devMpList []model.DevMpinfo //设备测点信息 sqlCommandText = fmt.Sprintf("select * from dev_mpinfo where deviceid=%d and appid=%s", c.DeviceId, RtelecManageApp().RegAppID) err = measureObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &devMpList) if err == nil { result["measure"] = devMpList } controlObject := logic.NewCpInfoLogic() type DevCpinfo struct { ID int32 `json:"id"` Cpid int64 `json:"cpid,string"` Cpname string `json:"cpname"` Zonename string `json:"zonename"` Positionname string `json:"positionname"` Appid int32 `json:"appid"` Modelid int32 `json:"modelid"` Deviceid int32 `json:"deviceid"` Attrname string `json:"attrname"` Mpid int64 `json:"mpid,string"` Mpname string `json:"mpname,string"` Action interface{} `json:"action"` } var controlList []DevCpinfo sqlCommandText = fmt.Sprintf("select c.*,null action ,m.attrname mattrname,m.mpname from dev_cpinfo c left JOIN dev_mpinfo m on m.mpid=c.mpid where c.deviceid=%d and c.appid=%s", c.DeviceId, RtelecManageApp().RegAppID) err = controlObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &controlList) if err == nil { for index, record := range controlList { list, err2 := c.devCpactionInfo(record.Cpid) if err2 == nil { controlList[index].Action = list } } result["control"] = controlList } return result, err } //控制动作详情 func (c *DeviceService) devCpactionInfo(controlId int64) ([]model.DevCpaction, error) { var ActionList []model.DevCpaction var sqlCommandText = fmt.Sprintf("select * from dev_cpaction where cpid=%d", controlId) controlObject := logic.NewCpInfoLogic() err := controlObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &ActionList) return ActionList, err } //设备统计信息 func (c *DeviceService) DeviceStatistics() (map[string]interface{}, error) { var AppId = cast.ToInt(RtelecManageApp().RegAppID) var result = make(map[string]interface{}) mpObject := logic.NewMpInfoLogic() //照明灯具统计 type mpTotal struct { Recordcount int `json:"recordcount"` } var total mpTotal var sqlCommandText = fmt.Sprintf("select count(1) recordcount from dev_devinfo a inner join dev_mpinfo b on a.deviceid=b.deviceid where a.appid=%d;", AppId) err := mpObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &total) if err == nil { result["bulb"] = total.Recordcount } //控制器统计 controlObject := logic.NewCpInfoLogic() sqlCommandText = fmt.Sprintf("select count(1) recordcount from dev_devinfo a inner join dev_cpinfo b on a.deviceid=b.deviceid where a.appid=%d;", AppId) err = controlObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &total) if err == nil { result["controller"] = total.Recordcount } //已开启照明灯具(该处未处理) result["light"] = c.online(AppId) //故障设备数量 result["fault"] = 0 sqlCommandText = fmt.Sprintf("select count(1) recordcount from dev_devinfo a inner join dev_mpinfo b on a.deviceid=b.deviceid where a.online!=2 and a.appid=%d;", AppId) err = mpObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &total) if err == nil { result["fault"] = total.Recordcount } return result, err } //根据DeviceId获取设备测点定义。以map结构返回,其中Key为测点ID func (c *DeviceService) GetMapInfoByDeviceId(deviceId int32) map[int64]orm.Params { var Result = make(map[int64]orm.Params) cachekey := fmt.Sprintf("MapInfoByDeviceId_%d", deviceId) if v, h := global.GoCahce.Get(cachekey); h { return v.(map[int64]orm.Params) } list, _, err := c.DeviceMpList(deviceId, 1, 10000) if err == nil && len(list) > 0 { for _, record := range list { mpid, _ := strconv.ParseInt(tools.IsEmpty(record["mpid"]), 10, 64) Result[mpid] = record } global.GoCahce.Set(cachekey, Result, -1) } return Result } func (c *DeviceService) online(AppId int) int { var result = 0 controlObject := logic.NewCpInfoLogic() type DeviceService struct { Deviceid int `json:"deviceid"` Attrname string `json:"attrname"` } var info []DeviceService var sqlCommandText = fmt.Sprintf("select b.deviceid,attrname from dev_devinfo a inner join dev_cpinfo b on a.deviceid=b.deviceid where a.appid=%d", AppId) err := controlObject.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &info) if err == nil { db := orm.NewOrm() for _, record := range info { sqlCommandText = "select val from dev_history where attrname=? and deviceid=? order by id desc limit 1" var sqlParameter = []interface{}{record.Attrname, record.Deviceid} var table []orm.Params _, err := db.Raw(sqlCommandText, sqlParameter).Values(&table) if err == nil && len(table) > 0 { var value = tools.IsEmpty(table[0]["val"]) if value == "1" { result += 1 } } } } return result } //获取设备控制点 func (c *DeviceService) GetDeviceControlId() (interface{}, error) { l := logic.NewCpInfoLogic() type Result struct { Id int64 `json:"id,string"` Name string `json:"name"` } var list []Result var sqlCommandText = fmt.Sprintf("select actid id,concat(devicename,'/',cpname,'/',actdesc) name from dev_cpinfo a inner join dev_cpaction b on a.cpid=b.cpid inner join dev_devinfo c on a.deviceid=c.deviceid where a.appid=%s;", RtelecManageApp().RegAppID) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) return list, err } //获取设备测点id func (c *DeviceService) GetDeviceMpId() (interface{}, error) { l := logic.NewCpInfoLogic() type Result struct { Id int64 `json:"id,string"` Name string `json:"name"` } var list []Result var sqlCommandText = fmt.Sprintf("select mpid id,concat(devicename,' / ',mpname) name from dev_mpinfo a inner join dev_devinfo b on a.deviceid=b.deviceid where a.appid=%s;", RtelecManageApp().RegAppID) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) return list, err } //根据设备id返回对应的modelid func (c *DeviceService) GetModelIdByDeviceId(deviceid int) (interface{}, error) { l := logic.NewDeviceLogic() var sqlCommandText = fmt.Sprintf("select modelid from dev_devinfo where deviceid=%d", deviceid) type modeidstruct struct { Modelid int } var list modeidstruct err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) return list, err } //获取区域名称 func (c *DeviceService) GetAreaName() (interface{}, error) { l := logic.NewCpInfoLogic() type Result struct { Id string `json:"id"` Name string `json:"name"` } var list []Result var sqlCommandText = fmt.Sprintf("select distinct zonename id,zonename name from dev_cpinfo where appid=%s;", RtelecManageApp().RegAppID) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) return list, err } //获取所有设备的信息。返回设备详情信息 func (c *DeviceService) GetAllDevice() ([]orm.Params, error) { if lst, has := global.GoCahce.Get("GetAllDevice"); has { return lst.([]orm.Params), nil } var appId = RtelecManageApp().RegAppID l := orm.NewOrm() l.Using("iss") list := []orm.Params{} var sqlCommandText = "select a.*,null children,0 mpid from dev_devinfo a where a.appid=?" _, err := l.Raw(sqlCommandText, appId).Values(&list) if err == nil { global.GoCahce.Set("GetAllDevice", list, -1) return list, nil } else { logger.Logger.Error(err, fmt.Sprintf("SQL:%s 参数:%s", sqlCommandText, appId)) } return nil, err } //获取场景对应的modelid func (c *DeviceService) GetModelIdBySceneName(scenename string) string { //2022-11-08增加场景分类对应的modelid获取,根据modelid再去获取场景中的设备 //---start--- var params = map[string]string{} var modelidParam = "" params["scenename"] = scenename var sceneinfo = new(SceneService) modelids, modeliderr := sceneinfo.QueryScene(params) if modeliderr != nil { tools.Log(modeliderr.Error()) } if len(modelids) > 0 { modelidParam = "(" for _, v := range modelids { modelidParam += v["modelid"].(string) + "," } modelidParam = modelidParam[:len(modelidParam)-1] + ")" } return modelidParam //---end----- } //首页设备控制列表 func (c *DeviceService) HomeDeviceList(area string, scenename string) (interface{}, error) { var AppId = cast.ToInt(RtelecManageApp().RegAppID) modelidParam := c.GetModelIdBySceneName(scenename) l := logic.NewDeviceLogic() type Result struct { Deviceid int `json:"deviced"` Devicename string `json:"devicename"` Online string `json:"online"` ControlInfo interface{} `json:"control_info"` MpValues interface{} `json:"mp_value"` } var list []Result var sqlCommandText = []string{} if area == "" { sqlCommandText = append(sqlCommandText, "select deviceid,devicename,modelid,online,null control_info,null mp_value from dev_devinfo where 1=1") if scenename != "" && modelidParam != "" { sqlCommandText = append(sqlCommandText, fmt.Sprintf(" and modelid in %s", modelidParam)) } sqlCommandText = append(sqlCommandText, fmt.Sprintf(" and appid=%d;", AppId)) } else { sqlCommandText = append(sqlCommandText, fmt.Sprintf("select deviceid,devicename,modelid,online,null control_info,null mp_value from dev_devinfo a where exists (select 1 from dev_cpinfo b where b.zonename='%s' and b.deviceid=a.deviceid and b.appid=%d) and appid=%d ", area, AppId, AppId)) if scenename != "" && modelidParam != "" { sqlCommandText = append(sqlCommandText, fmt.Sprintf("and modelid in %s", modelidParam)) } } err := l.SvcCtx.AlarmStrategy.Base.Raw(strings.Join(sqlCommandText, ""), &list) //获取设备最新的测点采集值 if err == nil { var wg = sync.WaitGroup{} wg.Add(len(list)) for index, record := range list { go func(ind int, rec Result) { dbo := orm.NewOrm() rowset := []orm.Params{} dt := time.Now().Local().Format("2006-01-02 15") //如果设置了当前模型指定测点的值转换参数,则判断当前值是否匹配设置时,如果相等,则将返回1(表示告警),否则返回测点原值 _, err := dbo.Raw("select t1.mpname,t1.attrname,case when t1.val=(select param_value from global_sys_param where param_name=concat(?,'_',t1.attrname,'_matchvalue')) then 'Y' else t1.val end val,t1.date from dev_history t1 ,(select max(t.id) id from dev_history t where t.deviceid=? and t.`date` BETWEEN ? and ? GROUP BY t.attrname limit 0,256) t2 where t1.id=t2.id", scenename, rec.Deviceid, dt+":00:00", dt+":59:59").Values(&rowset) if err != nil { logger.Logger.Error(err) } else { list[ind].MpValues = rowset } wg.Done() }(index, record) } wg.Wait() } //2022-11-08增加判断:开关属性是否是2个控制点.如果是2个控制点对应1个采集点,则需要为前端组装“采集点”->“动作点”的数据。 //如果是1个控制点本身又是采集点,则组要为前端组装“控制点”->“动作点”的数据 //http方式为1个控制点本身又是采集点 /* if scenename == "door" { if configure.AppConfigure.DoorWay == "http" { if err == nil { for index, record := range list { ControlInfo, mperror := getControlInfo(record.Deviceid, AppId) if mperror == nil { list[index].ControlInfo = ControlInfo } } } } else { if err == nil { for index, record := range list { //大点表的方式获取组装数据“采集点”->“动作点” ControlInfo, mperror := getControlInfo2(record.Deviceid, AppId) if mperror == nil { list[index].ControlInfo = ControlInfo } } } } return list, err } */ if err == nil { for index, record := range list { //大点表的方式获取组装数据“采集点”->“动作点” ControlInfo, mperror := c.getControlInfo2(record.Deviceid, AppId) if mperror == nil { list[index].ControlInfo = ControlInfo } } } return list, err } func (c *DeviceService) getControlInfo(deviceId int, AppId int) ([]CpInfo, error) { l := logic.NewCpInfoLogic() var data []CpInfo var sqlCommandText = fmt.Sprintf("select deviceid,attrname,cpname,positionname,null state,0 state_val from dev_cpinfo where deviceid=%d and appid=%d;", deviceId, AppId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &data) if err == nil { for index, record := range data { info := c.GetDeviceState(record.Deviceid, record.Attrname) data[index].State = info.State data[index].State_value = info.State_vale } } else { logger.Logger.Error(err) logger.Logger.Println(fmt.Sprintf("Error SQL:%s 参数:%d,%d", sqlCommandText, deviceId, AppId)) } return data, err } type Res struct { Deviceid int `json:"deviceid"` Attrname string `json:"attrname"` Mpid int64 `json:"mpid"` Mpname string `json:"cpname"` Positionname string `json:"positionname"` State string `json:"state"` Actions interface{} `json:"actions"` } //控制点和采集点分开的方式获取控制数据 func (c *DeviceService) getControlInfo2(deviceId int, AppId int) (interface{}, error) { l := logic.NewCpInfoLogic() var data []Res var sqlCommandText = fmt.Sprintf("SELECT DISTINCT c.mpid,c.deviceid,m.attrname,m.mpname,m.positionname FROM dev_cpinfo c LEFT JOIN dev_mpinfo m on m.mpid=c.mpid and m.deviceid=%d where c.appid=%d and c.deviceid=%d", deviceId, AppId, deviceId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &data) if err == nil { for index, record := range data { //采用通过网关去控制硬件的方式(大点表方式) //这里需要去获取这个采集点的状态,从历史数据表中获取 //因为这里是根据采集点去获取的历史状态,那么控制那边下了命令以后获取采集点状态回写历史表的时候就需要回写attrname是采集点的attrname info := c.GetDeviceState(record.Deviceid, record.Attrname) data[index].State = info.State_vale //获取采集点下属的动作 acts := c.GetActions(AppId, record.Deviceid, record.Mpid, true) data[index].Actions = acts } } return data, err } type deviceState struct { State string `json:"state"` State_vale string `json:"state_vale"` } //获取每一个控制点的状态 func (c *DeviceService) GetDeviceState(deviceId int, attrName string) deviceState { var state deviceState state.State_vale = "0" o := orm.NewOrm() var sqlCommandText = "select val from dev_history where attrname=? and deviceid=? order by id desc limit 1;" var sqlParameter = []interface{}{attrName, deviceId} table := []orm.Params{} _, err := o.Raw(sqlCommandText, sqlParameter).Values(&table) if err == nil && len(table) > 0 { val := table[0]["val"].(string) if val == "1" { state.State_vale = val } } return state } type ActionsInfo struct { Deviceid int `json:"deviceid"` //设备id Devicename string `json:"devicename"` //设备名称 Cpattrname string `json:"cpattrname"` //控制点属性名 Mpattrname string `json:"mpattrname"` //采集点属性名 Actdesc string `json:"actdesc"` //动作点名称 Value float64 `json:"value"` //动作点的值 } //根据doorway参数来判断是否是modbus方式下获取采集点下面的动作点,还是其他方式下获取控制点下面的动作点 // bool==true:采用大点表方式,控制点和采集点分开 func (c *DeviceService) GetActions(AppId int, deviceId int, mpid int64, doorway bool) []ActionsInfo { l := logic.NewCpInfoLogic() var actSql = fmt.Sprintf("SELECT i.deviceid,c.cpid,c.mpid,c.cpname,c.attrname cpattrname,a.actdesc,a.`value`,i.devicename FROM dev_cpinfo c INNER JOIN dev_cpaction a ON c.cpid = a.cpid INNER JOIN dev_devinfo i ON i.deviceid = c.deviceid WHERE c.appid =%d AND c.deviceid =%d and c.cpid=%d", AppId, deviceId, mpid) if doorway { actSql = fmt.Sprintf("SELECT i.deviceid,c.cpid,c.mpid,m.mpname,m.attrname mpattrname,a.actdesc,a.`value`,i.devicename,c.attrname cpattrname FROM dev_cpinfo c INNER JOIN dev_cpaction a ON c.cpid = a.cpid INNER JOIN dev_devinfo i ON i.deviceid = c.deviceid LEFT JOIN dev_mpinfo m ON m.mpid = c.mpid WHERE c.appid =%d AND c.deviceid = %d AND c.mpid = %d", AppId, deviceId, mpid) } var acts []ActionsInfo err := l.SvcCtx.AlarmStrategy.Base.Raw(actSql, &acts) if err != nil { tools.Log("获取动作点报错:" + err.Error()) return nil } return acts } //获取指令发送时需要的参数 //返回数据为:devicename,modelid func (c *DeviceService) GetCommandRestart() ([]orm.Params, error) { AppId := RtelecManageApp().RegAppID var list = []orm.Params{} var sqlCommandText = "select devicename,modelid from dev_devinfo where deviceid=? and appid=?" db := orm.NewOrm() db.Using("iss") _, err := db.Raw(sqlCommandText, c.DeviceId, AppId).Values(&list) if err != nil { logger.Logger.Error(err) } return list, err } //获取指令发送时需要的参数 func (c *DeviceService) GetCommandParameter() ([]ControlCommand, error) { AppId := cast.ToInt(RtelecManageApp().RegAppID) l := logic.NewDeviceLogic() var sqlCommandText = "" var list []ControlCommand sqlCommandText = "select b.deviceid,devicename,a.modelid,a.attrname attr_name,ifnull(mp.attrname,'') mpname from dev_cpinfo a inner join dev_devinfo b on a.deviceid=b.deviceid left join dev_mpinfo mp on a.mpid=mp.mpid where 1=1" if c.Model.AttrName != "" { sqlCommandText += fmt.Sprintf(" and a.attrname='%s'", c.Model.AttrName) } if c.DeviceId > 0 { sqlCommandText += fmt.Sprintf(" and a.deviceid=%d", c.DeviceId) } sqlCommandText += fmt.Sprintf(" and b.appid=%d", AppId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) if err != nil { logger.Logger.Error(err) logger.Logger.Println(sqlCommandText) } return list, err } //获取指令发送时需要的参数 func (t *DeviceService) GetCmdParameter() ([]ControlCommand, error) { AppId := cast.ToInt(RtelecManageApp().RegAppID) l := logic.NewDeviceLogic() var list []ControlCommand var sqlCommandText = "select devicename,a.modelid,attrname attr_name from dev_devinfo a inner join dev_mpinfo b on a.deviceid=b.deviceid " sqlCommandText += fmt.Sprintf(" where a.deviceid=%d", t.DeviceId) sqlCommandText += fmt.Sprintf(" and b.appid=%d", AppId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) if err != nil { logger.Logger.Error(err) logger.Logger.Println(sqlCommandText) } return list, err } type DeviceComboxList struct { Deviceid int `json:"deviceid"` Name string `json:"name"` Modelid int `json:"modelid"` } //根据设备名称获取指定设备名称的基本信息,包括deviceid,name,modileid func (t *DeviceService) GetComboxListByName(devicename string) *DeviceComboxList { lst, err := t.GetComboxList() if err != nil { return nil } for _, item := range lst { if item.Name == devicename { return &item } } return nil } //根据设备ID获取指定设备名称的基本信息,包括deviceid,name,modileid func (t *DeviceService) GetComboxListById(deviceid int32) *DeviceComboxList { lst, err := t.GetComboxList() if err != nil { return nil } for _, item := range lst { if item.Deviceid == int(deviceid) { return &item } } return nil } // 根据设备id获取该设备对应的数据表名 func (t *DeviceService) GetTableNameByDeviceId(deviceid int32) (string, error) { devInfo := t.GetComboxListById(deviceid) modelid := devInfo.Modelid ormrow, err := new(bo.Global).GetCodeInfo("model_table_mapping", cast.ToString(modelid)) if err != nil || tools.IsEmpty(ormrow["name"]) == "" { logger.Logger.Error(fmt.Sprintf("未找到模型id=d对应的数据表关系", modelid)) return "", err } localTable := "t_data_" + tools.IsEmpty(ormrow["name"]) return localTable, nil } //获取当前应用的所有设备 func (t *DeviceService) GetComboxList() ([]DeviceComboxList, error) { if lst, has := global.GoCahce.Get("devicelistall"); has { return lst.([]DeviceComboxList), nil } AppId := cast.ToInt(RtelecManageApp().RegAppID) l := logic.NewCpInfoLogic() var list []DeviceComboxList var sqlCommandText = fmt.Sprintf("select deviceid,devicename name,modelid from dev_devinfo where appid=%d;", AppId) err := l.SvcCtx.AlarmStrategy.Base.Raw(sqlCommandText, &list) if err != nil { logger.Logger.Error(err) logger.Logger.Println(sqlCommandText) } else { global.GoCahce.Set("devicelistall", list, -1) } return list, err } //总缆设备统计 func (t *DeviceService) TotalityWorking(modelidParam string) (map[int]interface{}, error) { AppId := cast.ToInt(RtelecManageApp().RegAppID) var result = map[int]interface{}{} dev := logic.NewCpInfoLogic() type DevTotal struct { TotalNum int `json:"TotalNum"` Modelid int `json:"Modelid"` OnlineNum int `json:"OnlineNum"` OfflineNum int `json:"OfflineNum"` } var devTotalObj = []DevTotal{} var sqlDevTotal = fmt.Sprintf("SELECT d.modelid, count(d.id) AS TotalNum, count(a.id) AS OnlineNum, (count(d.id)-count(a.id)) as OfflineNum FROM dev_devinfo d LEFT JOIN dev_devinfo a ON d.id = a.id and a.appid=%d and a.`online`=2 WHERE d.appid = %d ", AppId, AppId) if len(modelidParam) > 0 { sqlDevTotal += fmt.Sprintf(" and d.modelid in %s", modelidParam) } sqlDevTotal += " GROUP BY d.modelid " err := dev.SvcCtx.AlarmStrategy.Base.Raw(sqlDevTotal, &devTotalObj) if err == nil { for i := 0; i < len(devTotalObj); i++ { result[devTotalObj[i].Modelid] = devTotalObj[i] } } else { logger.Logger.Error(err) logger.Logger.Println(sqlDevTotal) } return result, nil } //检查设备状态.将超过指定时长未接收到数据的设备设置为离线状态。一般为应用完全启动成功后触发 func (t *DeviceService) CheckDeviceState() { var sqlCommandText = "" for { appid := RtelecManageApp().RegAppID if appid != "" { devicelist, _ := t.GetComboxList() if len(devicelist) == 0 { time.Sleep(1 * time.Minute) continue } mObject := new(ModelService) db := orm.NewOrm() db.Using("iss") for _, record := range mObject.GetModelListObj() { row := record.(map[string]interface{}) modelid := fmt.Sprintf("%s", row["id"].(json.Number)) v := fmt.Sprintf("%s", row["period"].(json.Number)) period, _ := strconv.ParseInt(v, 10, 64) sqlCommandText = "update dev_devinfo set online=1 where update_at 0 { v_modelid = modelid[0] } key := fmt.Sprintf("MpList_%d_%d", deviceId, v_modelid) var list = []orm.Params{} s1 := (pageindex - 1) * pagesize s2 := pageindex * pagesize if info, ok := deviceMpList.Load(key); ok { all := info.([]orm.Params) totalNum := len(all) if s2 > totalNum { s2 = totalNum } for i := s1; i < s2; i++ { list = append(list, all[i]) } return list, totalNum, nil } else { db := orm.NewOrm() db.Using("iss") var sqlCommandText = "select * from dev_mpinfo where deviceid=?" sqlParam := []interface{}{deviceId} if v_modelid > 0 { sqlCommandText = sqlCommandText + " and modelid=?" sqlParam = append(sqlParam, modelid) } _, err := db.Raw(sqlCommandText, sqlParam).Values(&list) if err == nil { if len(list) > 0 { deviceMpList.Store(key, list) relist := []orm.Params{} totalNum := len(list) if s2 > totalNum { s2 = totalNum } for i := s1; i < s2; i++ { relist = append(relist, list[i]) } return relist, totalNum, nil } } else { logger.Logger.Error(err) logger.Logger.Println(fmt.Sprintf("Error SQL:%s 参数:%+v", sqlCommandText, sqlParam)) return nil, 0, err } } return list, 0, nil } type ActionDataRow struct { Deviceid int `json:"deviceid"` Modelid int `json:"modelid"` Attrname string `json:"attrname"` Actdesc string `json:"actdesc"` Acttype string `json:"acttype"` Value float64 `json:"value"` Devicename string `json:"devicename"` Cpname string `json:"cpname"` Mpname string `json:"mpname"` } //根据设备ID返回对应的动作点信息 func (t *DeviceService) GetDeviceActionPoint(deviceid int) ([]ActionDataRow, error) { db := logic.NewDeviceLogic() var result = []ActionDataRow{} sql := fmt.Sprintf("select t.deviceid,t.modelid,t.attrname,t1.actdesc,t1.acttype,t1.value from dev_cpinfo t,dev_cpaction t1 where t.cpid=t1.cpid and t.deviceid=%d", deviceid) err := db.SvcCtx.AlarmStrategy.Base.Raw(sql, &result) if err != nil { logger.Logger.Error(err) } return result, err } //设备导入 //导入的数据列及顺序为:序号 区域名称(必填) 模型名称(必填) 设备名称(必填) 串口号 串口波特率 串口停止位 串口检测位 串口数据位 从设备ID IP地址 端口号 MQTT主题 微功耗传感器ID 设备类型(支持开关柜\台区\输电线路\杆塔) func (t *DeviceService) Imp(param map[string]interface{}) error { datalist := param["datalist"].([]map[int]string) regSrv := new(RegionService) modelSrv := new(ModelService) regLst, _ := regSrv.List(nil) regMap := map[string]string{} for _, item := range regLst { regMap[tools.IsEmpty(item["region_name"])] = tools.IsEmpty(item["id"]) } devType, _ := t.SearchDeviceTypeList() devTypeMap := map[string]string{} for _, row := range devType.([]orm.Params) { devTypeMap[tools.IsEmpty(row["type_name"])] = tools.IsEmpty(row["id"]) } modellist := modelSrv.GetModelListObj() modelMap := map[string]string{} for _, row2 := range modellist { row := row2.(map[string]interface{}) modelMap[tools.IsEmpty(row["model_name"])] = tools.IsEmpty(row["id"]) } logObj := new(bo.SystemLog) user := t.UserInfo logObj.UserInfo = map[string]interface{}{"name": user.Usrname, "ip": user.Ip} logObj.Audittype = enum.AuditType_device logObj.Eventtype = enum.OptEventType_Bus logObj.Eventlevel = enum.OptEventLevel_Hight logObj.Logtype = enum.LogType_imp logObj.Description = "导入设备" var AppId = cast.ToInt32(RtelecManageApp().RegAppID) for i, row := range datalist { var deviceField model.DevDevinfo deviceField.Appid = AppId pos := 1 regname := tools.IsEmpty(row[pos]) if _, h := regMap[regname]; !h { return errors.New(fmt.Sprintf("第%d行:无效的区域名称", i+2)) } regid, _ := strconv.Atoi(regMap[regname]) deviceField.RegionId = int32(regid) pos = pos + 1 modename := tools.IsEmpty(row[pos]) if _, h := modelMap[modename]; !h { return errors.New(fmt.Sprintf("第%d行:无效的模型名称", i+2)) } modelid, _ := strconv.Atoi(modelMap[modename]) deviceField.Modelid = int32(modelid) typename := tools.IsEmpty(row[len(row)-1]) if _, h := devTypeMap[typename]; !h { return errors.New(fmt.Sprintf("第%d行:无效的设备类型名称", i+2)) } typid, _ := strconv.Atoi(devTypeMap[typename]) deviceField.DevTypeId = int32(typid) pos = pos + 1 devicename := tools.IsEmpty(row[pos]) //判断是否名称是否已存在 if _, h := t.DeviceIdByDeviceName().Load(devicename); h { return errors.New(fmt.Sprintf("第%d行:设备名称已存在", i+2)) } deviceField.Devicename = devicename pos = pos + 1 serial := tools.IsEmpty(row[pos]) pos = pos + 1 rate := tools.IsEmpty(row[pos]) if serial != "" && rate == "" { rate = "9600" } pos = pos + 1 stopbit := tools.IsEmpty(row[pos]) if serial != "" && stopbit == "" { stopbit = "1" } pos = pos + 1 checkbit := tools.IsEmpty(row[pos]) if serial != "" && checkbit == "" { checkbit = "N" } pos = pos + 1 databit := tools.IsEmpty(row[pos]) if serial != "" && databit == "" { databit = "8" } pos = pos + 1 salveid := tools.IsEmpty(row[pos]) pos = pos + 1 ip := tools.IsEmpty(row[pos]) pos = pos + 1 port := tools.IsEmpty(row[pos]) pos = pos + 1 mqtttopic := tools.IsEmpty(row[pos]) pos = pos + 1 eid := tools.IsEmpty(row[pos]) if eid == "" { eid = "0" } if serial == "" && ip == "" && mqtttopic == "" { return errors.New(fmt.Sprintf("第%d行:串口号、IP、MQTT主题不能同时为空", i+2)) } if serial != "" && salveid == "" { return errors.New(fmt.Sprintf("第%d行:从设备号不能为空", i+2)) } if ip != "" && port == "" { return errors.New(fmt.Sprintf("第%d行:端口不能为空", i+2)) } deviceField.Serial = serial deviceField.Baudrate = cast.ToInt32(rate) deviceField.Checkbit = checkbit deviceField.Stopbit = cast.ToInt32(stopbit) deviceField.Databit = cast.ToInt32(databit) deviceField.Slaveid = cast.ToInt32(salveid) deviceField.IP = ip deviceField.Port = cast.ToInt32(port) deviceField.Mqtttopic = mqtttopic deviceField.Eid = eid deviceField.Appid = AppId deviceField.Disable = 1 deviceField.Online = 0 var messageId = tools.GetUid() msgobj := new(utils.MsgStateManage) msgobj.SetMessageStateValue(messageId, utils.MsgState{Success: false, State: false, Message: ""}) editError := t.CreateDevice(messageId, deviceField, nil, nil) if editError != nil { logger.Logger.Error(editError, fmt.Sprintf("操作数据:%+v", deviceField)) return editError } else { Result := msgobj.HanderMesage(messageId, 5) if !Result.Success { logdesc := fmt.Sprintf("导入设备[%s]失败,错误:%s,操作数据:%+v", deviceField.Devicename, Result.Message, deviceField) logObj.Description = logdesc logObj.Fail2() logger.Logger.Error(errors.New(logdesc)) return errors.New(logdesc) } } } global.GoCahce.Delete("devicelistall") global.GoCahce.Delete("GetAllDevice") logObj.Success2() return nil } //设备导出 func (t *DeviceService) Exp() ([]orm.Params, error) { logObj := new(bo.SystemLog) user := t.UserInfo logObj.UserInfo = map[string]interface{}{"name": user.Usrname, "ip": user.Ip} logObj.Audittype = enum.AuditType_device logObj.Eventtype = enum.OptEventType_Bus logObj.Eventlevel = enum.OptEventLevel_Hight logObj.Logtype = enum.LogType_exp logObj.Description = "导出设备数据" list, _, err := t.SearchDeviceList(map[string]interface{}{"PageIndex": 1, "PageSize": 1000}) if err != nil { logObj.Description = err.Error() logObj.Fail2() return nil, err } regSrv := new(RegionService) modelSrv := new(ModelService) regLst, _ := regSrv.List(nil) regMap := map[string]string{} for _, item := range regLst { regMap[tools.IsEmpty(item["id"])] = tools.IsEmpty(item["region_name"]) } modellist := modelSrv.GetModelListObj() modelMap := map[string]string{} for _, row2 := range modellist { row := row2.(map[string]interface{}) modelMap[tools.IsEmpty(row["id"])] = tools.IsEmpty(row["model_name"]) } devType, _ := t.SearchDeviceTypeList() devTypeMap := map[string]string{} for _, row := range devType.([]orm.Params) { devTypeMap[tools.IsEmpty(row["id"])] = tools.IsEmpty(row["type_name"]) } result := list.([]orm.Params) for i, row := range result { row["model_name"] = modelMap[tools.IsEmpty(row["modelid"])] row["dev_type_name"] = devTypeMap[tools.IsEmpty(row["dev_type_id"])] row["region_name"] = regMap[tools.IsEmpty(row["region_id"])] result[i] = row } logObj.Success2() return result, nil } //设备测点导出 func (t *DeviceService) ExpMp(deviceid int32) ([]orm.Params, error) { deviceidStr := tools.IsEmpty(deviceid) devicename := "" if v, h := t.DeviceNameByID().Load(deviceidStr); h { devicename = tools.IsEmpty(v) } else { return nil, errors.New("无效的设备ID") } logObj := new(bo.SystemLog) user := t.UserInfo logObj.UserInfo = map[string]interface{}{"name": user.Usrname, "ip": user.Ip} logObj.Audittype = enum.AuditType_device logObj.Eventtype = enum.OptEventType_Bus logObj.Eventlevel = enum.OptEventLevel_Hight logObj.Logtype = enum.LogType_exp logObj.Description = "导出设备" + devicename + "的测点数据" /* regSrv := new(RegionService) regLst, _ := regSrv.List(nil) regMap := map[string]string{} for _, item := range regLst { regMap[tools.IsEmpty(item["id"])] = tools.IsEmpty(item["region_name"]) } */ modelSrv := new(ModelService) modellist := modelSrv.GetModelListObj() modelMap := map[string]string{} for _, row2 := range modellist { row := row2.(map[string]interface{}) modelMap[tools.IsEmpty(row["id"])] = tools.IsEmpty(row["model_name"]) } //modelAttrMap := map[string]interface{}{} //模型属性 mplist, _, err := t.DeviceMpList(deviceid, 1, 1000) if err != nil { return nil, err } result := []orm.Params{} for _, row := range mplist { row["devicename"] = devicename row["modelname"] = modelMap[tools.IsEmpty(row["modelid"])] result = append(result, row) } logObj.Success2() return result, nil } //设备测点导入 func (t *DeviceService) ImpMp(param map[string]interface{}) error { datalist := param["datalist"].([]map[int]string) devicelist, _ := t.GetAllDevice() deviceMap := map[string]int32{} for _, row := range devicelist { deviceMap[tools.IsEmpty(row["devicename"])] = cast.ToInt32(row["deviceid"]) } logObj := new(bo.SystemLog) user := t.UserInfo logObj.UserInfo = map[string]interface{}{"name": user.Usrname, "ip": user.Ip} logObj.Audittype = enum.AuditType_device logObj.Eventtype = enum.OptEventType_Bus logObj.Eventlevel = enum.OptEventLevel_Hight logObj.Logtype = enum.LogType_imp logObj.Description = "导入设备测点数据" regSrv := new(RegionService) regLst, _ := regSrv.List(nil) regMap := map[string]string{} for _, item := range regLst { regMap[tools.IsEmpty(item["id"])] = tools.IsEmpty(item["region_name"]) } modelSrv := new(ModelService) modellist := modelSrv.GetModelListObj() modelMap := map[string]int32{} for _, row2 := range modellist { row := row2.(map[string]interface{}) modelMap[tools.IsEmpty(row["model_name"])] = cast.ToInt32(tools.IsEmpty(row["id"])) } logger.Logger.Debug(modelMap) modelAttrMap := map[int32]interface{}{} //模型属性 appid := cast.ToInt32(RtelecManageApp().RegAppID) i := 2 for _, row := range datalist { mp_Field := model.DevMpinfo{} mp_Field.Online = 1 //新增测点时,默认为离线 mp_Field.Disable = 1 //新增时默认为启用 mp_Field.Appid = appid if row[1] == "" { return errors.New(fmt.Sprintf("第%d行:设备名称不能为空", i)) } mp_Field.Deviceid = deviceMap[row[1]] if mp_Field.Deviceid == 0 { return errors.New(fmt.Sprintf("第%d行:无效的设备名称%s", i, row[1])) } if row[2] == "" { return errors.New(fmt.Sprintf("第%d行:测点名称不能为空", i)) } mp_Field.Mpname = row[2] mp_Field.Zonename = row[3] mp_Field.Positionname = row[4] if row[5] == "" { return errors.New(fmt.Sprintf("第%d行:模型名称不能为空", i)) } mp_Field.Modelid = modelMap[row[5]] if mp_Field.Modelid == 0 { return errors.New(fmt.Sprintf("第%d行:无效的模型名称%s", i, row[5])) } if row[6] == "" { return errors.New(fmt.Sprintf("第%d行:模型属性名称不能为空", i)) } if modelAttrMap[mp_Field.Modelid] == nil { modelAttrMap[mp_Field.Modelid] = modelSrv.GetModelAttrMap(int64(mp_Field.Modelid)) } if _, h := modelAttrMap[mp_Field.Modelid].(map[string]interface{})[row[6]]; !h { return errors.New(fmt.Sprintf("第%d行:无效的模型属性名称%s", i, row[6])) } mp_Field.Attrname = row[6] mp_Field.Phase = row[7] mpinfoObject := logic.NewMpInfoLogic() mp_Field.Mpid = new(utils.ToolsLogic).GetOnlyId(int64(appid)) err := mpinfoObject.AddMpInfo(&mp_Field) if err != nil { logger.Logger.Error(err, fmt.Sprintf("操作数据:%+v", mp_Field)) return err } deviceMpList.Delete(fmt.Sprintf("MpList_%d_0", mp_Field.Deviceid)) //清除缓存的测点列表 global.GoCahce.Delete(fmt.Sprintf("MpInfo_%d", mp_Field.Deviceid)) //清除以模型属性缓存的测点定义 global.GoCahce.Delete(fmt.Sprintf("MapInfoByDeviceId_%d", mp_Field.Deviceid)) //清除以测点id缓存的测点定义 i = i + 1 } logObj.Success2() return nil }