github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/mappers/bluetooth_mapper/helper/helper.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 helper
    18  
    19  import (
    20  	"crypto/tls"
    21  	"encoding/json"
    22  	"sync"
    23  	"time"
    24  
    25  	MQTT "github.com/eclipse/paho.mqtt.golang"
    26  	"k8s.io/klog"
    27  )
    28  
    29  var (
    30  	DeviceETPrefix            = "$hw/events/device/"
    31  	DeviceETStateUpdateSuffix = "/state/update"
    32  	TwinETUpdateSuffix        = "/twin/update"
    33  	TwinETCloudSyncSuffix     = "/twin/cloud_updated"
    34  	TwinETGetSuffix           = "/twin/get"
    35  	TwinETGetResultSuffix     = "/twin/get/result"
    36  )
    37  
    38  var TwinResult DeviceTwinResult
    39  var Wg sync.WaitGroup
    40  var ControllerWg sync.WaitGroup
    41  var TwinAttributes []string
    42  
    43  var TokenClient Token
    44  var ClientOpts *MQTT.ClientOptions
    45  var Client MQTT.Client
    46  
    47  //Token interface to validate the MQTT connection.
    48  type Token interface {
    49  	Wait() bool
    50  	WaitTimeout(time.Duration) bool
    51  	Error() error
    52  }
    53  
    54  //DeviceStateUpdate is the structure used in updating the device state
    55  type DeviceStateUpdate struct {
    56  	State string `json:"state,omitempty"`
    57  }
    58  
    59  //BaseMessage the base struct of event message
    60  type BaseMessage struct {
    61  	EventID   string `json:"event_id"`
    62  	Timestamp int64  `json:"timestamp"`
    63  }
    64  
    65  //TwinValue the struct of twin value
    66  type TwinValue struct {
    67  	Value    *string        `json:"value,omitempty"`
    68  	Metadata *ValueMetadata `json:"metadata,omitempty"`
    69  }
    70  
    71  //ValueMetadata the meta of value
    72  type ValueMetadata struct {
    73  	Timestamp int64 `json:"timestamp,omitempty"`
    74  }
    75  
    76  //TypeMetadata the meta of value type
    77  type TypeMetadata struct {
    78  	Type string `json:"type,omitempty"`
    79  }
    80  
    81  //TwinVersion twin version
    82  type TwinVersion struct {
    83  	CloudVersion int64 `json:"cloud"`
    84  	EdgeVersion  int64 `json:"edge"`
    85  }
    86  
    87  //MsgTwin the struct of device twin
    88  type MsgTwin struct {
    89  	Expected        *TwinValue    `json:"expected,omitempty"`
    90  	Actual          *TwinValue    `json:"actual,omitempty"`
    91  	Optional        *bool         `json:"optional,omitempty"`
    92  	Metadata        *TypeMetadata `json:"metadata,omitempty"`
    93  	ExpectedVersion *TwinVersion  `json:"expected_version,omitempty"`
    94  	ActualVersion   *TwinVersion  `json:"actual_version,omitempty"`
    95  }
    96  
    97  //DeviceTwinUpdate the struct of device twin update
    98  type DeviceTwinUpdate struct {
    99  	BaseMessage
   100  	Twin map[string]*MsgTwin `json:"twin"`
   101  }
   102  
   103  //DeviceTwinResult device get result
   104  type DeviceTwinResult struct {
   105  	BaseMessage
   106  	Twin map[string]*MsgTwin `json:"twin"`
   107  }
   108  
   109  // HubclientInit create mqtt client config
   110  func HubClientInit(server, clientID, username, password string) *MQTT.ClientOptions {
   111  	opts := MQTT.NewClientOptions().AddBroker(server).SetClientID(clientID).SetCleanSession(true)
   112  	if username != "" {
   113  		opts.SetUsername(username)
   114  		if password != "" {
   115  			opts.SetPassword(password)
   116  		}
   117  	}
   118  	tlsConfig := &tls.Config{InsecureSkipVerify: true, ClientAuth: tls.NoClientCert}
   119  	opts.SetTLSConfig(tlsConfig)
   120  	return opts
   121  }
   122  
   123  //MqttConnect function felicitates the MQTT connection
   124  func MqttConnect(mqttMode int, mqttInternalServer, mqttServer string) {
   125  	// Initiate the MQTT connection
   126  	if mqttMode == 0 {
   127  		ClientOpts = HubClientInit(mqttInternalServer, "eventbus", "", "")
   128  	} else if mqttMode == 1 {
   129  		ClientOpts = HubClientInit(mqttServer, "eventbus", "", "")
   130  	}
   131  	Client = MQTT.NewClient(ClientOpts)
   132  	if TokenClient = Client.Connect(); TokenClient.Wait() && TokenClient.Error() != nil {
   133  		klog.Errorf("client.Connect() Error is %s", TokenClient.Error())
   134  	}
   135  }
   136  
   137  //ChangeTwinValue sends the updated twin value to the edge through the MQTT broker
   138  func ChangeTwinValue(updateMessage DeviceTwinUpdate, deviceID string) {
   139  	twinUpdateBody, err := json.Marshal(updateMessage)
   140  	if err != nil {
   141  		klog.Errorf("Error in marshalling: %s", err)
   142  	}
   143  	deviceTwinUpdate := DeviceETPrefix + deviceID + TwinETUpdateSuffix
   144  	TokenClient = Client.Publish(deviceTwinUpdate, 0, false, twinUpdateBody)
   145  	if TokenClient.Wait() && TokenClient.Error() != nil {
   146  		klog.Errorf("client.publish() Error in device twin update is %s", TokenClient.Error())
   147  	}
   148  }
   149  
   150  //SyncToCloud function syncs the updated device twin information to the cloud
   151  func SyncToCloud(updateMessage DeviceTwinUpdate, deviceID string) {
   152  	deviceTwinResultUpdate := DeviceETPrefix + deviceID + TwinETCloudSyncSuffix
   153  	twinUpdateBody, err := json.Marshal(updateMessage)
   154  	if err != nil {
   155  		klog.Errorf("Error in marshalling: %s", err)
   156  	}
   157  	TokenClient = Client.Publish(deviceTwinResultUpdate, 0, false, twinUpdateBody)
   158  	if TokenClient.Wait() && TokenClient.Error() != nil {
   159  		klog.Errorf("client.publish() Error in device twin update is: %s", TokenClient.Error())
   160  	}
   161  }
   162  
   163  //GetTwin function is used to get the device twin details from the edge
   164  func GetTwin(updateMessage DeviceTwinUpdate, deviceID string) {
   165  	getTwin := DeviceETPrefix + deviceID + TwinETGetSuffix
   166  	twinUpdateBody, err := json.Marshal(updateMessage)
   167  	if err != nil {
   168  		klog.Errorf("Error in marshalling: %s", err)
   169  	}
   170  	TokenClient = Client.Publish(getTwin, 0, false, twinUpdateBody)
   171  	if TokenClient.Wait() && TokenClient.Error() != nil {
   172  		klog.Errorf("client.publish() Error in device twin get  is: %s ", TokenClient.Error())
   173  	}
   174  }
   175  
   176  //subscribe function subscribes  the device twin information through the MQTT broker
   177  func TwinSubscribe(deviceID string) {
   178  	getTwinResult := DeviceETPrefix + deviceID + TwinETGetResultSuffix
   179  	TokenClient = Client.Subscribe(getTwinResult, 0, OnTwinMessageReceived)
   180  	if TokenClient.Wait() && TokenClient.Error() != nil {
   181  		klog.Errorf("subscribe() Error in device twin result get  is: %s", TokenClient.Error())
   182  	}
   183  	for {
   184  		time.Sleep(1 * time.Second)
   185  		if TwinResult.Twin != nil {
   186  			for k := range TwinResult.Twin {
   187  				TwinAttributes = append(TwinAttributes, k)
   188  			}
   189  			Wg.Done()
   190  			break
   191  		}
   192  	}
   193  }
   194  
   195  // OnTwinMessageReceived callback function which is called when message is received
   196  func OnTwinMessageReceived(client MQTT.Client, message MQTT.Message) {
   197  	err := json.Unmarshal(message.Payload(), &TwinResult)
   198  	if err != nil {
   199  		klog.Errorf("Error in unmarshalling:  %s", err)
   200  	}
   201  }
   202  
   203  //CreateActualUpdateMessage function is used to create the device twin update message
   204  func CreateActualUpdateMessage(updatedTwinAttributes map[string]string) DeviceTwinUpdate {
   205  	var deviceTwinUpdateMessage DeviceTwinUpdate
   206  	deviceTwinUpdateMessage.Twin = map[string]*MsgTwin{}
   207  	for _, twinAttribute := range TwinAttributes {
   208  		if actualValue, ok := updatedTwinAttributes[twinAttribute]; ok {
   209  			deviceTwinUpdateMessage.Twin[twinAttribute] = &MsgTwin{}
   210  			deviceTwinUpdateMessage.Twin[twinAttribute].Actual = &TwinValue{Value: &actualValue}
   211  			deviceTwinUpdateMessage.Twin[twinAttribute].Metadata = &TypeMetadata{Type: "Updated"}
   212  		}
   213  	}
   214  	return deviceTwinUpdateMessage
   215  }