package productconfig import ( "encoding/json" "errors" "fmt" "sparrow/pkg/protocol" "sparrow/pkg/tlv" ) // CommandOrEventParam command or a event param struct type CommandOrEventParam struct { ValueType int32 `json:"value_type"` Name string } // ProductCommandOrEvent `` type ProductCommandOrEvent struct { No int Part int Name string Priority int Params []CommandOrEventParam } // StatusParam 上报类型的参数 type StatusParam struct { ValueType int32 `json:"value_type"` Name string `json:"name"` ID uint `json:"pid"` //protocal id 与后台对应 } // ProductObject 产品对象 type ProductObject struct { Id int No int Label string Part int Status []StatusParam } // ProductConfig product config parses the JSON product config string. type ProductConfig struct { Objects []ProductObject `json:"objects"` Commands []ProductCommandOrEvent `json:"commands"` Events []ProductCommandOrEvent `json:"events"` } // New create a new productConfig func New(config string) (*ProductConfig, error) { v := &ProductConfig{} err := json.Unmarshal([]byte(config), v) if err != nil { return nil, err } return v, nil } // ValidateStatus validate the status func (config *ProductConfig) ValidateStatus(label string, params []interface{}) (*ProductObject, []interface{}, error) { // search for status name var paramInfo []StatusParam var status *ProductObject found := false for _, obj := range config.Objects { if obj.Label == label { paramInfo = obj.Status status = &obj found = true break } } if found == false { return nil, []interface{}{}, errors.New("object not found.") } if len(paramInfo) != len(params) { return nil, []interface{}{}, errors.New("wrong status parameters.") } realParams := make([]interface{}, len(params)) for idx, para := range paramInfo { realParams[idx] = tlv.CastTLV(params[idx], para.ValueType) } return status, realParams, nil } // ValidateCommandOrEvent validate command or event func (config *ProductConfig) ValidateCommandOrEvent(name string, params []interface{}, typ string) (*ProductCommandOrEvent, []interface{}, error) { var target []ProductCommandOrEvent if typ == "command" { target = config.Commands } else if typ == "event" { target = config.Events } else { return nil, []interface{}{}, errors.New("wrong target type.") } // search for name var paramInfo []CommandOrEventParam var coe *ProductCommandOrEvent found := false for _, one := range target { if one.Name == name { paramInfo = one.Params coe = &one found = true break } } if found == false { return nil, []interface{}{}, errors.New("command or event not found.") } if len(paramInfo) != len(params) { return nil, []interface{}{}, errors.New("wrong parameters.") } realParams := make([]interface{}, len(params)) for idx, para := range paramInfo { realParams[idx] = tlv.CastTLV(params[idx], para.ValueType) } return coe, realParams, nil } // StatusToMap struct to map func (config *ProductConfig) StatusToMap(status []protocol.SubData) (map[string]interface{}, error) { result := make(map[string]interface{}) for _, sub := range status { val, err := tlv.ReadTLVs(sub.Params) if err != nil { return nil, err } label := "" values := make(map[string]interface{}) for _, obj := range config.Objects { if obj.No == int(sub.Head.PropertyNum) { label = obj.Label for k, v := range obj.Status { values[v.Name] = val[k] } } } result[label] = values result["device_id"] = sub.Head.SubDeviceid } return result, nil } // EventToMap event ot map func (config *ProductConfig) EventToMap(event *protocol.Event) (map[string]interface{}, error) { result := make(map[string]interface{}) val, err := tlv.ReadTLVs(event.Params) if err != nil { return nil, err } label := "" values := make(map[string]interface{}) for _, obj := range config.Events { if obj.No == int(event.Head.No) { label = obj.Name for k, v := range obj.Params { values[v.Name] = val[k] } } } result[label] = values result["device_id"] = event.Head.SubDeviceid return result, nil } // MapToStatus map to status func (config *ProductConfig) MapToStatus(data map[string]interface{}) ([]protocol.SubData, error) { var result []protocol.SubData for label, one := range data { params, ok := one.([]interface{}) if !ok { return nil, fmt.Errorf("status format error: %v", one) } obj, realParams, err := config.ValidateStatus(label, params) if err != nil { return nil, err } tlvs, err := tlv.MakeTLVs(realParams) if err != nil { return nil, err } result = append(result, protocol.SubData{ Head: protocol.SubDataHead{ SubDeviceid: uint16(obj.Part), PropertyNum: uint16(obj.No), ParamsCount: uint16(len(realParams)), }, Params: tlvs, }) } return result, nil } func (config *ProductConfig) MapToCommand(cmd map[string]interface{}) (*protocol.Command, error) { result := &protocol.Command{} for name, one := range cmd { params, ok := one.([]interface{}) if !ok { return nil, fmt.Errorf("command format error: %v", one) } c, realParams, err := config.ValidateCommandOrEvent(name, params, "command") if err != nil { return nil, err } tlvs, err := tlv.MakeTLVs(realParams) if err != nil { return nil, err } result.Head.No = uint16(c.No) result.Head.Priority = uint16(c.Priority) result.Head.SubDeviceid = uint16(c.Part) result.Head.ParamsCount = uint16(len(realParams)) result.Params = tlvs } return result, nil }