From 72a6712acf520f1d398cb91dd5131a889832ea62 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 13 Mar 2023 21:19:06 +0800 Subject: [PATCH] update log level and support twin for string, bool and float type Signed-off-by: Ryan --- config/config.go | 13 ++++- config/config.yaml | 1 + mappers/modbus-dmi/config.yaml | 1 + mappers/modbus-dmi/device/device.go | 84 +++++++++++++++++++++++---- mappers/modbus-dmi/device/twindata.go | 47 ++++++++++++++- pkg/driver/modbus/client.go | 38 +++++++++++- 6 files changed, 164 insertions(+), 20 deletions(-) diff --git a/config/config.go b/config/config.go index 8086ba38..37c9f4b4 100644 --- a/config/config.go +++ b/config/config.go @@ -39,6 +39,7 @@ type Config struct { GrpcServer GRPCServer `yaml:"grpc_server"` Common Common `yaml:"common"` DevInit DevInit `yaml:"dev_init"` + LogLevel string `yaml:"log_level"` } type GRPCServer struct { @@ -63,9 +64,13 @@ type DevInit struct { func (c *Config) Parse() error { var level klog.Level var loglevel string - var configFile string pflag.StringVar(&loglevel, "v", "1", "log level") + if err := level.Set(loglevel); err != nil { + return err + } + + var configFile string pflag.StringVar(&configFile, "config-file", defaultConfigFile, "Config file name") cf, err := ioutil.ReadFile(configFile) @@ -75,8 +80,10 @@ func (c *Config) Parse() error { if err = yaml.Unmarshal(cf, c); err != nil { return err } - if err = level.Set(loglevel); err != nil { - return err + if len(c.LogLevel) != 0 && c.LogLevel != "0" { + if serr := level.Set(loglevel); serr != nil { + return serr + } } switch c.DevInit.Mode { diff --git a/config/config.yaml b/config/config.yaml index ca627482..56e7d609 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -10,3 +10,4 @@ common: dev_init: mode: register #register/configmap configmap: /opt/kubeedge/deviceProfile.json +log_level: 1 \ No newline at end of file diff --git a/mappers/modbus-dmi/config.yaml b/mappers/modbus-dmi/config.yaml index 19616cda..5fc4263a 100644 --- a/mappers/modbus-dmi/config.yaml +++ b/mappers/modbus-dmi/config.yaml @@ -9,3 +9,4 @@ common: edgecore_sock: /etc/kubeedge/dmi.sock dev_init: mode: register #register/configmap +log_level: 1 \ No newline at end of file diff --git a/mappers/modbus-dmi/device/device.go b/mappers/modbus-dmi/device/device.go index 7b93e06b..c0308a6b 100644 --- a/mappers/modbus-dmi/device/device.go +++ b/mappers/modbus-dmi/device/device.go @@ -18,9 +18,11 @@ package device import ( "context" + "encoding/binary" "encoding/json" "errors" "fmt" + "math" "regexp" "strconv" "sync" @@ -51,17 +53,65 @@ func setVisitor(visitorConfig *modbus.ModbusVisitorConfig, twin *common.Twin, cl return } - klog.V(2).Infof("Convert type: %s, value: %s ", twin.PVisitor.PProperty.DataType, twin.Desired.Value) - value, err := common.Convert(twin.PVisitor.PProperty.DataType, twin.Desired.Value) - if err != nil { - klog.Errorf("Convert error: %v", err) - return - } - - valueInt, _ := value.(int64) - _, err = client.Set(visitorConfig.Register, visitorConfig.Offset, uint16(valueInt)) - if err != nil { - klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + klog.Infof("Convert type: %s, value: %s ", twin.PVisitor.PProperty.DataType, twin.Desired.Value) + value := twin.Desired.Value + switch twin.PVisitor.PProperty.DataType { + case "int": + valueInt, err := strconv.ParseInt(value, 10, 64) + if err != nil { + klog.Errorf("twin %s Convert error: %v", value, err) + return + } + _, err = client.Set(visitorConfig.Register, visitorConfig.Offset, uint16(valueInt)) + if err != nil { + klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + return + } + case "float": + valueFloat, err := strconv.ParseFloat(value, 32) + if err != nil { + klog.Errorf("twin %s Convert error: %v", value, err) + return + } + _, err = client.SetString(visitorConfig.Register, visitorConfig.Offset, visitorConfig.Limit, string(ConvertFloat32ToBytes(float32(valueFloat)))) + if err != nil { + klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + return + } + case "double": + valueDouble, err := strconv.ParseFloat(value, 64) + if err != nil { + klog.Errorf("twin %s Convert error: %v", value, err) + return + } + _, err = client.SetString(visitorConfig.Register, visitorConfig.Offset, visitorConfig.Limit, string(ConvertFloat64ToBytes(valueDouble))) + if err != nil { + klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + return + } + case "boolean": + valueBool, err := strconv.ParseBool(value) + if err != nil { + klog.Errorf("twin %s Convert error: %v", value, err) + return + } + var valueSet uint16 = 0x0000 + if valueBool { + valueSet = 0xFF00 + } + _, err = client.Set(visitorConfig.Register, visitorConfig.Offset, valueSet) + if err != nil { + klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + return + } + case "string": + _, err := client.SetString(visitorConfig.Register, visitorConfig.Offset, visitorConfig.Limit, value) + if err != nil { + klog.Errorf("Set visitor error: %v %v", err, visitorConfig) + return + } + default: + klog.Errorf("wrong DataType of twin %s: %s", value, twin.PVisitor.PProperty.DataType) return } } @@ -350,3 +400,15 @@ func (d *DevPanel) UpdateModel(model *common.DeviceModel) { func (d *DevPanel) RemoveModel(modelName string) { delete(d.models, modelName) } + +func ConvertFloat64ToBytes(f float64) []byte { + res := make([]byte, 8) + binary.BigEndian.PutUint64(res, math.Float64bits(f)) + return res +} + +func ConvertFloat32ToBytes(f float32) []byte { + res := make([]byte, 4) + binary.BigEndian.PutUint32(res, math.Float32bits(f)) + return res +} diff --git a/mappers/modbus-dmi/device/twindata.go b/mappers/modbus-dmi/device/twindata.go index fa489429..7fdd062c 100644 --- a/mappers/modbus-dmi/device/twindata.go +++ b/mappers/modbus-dmi/device/twindata.go @@ -114,18 +114,59 @@ func TransferData(isRegisterSwap bool, isSwap bool, } bits := binary.BigEndian.Uint32(value) data := float64(math.Float32frombits(bits)) * scale - sData := strconv.FormatFloat(data, 'f', 6, 64) + sData := strconv.FormatFloat(data, 'f', 2, 64) return sData, nil case "boolean": - return strconv.FormatBool(value[0] == 1), nil + return strconv.FormatBool(value[0] == 0xFF), nil case "string": - data := string(value) + for i, b := range value { + if !isUpper(b) && !isLowercase(b) && !isNumber(b) && !isSpecial(b) { + value[i] = ' ' + } + } + data := strings.ReplaceAll(string(value), " ", "") return data, nil default: return "", errors.New("data type is not support") } } +func isUpper(b byte) bool { + return 'A' <= b && b <= 'Z' +} + +func isLowercase(b byte) bool { + return 'a' <= b && b <= 'z' +} + +func isNumber(b byte) bool { + return '0' <= b && b <= '9' +} + +func isSpecial(b byte) bool { + whiteList := map[byte]byte{ + '/': '/', + '-': '-', + '_': '_', + '.': '.', + '%': '%', + '+': '+', + ',': ',', + '=': '=', + '@': '@', + '#': '#', + ':': ':', + '^': '^', + '~': '~', + '?': '?', + '&': '&', + '!': '!', + '*': '*', + } + _, ok := whiteList[b] + return ok +} + func (td *TwinData) GetPayload() ([]byte, bool, error) { var err error diff --git a/pkg/driver/modbus/client.go b/pkg/driver/modbus/client.go index 38d8dda6..0bfe9762 100644 --- a/pkg/driver/modbus/client.go +++ b/pkg/driver/modbus/client.go @@ -159,7 +159,7 @@ func (c *ModbusClient) Get(registerType string, addr uint16, quantity uint16) (r case "InputRegister": results, err = c.Client.ReadInputRegisters(addr, quantity) default: - return nil, errors.New("Bad register type") + return nil, errors.New("bad register type") } klog.V(2).Info("Get result: ", results) return results, err @@ -181,18 +181,50 @@ func (c *ModbusClient) Set(registerType string, addr uint16, value uint16) (resu case 1: valueSet = 0xFF00 default: - return nil, errors.New("Wrong value") + return nil, errors.New("wrong value") } results, err = c.Client.WriteSingleCoil(addr, valueSet) case "HoldingRegister": results, err = c.Client.WriteSingleRegister(addr, value) default: - return nil, errors.New("Bad register type") + return nil, errors.New("bad register type") } klog.V(1).Info("Set result:", err, results) return results, err } +func (c *ModbusClient) SetString(registerType string, offset uint16, limit int, value string) (results []byte, err error) { + c.mu.Lock() + defer c.mu.Unlock() + + klog.V(1).Info("ModbusClient Set:", "register", registerType, "offset", offset, "limit", limit, "value", value) + + switch registerType { + case "CoilRegister": + var valueSet uint16 + switch value { + case "0": + valueSet = 0x0000 + case "1": + valueSet = 0xFF00 + default: + return nil, errors.New("wrong value") + } + results, err = c.Client.WriteSingleCoil(offset, valueSet) + case "HoldingRegister": + valueBytes := make([]byte, limit*2) + copy(valueBytes, value) + results, err = c.Client.WriteMultipleRegisters(offset, uint16(limit), valueBytes) + if err != nil { + klog.ErrorS(err, "Failed to set HoldingRegister", "offset", offset, "limit", limit, "value", value) + } + default: + return nil, errors.New("bad register type") + } + klog.V(1).Info("ModbusClient Set result", "results", results) + return results, err +} + // parity convert into the format that modbus driver requires. func parity(ori string) string { var p string