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_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)
Exemple #3
0
    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
Exemple #4
0
    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()
Exemple #5
0
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 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
        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
Exemple #9
0
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)
        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))
    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)
Exemple #13
0
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)
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)
Exemple #15
0
    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
Exemple #16
0
    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)