def __init__(self, host, rootCA, cert, key, thingName, stateChangeQueue=None): self.logger = logging.getLogger("GreengrassAwareConnection") self.logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) self.logger.addHandler(streamHandler) self.host = host self.rootCA = rootCA self.cert = cert self.key = key self.thingName = thingName self.stateChangeQueue = stateChangeQueue self.backOffCore = ProgressiveBackOffCore() self.discovered = False self.discoverBroker() self.connected = False self.connect() self.shadowConnected = False self.connectShadow()
def discover_core(self): # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self.host) discoveryInfoProvider.configureCredentials(self.rootCAPath, self.certificatePath, self.privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = Visualizador.MAX_DISCOVERY_RETRIES discovered = False self.groupCA = None self.coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(self.thingName) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] self.coreInfo = coreList[0] print("Discovered GGC: %s from Group: %s" % (self.coreInfo.coreThingArn, groupId)) print("Now we persist the connectivity/identity information...") self.groupCA = Visualizador.GROUP_CA_PATH + groupId + "_CA_" + str(uuid.uuid4()) + ".crt" if not os.path.exists(Visualizador.GROUP_CA_PATH): os.makedirs(Visualizador.GROUP_CA_PATH) groupCAFile = open(self.groupCA, "w") groupCAFile.write(ca) groupCAFile.close() discovered = True print("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, Visualizador.MAX_DISCOVERY_RETRIES)) print("Backing off...\n") backOffCore.backOff() if not discovered: print("Discovery failed after %d retries. Exiting...\n" % (Visualizador.MAX_DISCOVERY_RETRIES)) sys.exit(-1)
def __get_core_ca_from_aws(self): GROUP_CA_PATH = "./groupCA/" # Progressive back off core backoff_core = ProgressiveBackOffCore() MAX_DISCOVERY_RETRIES = 10 retryCount = MAX_DISCOVERY_RETRIES while retryCount != 0: try: discoveryInfo = self.__discoveryInfoProvider.discover( self.__thing_name) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # TODO handle cases where thing belongs to multiple Greengrass groups # We only pick the first ca and core info, a thing could ofcourse belong to multiple Greengrass core groups # but we'll handle that later (aka never) groupId, ca = caList[0] coreInfo = coreList[0] logger.info("Discovered GGC: %s from Group: %s" % (coreInfo.coreThingArn, groupId)) print("Now we persist the connectivity/identity information...") groupCA = GROUP_CA_PATH + groupId + \ "_CA_" + str(uuid.uuid4()) + ".crt" if not os.path.exists(GROUP_CA_PATH): os.makedirs(GROUP_CA_PATH) groupCAFile = open(groupCA, "w") groupCAFile.write(ca) groupCAFile.close() discovered = True logger.info("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: # TODO cleanup code duplication logger.error("Invalid discovery request detected!") logger.error("Type: %s" % str(type(e))) logger.error("Error message: %s" % e.message) logger.error("Stopping...") break except BaseException as e: logger.error("Error in discovery!") logger.error("Error message: %s", str(e)) retryCount -= 1 logger.info("\n%d/%d retries left\n" % (retryCount, MAX_DISCOVERY_RETRIES)) logger.info("Backing off...\n") backoff_core.backOff() if not discovered: logger.fatal("Discovery failed after %d retries. Exiting...\n" % (MAX_DISCOVERY_RETRIES)) sys.exit(-1) return groupCA, coreInfo
def discover(self, thing, retry_count=5): """Performs GG Core discovery""" # Progressive back off core backOffCore = ProgressiveBackOffCore() MAX_RETRY_COUNT = retry_count discovered = False core_info = None group_ca_path = None while retry_count != 0: try: discovery_info = self._discovery_info_provider.discover(thing) ca_list = discovery_info.getAllCas() core_list = discovery_info.getAllCores() # only pick the first ca and core info group_id, ca = ca_list[0] core_info = core_list[0] logger.info('Discovered GGC: {} from Group: {}'.format( core_info.coreThingArn, group_id)) logger.debug('Persist connectivity/identity information...') # cleanup old certificates if os.path.exists(GROUP_CA_PATH): shutil.rmtree(GROUP_CA_PATH) # persist new certificate group_ca_path = GROUP_CA_PATH + group_id + \ "_CA_" + str(uuid.uuid4()) + ".crt" if not os.path.exists(GROUP_CA_PATH): os.makedirs(GROUP_CA_PATH) with open(group_ca_path, "w") as group_ca_file: group_ca_file.write(ca) self._store_connectivityinfo(core_info, group_ca_path) discovered = True break except BaseException as e: retry_count -= 1 logger.debug('Discovery Error: %s\n%d/%d retries left', e, retry_count, MAX_RETRY_COUNT) backOffCore.backOff() if not discovered and self._cache_empty(): raise DiscoverCoreFailedException() elif not discovered: core_info, group_ca_path = self._get_connectivityinfo() return core_info, group_ca_path
def connect(self, core_info, group_ca, certificate_path, private_key_path, retry_count=5): """Attempts to connect to one of the discovered greengrass core devices""" self._client.configureCredentials(group_ca, private_key_path, certificate_path) # Progressive back off core backOffCore = ProgressiveBackOffCore() MAX_RETRY_COUNT = retry_count connected = False while retry_count != 0: # Attempt connecting to any of the endpoint in the connectivity list for connectivity_info in core_info.connectivityInfoList: current_host = connectivity_info.host current_port = connectivity_info.port logger.debug('Trying to connect to core at %s:%s', current_host, current_port) # Configure Endpoint self._client.configureEndpoint(current_host, current_port) try: # Connect client to Core self._client.connect() connected = True break except BaseException as e: logger.debug(e) if not connected: retry_count -= 1 logger.debug('Connection Error\n%d/%d retries left', retry_count, MAX_RETRY_COUNT) backOffCore.backOff() else: break if not connected: raise EstablishConnectionFailedException()
def GreenGrassCoreDiscovery(): global retryCount, discovered, groupCA, coreInfo # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(host) discoveryInfoProvider.configureCredentials(rootCAPath, certificatePath, privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(thingName) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] coreInfo = coreList[0] print("Discovered GGC: %s from Group: %s" % (coreInfo.coreThingArn, groupId)) print("Now we persist the connectivity/identity information...") groupCA = GROUP_CA_PATH + groupId + "_CA_" + str(uuid.uuid4()) + ".crt" if not os.path.exists(GROUP_CA_PATH): os.makedirs(GROUP_CA_PATH) groupCAFile = open(groupCA, "w") groupCAFile.write(ca) groupCAFile.close() discovered = True print("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, MAX_DISCOVERY_RETRIES)) print("Backing off...\n") backOffCore.backOff() if not discovered: subprocess.Popen(['mpg321', 'sound/GreenGrass.mp3']).wait() print("Discovery failed after %d retries. Exiting...\n" % (MAX_DISCOVERY_RETRIES)) sys.exit(-1)
def __init__(self, host, rootCA, cert, key, thingName, stateChangeQueue=None, config={}): self.logger = logging.getLogger("GreengrassAwareConnection") self.logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) self.logger.addHandler(streamHandler) self.config = config self.max_discovery_retries = self.config.get('MAX_DISCOVERY_RETRIES', 3) self.group_ca_path = self.config.get('GROUP_CA_PATH', "./groupCA/") self.offline_queue_depth = self.config.get('OFFLINE_QUEUE_DEPTH', 100) self.host = host self.rootCA = rootCA self.cert = cert self.key = key self.thingName = thingName self.stateChangeQueue = stateChangeQueue self.backOffCore = ProgressiveBackOffCore() self.discovered = False self.discoverBroker() self.connected = False self.connect() self.shadowConnected = False self.connectShadow() self.published_ids = []
def ggc_discovery(thing_name, discovery_info_provider, retry_count=10, max_groups=1): back_off_core = ProgressiveBackOffCore() discovered = False discovery_info = None while retry_count != 0: try: discovery_info = discovery_info_provider.discover(thing_name) group_list = discovery_info.getAllGroups() if len(group_list) > max_groups: raise DiscoveryFailure("Discovered more groups than expected") discovered = True break except DiscoveryFailure as df: logging.error( "Discovery failed! Error:{0} type:{1} message:{2}".format( df, str(type(df)), df.message) ) back_off = True except DiscoveryInvalidRequestException as e: logging.error("Invalid discovery request! Error:{0}".format(e)) logging.error("Stopping discovery...") break except BaseException as e: logging.error( "Error in discovery:{0} type:{1} message:{2} thing_name:{3} " "dip:{4}".format( e, str(type(e)), e.message, thing_name, discovery_info_provider) ) back_off = True if back_off: retry_count -= 1 logging.info("{0} retries left\n".format(retry_count)) logging.debug("Backing off...\n") back_off_core.backOff() return discovered, discovery_info
def ggc_discovery(thing_name, discovery_info_provider, retry_count=10, max_groups=1): back_off_core = ProgressiveBackOffCore() discovered = False discovery_info = None while retry_count != 0: try: discovery_info = discovery_info_provider.discover(thing_name) group_list = discovery_info.getAllGroups() if len(group_list) > max_groups: raise DiscoveryFailure("Discovered more groups than expected") discovered = True break except DiscoveryFailure as df: logging.error( "Discovery failed! Error:{0} type:{1} message:{2}".format( df, str(type(df)), df.message)) back_off = True except DiscoveryInvalidRequestException as e: logging.error("Invalid discovery request! Error:{0}".format(e)) logging.error("Stopping discovery...") break except BaseException as e: logging.error( "Error in discovery:{0} type:{1} message:{2} thing_name:{3} " "dip:{4}".format(e, str(type(e)), e.message, thing_name, discovery_info_provider)) back_off = True if back_off: retry_count -= 1 logging.info("{0} retries left\n".format(retry_count)) logging.debug("Backing off...\n") back_off_core.backOff() return discovered, discovery_info
if not args.certificatePath or not args.privateKeyPath: parser.error("Missing credentials for authentication.") exit(2) # Configure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler) # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(host) discoveryInfoProvider.configureCredentials(rootCAPath, certificatePath, privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = MAX_DISCOVERY_RETRIES discovered = False groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(thingName)
# GPIOs logger.info("GPIO setup") GPIO.setmode(GPIO.BCM) GPIO.setup(GPIO_PWM_OUT, GPIO.OUT) GPIO.setup(GPIO_LED_OPEN, GPIO.OUT) GPIO.setup(GPIO_LED_CLOSE, GPIO.OUT) GPIO.setup(GPIO_BTN_OPEN, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(GPIO_BTN_CLOSE, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(GPIO_BTN_POS1, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(GPIO_BTN_POS2, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(GPIO_BTN_POS3, GPIO.IN, pull_up_down=GPIO.PUD_UP) logger.info("GPIO setup done") # Progressive back off core backOffCore = ProgressiveBackOffCore() myAWSIoTMQTTShadowClient = None myAWSIoTMQTTShadowClientDesire = None mqttClient = None deviceShadowHandler = None deviceShadowHandlerDesire = None # subscribe callback def receive_rail_command(client, userdata, message): logger.info(message.payload) cmd = json.loads(message.payload) move_servo(cmd["action"]) def dicovery_greengrass():
def discoverGGC(host, iotCAPath, certificatePath, privateKeyPath, clientId): # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(host) discoveryInfoProvider.configureCredentials(iotCAPath, certificatePath, privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec print("Iot end point: " + host) print("Iot CA Path: " + iotCAPath) print("GGAD cert path: " + certificatePath) print("GGAD private key path: " + privateKeyPath) print("GGAD thing name : " + clientId) retryCount = MAX_DISCOVERY_RETRIES discovered = False groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(clientId) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # In this example we only have one core # So we pick the first ca and core info groupId, ca = caList[0] coreInfo = coreList[0] print("Discovered GGC: " + coreInfo.coreThingArn + " from Group: " + groupId) hostAddr = "" # In this example Ip detector lambda is turned on which reports # the GGC hostAddr to the CIS (Connectivity Information Service) that stores the # connectivity information for the AWS Greengrass core associated with your group. # This is the information used by discovery and the list of host addresses # could be outdated or wrong and you would normally want to # validate it in a better way. # For simplicity, we will assume the first host address that looks like an ip # is the right one to connect to GGC. # Note: this can also be set manually via the update-connectivity-info CLI for addr in coreInfo.connectivityInfoList: hostAddr = addr.host if isIpAddress(hostAddr): break print("Discovered GGC Host Address: " + hostAddr) print("Now we persist the connectivity/identity information...") groupCA = GROUP_PATH + CA_NAME ggcHostPath = GROUP_PATH + GGC_ADDR_NAME if not os.path.exists(GROUP_PATH): os.makedirs(GROUP_PATH) groupCAFile = open(groupCA, "w") groupCAFile.write(ca) groupCAFile.close() groupHostFile = open(ggcHostPath, "w") groupHostFile.write(hostAddr) groupHostFile.close() discovered = True print("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: " + str(type(e))) print("Error message: " + e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: " + str(type(e))) print("Error message: " + e.message) retryCount -= 1 print("\n" + str(retryCount) + "/" + str(MAX_DISCOVERY_RETRIES) + " retries left\n") print("Backing off...\n") backOffCore.backOff() if not discovered: print("Discovery failed after " + str(MAX_DISCOVERY_RETRIES) + " retries. Exiting...\n") sys.exit(-1)
exit(3) if not os.path.isfile(privateKeyPath): parser.error("No private key found at {}".format(privateKeyPath)) exit(3) # Configure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler) # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(host) discoveryInfoProvider.configureCredentials(rootCAPath, certificatePath, privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = MAX_DISCOVERY_RETRIES discovered = False groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(thingName) caList = discoveryInfo.getAllCas()
def _discover_core(self, client_id, device_certificate_path, device_private_key_path): """Performing the discovery of the core belonging to the same group of the given client identifier. Args: client_id (str): Name of a client, as it is on the cloud, belonging to the same group of the core. device_certificate_path (str): Relative path of a device's certificate stored on the core device, belonging to the same group of the core. device_private_key_path (str): Relative path of a device's private key stored on the core device, belonging to the same group of the core. """ # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self._endpoint) discoveryInfoProvider.configureCredentials(self._root_ca_path, device_certificate_path, device_private_key_path) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = self.MAX_DISCOVERY_ATTEMPTS discovered = False while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(client_id) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] self._core_info = coreList[0] print("Discovered GGC: %s from Group: %s" % (self._core_info.coreThingArn, groupId)) print( "Now we persist the connectivity/identity information...") self._group_ca_path = self._GROUP_CA_PATH + groupId + "_CA_" + str( uuid.uuid4()) + ".crt" if not os.path.exists(self._GROUP_CA_PATH): os.makedirs(self._GROUP_CA_PATH) group_ca_path_file = open(self._group_ca_path, "w") group_ca_path_file.write(ca) group_ca_path_file.close() discovered = True print("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, self.MAX_DISCOVERY_ATTEMPTS)) print("Backing off...\n") backOffCore.backOff() if not discovered: print("Discovery failed after %d retries. Exiting...\n" % (self.MAX_DISCOVERY_ATTEMPTS)) sys.exit(-1) self._configure_logging() AWSGreengrass._discovery_completed = True
class GreengrassAwareConnection: def __init__(self, host, rootCA, cert, key, thingName, stateChangeQueue=None, config={}): self.logger = logging.getLogger("GreengrassAwareConnection") self.logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) self.logger.addHandler(streamHandler) self.config = config self.max_discovery_retries = self.config.get('MAX_DISCOVERY_RETRIES', 3) self.group_ca_path = self.config.get('GROUP_CA_PATH', "./groupCA/") self.offline_queue_depth = self.config.get('OFFLINE_QUEUE_DEPTH', 100) self.host = host self.rootCA = rootCA self.cert = cert self.key = key self.thingName = thingName self.stateChangeQueue = stateChangeQueue self.backOffCore = ProgressiveBackOffCore() self.discovered = False self.discoverBroker() self.connected = False self.connect() self.shadowConnected = False self.connectShadow() self.published_ids = [] def hasDiscovered(self): return self.discovered def discoverBroker(self): if self.hasDiscovered(): return # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self.host) discoveryInfoProvider.configureCredentials(self.rootCA, self.cert, self.key) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = self.max_discovery_retries self.groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(self.thingName) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] self.coreInfo = coreList[0] self.logger.info("Discovered GGC: %s from Group: %s" % (self.coreInfo.coreThingArn, groupId)) self.groupCA = self.group_ca_path + groupId + "_CA_" + str( uuid.uuid4()) + ".crt" if not os.path.exists(self.group_ca_path): os.makedirs(self.group_ca_path) groupCAFile = open(self.groupCA, "w") groupCAFile.write(ca) groupCAFile.close() self.discovered = True break except DiscoveryFailure as e: # device is not configured for greengrass, revert to IoT Core cl = Obj() cl.host = self.host cl.port = 8883 self.coreInfo = Obj() self.coreInfo.connectivityInfoList = [cl] break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) # print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, self.max_discovery_retries)) print("Backing off...\n") self.backOffCore.backOff() def isConnected(self): return self.connected def _getCA(self): return self.groupCA if self.hasDiscovered() else self.rootCA def onOnline(self): # print("online callback") pass def onOffline(self): # print("offline callback") pass def connect(self): if self.isConnected(): return self.client = AWSIoTMQTTClient(self.thingName) self.client.configureCredentials(self._getCA(), self.key, self.cert) for connectivityInfo in self.coreInfo.connectivityInfoList: currentHost = connectivityInfo.host currentPort = connectivityInfo.port self.logger.info("Trying to connect to core at %s:%d" % (currentHost, currentPort)) self.client.configureEndpoint(currentHost, currentPort) try: self.client.configureAutoReconnectBackoffTime(1, 128, 20) self.client.configureOfflinePublishQueueing( self.offline_queue_depth) self.client.configureDrainingFrequency(50) self.client.configureMQTTOperationTimeout(10) self.client.onOnline = self.onOnline self.client.onOffline = self.onOffline self.client.connect() self.connected = True self.currentHost = currentHost self.currentPort = currentPort break except BaseException as e: self.logger.warn("Error in Connect: Type: %s" % str(type(e))) def disconnect(self): if not self.isConnected(): return if self.shadowConnected: self.disconnectShadow() self.client.disconnect() self.connected = False def pubAck(self, mid): # print(f"puback: {mid}") self.published_ids.remove(mid) def publicationIsBlocked(self): # return self.pubIsQueued return False def publishMessageOnTopic(self, message, topic, qos=0): if not self.isConnected(): raise ConnectionError() result = MQTT_ERR_SUCCESS did_publish = False try: result = self.client.publishAsync(topic, message, qos, self.pubAck) did_publish = True # may be QUEUED or has ID self.published_ids.append(int(result)) except ValueError as e: # print(f"message queued - {result}") pass except publishError as e: print(f"Publish Error: {e.message}") except publishQueueFullException as e: print(f"Publish Full Exception: {e.message}") except Exception as e: print(f"Another Exception: {type(e)}") return did_publish def isShadowConnected(self): return self.shadowConnected def deltaHandler(self, payload, responseStatus, token): print("got a delta message " + payload) payloadDict = json.loads(payload) state = payloadDict['state'] try: self.stateChangeQueue.append(state) except Exception as e: pass def shadowUpdate_callback(self, payload, responseStatus, token): if responseStatus != 'accepted': print(f"\n Update Status: {responseStatus}") print(json.dumps(payload)) print("\n") def shadowDelete_callback(self, payload, responseStatus, token): print("shadow deleted") # print(json.dumps({'payload': payload, 'responseStatus': responseStatus, 'token':token})) def connectShadow(self): if not self.isConnected(): self.logger.warn( "connect regula client first to get host and port") raise ConnectionError self.shadowClient = AWSIoTMQTTShadowClient(self.thingName) self.shadowClient.configureEndpoint(self.currentHost, self.currentPort) self.shadowClient.configureCredentials(self._getCA(), self.key, self.cert) # AWSIoTMQTTShadowClient configuration self.shadowClient.configureAutoReconnectBackoffTime(1, 32, 20) self.shadowClient.configureConnectDisconnectTimeout(10) # 10 sec self.shadowClient.configureMQTTOperationTimeout(5) # 5 sec self.shadowClient._AWSIoTMQTTClient.configureOfflinePublishQueueing( self.offline_queue_depth, DROP_OLDEST) self.shadowClient.connect() # Create a deviceShadow with persistent subscription self.deviceShadowHandler = self.shadowClient.createShadowHandlerWithName( self.thingName, True) self.deviceShadowHandler.shadowRegisterDeltaCallback(self.deltaHandler) self.shadowConnected = True def disconnectShadow(self): if not self.shadowConnected: return self.shadowClient.disconnect() self.shadowConnected = False def updateShadow(self, update): if not self.isShadowConnected(): raise ConnectionError state = {'state': {'reported': update}} try: self.deviceShadowHandler.shadowUpdate(json.dumps(state), self.shadowUpdate_callback, 10) except Exception as e: print("Exception updating shadow") def deleteShadow(self): if not self.isShadowConnected(): raise ConnectionError self.deviceShadowHandler.shadowDelete(self.shadowDelete_callback, 15)
def awsgreengrass_connect(distance): distance = distance AllowedActions = ['both', 'publish', 'subscribe'] # General message notification callback def customOnMessage(message): print('Received message on topic %s: %s\n' % (message.topic, message.payload)) MAX_DISCOVERY_RETRIES = 10 GROUP_CA_PATH = "./groupCA/" host = "a3drj1nn7u6229.iot.us-east-1.amazonaws.com" rootCAPath = "root-ca-cert.pem" certificatePath = "62f5a3886d.cert.pem" privateKeyPath = "62f5a3886d.private.key" clientId = "rpi4" thingName = "rpi4" topic = "hello/world/send" mode = "publish" if mode not in AllowedActions: parser.error("Unknown --mode option %s. Must be one of %s" % (mode, str(AllowedActions))) exit(2) if not certificatePath or not privateKeyPath: parser.error("Missing credentials for authentication.") exit(2) # Configure logging logger = logging.getLogger("AWSIoTPythonSDK.core") logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) logger.addHandler(streamHandler) # Progressive back off core backOffCore = ProgressiveBackOffCore() # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(host) discoveryInfoProvider.configureCredentials(rootCAPath, certificatePath, privateKeyPath) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = MAX_DISCOVERY_RETRIES discovered = False groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(thingName) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] coreInfo = coreList[0] print("Discovered GGC: %s from Group: %s" % (coreInfo.coreThingArn, groupId)) print("Now we persist the connectivity/identity information...") groupCA = GROUP_CA_PATH + groupId + "_CA_" + str( uuid.uuid4()) + ".crt" if not os.path.exists(GROUP_CA_PATH): os.makedirs(GROUP_CA_PATH) groupCAFile = open(groupCA, "w") groupCAFile.write(ca) groupCAFile.close() discovered = True print("Now proceed to the connecting flow...") break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, MAX_DISCOVERY_RETRIES)) print("Backing off...\n") backOffCore.backOff() if not discovered: print("Discovery failed after %d retries. Exiting...\n" % (MAX_DISCOVERY_RETRIES)) sys.exit(-1) # Iterate through all connection options for the core and use the first successful one myAWSIoTMQTTClient = AWSIoTMQTTClient(clientId) myAWSIoTMQTTClient.configureCredentials(groupCA, privateKeyPath, certificatePath) myAWSIoTMQTTClient.onMessage = customOnMessage connected = False for connectivityInfo in coreInfo.connectivityInfoList: currentHost = connectivityInfo.host currentPort = connectivityInfo.port print("Trying to connect to core at %s:%d" % (currentHost, currentPort)) myAWSIoTMQTTClient.configureEndpoint(currentHost, currentPort) try: myAWSIoTMQTTClient.connect() connected = True break except BaseException as e: print("Error in connect!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) if not connected: print("Cannot connect to core %s. Exiting..." % coreInfo.coreThingArn) sys.exit(-2) # Successfully connected to the core if mode == 'both' or mode == 'subscribe': myAWSIoTMQTTClient.subscribe(topic, 0, None) time.sleep(2) if mode == 'both' or mode == 'publish': # publish distance over greengrass message = {} message['message'] = "rpi4" message['distance4'] = distance messageJson = json.dumps(message) myAWSIoTMQTTClient.publish(topic, messageJson, 0) if mode == 'publish': print('Published topic %s: %s\n' % (topic, messageJson)) time.sleep(2)
def discover_ggc(self): backOffCore = ProgressiveBackOffCore() discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self.iot_endpoint) discoveryInfoProvider.configureCredentials(self.iot_ca_path, self.cert_path, self.private_key_path) print('Endpoint: {}'.format(self.iot_endpoint)) print('iot_ca_path: {}'.format(self.iot_ca_path)) print('cert_path: {}'.format(self.cert_path)) print('private_key_path: {}'.format(self.private_key_path)) print('device_name: {}'.format(self.device_name)) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = self.max_discovery_retries discovered = False groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover( self.device_name) # noqa: E501 caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() groupId, ca = caList[0] coreInfo = coreList[0] print('Discovered GGC: ' + coreInfo.coreThingArn + ' from Group: ' + groupId) host_addr = '' for addr in coreInfo.connectivityInfoList: host_addr = addr.host if self.isIpAddress(host_addr): break print('Discovered GGC Host Address: ' + host_addr) self.ggc_host_addr = host_addr print('Now we persist the connectivity/identity information') groupCA = os.path.join(self.device_path, self.ca_name) ggcHostPath = os.path.join(self.device_path, self.ggc_addr_name) # noqa: E501 groupCAFile = open(groupCA, 'w') groupCAFile.write(ca) groupCAFile.close() groupHostFile = open(ggcHostPath, 'w') groupHostFile.write(host_addr) groupHostFile.close() discovered = True print('Now proceed to the connecting flow...') break except DiscoveryInvalidRequestException as e: print('Invalid discovery request detected!') print('Type: ' + str(type(e))) print('Error message: ' + e.message) print('Stopping...') break except BaseException as e: print('Error in discovery!') print('Type: ' + str(type(e))) print('Error message: ' + e.message) retryCount -= 1 raise print('\n' + str(retryCount) + '/' + str(self.max_discovery_retries) + ' retries left\n') print('Backing off...\n') backOffCore.backOff() if not discovered: print('Discovery failed after ' + str(self.max_discovery_retries) + ' retries. Exiting...\n') sys.exit(-1)
class GreengrassAwareConnection: MAX_DISCOVERY_RETRIES = 10 GROUP_CA_PATH = "./groupCA/" OFFLINE_QUEUE_DEPTH = 100 def __init__(self, host, rootCA, cert, key, thingName, stateChangeQueue=None): self.logger = logging.getLogger("GreengrassAwareConnection") self.logger.setLevel(logging.DEBUG) streamHandler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s') streamHandler.setFormatter(formatter) self.logger.addHandler(streamHandler) self.host = host self.rootCA = rootCA self.cert = cert self.key = key self.thingName = thingName self.stateChangeQueue = stateChangeQueue self.backOffCore = ProgressiveBackOffCore() self.discovered = False self.discoverBroker() self.connected = False self.connect() self.shadowConnected = False self.connectShadow() def hasDiscovered(self): return self.discovered def discoverBroker(self): if self.hasDiscovered(): return # Discover GGCs discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self.host) discoveryInfoProvider.configureCredentials(self.rootCA, self.cert, self.key) discoveryInfoProvider.configureTimeout(10) # 10 sec retryCount = self.MAX_DISCOVERY_RETRIES self.groupCA = None coreInfo = None while retryCount != 0: try: discoveryInfo = discoveryInfoProvider.discover(self.thingName) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # We only pick the first ca and core info groupId, ca = caList[0] self.coreInfo = coreList[0] self.logger.info("Discovered GGC: %s from Group: %s" % (self.coreInfo.coreThingArn, groupId)) self.groupCA = self.GROUP_CA_PATH + groupId + "_CA_" + str( uuid.uuid4()) + ".crt" if not os.path.exists(self.GROUP_CA_PATH): os.makedirs(self.GROUP_CA_PATH) groupCAFile = open(self.groupCA, "w") groupCAFile.write(ca) groupCAFile.close() self.discovered = True break except DiscoveryInvalidRequestException as e: print("Invalid discovery request detected!") print("Type: %s" % str(type(e))) print("Error message: %s" % e.message) print("Stopping...") break except BaseException as e: print("Error in discovery!") print("Type: %s" % str(type(e))) # print("Error message: %s" % e.message) retryCount -= 1 print("\n%d/%d retries left\n" % (retryCount, self.MAX_DISCOVERY_RETRIES)) print("Backing off...\n") self.backOffCore.backOff() def isConnected(self): return self.connected def connect(self): if self.isConnected(): return self.client = AWSIoTMQTTClient(self.thingName) self.client.configureCredentials(self.groupCA, self.key, self.cert) # myAWSIoTMQTTClient.onMessage = customOnMessage for connectivityInfo in self.coreInfo.connectivityInfoList: currentHost = connectivityInfo.host currentPort = connectivityInfo.port self.logger.info("Trying to connect to core at %s:%d" % (currentHost, currentPort)) self.client.configureEndpoint(currentHost, currentPort) try: self.client.connect() self.connected = True self.currentHost = currentHost self.currentPort = currentPort break except BaseException as e: self.logger.warn("Error in Connect: Type: %s" % str(type(e))) def publishMessageOnTopic(self, message, topic, qos=0): if not self.isConnected(): raise ConnectionError() return self.client.publish(topic, message, qos) def isShadowConnected(self): return self.shadowConnected def memberDeltaHandler(self, payload, responseStatus, token): payloadDict = json.loads(payload) state = payloadDict['state'] if self.stateChangeQueue != None: self.stateChangeQueue.append(state) def connectShadow(self): if not self.isConnected(): self.logger.warn( "connect regula client first to get host and port") raise ConnectionError self.shadowClient = AWSIoTMQTTShadowClient(self.thingName) self.shadowClient.configureEndpoint(self.currentHost, self.currentPort) self.shadowClient.configureCredentials(self.groupCA, self.key, self.cert) # AWSIoTMQTTShadowClient configuration self.shadowClient.configureAutoReconnectBackoffTime(1, 32, 20) self.shadowClient.configureConnectDisconnectTimeout(10) # 10 sec self.shadowClient.configureMQTTOperationTimeout(5) # 5 sec self.shadowClient._AWSIoTMQTTClient.configureOfflinePublishQueueing( self.OFFLINE_QUEUE_DEPTH, DROP_OLDEST) self.shadowClient.connect() # Create a deviceShadow with persistent subscription self.deviceShadowHandler = self.shadowClient.createShadowHandlerWithName( self.thingName, True) self.deviceShadowHandler.shadowRegisterDeltaCallback( self.memberDeltaHandler) self.shadowConnected = True def updateShadow(self, update): if not self.isShadowConnected(): raise ConnectionError state = {'state': {'reported': update}} self.deviceShadowHandler.shadowUpdate(json.dumps(state), shadowUpdate_callback, 10) def deleteShadow(self): if not self.isShadowConnected(): raise ConnectionError self.deviceShadowHandler.shadowDelete(shadowDelete_callback, 5)
def _discover_core(self, client_id, device_certificate_path, device_private_key_path): """Performing the discovery of the core belonging to the same group of the given client name. :param client_id: Name of a client, as it is on the cloud, belonging to the same group of the core. :type client_id: str :param device_certificate_path: Relative path of a device's certificate stored on the core device, belonging to the same group of the core. :type device_certificate_path: str :param device_private_key_path: Relative path of a device's private key stored on the core device, belonging to the same group of the core. :type device_private_key_path: str :returns: The name of the core. :rtype: str :raises EdgeSTInvalidOperationException: is raised if the discovery of the core fails. :raises EdgeSTInvalidDataException: is raised a wrong configuration data is provided. """ # Checking configuration parameters. if not os.access(self._root_ca_path, os.R_OK): msg = '\nRoot Certification Authority certificate path "%s" is not ' \ 'accessible.\r\n' \ 'Please run the application with \"sudo\".' \ % (self._root_ca_path) raise EdgeSTInvalidDataException(msg) if not os.path.exists(device_certificate_path): msg = '\nInvalid device certificate path: "%s"' \ % (device_certificate_path) raise EdgeSTInvalidDataException(msg) if not os.path.exists(device_private_key_path): msg = '\nInvalid device private key path: "%s"' \ % (device_private_key_path) raise EdgeSTInvalidDataException(msg) # Updating service. self._update_status(AWSGreengrassStatus.DISCOVERING_CORE) # Progressive back off core. backOffCore = ProgressiveBackOffCore() # Discover GGCs. discoveryInfoProvider = DiscoveryInfoProvider() discoveryInfoProvider.configureEndpoint(self._endpoint) discoveryInfoProvider.configureCredentials(self._root_ca_path, device_certificate_path, device_private_key_path) discoveryInfoProvider.configureTimeout(self._TIMEOUT_s) attempts = AWSGreengrass.MAX_DISCOVERY_ATTEMPTS while attempts != 0: try: # Discovering information. discoveryInfo = discoveryInfoProvider.discover(client_id) caList = discoveryInfo.getAllCas() coreList = discoveryInfo.getAllCores() # Picking only the first ca and core info. group_id, ca = caList[0] self._core_info = coreList[0] # Persisting connectivity/identity information. self._group_ca_path = self._GROUP_CA_PATH + group_id + \ '_CA_' + str(uuid.uuid4()) + '.crt' if not os.path.exists(self._GROUP_CA_PATH): os.makedirs(self._GROUP_CA_PATH) group_ca_path_file = open(self._group_ca_path, 'w') group_ca_path_file.write(ca) group_ca_path_file.close() break except DiscoveryInvalidRequestException as e: raise EdgeSTInvalidOperationException( 'Invalid discovery request detected: %s' % (e.message)) except BaseException as e: attempts -= 1 backOffCore.backOff() if attempts == 0: raise EdgeSTInvalidOperationException( 'Discovery of the core related to the client "%s", with ' \ 'certificate "%s" and key "%s", failed after %d retries.' % \ (client_id, device_certificate_path, device_private_key_path, AWSGreengrass.MAX_DISCOVERY_ATTEMPTS)) self._configure_logging() AWSGreengrass._discovery_completed = True # Updating service. self._update_status(AWSGreengrassStatus.CORE_DISCOVERED) return self._core_info.coreThingArn