Exemple #1
0
    async def _exec_plugin_poll(self) -> None:
        """Executes poll type plugin
        """
        _LOGGER.info('Started South Plugin: {}'.format(self._name))
        try_count = 1

        # pollInterval is expressed in milliseconds
        if int(self._plugin_handle['pollInterval']['value']) <= 0:
            self._plugin_handle['pollInterval']['value'] = '1000'
            _LOGGER.warning(
                'Plugin {} pollInterval must be greater than 0, defaulting to {} ms'
                .format(self._name,
                        self._plugin_handle['pollInterval']['value']))
        sleep_seconds = int(
            self._plugin_handle['pollInterval']['value']) / 1000.0
        _TIME_TO_WAIT_BEFORE_RETRY = sleep_seconds

        while self._plugin and try_count <= _MAX_RETRY_POLL:
            try:
                t1 = self._event_loop.time()
                data = self._plugin.plugin_poll(self._plugin_handle)
                if len(data) > 0:
                    if isinstance(data, list):
                        for reading in data:
                            asyncio.ensure_future(
                                Ingest.add_readings(
                                    asset=reading['asset'],
                                    timestamp=reading['timestamp'],
                                    key=reading['key'],
                                    readings=reading['readings']))
                    elif isinstance(data, dict):
                        asyncio.ensure_future(
                            Ingest.add_readings(asset=data['asset'],
                                                timestamp=data['timestamp'],
                                                key=data['key'],
                                                readings=data['readings']))
                delta = self._event_loop.time() - t1
                # If delta somehow becomes > sleep_seconds, then ignore delta
                sleep_for = sleep_seconds - delta if delta < sleep_seconds else sleep_seconds
                await asyncio.sleep(sleep_for)
            except asyncio.CancelledError:
                pass
            except KeyError as ex:
                try_count = 2
                _LOGGER.exception('Key error plugin {} : {}'.format(
                    self._name, str(ex)))
            except exceptions.QuietError:
                try_count = 2
                await asyncio.sleep(_TIME_TO_WAIT_BEFORE_RETRY)
            except (Exception, RuntimeError,
                    exceptions.DataRetrievalError) as ex:
                try_count = 2
                _LOGGER.error('Failed to poll for plugin {}'.format(
                    self._name))
                _LOGGER.debug('Exception poll plugin {}'.format(str(ex)))
                await asyncio.sleep(_TIME_TO_WAIT_BEFORE_RETRY)

        _LOGGER.warning('Stopped all polling tasks for plugin: {}'.format(
            self._name))
Exemple #2
0
 async def _exec_plugin_poll(self) -> None:
     """Executes poll type plugin
     """
     _LOGGER.info('Started South Plugin: {}'.format(self._name))
     try_count = 1
     while self._plugin and try_count <= _MAX_RETRY_POLL:
         try:
             data = self._plugin.plugin_poll(self._plugin_handle)
             if len(data) > 0:
                 if isinstance(data, list):
                     for reading in data:
                         asyncio.ensure_future(
                             Ingest.add_readings(
                                 asset=reading['asset'],
                                 timestamp=reading['timestamp'],
                                 key=reading['key'],
                                 readings=reading['readings']))
                 elif isinstance(data, dict):
                     asyncio.ensure_future(
                         Ingest.add_readings(asset=data['asset'],
                                             timestamp=data['timestamp'],
                                             key=data['key'],
                                             readings=data['readings']))
             # pollInterval is expressed in milliseconds
             sleep_seconds = int(
                 self._plugin_handle['pollInterval']['value']) / 1000.0
             await asyncio.sleep(sleep_seconds)
             # If successful, then set retry count back to 1, meaning that
             # only in case of 3 successive failures, exit.
             try_count = 1
         except KeyError as ex:
             _LOGGER.exception('Key error plugin {} : {}'.format(
                 self._name, str(ex)))
         except (Exception, RuntimeError,
                 exceptions.DataRetrievalError) as ex:
             try_count += 1
             _LOGGER.exception(
                 'Failed to poll for plugin {}, retry count: {}'.format(
                     self._name, try_count))
             await asyncio.sleep(_TIME_TO_WAIT_BEFORE_RETRY)
     _LOGGER.exception(
         'Max retries exhausted in starting South plugin: {}'.format(
             self._name))
Exemple #3
0
 async def _exec_plugin_poll(self, config) -> None:
     """Executes poll type plugin
     """
     await Ingest.start(self._core_management_host,
                        self._core_management_port)
     max_retry = 3
     try_count = 1
     while True and try_count <= max_retry:
         try:
             data = self._plugin.plugin_poll(self._plugin_handle)
             if len(data) > 0:
                 if isinstance(data, list):
                     for reading in data:
                         asyncio.ensure_future(
                             Ingest.add_readings(
                                 asset=reading['asset'],
                                 timestamp=reading['timestamp'],
                                 key=reading['key'],
                                 readings=reading['readings']))
                 elif isinstance(data, dict):
                     asyncio.ensure_future(
                         Ingest.add_readings(asset=data['asset'],
                                             timestamp=data['timestamp'],
                                             key=data['key'],
                                             readings=data['readings']))
             # pollInterval is expressed in milliseconds
             sleep_seconds = int(config['pollInterval']['value']) / 1000.0
             await asyncio.sleep(sleep_seconds)
             # If successful, then set retry count back to 1, meaning that only in case of 3 successive failures, exit.
             try_count = 1
         except KeyError as ex:
             _LOGGER.exception('Keyerror plugin {} : {}'.format(
                 self._name, str(ex)))
         except Exception as ex:
             try_count += 1
             _LOGGER.exception(
                 'Failed to poll for plugin {}, retry count: {}'.format(
                     self._name, try_count))
             await asyncio.sleep(2)
Exemple #4
0
def on_message(client, userdata, msg):
    global _callback_event_loop
    #_LOGGER.info('{} has a message.'.format(_PLUGIN_NAME))    
    try:
        if not Ingest.is_available():
            _LOGGER.error("Ingest is not availabe")
        else:
            inboundPayload = sparkplug_b_pb2.Payload()
            inboundPayload.ParseFromString(msg.payload)
            time_stamp = utils.local_timestamp()
            
            if _callback_event_loop is None:
                    _LOGGER.debug("Message processing event doesn't yet exist - creating new event loop.")
                    asyncio.set_event_loop(asyncio.new_event_loop())
                    _callback_event_loop = asyncio.get_event_loop()
                    
            for metric in inboundPayload.metrics:
                readingKey = str(uuid.uuid4())
                data = {
                    'asset' : metric.name,
                    'timestamp' : time_stamp, #metric.timestamp,
                    'key' : readingKey,
                    'readings' : {                        
                        "value": metric.float_value,
                    }                    
                }
                #_LOGGER.info("UUID: " + readingKey)
                #_LOGGER.info("Metric Name: " + str(metric.name))
                #_LOGGER.info(metric)
                
           
                _callback_event_loop.run_until_complete(save_data(data))              
            
            #_LOGGER.info('Exiting message callback.')
    except Exception as e:
        _LOGGER.error(e)
Exemple #5
0
    async def render_post(request):
        """Store sensor readings from CoAP to FogLAMP

        Args:
            request:
                The payload is a cbor-encoded array that decodes to JSON
                similar to the following:

                .. code-block:: python

                    {
                        "timestamp": "2017-01-02T01:02:03.23232Z-05:00",
                        "asset": "pump1",
                        "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4",
                        "readings": {
                            "velocity": "500",
                            "temperature": {
                                "value": "32",
                                "unit": "kelvin"
                            }
                        }
                    }
        """
        # aiocoap handlers must be defensive about exceptions. If an exception
        # is raised out of a handler, it is permanently disabled by aiocoap.
        # Therefore, Exception is caught instead of specific exceptions.

        # TODO: The payload is documented at
        # https://docs.google.com/document/d/1rJXlOqCGomPKEKx2ReoofZTXQt9dtDiW_BHU7FYsj-k/edit#
        # and will be moved to a .rst file

        code = aiocoap.numbers.codes.Code.VALID
        # TODO: Decide upon the correct format of message
        message = ''
        try:
            if not Ingest.is_available():
                message = '{"busy": true}'
                raise aiocoap.error.CommunicationKilled(message)

            try:
                payload = cbor2.loads(request.payload)
            except Exception:
                raise ValueError('Payload must be a dictionary')

            asset = payload['asset']
            timestamp = payload['timestamp']
            key = payload['key']

            # readings or sensor_values are optional
            try:
                readings = payload['readings']
            except KeyError:
                readings = payload[
                    'sensor_values']  # sensor_values is deprecated

            # if optional then
            # TODO: confirm, do we want to check this?
            if not isinstance(readings, dict):
                raise ValueError('readings must be a dictionary')

            await Ingest.add_readings(asset=asset,
                                      timestamp=timestamp,
                                      key=key,
                                      readings=readings)

        except (KeyError, ValueError, TypeError) as e:
            Ingest.increment_discarded_readings()
            _LOGGER.exception("%d: %s", aiocoap.numbers.codes.Code.BAD_REQUEST,
                              str(e))
            raise aiocoap.error.BadRequest(str(e))
        except Exception as ex:
            Ingest.increment_discarded_readings()
            _LOGGER.exception("%d: %s",
                              aiocoap.numbers.codes.Code.INTERNAL_SERVER_ERROR,
                              str(ex))
            raise aiocoap.error.ConstructionRenderableError(str(ex))

        return aiocoap.Message(payload=message.encode('utf-8'), code=code)
Exemple #6
0
    async def render_post(request):
        """Store sensor readings from CoAP to FogLAMP

        Args:
            request:
                The payload decodes to JSON similar to the following:

                .. code-block:: python

                    {
                        "timestamp": "2017-01-02T01:02:03.23232Z-05:00",
                        "asset": "pump1",
                        "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4",
                        "readings": {
                            "velocity": "500",
                            "temperature": {
                                "value": "32",
                                "unit": "kelvin"
                            }
                        }
                    }
        Example:
            curl -X POST http://localhost:6683/sensor-reading -d '{"timestamp": "2017-01-02T01:02:03.23232Z-05:00", "asset": "pump1", "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4", "readings": {"velocity": "500", "temperature": {"value": "32", "unit": "kelvin"}}}'
        """
        # TODO: The payload is documented at
        # https://docs.google.com/document/d/1rJXlOqCGomPKEKx2ReoofZTXQt9dtDiW_BHU7FYsj-k/edit#
        # and will be moved to a .rst file

        increment_discarded_counter = False

        # TODO: Decide upon the correct format of message
        message = {'result': 'success'}
        code = web.HTTPOk.status_code

        try:
            if not Ingest.is_available():
                increment_discarded_counter = True
                message = {'busy': True}
            else:
                payload = await request.json()

                if not isinstance(payload, dict):
                    raise ValueError('Payload must be a dictionary')

                asset = payload.get('asset')
                timestamp = payload.get('timestamp')
                key = payload.get('key')

                # readings and sensor_readings are optional
                try:
                    readings = payload.get('readings')
                except KeyError:
                    readings = payload.get('sensor_values')  # sensor_values is deprecated

                if not isinstance(readings, dict):
                    raise ValueError('readings must be a dictionary')

                await Ingest.add_readings(asset=asset, timestamp=timestamp, key=key, readings=readings)
        except (ValueError, TypeError) as e:
            increment_discarded_counter = True
            code = web.HTTPBadRequest.status_code
            message = {'error': str(e)}
            _LOGGER.exception(str(e))
        except Exception as e:
            increment_discarded_counter = True
            code = web.HTTPInternalServerError.status_code
            message = {'error': str(e)}
            _LOGGER.exception(str(e))

        if increment_discarded_counter:
            Ingest.increment_discarded_readings()

        # expect keys in response:
        # (code = 2xx) result Or busy
        # (code = 4xx, 5xx) error
        message['status'] = code

        return web.json_response(message)
Exemple #7
0
    async def render_post(request):
        """Store sensor readings from CoAP to FogLAMP

        Args:
            request:
                The payload decodes to JSON similar to the following:

                .. code-block:: python

                    {
                        "timestamp": "2017-01-02T01:02:03.23232Z-05:00",
                        "asset": "pump1",
                        "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4",
                        "readings": {"humidity": 0.0, "temperature": -40.0}
                        }
                    }
        Example:
            curl -X POST http://localhost:6683/sensor-reading -d '{"timestamp": "2017-01-02T01:02:03.23232Z-05:00", "asset": "pump1", "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4", "readings": {"humidity": 0.0, "temperature": -40.0}}'
        """
        # TODO: The payload is documented at
        # https://docs.google.com/document/d/1rJXlOqCGomPKEKx2ReoofZTXQt9dtDiW_BHU7FYsj-k/edit#
        # and will be moved to a .rst file

        # TODO: Decide upon the correct format of message
        message = {'result': 'success'}
        try:
            if not Ingest.is_available():
                message = {'busy': True}
                raise web.HTTPServiceUnavailable(reason=message)

            try:
                payload = await request.json()
            except Exception:
                raise ValueError('Payload must be a dictionary')

            asset = payload['asset']
            timestamp = payload['timestamp']
            key = payload['key']

            # readings or sensor_values are optional
            try:
                readings = payload['readings']
            except KeyError:
                readings = payload[
                    'sensor_values']  # sensor_values is deprecated

            # if optional then
            # TODO: confirm, do we want to check this?
            if not isinstance(readings, dict):
                raise ValueError('readings must be a dictionary')

            await Ingest.add_readings(asset=asset,
                                      timestamp=timestamp,
                                      key=key,
                                      readings=readings)
        except (KeyError, ValueError, TypeError) as e:
            Ingest.increment_discarded_readings()
            _LOGGER.exception("%d: %s", web.HTTPBadRequest.status_code, str(e))
            raise web.HTTPBadRequest(reason=str(e))
        except Exception as ex:
            Ingest.increment_discarded_readings()
            _LOGGER.exception("%d: %s",
                              web.HTTPInternalServerError.status_code, str(ex))
            raise web.HTTPInternalServerError(reason=str(ex))

        return web.json_response(message)
Exemple #8
0
    async def render_post(request):
        """Store sensor readings from CoAP to FogLAMP

        Args:
            request:
                The payload is a cbor-encoded array that decodes to JSON
                similar to the following:

                .. code-block:: python

                    {
                        "timestamp": "2017-01-02T01:02:03.23232Z-05:00",
                        "asset": "pump1",
                        "key": "80a43623-ebe5-40d6-8d80-3f892da9b3b4",
                        "readings": {
                            "velocity": "500",
                            "temperature": {
                                "value": "32",
                                "unit": "kelvin"
                            }
                        }
                    }
        """
        # aiocoap handlers must be defensive about exceptions. If an exception
        # is raised out of a handler, it is permanently disabled by aiocoap.
        # Therefore, Exception is caught instead of specific exceptions.

        # TODO: The payload is documented at
        # https://docs.google.com/document/d/1rJXlOqCGomPKEKx2ReoofZTXQt9dtDiW_BHU7FYsj-k/edit#
        # and will be moved to a .rst file

        code = aiocoap.numbers.codes.Code.INTERNAL_SERVER_ERROR
        increment_discarded_counter = True
        message = ''

        try:
            if not Ingest.is_available():
                message = '{"busy": true}'
            else:
                payload = cbor2.loads(request.payload)

                if not isinstance(payload, dict):
                    raise ValueError('Payload must be a dictionary')

                asset = payload.get('asset')
                timestamp = payload.get('timestamp')

                key = payload.get('key')

                # readings and sensor_readings are optional
                try:
                    readings = payload['readings']
                except KeyError:
                    readings = payload.get(
                        'sensor_values')  # sensor_values is deprecated

                increment_discarded_counter = False

                await Ingest.add_readings(asset=asset,
                                          timestamp=timestamp,
                                          key=key,
                                          readings=readings)

                # Success
                code = aiocoap.numbers.codes.Code.VALID
        except (ValueError, TypeError) as e:
            code = aiocoap.numbers.codes.Code.BAD_REQUEST
            message = json.dumps({message: str(e)})
        except Exception:
            _LOGGER.exception('Add readings failed')

        if increment_discarded_counter:
            Ingest.increment_discarded_readings()

        return aiocoap.Message(payload=message.encode('utf-8'), code=code)