Skip to content
This repository was archived by the owner on Mar 15, 2021. It is now read-only.

Commit bbe7efa

Browse files
authored
Merge pull request #210 from KohliDev/handle-exception
User Package Update
2 parents 1c63cb9 + a56d5e9 commit bbe7efa

File tree

4 files changed

+356
-96
lines changed

4 files changed

+356
-96
lines changed

packages/user_packages/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ IoTCC over MQTT Protocol to acquire "registered edge system", i.e. iotcc_edge_sy
1515
which is pre-loaded during the installation in order to provide the required credentials and configuration parameters in the liota package manager registry.
1616
The properties for the edge system can be set as 'key:value' pair, you can also set the location by passing the
1717
'latitude:value' and 'longitude:value' as properties in the user package.
18-
Kindly include the unregister edge_system call in the clean up method required during the unload of the package.
18+
If the unregister call is included in the clean up method then the resource will be unregistered and the entire history will be deleted
19+
from Pulse IoT Control Center so comment the logic if the unregsitration of the resource is not required to be done on the package unload.
20+
The retry mechanism has been implemented for important calls like registration, create_relationship or set_property in case of exception. User Configurable Retry and Delay Settings can be tweaked by user as per the targeted scale.
1921

2022
* iotcc_mqtt_edge_system_stats.py
2123

@@ -24,3 +26,10 @@ monitor the health status of the edge system from Pulse IoT Control Center.
2426
Optional mechanism: If the device raises an intermittent exception during metric collection process it will be required to be handled in the user code
2527
otherwise if an exception is thrown from user code the collection process will be stopped for that metric.
2628
If the None value is returned by User Defined Method(UDM) then metric value for that particular collector instance won't be published.
29+
30+
* iotcc_mqtt_device.py
31+
32+
This is a sample device package which registers five devices to Pulse IoT Control Center and then a relationship is established to Edge System.
33+
A basic UDM returns random value it should be tweaked by user in order to collect device specific metric, all the five devices are loaded with dev_metric.
34+
The retry mechanism has been implemented for important calls like registration, create_relationship or set_property in case of exception.
35+
User Configurable Retry and Delay Settings can be tweaked by user as per the targeted scale.

packages/user_packages/iotcc_mqtt.py

Lines changed: 91 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,37 @@
3131
# ----------------------------------------------------------------------------#
3232

3333
from liota.core.package_manager import LiotaPackage
34+
import time
35+
import logging
36+
import random
37+
38+
log = logging.getLogger(__name__)
3439

3540
dependencies = ["general_edge_system", "credentials"]
3641

42+
# --------------------User Configurable Retry and Delay Settings------------------------------#
43+
44+
# The value mentioned below is the total number of Edge System being deployed in the infrastructure
45+
# minimum 1 for 1K, 2 for 2K, 3 for 3K, 4 for 4K and 5 for 5K Edge Systems
46+
no_of_edge_system_in_thousands = 1
47+
# Number of Retries for Connection and Registrations
48+
no_of_retries_for_connection = 5
49+
# MQTT Connection Delay Min Value in seconds
50+
mqtt_connection_retry_delay_min = 10
51+
# MQTT Connection Delay Max Value in seconds
52+
mqtt_connection_retry_delay_max = 600
53+
# Retry delay Min Value in seconds
54+
delay_retries_min = 600
55+
# Retry delay Max Value in seconds
56+
retries_delay_max = 1800
57+
58+
# Lambda Function Multiplier uses the above settings for calculating retry and delay logic
59+
lfm = lambda x: x * no_of_edge_system_in_thousands
60+
retry_attempts = lfm(no_of_retries_for_connection)
61+
mqtt_connection_delay_retries = random.randint(lfm(mqtt_connection_retry_delay_min),
62+
lfm(mqtt_connection_retry_delay_max))
63+
delay_retries = random.randint(lfm(delay_retries_min), lfm(retries_delay_max))
64+
3765

3866
class PackageClass(LiotaPackage):
3967
"""
@@ -44,19 +72,15 @@ class PackageClass(LiotaPackage):
4472
def run(self, registry):
4573
"""
4674
The execution function of a liota package.
47-
4875
Establishes connection with IoTControlCenter DCC using MqttDccComms
49-
5076
:param registry: the instance of ResourceRegistryPerPackage of the package
5177
:return:
5278
"""
5379
import copy
54-
import time
5580
from liota.lib.utilities.identity import Identity
5681
from liota.dccs.iotcc import IotControlCenter
5782
from liota.dcc_comms.mqtt_dcc_comms import MqttDccComms
5883
from liota.lib.transports.mqtt import MqttMessagingAttributes
59-
from liota.dccs.dcc import RegistrationFailure
6084
from liota.lib.utilities.tls_conf import TLSConf
6185

6286
# Acquire resources from the registry
@@ -76,50 +100,78 @@ def run(self, registry):
76100
# Initialize DCC object with MQTT transport
77101
mqtt_msg_attr = MqttMessagingAttributes(pub_topic="liota/" + registry.get("broker_username") + "/request",
78102
sub_topic="liota/" + registry.get("broker_username") + "/response")
79-
self.iotcc = IotControlCenter(MqttDccComms(edge_system_name=edge_system.name,
80-
url=registry.get("broker_ip"), port=registry.get("broker_port"),
81-
identity=identity,
82-
tls_conf=tls_conf, client_id=registry.get("broker_username"),
83-
enable_authentication=True, mqtt_msg_attr=mqtt_msg_attr))
103+
104+
# Attempts for establishing MQTT Connection
105+
conn_attempts = 0
84106

85107
try:
86-
# Register edge system (gateway)
87-
self.iotcc_edge_system = self.iotcc.register(edge_system)
88-
# Set the properties for edge system as key:value pair, you can also set the location
89-
# by passing the latitude and longitude as a property in the user package
90-
# If the set_properties or register call fails due to DCC_Comms Publish exception
91-
# the optional retry mechanism can be implemented in the following way
92-
attempts = 0
93-
max_retry_attempts = 3
94-
while attempts < max_retry_attempts:
108+
# Trying to establish MQTT Connection with retry attempts in case of exception
109+
while conn_attempts <= retry_attempts:
110+
try:
111+
self.iotcc = IotControlCenter(
112+
MqttDccComms(edge_system_name=edge_system.name, url=registry.get("broker_ip"),
113+
port=registry.get("broker_port"), identity=identity, tls_conf=tls_conf,
114+
client_id=registry.get("broker_username"), enable_authentication=True,
115+
mqtt_msg_attr=mqtt_msg_attr))
116+
break
117+
except Exception as e:
118+
if conn_attempts == retry_attempts:
119+
raise
120+
conn_attempts += 1
121+
log.error('MQTT Connection failed - {0}'.format(str(e)))
122+
log.info('Trying MQTT Connection: Attempt - {0}'.format(str(conn_attempts)))
123+
time.sleep(mqtt_connection_delay_retries)
124+
125+
# Attempts for Edge System Registration
126+
reg_attempts = 0
127+
# Edge System Registration with retry attempts in case of exception
128+
while reg_attempts <= retry_attempts:
95129
try:
96-
# Register edge system (gateway)
97-
self.iotcc.set_properties(self.iotcc_edge_system, {"key1": "value1", "key2": "value2"})
130+
self.iotcc_edge_system = self.iotcc.register(edge_system)
98131
break
99-
except Exception:
100-
# In the third attempt if get exception raise it
101-
if attempts == max_retry_attempts:
132+
except Exception as e:
133+
if reg_attempts == retry_attempts:
102134
raise
103-
attempts += 1
104-
# The sleep time before re-trying depends on the infrastructure requirement of broker to restart
105-
# It can be modified or removed as per the infrastructure requirement
106-
time.sleep(5)
135+
reg_attempts += 1
136+
log.error('Exception while registering Edge System- {0}'.format(str(e)))
137+
log.info('Trying Edge System {0} Registration: Attempt - {1}'.format(edge_system.name,
138+
str(reg_attempts)))
139+
time.sleep(delay_retries)
140+
107141
registry.register("iotcc_mqtt", self.iotcc)
108-
# Store the registered edge system object in liota package manager registry after the
109142
registry.register("iotcc_mqtt_edge_system", self.iotcc_edge_system)
110143

111-
except RegistrationFailure:
112-
print "EdgeSystem registration to IOTCC failed"
144+
# Attempts for setting edge system properties
145+
prop_attempts = 0
146+
# Set multiple properties by passing Dictonary object for Edge System with the retry attempts
147+
# in case of exceptions
148+
while prop_attempts < retry_attempts:
149+
try:
150+
self.iotcc.set_properties(self.iotcc_edge_system,
151+
{"Country": "USA-G", "State": "California", "City": "Palo Alto",
152+
"Location": "VMware HQ", "Building": "Promontory H Lab",
153+
"Floor": "First Floor"})
154+
break
155+
except Exception as e:
156+
prop_attempts += 1
157+
log.error(
158+
'Exception while setting Property for Edge System {0} - {1}'.format(edge_system.name, str(e)))
159+
log.info('Trying setting properties for Edge System {0}: Attempt - {1}'.format(edge_system.name,
160+
str(prop_attempts)))
161+
time.sleep(delay_retries)
162+
163+
except Exception:
164+
log.error("EdgeSystem registration to IOTCC failed even after all the retries, starting connection cleanup")
165+
# Disconnecting MQTT
166+
self.iotcc.comms.client.disconnect()
167+
raise
113168

114169
def clean_up(self):
115-
"""
116-
The clean up function of a liota package.
117-
118-
Disconnects from IoTControlCenter DCC and un-registers the edge-system.
119-
120-
:return:
121-
"""
122-
# Unregister the edge system on package unload
123-
# Kindly include the edge system un-register call on package unload
170+
# Unregister the edge system
171+
# On the unload of the package the Edge System will get unregistered and the entire history will be deleted
172+
# from Pulse IoT Control Center so comment the below logic if the unregsitration of the device is not required
173+
# to be done on the package unload
124174
self.iotcc.unregister(self.iotcc_edge_system)
175+
# Disconnecting MQTT
125176
self.iotcc.comms.client.disconnect()
177+
log.info("Cleanup completed successfully")

0 commit comments

Comments
 (0)