def handle_request(self, request):
     if request.method != 'POST':
         return HttpResponse('Only POST with JSON body is allowed',
                             status=405)
     serialised_request = serialize_django_request(request)
     ok, body = decode_json_body(serialised_request['request.body'])
     if ok is False:
         return HttpResponse(f'JSON ERROR: {body}',
                             status=400,
                             content_type='text/plain')
     try:
         devid = body['deviceId']
     except KeyError as err:
         return HttpResponse(
             f'Invalid request payload, no devid found: {body}',
             status=400,
             content_type='text/plain')
     serialised_request['devid'] = devid
     serialised_request['time'] = datetime.datetime.utcnow().isoformat(
     ) + 'Z'
     message = data_pack(serialised_request)
     key = create_routing_key('ruuvistation', devid)
     send_message(settings.RAW_HTTP_EXCHANGE, key, message)
     if devid is not None:
         datalogger, created = get_datalogger(devid=devid,
                                              update_activity=True)
     return HttpResponse('OK', content_type='text/plain')
 def handle_request(self, request):
     """
     Decode json body and send serialised request to RabbitMQ exchange
     :param request: Django HttpRequest
     :return: HttpResponse
     """
     if request.method != 'POST':
         return HttpResponse('Only POST with JSON body is allowed',
                             status=405)
     serialised_request = serialize_django_request(request)
     ok, body = decode_json_body(serialised_request['request.body'])
     if ok is False:
         err_msg = f'JSON ERROR: {body}'
         logging.error(err_msg)  # Error or warning?
         return HttpResponse(err_msg, status=400, content_type='text/plain')
     # TODO: this will fail if json is malformed
     devid = body['meta'].get('device', 'unknown')
     serialised_request['devid'] = devid
     serialised_request['time'] = datetime.datetime.utcnow().isoformat(
     ) + 'Z'
     logging.debug(json.dumps(body))
     message = data_pack(serialised_request)
     key = create_routing_key('everynet', devid)
     send_message(settings.RAW_HTTP_EXCHANGE, key, message)
     if body.get('type') == 'uplink':
         datalogger, created = get_datalogger(devid=devid,
                                              update_activity=True)
         if created:
             logging.info(f'Created new Datalogger {devid}')
     return HttpResponse('OK', content_type='text/plain')
def parse_ruuvistation_request(serialised_request, data):
    # TODO: This may fail, so prepare to handle exception properly
    devid = data['deviceId']
    datalogger, created = get_datalogger(devid=devid, update_activity=False)
    # Test it by configuring wrong decoder for some Datalogger
    try:
        parsed_data = decode_payload(datalogger, data, '')
        # print(json.dumps(parsed_data, indent=1))
    except ValueError as err:
        decoder = get_datalogger_decoder(datalogger)
        err_msg = f'Failed to parse "{data}" using "{decoder}" for "{devid}": {err}'
        logger.warning(err_msg)
        # print(err_msg)
        serialised_request['parse_fail'] = {
            'error_message': str(err),
            'decoder': get_datalogger_decoder(datalogger)
        }
        save_parse_fail_datalogger_message(devid,
                                           data_pack(serialised_request))
        return True
    logging.debug(parsed_data)

    # RabbitMQ part
    exchange = settings.PARSED_DATA_HEADERS_EXCHANGE
    # If gateway object is in parsed_data it should be looped also here
    for tag in parsed_data['ruuvitags']:  # + [parsed_data['gateway']]:
        devid = tag['devid']
        key = create_routing_key('ruuvistation', devid)
        datalines = tag['datalines']
        message = create_parsed_data_message(devid, datalines=datalines)
        packed_message = data_pack(message)
        logger.debug(
            f'exchange={settings.PARSED_DATA_EXCHANGE} key={key}  packed_message={packed_message}'
        )
        config = {}
        # TODO: implement and use get_datalogger_config()
        if datalogger.application:
            config = json.loads(datalogger.application.config)
        # TODO: get influxdb variables from Application / Datalogger / Forward etc config
        if 'influxdb_database' in config and 'influxdb_measurement' in config:
            config['influxdb'] = '1'
            # Use key name as measurement's name, this will override what is set elsewhere
            # (e.g. in Application config), check save2influxdb.py
            # config['influxdb_measurement'] = 'ruuvitag'
        send_message(exchange, '', packed_message, headers=config)
    return True
Ejemplo n.º 4
0
def send_to_exchange(devid, datalogger, datalines, override_measurement=None):
    # RabbitMQ part
    key = create_routing_key('thingpark', devid)
    message = create_parsed_data_message(devid, datalines=datalines)
    packed_message = data_pack(message)
    exchange = settings.PARSED_DATA_HEADERS_EXCHANGE
    logger.debug(f'exchange={settings.PARSED_DATA_EXCHANGE} key={key}  packed_message={packed_message}')
    config = {}
    # TODO: implement and use get_datalogger_config()
    if datalogger.application:
        config = json.loads(datalogger.application.config)
    # TODO: get influxdb variables from Application / Datalogger / Forward etc config
    if 'influxdb_database' in config and 'influxdb_measurement' in config:
        config['influxdb'] = '1'
        if override_measurement is not None:
            config['influxdb_measurement'] = override_measurement
    send_message(exchange, '', packed_message, headers=config)
Ejemplo n.º 5
0
def parse_thingpark_request(serialised_request, data):
    d = data['DevEUI_uplink']
    devid = d['DevEUI']
    port = d['FPort']
    datalogger, created = get_datalogger(devid=devid, update_activity=False)
    timestamp = parse(d['Time'])
    timestamp = timestamp.astimezone(pytz.UTC)
    payload_hex = d['payload_hex']
    rssi = d['LrrRSSI']
    # TODO: This may fail, so prepare to handle exception properly
    # Test it by configuring wrong decoder for some Datalogger
    try:
        payload = decode_payload(datalogger, payload_hex, port, serialised_request=serialised_request)
    except ValueError as err:
        decoder = get_datalogger_decoder(datalogger)
        err_msg = f'Failed to parse "{payload_hex}" using "{decoder}" for "{devid}": {err}'
        logger.warning(err_msg)
        serialised_request['parse_fail'] = {
            'error_message': str(err),
            'decoder': get_datalogger_decoder(datalogger)
        }
        save_parse_fail_datalogger_message(devid, data_pack(serialised_request))
        return True
    logging.debug(payload)

    # Some sensors may already return a dict of lists of datalines
    if not payload:
        return True
    if isinstance(payload, dict) and isinstance(payload[list(payload.keys())[0]], dict):
        parsed_data = payload
        for k in parsed_data.keys():
            datalines = parsed_data[k]['datalines']
            if len(datalines) > 0:
                datalines[-1]['data']['rssi'] = float(rssi)  # Add rssi value to the latest dataline
                send_to_exchange(devid, datalogger, datalines, override_measurement=k)
    else:  # Some sensors may already return a list of datalines
        if isinstance(payload, list):
            datalines = payload  # Use payload as datalines (which already have timestamps)
        else:
            dataline = create_dataline(timestamp, payload)  # Create dataline from LoRaWAN timestamp and payload
            datalines = [dataline]
        datalines[-1]['data']['rssi'] = float(rssi)  # Add rssi value to the latest dataline
        send_to_exchange(devid, datalogger, datalines)
    return True
Ejemplo n.º 6
0
def parse_everynet_request(serialised_request, body):
    # FIXME: currently this parses only payload_hex from PAXCOUNTER. MUST check BKS too and others
    # TODO: create utility function, which extracts all interesting fields (needed here) out from request data
    devid = body['meta'].get('device', 'unknown')
    payload_base64 = body['params']['payload']
    payload_hex = binascii.hexlify(base64.b64decode(payload_base64))
    port = body['params']['port']
    rssi = body['params']['radio']['hardware']['rssi']
    timestamp = datetime.datetime.utcfromtimestamp(body['params']['rx_time'])
    timestamp = timestamp.astimezone(pytz.UTC)
    # TODO: this may fail if database is offline
    datalogger, created = get_datalogger(devid=devid, update_activity=False)
    payload = decode_payload(datalogger, payload_hex, port)
    payload['rssi'] = rssi

    # RabbitMQ part
    key = create_routing_key('everynet', devid)
    dataline = create_dataline(timestamp, payload)
    datalines = [dataline]
    message = create_parsed_data_message(devid, datalines=datalines)
    packed_message = data_pack(message)
    send_message(settings.PARSED_DATA_EXCHANGE, key, packed_message)
    return True