| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854 |
- package controllers
- import (
- "fmt"
- "strconv"
- "strings"
- "time"
- "github.com/sirupsen/logrus"
- "github.com/astaxie/beego"
- validation "github.com/go-ozzo/ozzo-validation/v4"
- "github.com/go-ozzo/ozzo-validation/v4/is"
- "lc/common/models"
- "lc/common/mqtt"
- "lc/common/protocol"
- "lc/common/util"
- )
- // LampStrategyQueue redis缓存
- var LampStrategyQueue = "lamp_strategy_queue" //已修改的灯控编码列表,队列方式,先进先出
- var LampHlMqttDown = "hllk/113/lamp/longchi/down"
- var LampHlMqttUp = "hllk/113/lamp/longchi/up"
- type LampController struct {
- BaseController
- }
- type ConcentratorInfo struct {
- GID string
- TID int
- }
- type ReqLampController struct {
- Code string `json:"code"` //设备编号,禁止修改
- GID string `json:"gid"` //网关ID
- Tenant string `json:"tenant"` //租户ID
- Name string `json:"name"` //设备名称
- Brand int `json:"brand"` //品牌
- Model int `json:"model"` //型号
- CtlType int `json:"ctltype"` //单灯控制器类型,nb-iot:1,485:2,zigbee:3
- Concentrator string `json:"concentrator"` //集中器编号,zigbee灯控专用,其他类型灯控置空
- Netid int `json:"netid"` //网络号,zigbee灯控专用,其他类型灯控置0
- Channel int `json:"channel"` //通道号,zigbee灯控专用,其他类型灯控置0
- OrgNumber string `json:"orgnumber"` //灯编号, zigbee灯控专用,设备上原始的编号,字符串类型
- Strategy string `json:"strategy"` //关联的策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- State int `json:"state"` //1启用,0禁用
- }
- func (a ReqLampController) Validate() error {
- var rules []*validation.FieldRules
- rules = append(rules, validation.Field(&a.Code, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)))
- rules = append(rules, validation.Field(&a.CtlType, validation.Required, validation.In(1, 2, 3, 4)))
- rules = append(rules, validation.Field(&a.Strategy, validation.Required, validation.Length(1, 32)))
- rules = append(rules, validation.Field(&a.State, validation.In(0, 1)))
- if a.CtlType == 2 { //485需要网关ID,其他暂不需要
- rules = append(rules, validation.Field(&a.GID, validation.Required, validation.Length(4, 32)))
- } else if a.CtlType == 3 {
- rules = append(rules, validation.Field(&a.Concentrator, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.OrgNumber, validation.Required, validation.Length(3, 8)))
- } else if a.CtlType == 4 {
- rules = append(rules, validation.Field(&a.Concentrator, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.OrgNumber, validation.Required, validation.Length(3, 32)))
- }
- return validation.ValidateStruct(&a, rules...)
- }
- type LampControllerDev struct {
- Code string `json:"code"` //设备编号,禁止修改
- GID string `json:"gid"` //网关ID
- Name string `json:"name"` //设备名称
- Brand int `json:"brand"` //品牌
- Model int `json:"model"` //型号
- CtlType int `json:"ctltype"` //单灯控制器类型,nb-iot:1,485:2,zigbee:3
- Concentrator string `json:"concentrator"` //集中器编号,zigbee灯控专用,其他类型灯控置空
- Netid int `json:"netid"` //网络号,zigbee灯控专用,其他类型灯控置0
- Channel int `json:"channel"` //通道号,zigbee灯控专用,其他类型灯控置0
- OrgNumber string `json:"orgnumber"` //灯编号, zigbee灯控专用,设备上原始的编号,字符串类型
- Strategy string `json:"strategy"` //关联的策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- State int `json:"state"` //1启用,0禁用
- }
- func (a LampControllerDev) Validate() error {
- var rules []*validation.FieldRules
- rules = append(rules, validation.Field(&a.Code, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.CtlType, validation.Required, validation.In(1, 2, 3, 4)))
- rules = append(rules, validation.Field(&a.Strategy, validation.Required, validation.Length(1, 32)))
- rules = append(rules, validation.Field(&a.State, validation.In(0, 1)))
- if a.CtlType == 2 { //485需要网关ID,其他暂不需要
- rules = append(rules, validation.Field(&a.GID, validation.Required, validation.Length(4, 32)))
- } else if a.CtlType == 3 {
- rules = append(rules, validation.Field(&a.Concentrator, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.OrgNumber, validation.Required, validation.Length(3, 8)))
- } else if a.CtlType == 4 {
- rules = append(rules, validation.Field(&a.Concentrator, validation.Required, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.OrgNumber, validation.Required, validation.Length(3, 32)))
- }
- return validation.ValidateStruct(&a, rules...)
- }
- type ReqImportLampControllerDev struct {
- Tenant string `json:"tenant"` //租户ID
- List []LampControllerDev `json:"list"` //灯控列表
- }
- func (a ReqImportLampControllerDev) Validate() error {
- var rules []*validation.FieldRules
- rules = append(rules, validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)))
- rules = append(rules, validation.Field(&a.List, validation.Required))
- return validation.ValidateStruct(&a, rules...)
- }
- // ReqStrategy 关联策略
- type ReqStrategy struct {
- Tenant string `json:"tenant"` //租户ID
- Codes []string `json:"codes"` //数组 灯控编码数组
- Strategy string `json:"strategy"` // 策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- }
- func (a ReqStrategy) Validate() error {
- return validation.ValidateStruct(&a,
- validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)),
- validation.Field(&a.Codes, validation.Required),
- validation.Field(&a.Strategy, validation.Required, validation.Length(1, 32)),
- )
- }
- // LampStrategy 创建更新策略
- type LampStrategy struct {
- Ontime string `json:"ontime"` //开始时间,24小时制,格式{小时}:{分钟}:{秒}类似13:06:00,为13点6分
- Offtime string `json:"offtime"` //结束时间,24小时制,格式同ontime
- Brightness int `json:"brightness"` //亮度,1到100
- }
- func (a LampStrategy) Validate() error {
- return validation.ValidateStruct(&a,
- validation.Field(&a.Ontime, validation.Required, validation.Date("15:04:05")),
- validation.Field(&a.Offtime, validation.Required, validation.Date("15:04:05")),
- validation.Field(&a.Brightness, validation.Min(1), validation.Max(100)),
- )
- }
- type ReqLampStrategy struct {
- Tenant string `json:"tenant"` //租户ID
- Name string `json:"name"` //策略名称
- Code string `json:"code"` //策略编码,禁止修改
- TimeInfo []LampStrategy `json:"timeinfo"` //时间及亮度内容数组,最多4个元素,最少1个元素
- Sunset int `json:"sunset"` //是否启用
- Ctltype int `json:"ctltype"` //单灯控制器类型,nb-iot:1,485:2,zigbee:3 不同灯控可能支持的时间亮度有不同的设置,备用
- Start string `json:"start"` //时间格式,类似2020-07-20 06:06:06
- End string `json:"end"` //时间格式,类似2020-09-20 06:06:06
- Year int `json:"year"` //是否全年,1全年,0非全年
- Auto int `json:"auto"` //1,自动延续,0非自动延续
- Longitude string `json:"longitude"` //东正西负。双精度浮点数,整数最多3字符,小数最多6字符
- Latitude string `json:"latitude"` //北正南负,双精度浮点数,整数最多2字符,小数最多6字符
- }
- func (a ReqLampStrategy) Validate() error {
- var rules []*validation.FieldRules
- rules = append(rules, validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)))
- rules = append(rules, validation.Field(&a.Code, validation.Length(4, 32)))
- rules = append(rules, validation.Field(&a.TimeInfo, validation.Length(1, 4))) //最少1个,最多4个
- rules = append(rules, validation.Field(&a.Sunset, validation.In(0, 1)))
- rules = append(rules, validation.Field(&a.Year, validation.In(0, 1)))
- rules = append(rules, validation.Field(&a.Auto, validation.In(0, 1)))
- //rules = append(rules, validation.Field(&a.Ctltype, validation.Required, validation.In(1, 2, 3)))
- rules = append(rules, validation.Field(&a.Start, validation.Required, validation.Date("2006-01-02 15:04:05")))
- rules = append(rules, validation.Field(&a.End, validation.Required, validation.Date("2006-01-02 15:04:05")))
- rules = append(rules, validation.Field(&a.Longitude, validation.Required, is.Longitude))
- rules = append(rules, validation.Field(&a.Latitude, validation.Required, is.Latitude))
- return validation.ValidateStruct(&a, rules...)
- }
- // ReqSwitch 开/关灯
- type ReqSwitch struct {
- Tenant string `json:"tenant"` //租户ID
- Codes []string `json:"codes"` //数组 灯控编码数组,一次开关灯多个
- Recovery int `json:"recovery"` //恢复时间,即开或关灯时长,超过这个时间则自动恢复时控模式
- Brightness int `json:"brightness"` //0~100,0相当于关等,100最大亮度
- SwitchOn int `json:"switchon"` //1开灯,0关灯
- Whole int `json:"whole,omitempty"` //1为集控
- }
- func (a ReqSwitch) Validate() error {
- return validation.ValidateStruct(&a,
- validation.Field(&a.Tenant, validation.Required, validation.Length(4, 8)),
- validation.Field(&a.Codes, validation.Required),
- validation.Field(&a.Recovery, validation.Required, validation.Min(1), validation.Max(480)),
- validation.Field(&a.Brightness, validation.Min(0), validation.Max(100)),
- validation.Field(&a.SwitchOn, validation.In(0, 1)),
- // validation.Field(&a.Whole, validation.In(0, 1)),
- )
- }
- // ConvertNumber 长和zigbee单灯控制器编号,短横线连接
- func ConvertNumber(strNumber string) uint16 {
- strlist := strings.Split(strNumber, "-")
- if len(strlist) == 2 {
- hight, err0 := strconv.Atoi(strlist[0])
- low, err1 := strconv.Atoi(strlist[1])
- if err0 == nil && err1 == nil {
- return uint16(hight<<8 | low)
- }
- }
- return 0
- }
- // CreateLampController @Title 创建灯控设备
- // @Description 创建灯控设备
- // @Param body body controllers.ReqLampController true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/create [post]
- func (o *LampController) CreateLampController() {
- var obj ReqLampController
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- var number uint16 = 0
- if obj.CtlType == 3 { //长和zigbee集控器
- number = ConvertNumber(obj.OrgNumber)
- if number == 0 {
- beego.Error("请求的编号格式不正确,要求\"xx-xx\"")
- o.Response(Failure, "请求的编号格式不正确,要求\"xx-xx\"", nil)
- }
- }
- oo := models.DeviceLampController{
- ID: obj.Code, //设备ID,DID
- Name: obj.Name,
- GID: obj.GID, //网关ID
- Brand: obj.Brand, //品牌
- Model: obj.Model, //型号
- CtlType: obj.CtlType, //单灯控制器类型,nb-iot:1,485:2,zigbee:3
- Concentrator: obj.Concentrator, //集中器编号,zigbee灯控专用,其他类型灯控置空
- Netid: obj.Netid, //网络号,zigbee灯控专用,其他类型灯控置0
- Channel: obj.Channel, //通道号,zigbee灯控专用,其他类型灯控置0
- Number: number, //灯编号, zigbee灯控专用,其他类型灯控置0
- OrgNumber: obj.OrgNumber, //灯编号, zigbee灯控专用,设备上原始的编号,字符串类型
- Strategy: obj.Strategy, //关联的策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- Tenant: obj.Tenant, //租户ID
- State: obj.State, //1启用,0禁用
- }
- //检查是否有网关ID
- if obj.CtlType == 3 || obj.CtlType == 4 { //查找灯控关联的zigbee集中器信息
- if concentrator, err := models.GetConcentratorbyID(obj.Concentrator); err == nil {
- oo.GID = concentrator.GID
- oo.TID = concentrator.TID
- } else {
- beego.Error(fmt.Sprintf("操作失败,请先创建zigbee集控器:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("操作失败,请先创建zigbee集控器:%s", err.Error()), nil)
- return
- }
- } else if obj.CtlType == 2 {
- oo.TID = 2
- }
- if err := oo.SaveFromWeb(obj.CtlType); err != nil {
- o.Response(Failure, fmt.Sprintf("数据插入失败:%s", err.Error()), nil)
- return
- }
- //存入redis,等待下发给设备
- if err := redisCltRawdata.LPush(LampStrategyQueue, obj.Code).Err(); err != nil {
- logrus.Errorf("LampController.CreateLampController:创建灯控缓存redis失败,灯控编码:%s,失败原因:%s", obj.Code, err.Error())
- }
- o.Response(Success, "成功", oo.ID)
- }
- // UpdateLampController @Title 更新灯控设备
- // @Description 更新灯控设备
- // @Param body body controllers.ReqLampController true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/update [post]
- func (o *LampController) UpdateLampController() {
- var obj ReqLampController
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- var number uint16 = 0
- if obj.CtlType == 3 { //长和zigbee集控器
- number = ConvertNumber(obj.OrgNumber)
- if number == 0 {
- beego.Error("请求的编号格式不正确,要求\"xx-xx\"")
- o.Response(Failure, "请求的编号格式不正确,要求\"xx-xx\"", nil)
- }
- }
- oo := models.DeviceLampController{
- ID: obj.Code, //设备ID,DID
- Name: obj.Name,
- GID: obj.GID, //网关ID
- Brand: obj.Brand, //品牌
- Model: obj.Model, //型号
- CtlType: obj.CtlType, //单灯控制器类型,nb-iot:1,485:2,zigbee:3
- Concentrator: obj.Concentrator, //集中器编号,zigbee灯控专用,其他类型灯控置空
- Netid: obj.Netid, //网络号,zigbee灯控专用,其他类型灯控置0
- Channel: obj.Channel, //通道号,zigbee灯控专用,其他类型灯控置0
- Number: number, //灯编号, zigbee灯控专用,其他类型灯控置0
- OrgNumber: obj.OrgNumber, //灯编号, zigbee灯控专用,设备上原始的编号,字符串类型
- Strategy: obj.Strategy, //关联的策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- Tenant: obj.Tenant, //租户ID
- State: obj.State, //1启用,0禁用
- }
- //检查是否有网关ID
- if obj.CtlType == 3 { //查找灯控关联的zigbee集中器信息
- if concentrator, err := models.GetConcentratorbyID(obj.Concentrator); err == nil {
- oo.GID = concentrator.GID
- oo.TID = concentrator.TID
- } else {
- beego.Error(fmt.Sprintf("操作失败,请先创建zigbee集控器:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("操作失败,请先创建zigbee集控器:%s", err.Error()), nil)
- return
- }
- } else if obj.CtlType == 2 {
- oo.TID = 2
- }
- if err := oo.SaveFromWeb(obj.CtlType); err != nil {
- o.Response(Failure, fmt.Sprintf("数据更新失败:%s", err.Error()), nil)
- return
- }
- //存入redis,等待下发给设备
- if err := redisCltRawdata.LPush(LampStrategyQueue, obj.Code).Err(); err != nil {
- logrus.Errorf("LampController.UpdateLampController:创建灯控缓存redis失败,灯控编码:%s,失败原因:%s", obj.Code, err.Error())
- }
- o.Response(Success, "成功", oo.ID)
- }
- // DeleteLampController @Title 删除灯控设备
- // @Description 删除灯控设备
- // @Param code query string true "设备ID"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/delete [post]
- func (o *LampController) DeleteLampController() {
- code := strings.Trim(o.GetString("code"), " ")
- if err := validation.Validate(code, validation.Required, validation.Length(4, 100)); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- c := models.DeviceLampController{
- ID: code,
- }
- if err := c.Delete(); err != nil {
- beego.Error(fmt.Sprintf("删除失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("数据删除失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", c.ID)
- }
- // UpdateState @Title 更新灯控设备启用禁用状态
- // @Description 更新灯控设备启用禁用状态
- // @Param body controllers.ProgramsState true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/update/state [POST]
- func (o *LampController) UpdateState() {
- code := o.GetString("code")
- state, err := o.GetUint8("state", 0)
- if code == "" || state > 1 || err != nil {
- beego.Error("参数错误")
- o.Response(Failure, "参数错误", nil)
- return
- }
- err = models.LampControllerUpdateState(code, int(state))
- if err != nil {
- beego.Error("更新灯控设备状态错误:", err.Error())
- o.Response(Failure, "失败", err.Error())
- return
- }
- o.Response(Success, "成功", code)
- }
- // ImportLampControllerDev @Title 导入灯控设备
- // @Description 导入灯控设备
- // @Param body body controllers.ReqImportLampControllerDev true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/import [post]
- func (o *LampController) ImportLampControllerDev() {
- var obj ReqImportLampControllerDev
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- var resp []RespImport
- mapConcentratorInfo := make(map[string]*ConcentratorInfo)
- for _, v := range obj.List {
- var aresp RespImport
- aresp.Code = v.Code
- var number uint16 = 0
- if v.CtlType == 3 { //长和zigbee集控器
- number = ConvertNumber(v.OrgNumber)
- }
- oo := models.DeviceLampController{
- ID: v.Code, //设备ID,DID
- Name: v.Name,
- GID: v.GID, //网关ID
- Brand: v.Brand, //品牌
- Model: v.Model, //型号
- CtlType: v.CtlType, //单灯控制器类型,nb-iot:1,485:2,zigbee:3
- Concentrator: v.Concentrator, //集中器编号,zigbee灯控专用,其他类型灯控置空
- Netid: v.Netid, //网络号,zigbee灯控专用,其他类型灯控置0
- Channel: v.Channel, //通道号,zigbee灯控专用,其他类型灯控置0
- Number: number, //灯编号, zigbee灯控专用,其他类型灯控置0
- OrgNumber: v.OrgNumber, //灯编号, zigbee灯控专用,设备上原始的编号,字符串类型
- Strategy: v.Strategy, //关联的策略编码,无则置空,多个则用逗号分开,暂时只支持一个
- Tenant: obj.Tenant, //租户ID
- State: v.State, //1启用,0禁用
- }
- //检查是否有网关ID
- if v.CtlType == 3 { //查找灯控关联的zigbee集中器信息
- if ci, ok := mapConcentratorInfo[v.Concentrator]; ok {
- oo.GID = ci.GID
- oo.TID = ci.TID
- } else {
- if concentrator, err := models.GetConcentratorbyID(v.Concentrator); err == nil {
- oo.GID = concentrator.GID
- oo.TID = concentrator.TID
- mapConcentratorInfo[v.Concentrator] = &ConcentratorInfo{GID: concentrator.GID, TID: concentrator.TID}
- } else {
- beego.Error(fmt.Sprintf("操作失败,请先创建zigbee集控器:%s", err.Error()))
- aresp.Error = err.Error()
- continue
- }
- }
- } else if v.CtlType == 2 {
- oo.TID = 2
- }
- err := oo.SaveFromWeb(v.CtlType)
- if err != nil {
- beego.Error(fmt.Sprintf("zigbee集控器数据导入失败,code=%s,失败原因:%s", v.Code, err.Error()))
- aresp.Error = err.Error()
- continue
- }
- //存入redis,等待下发给设备
- if err := redisCltRawdata.LPush(LampStrategyQueue, v.Code).Err(); err != nil {
- logrus.Errorf("LampController.CreateLampController:创建灯控缓存redis失败,灯控编码:%s,失败原因:%s", v.Code, err.Error())
- }
- }
- o.Response(Success, "成功", resp)
- }
- // RelateStrategy @Title 关联策略
- // @Description 关联策略
- // @Param body controllers.ReqStrategy true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/relate/strategy [post]
- func (o *LampController) RelateStrategy() {
- var obj ReqStrategy
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- if err := models.UpdateStrategy(obj.Codes, obj.Strategy); err != nil {
- beego.Error(fmt.Sprintf("关联策略失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("关联策略失败:%s", err.Error()), nil)
- return
- }
- //存入redis,等待下发给设备
- if len(obj.Codes) > 0 {
- codelist := make([]interface{}, 0, len(obj.Codes))
- for _, v := range obj.Codes {
- codelist = append(codelist, v)
- }
- if err := redisCltRawdata.LPush(LampStrategyQueue, codelist...).Err(); err != nil {
- logrus.Errorf("LampController.RelateStrategy:创建灯控缓存redis失败,灯控编码:%v,失败原因:%s", codelist, err.Error())
- }
- }
- o.Response(Success, "成功", nil)
- }
- // CreateStrategy @Title 创建灯控策略
- // @Description 创建灯控策略
- // @Param body controllers.ReqLampStrategy true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/create/strategy [post]
- func (o *LampController) CreateStrategy() {
- var obj ReqLampStrategy
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- tstart, err1 := util.MlParseTime(obj.Start)
- tend, err2 := util.MlParseTime(obj.End)
- if err1 != nil || err2 != nil || tstart.After(tend) {
- o.Response(Failure, "有效期时间错误", nil)
- return
- }
- timeInfo, _ := json.MarshalIndent(&obj.TimeInfo, "", " ")
- longitude, _ := strconv.ParseFloat(obj.Longitude, 64)
- latitude, _ := strconv.ParseFloat(obj.Latitude, 64)
- oo := models.Lampstrategy{
- ID: obj.Code,
- Name: obj.Name,
- CtlType: obj.Ctltype,
- TimeInfo: string(timeInfo),
- Sunset: obj.Sunset,
- Start: tstart,
- End: tend,
- Year: obj.Year,
- Auto: obj.Auto,
- Tenant: obj.Tenant,
- Longitude: longitude,
- Latitude: latitude,
- }
- if err := oo.SaveFromWeb(); err != nil {
- o.Response(Failure, fmt.Sprintf("数据插入失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", obj.Code)
- }
- // UpdateStrategy @Title 更新灯控策略
- // @Description 更新灯控策略
- // @Param body controllers.ReqLampStrategy true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/update/strategy [post]
- func (o *LampController) UpdateStrategy() {
- o.Response(Failure, "不允许更改照明策略,可新建照明策略,并关联新策略", nil)
- /* var obj ReqLampStrategy
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- tstart, err1 := util.MlParseTime(obj.Start)
- tend, err2 := util.MlParseTime(obj.End)
- if err1 != nil || err2 != nil || tstart.After(tend) {
- o.Response(Failure, "有效期时间错误", nil)
- return
- }
- time_info, _ := json.MarshalIndent(&obj.TimeInfo, "", " ")
- longitude, _ := strconv.ParseFloat(obj.Longitude, 64)
- latitude, _ := strconv.ParseFloat(obj.Latitude, 64)
- oo := models.Lampstrategy{
- ID: obj.Code,
- Name: obj.Name,
- CtlType: obj.Ctltype,
- TimeInfo: string(time_info),
- Sunset: obj.Sunset,
- Start: tstart,
- End: tend,
- Year: obj.Year,
- Auto: obj.Auto,
- Tenant: obj.Tenant,
- Longitude: longitude,
- Latitude: latitude,
- }
- if err := oo.SaveFromWeb(); err != nil {
- o.Response(Failure, fmt.Sprintf("数据插入失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", obj.Code)
- */
- }
- // DeleteStrategy @Title 删除灯控策略
- // @Description 删除灯控策略
- // @Param code query string true "设备ID"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/delete/strategy [post]
- func (o *LampController) DeleteStrategy() {
- code := strings.Trim(o.GetString("code"), " ")
- if err := validation.Validate(code, validation.Required, validation.Length(4, 100)); err != nil {
- beego.Error(fmt.Sprintf("请求参数验证失败:%s", err.Error()))
- o.Response(Failure, err.Error(), nil)
- return
- }
- c := models.Lampstrategy{
- ID: code,
- }
- if err := models.G_db.Delete(c).Error; err != nil {
- beego.Error(fmt.Sprintf("删除失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("数据删除失败:%s", err.Error()), nil)
- return
- }
- o.Response(Success, "成功", c.ID)
- }
- // Switch @Title 开灯/关灯
- // @Description 开灯/关灯
- // @Param body controllers.ReqSwitch true "数据"
- // @Success 0 {int} BaseResponse.Code "成功"
- // @Failure 1 {int} BaseResponse.Code "失败"
- // @router /v1/switch [post]
- func (o *LampController) Switch() {
- var obj ReqSwitch
- if err := json.Unmarshal(o.Ctx.Input.RequestBody, &obj); err != nil {
- beego.Debug(string(o.Ctx.Input.RequestBody))
- o.Response(Failure, fmt.Sprintf("数据包解析错误:%s", err.Error()), nil)
- return
- }
- if err := obj.Validate(); err != nil {
- beego.Error(fmt.Sprintf("LampController.Switch:请求参数验证失败:%s", err.Error()))
- o.Response(Failure, fmt.Sprintf("请求参数验证失败:%s", err.Error()), nil)
- return
- }
- arr, err := models.GetLampControllerByID(obj.Codes)
- if err != nil {
- o.Response(Failure, err.Error(), nil)
- return
- }
- //处理zigbee单灯控制器
- var mapConcentrator = make(map[string][]uint32)
- var mapConcentratorGateway = make(map[string]string)
- for _, v := range arr {
- if v.CtlType == 3 && v.Concentrator != "" && v.Number > 0 { //长和zigbee
- mapConcentrator[v.Concentrator] = append(mapConcentrator[v.Concentrator], uint32(v.Number)) //集控器
- mapConcentratorGateway[v.Concentrator] = v.GID //网关
- }
- }
- for k, v := range mapConcentrator {
- seq := GetNextUint64()
- var sw protocol.Pack_CHZB_Switch
- str, err := sw.EnCode(k, mapConcentratorGateway[k], seq, uint8(obj.SwitchOn), uint8(obj.Brightness), uint(obj.Recovery*60), v)
- if err != nil {
- beego.Error(fmt.Sprintf("LampController.Switch:编码错误:%s", err.Error()))
- continue
- }
- topic := GetTopic(obj.Tenant, protocol.DT_CONCENTRATOR, k, protocol.TP_CHZB_SET_SWITCH)
- err = GetMqttHandler().PublishString(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("LampController.Switch:消息发布错误:%s", err.Error()))
- continue
- }
- //进入指令表
- var msg string
- if msg0, errmsg := json.MarshalIndent(sw, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- dcr := models.DeviceCmdRecord{
- ID: seq,
- GID: mapConcentratorGateway[k],
- DID: k, //集控器编号
- Topic: topic,
- State: 0,
- Message: msg,
- }
- if err := models.G_db.Create(&dcr).Error; err != nil {
- logrus.Errorf("LampController.Switch:开关灯指令插入指令表:%s", err.Error())
- }
- }
- //处理裕明485单灯控制器
- for _, v := range arr {
- if v.CtlType == 2 {
- seq := GetNextUint64()
- var sw protocol.Pack_CHZB_Switch
- str, err := sw.EnCode(v.ID, v.GID, seq, uint8(obj.SwitchOn), uint8(obj.Brightness), uint(obj.Recovery*60), nil)
- if err != nil {
- beego.Error(fmt.Sprintf("LampController.Switch:编码错误:%s", err.Error()))
- continue
- }
- topic := GetTopic(obj.Tenant, protocol.DT_LAMPCONTROLLER, v.ID, protocol.TP_YM_SET_SWITCH)
- err = GetMqttHandler().PublishString(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("LampController.Switch:消息发布错误:%s", err.Error()))
- continue
- }
- //进入指令表
- var msg string
- if msg0, errmsg := json.MarshalIndent(sw, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- dcr := models.DeviceCmdRecord{
- ID: seq,
- GID: v.GID,
- DID: v.ID,
- Topic: topic,
- State: 0,
- Message: msg,
- }
- if err := models.G_db.Create(&dcr).Error; err != nil {
- logrus.Errorf("LampController.Switch:开关灯指令插入指令表:%s", err.Error())
- }
- }
- }
- //海蓝zigbee单灯控制器
- for _, v := range arr {
- if v.CtlType == 4 {
- // seq := GetNextUint64()
- seq := uint64(util.MlNow().Unix())
- var str string
- var err error
- if obj.Whole == 0 { //集控器开关
- var sw protocol.HLWLZB_Switch
- str, err = sw.EnCode(v.ID, v.GID, seq, uint8(obj.SwitchOn), uint8(obj.Brightness), uint(obj.Recovery*60), nil)
- if err != nil {
- beego.Error(fmt.Sprintf("HLWLLampController.Switch:编码错误:%s", err.Error()))
- continue
- }
- beego.Debug(fmt.Sprintf("HLWLLampController.Switch:%s", str))
- topic := GethltopicDown(obj.Tenant, protocol.DT_LAMPCONTROLLER, v.ID, protocol.TP_YM_SET_SWITCH)
- err = GetMqttHandlerHL().PublishString(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("HLWLLampController.Switch:消息发布错误:%s", err.Error()))
- continue
- }
- //进入指令表
- var msg string
- if msg0, errmsg := json.MarshalIndent(sw, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- dcr := models.DeviceCmdRecord{
- ID: seq,
- GID: v.GID,
- DID: v.ID,
- Topic: topic,
- State: 0,
- Message: msg,
- }
- if err := models.G_db.Create(&dcr).Error; err != nil {
- logrus.Errorf("LampController.Switch:开关灯指令插入指令表:%s", err.Error())
- }
- } else { //普通开关
- var sw protocol.HLWLZB_Whole_Switch
- str, err = sw.EnCode(v.ID, v.GID, seq, uint8(obj.SwitchOn), uint8(obj.Brightness), uint(obj.Recovery*60), nil)
- if err != nil {
- beego.Error(fmt.Sprintf("HLWLLampController.Switch:编码错误:%s", err.Error()))
- continue
- }
- beego.Debug(fmt.Sprintf("HLWLLampController.Switch:%s", str))
- topic := GethltopicDown(obj.Tenant, protocol.DT_LAMPCONTROLLER, v.ID, protocol.TP_YM_SET_SWITCH)
- err = GetMqttHandlerHL().PublishString(topic, str, mqtt.AtLeastOnce)
- if err != nil {
- beego.Error(fmt.Sprintf("HLWLLampController.Switch:消息发布错误:%s", err.Error()))
- continue
- }
- //进入指令表
- var msg string
- if msg0, errmsg := json.MarshalIndent(sw, "", " "); errmsg == nil {
- msg = string(msg0)
- } else {
- msg = str
- }
- dcr := models.DeviceCmdRecord{
- ID: seq,
- GID: v.GID,
- DID: v.ID,
- Topic: topic,
- State: 0,
- Message: msg,
- }
- if err := models.G_db.Create(&dcr).Error; err != nil {
- logrus.Errorf("LampController.Switch:开关灯指令插入指令表:%s", err.Error())
- }
- }
- }
- }
- var lsrs []models.LampSwitchRecord
- tt := util.MlNow()
- ttend := tt.Add(time.Duration(obj.Recovery) * time.Minute)
- for _, v := range obj.Codes {
- lsr := models.LampSwitchRecord{
- DID: v,
- SwitchOn: uint8(obj.SwitchOn),
- Duration: uint(obj.Recovery * 60),
- Brightness: uint8(obj.Brightness),
- TStart: tt,
- TEnd: ttend,
- CreatedAt: util.MlNow(),
- }
- lsrs = append(lsrs, lsr)
- }
- if err := models.MultiInsertLampSwitchRecord(lsrs); err != nil {
- beego.Error("LampController.Switch:批量插入开关灯记录错误:", err.Error())
- }
- o.Response(Success, "成功", nil)
- }
- // GetTopic 下发的控制命令
- //topic格式:{tenant}/{GID}/{did}/{TP}
- //func GetCtrlTopic(tenant, gid, did, tp string) string {
- // return tenant + "/" + gid + "/" + did + "/" + tp
- //}
- func GetTopic(tenant, devtype, id, topic string) string {
- return tenant + "/" + devtype + "/" + id + "/" + topic
- }
- // GethltopicDown 下发的控制命令先固定,再从配置文件读
- //topic格式:hllk/113/lamp/longchi/down
- func GethltopicDown(tenant, devtype, id, topic string) string {
- return "hllk/113/lamp/longchi/down"
- }
|