github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/mappers/bluetooth_mapper/configuration/config.go (about)

     1  /*
     2  Copyright 2019 The KubeEdge Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8     http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package configuration
    18  
    19  import (
    20  	"encoding/json"
    21  	"errors"
    22  	"io/ioutil"
    23  	"reflect"
    24  	"strings"
    25  
    26  	"gopkg.in/yaml.v2"
    27  
    28  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/action_manager"
    29  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/data_converter"
    30  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/scheduler"
    31  	"github.com/kubeedge/kubeedge/mappers/bluetooth_mapper/watcher"
    32  )
    33  
    34  //ConfigFilePath contains the location of the configuration file
    35  var ConfigFilePath = "configuration/config.yaml"
    36  
    37  //ConfigMapPath contains the location of the configuration file
    38  var ConfigMapPath = "/opt/kubeedge/deviceProfile.json"
    39  
    40  //Config is the global configuration used by all the modules of the mapper
    41  var Config *BLEConfig
    42  
    43  //Blutooth protocol name
    44  const (
    45  	ProtocolName string = "BLUETOOTH"
    46  	READWRITE    string = "ReadWrite"
    47  	READ         string = "ReadOnly"
    48  )
    49  
    50  //BLEConfig is the main structure that stores the configuration information read from both the config file as well as the config map
    51  type BLEConfig struct {
    52  	Mqtt          Mqtt                        `yaml:"mqtt"`
    53  	Device        Device                      `yaml:"device"`
    54  	Watcher       watcher.Watcher             `yaml:"watcher"`
    55  	Scheduler     scheduler.Scheduler         `yaml:"scheduler"`
    56  	ActionManager actionmanager.ActionManager `yaml:"action-manager"`
    57  	Converter     dataconverter.Converter     `yaml:"data-converter"`
    58  }
    59  
    60  //ReadConfigFile is the structure that is used to read the config file to get configuration information from the user
    61  type ReadConfigFile struct {
    62  	Mqtt            Mqtt                `yaml:"mqtt"`
    63  	DeviceModelName string              `yaml:"device-model-name"`
    64  	ActionManager   ActionManagerConfig `yaml:"action-manager"`
    65  	Watcher         watcher.Watcher     `yaml:"watcher"`
    66  	Scheduler       scheduler.Scheduler `yaml:"scheduler"`
    67  }
    68  
    69  //ActionManagerConfig is a structure that contains a list of actions
    70  type ActionManagerConfig struct {
    71  	Actions []Action `yaml:"actions"`
    72  }
    73  
    74  //Action is structure to define a device action
    75  type Action struct {
    76  	//PerformImmediately signifies whether the action is to be performed by the action-manager immediately or not
    77  	PerformImmediately bool `yaml:"perform-immediately" json:"perform-immediately"`
    78  	//Name is the name of the Action
    79  	Name string `yaml:"name" json:"name"`
    80  	//PropertyName is the name of the property defined in the device CRD
    81  	PropertyName string `yaml:"device-property-name" json:"device-property-name"`
    82  }
    83  
    84  //Mqtt structure contains the MQTT specific configurations
    85  type Mqtt struct {
    86  	Mode           int    `yaml:"mode"`
    87  	InternalServer string `yaml:"internal-server"`
    88  	Server         string `yaml:"server"`
    89  }
    90  
    91  //Device structure contains the device specific configurations
    92  type Device struct {
    93  	ID   string `yaml:"id"`
    94  	Name string `yaml:"name"`
    95  }
    96  
    97  //ReadFromConfigFile is used to load the information from the configuration file
    98  func (readConfigFile *ReadConfigFile) ReadFromConfigFile() error {
    99  	yamlFile, err := ioutil.ReadFile(ConfigFilePath)
   100  	if err != nil {
   101  		return err
   102  	}
   103  	err = yaml.Unmarshal(yamlFile, readConfigFile)
   104  	if err != nil {
   105  		return err
   106  	}
   107  	return nil
   108  }
   109  
   110  //Load is used to consolidate the information loaded from the configuration file and the configmaps
   111  func (b *BLEConfig) Load() error {
   112  	readConfigFile := ReadConfigFile{}
   113  	readConfigMap := DeviceProfile{}
   114  	err := readConfigFile.ReadFromConfigFile()
   115  	if err != nil {
   116  		return errors.New("Error while reading from configuration file " + err.Error())
   117  	}
   118  	err = readConfigMap.ReadFromConfigMap()
   119  	if err != nil {
   120  		return errors.New("Error while reading from config map " + err.Error())
   121  	}
   122  	b.Mqtt = readConfigFile.Mqtt
   123  	b.Scheduler = readConfigFile.Scheduler
   124  	b.Watcher = readConfigFile.Watcher
   125  	// Assign device information obtained from config file
   126  	for _, device := range readConfigMap.DeviceInstances {
   127  		if strings.EqualFold(device.Model, readConfigFile.DeviceModelName) {
   128  			b.Device.ID = device.ID
   129  			b.Device.Name = device.Model
   130  		}
   131  	}
   132  	// Assign information required by action manager
   133  	for _, actionConfig := range readConfigFile.ActionManager.Actions {
   134  		action := actionmanager.Action{}
   135  		action.Name = actionConfig.Name
   136  		action.PerformImmediately = actionConfig.PerformImmediately
   137  
   138  		for _, propertyVisitor := range readConfigMap.PropertyVisitors {
   139  			if strings.EqualFold(propertyVisitor.ModelName, b.Device.Name) && strings.EqualFold(propertyVisitor.PropertyName, actionConfig.PropertyName) && strings.ToUpper(propertyVisitor.Protocol) == ProtocolName {
   140  				propertyVisitorBytes, err := json.Marshal(propertyVisitor.VisitorConfig)
   141  				if err != nil {
   142  					return errors.New("Error in marshalling data property visitor configuration: " + err.Error())
   143  				}
   144  				bluetoothPropertyVisitor := VisitorConfigBluetooth{}
   145  				err = json.Unmarshal(propertyVisitorBytes, &bluetoothPropertyVisitor)
   146  				if err != nil {
   147  					return errors.New("Error in unmarshalling data property visitor configuration: " + err.Error())
   148  				}
   149  				action.Operation.CharacteristicUUID = bluetoothPropertyVisitor.CharacteristicUUID
   150  				newBluetoothVisitorConfig := VisitorConfigBluetooth{}
   151  				if !reflect.DeepEqual(bluetoothPropertyVisitor.BluetoothDataConverter, newBluetoothVisitorConfig.BluetoothDataConverter) {
   152  					readAction := dataconverter.ReadAction{}
   153  					readAction.ActionName = actionConfig.Name
   154  					readAction.ConversionOperation.StartIndex = bluetoothPropertyVisitor.BluetoothDataConverter.StartIndex
   155  					readAction.ConversionOperation.EndIndex = bluetoothPropertyVisitor.BluetoothDataConverter.EndIndex
   156  					readAction.ConversionOperation.ShiftRight = bluetoothPropertyVisitor.BluetoothDataConverter.ShiftRight
   157  					readAction.ConversionOperation.ShiftLeft = bluetoothPropertyVisitor.BluetoothDataConverter.ShiftLeft
   158  					for _, readOperations := range bluetoothPropertyVisitor.BluetoothDataConverter.OrderOfOperations {
   159  						readAction.ConversionOperation.OrderOfExecution = append(readAction.ConversionOperation.OrderOfExecution, readOperations.BluetoothOperationType)
   160  						switch strings.ToUpper(readOperations.BluetoothOperationType) {
   161  						case strings.ToUpper(BluetoothAdd):
   162  							readAction.ConversionOperation.Add = readOperations.BluetoothOperationValue
   163  						case strings.ToUpper(BluetoothSubtract):
   164  							readAction.ConversionOperation.Subtract = readOperations.BluetoothOperationValue
   165  						case strings.ToUpper(BluetoothMultiply):
   166  							readAction.ConversionOperation.Multiply = readOperations.BluetoothOperationValue
   167  						case strings.ToUpper(BluetoothDivide):
   168  							readAction.ConversionOperation.Divide = readOperations.BluetoothOperationValue
   169  						}
   170  					}
   171  					b.Converter.DataRead.Actions = append(b.Converter.DataRead.Actions, readAction)
   172  				}
   173  				if bluetoothPropertyVisitor.DataWriteToBluetooth != nil {
   174  					writeAttribute := dataconverter.WriteAttribute{}
   175  					writeAttribute.Operations = make(map[string]dataconverter.DataMap, 1)
   176  					dataMap := dataconverter.DataMap{}
   177  					dataMap.DataMapping = bluetoothPropertyVisitor.DataWriteToBluetooth
   178  					writeAttribute.Operations[actionConfig.Name] = dataMap
   179  					writeAttribute.Name = propertyVisitor.PropertyName
   180  					b.Converter.DataWrite.Attributes = append(b.Converter.DataWrite.Attributes, writeAttribute)
   181  				}
   182  			}
   183  		}
   184  		for _, deviceModel := range readConfigMap.DeviceModels {
   185  			if strings.EqualFold(deviceModel.Name, b.Device.Name) {
   186  				for _, property := range deviceModel.Properties {
   187  					if strings.EqualFold(property.Name, actionConfig.PropertyName) {
   188  						if property.AccessMode == READWRITE {
   189  							action.Operation.Action = "Write"
   190  							if strings.ToUpper(property.DataType) == "INT" {
   191  								value := string(int(property.DefaultValue.(float64)))
   192  								action.Operation.Value = []byte(value)
   193  							} else if strings.ToUpper(property.DataType) == "STRING" {
   194  								for _, converterAttribute := range b.Converter.DataWrite.Attributes {
   195  									if strings.EqualFold(converterAttribute.Name, actionConfig.PropertyName) {
   196  										for operationName, dataMap := range converterAttribute.Operations {
   197  											if action.Name == operationName {
   198  												if _, ok := dataMap.DataMapping[property.DefaultValue.(string)]; ok {
   199  													action.Operation.Value = dataMap.DataMapping[property.DefaultValue.(string)]
   200  												}
   201  											}
   202  										}
   203  									}
   204  								}
   205  							}
   206  						} else if property.AccessMode == READ {
   207  							action.Operation.Action = "Read"
   208  						}
   209  					}
   210  				}
   211  			}
   212  		}
   213  		b.ActionManager.Actions = append(b.ActionManager.Actions, action)
   214  	}
   215  	Config = b
   216  	return nil
   217  }