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 }