Example #1
0
def parse_sentilo_data(data):
    measurements = []
    for item in data['sensors']:
        ts_str = item['observations'][0].get('timestamp')
        if ts_str is not None:
            ts = parse(item['observations'][0]['timestamp'], dayfirst=True)
        else:
            ts = datetime.datetime.utcnow()
            print(ts.strftime("%Y-%m-%dT%H:%M:%S.%fZ data without timestamp!"))
        dev_id = item['sensor'][0:-2]
        if item['sensor'].endswith('N'):
            fields = {'dBA': float(item['observations'][0]['value'])}
            measurement = create_influxdb_obj(dev_id,
                                              'LAeq',
                                              fields,
                                              timestamp=ts)
            measurements.append(measurement)
        if item['sensor'].endswith('S'):
            cnt = 0
            secvals = item['observations'][0]['value'].split(';')
            secvals.reverse()
            for val in secvals:
                fields = {'dBA': float(val.split(',')[0])}
                measurement = create_influxdb_obj(
                    dev_id,
                    'LAeq1s',
                    fields,
                    timestamp=(ts - datetime.timedelta(seconds=cnt)))
                cnt += 1
                measurements.append(measurement)
    return measurements
Example #2
0
    def view_func(self, request):
        """
        Endpoint requires idcode, sensor and data parameters. Also a valid Django user must exist. Test like this:

        export ESPEASY_URL=esp
        echo -n "idcode=unique_id_here&sensor=bme280&id=0&data=Temperature=24.84,Humidity=52.05,Pressure=1002.50" | \
           http -v --auth user:pass --form POST http://127.0.0.1:8000/esp
        """
        uname, passwd, user = basicauth(request)
        p = request.POST
        if user is None:
            return HttpResponse("Authentication failure", status=401)
        if request.method == 'GET':
            return HttpResponse('ok', status=200)
        idcode = p.get('idcode')
        sensor = p.get('sensor')
        data = p.get('data')
        # Reject request if required variables are not set
        if None in [idcode, sensor, data]:
            err_msg = '[ESPEASY] idcode, sensor and/or data is missing in request form data'
            logger.error(err_msg)
            return HttpResponse(err_msg, status=400)
        data = data.strip()
        # Reject request if data is not comma separated key=value pairs or value is not float
        try:
            fields = dict([tuple(x.split('=')) for x in data.split(',')])
            for k in fields.keys():
                fields[k] = float(fields[k])
        except ValueError as err:
            err_msg = '[ESPEASY] data error: {}. Hint: data was "{}".'.format(err, data)
            logger.error(err_msg)
            response = HttpResponse(err_msg, status=400)
            return response
        measurement = create_influxdb_obj(idcode, sensor, fields)
        measurements = [measurement]
        # import json; print(json.dumps(measurement, indent=1)); print(data)
        dbname = uname  # Use username as database name
        try:
            save_to_influxdb.delay(dbname, measurements)
        except Exception as err:
            logger.error(err)
            raise
        # iclient = get_influxdb_client(database=dbname)
        # try:
        #     iclient.create_database(dbname)
        #     iclient.write_points(measurements)
        #     response = HttpResponse("ok")
        # except InfluxDBClientError as err:
        #     err_msg = '[ESPEASY] InfluxDB error: {}'.format(err)
        #     logger.error(err_msg)
        #     response = HttpResponse(err_msg, status=500)
        response = HttpResponse("ok")
        return response
Example #3
0
 def view_func(self, request):
     res = dump_request(request, postfix='democam')
     ok_response = HttpResponse("ok")
     body_data = ''
     if request.method not in ['POST']:
         return HttpResponse('Only POST methdod is allowed', status=405)
     try:
         body_data = request.body
         data = json.loads(body_data.decode('utf-8'))
     except (ValueError, UnicodeDecodeError) as err:
         return invalid_data(body_data,
                             "Hint: should be UTF-8 json.",
                             status=400)
     # Validate data
     if "direction" not in data.keys():
         data["direction"] = -1
     for k in ["plate", "date", "country", "confidence", "ip", "direction"]:
         if k not in data.keys():
             return invalid_data(body_data,
                                 "Hint: key '{}' is missing.".format(k),
                                 status=400)
     timestamp = parse(data['date'])
     plate = Plate(plate=data['plate'],
                   timestamp=timestamp,
                   country=data['country'],
                   confidence=float(data['confidence']),
                   ip=data['ip'],
                   direction=int(data['direction']))
     plate.save()
     idata = {'vehicle': 1}
     measurement = create_influxdb_obj('001', 'cnt', idata, timestamp)
     measurements = [measurement]
     dbname = 'vehicle'
     iclient = get_influxdb_client(database=dbname)
     iclient.create_database(dbname)
     try:
         iclient.write_points(measurements)
         response = HttpResponse("OK")
     except InfluxDBClientError as err:
         err_msg = '[PLATECAMERA] InfluxDB error: {}'.format(err)
         logger.error(err_msg)
         response = HttpResponse(err_msg, status=500)
     return response
def parse_tag_data(data):
    measurements = []
    for tag in data['tags']:
        ts = dateutil.parser.parse(tag['updateAt'])
        if ts.tzinfo is None or ts.tzinfo.utcoffset(ts) is None:
            ts = get_default_timezone().localize(ts)
        dev_id = tag['id']
        extratags = {}
        name = tag.get('name')
        if name:
            extratags['name'] = name
        fields = {}
        for key in to_save:
            fields[key] = tag.get(key)
        measurement = create_influxdb_obj(dev_id,
                                          'ruuvitag',
                                          fields,
                                          timestamp=ts,
                                          extratags=extratags)
        measurements.append(measurement)
        # print(measurements)
    return measurements
Example #5
0
    def view_func(self, request):
        """
        Endpoint requires idcode, sensor and data parameters. Also a valid Django user must exist. Test like this:

        export EVERYNET_URL=everynet
        """
        ok_response = HttpResponse("ok")
        body_data = ''
        if request.method not in ['OPTIONS', 'POST']:
            return HttpResponse('Only OPTIONS, POST methdods are allowed',
                                status=405)
        if request.method == 'OPTIONS':  # FIXME: I don't know is this a correct answer
            return HttpResponse('OK', status=200)
        try:
            body_data = request.body
            data = json.loads(body_data.decode('utf-8'))
        except (ValueError, UnicodeDecodeError) as err:
            return invalid_data(body_data,
                                "Hint: should be UTF-8 json.",
                                status=400)
        # meta and type keys should be always in request json
        try:
            device = data['meta']['device']
            times = str(data['meta']['time'])
            packet_type = data['type']
        except KeyError as err:
            err_msg = 'Invalid json structure: "{}". Hint: missing key {}.'.format(
                body_data, err)
            return invalid_data(body_data, err_msg, status=400)
        now = timezone.now().astimezone(pytz.utc)
        path = os.path.join(settings.MEDIA_ROOT, 'everynet',
                            now.strftime('%Y-%m-%d'), device)
        os.makedirs(path, exist_ok=True)
        fpath = os.path.join(path, now.strftime('%Y%m%dT%H%M%S.%fZ.json'))
        dl_descr = 'everynet'
        if random.randint(
                0, 50) == 10:  # Save 1/50 of packages for debugging purposes
            with open(fpath, 'wt') as destination:
                destination.write(json.dumps(data, indent=1))
                dump_request(request, postfix='everynet')
        if packet_type == 'error':
            logger.warning(
                '[EVERYNET]: Got error msg, check {} for details.'.format(
                    fpath))
            return ok_response
        elif packet_type == 'uplink':
            payload = data['params']['payload'].encode()
            _type = request.GET.get('type')
            if _type == 'paxcounter':
                data_str = base64.decodebytes(payload)
                idata = handle_paxcounter(data_str)
                keys_str = 'wifi-ble'
                dl_descr = 'paxcounter'
            elif _type == 'keyval':  # data should be key=val,key2=val2,... formatted
                data_str = base64.decodebytes(payload).decode('utf8')
                print(data_str, type(data_str))
                idata = handle_keyval(data_str)
                try:  # convert values to floats in dict
                    idata = {k: float(v) for k, v in idata.items()}
                except ValueError as err:
                    err_msg = 'Should be base64 encoded key=val pairs, comma separated.'.format(
                        data_str[:50])
                    return invalid_data(data_str, err_msg, status=400)
                print(idata)
                keys = list(idata.keys())
                keys.sort()
                if len(keys) == 0:
                    err_msg = 'Should be base64 encoded key=val pairs, comma separated.'
                    # NOTE: from everynet's point of view this is not error.
                    return invalid_data(data_str, err_msg, status=200)

                keys_str = '_'.join(keys)
                dl_descr = 'keyval'
            else:
                data_str = base64.decodebytes(payload).decode('utf8')
                handle_v1(data_str)  # TODO
                try:
                    sensordata = json.loads(data_str)
                    if not isinstance(sensordata, dict):
                        err_msg = '[EVERYNET] payload is not json: {}'.format(
                            data_str)
                        logger.warning(err_msg)
                        return HttpResponse("OK: dumped data to a file.")
                except (ValueError) as err:
                    return invalid_data(data_str,
                                        "Hint: should be UTF-8 json.",
                                        status=400)
                if 'id' in sensordata and 'sensor' in sensordata:
                    keys = list(sensordata['data'].keys())
                    idata = sensordata['data']
                    pass
                else:  # old method
                    keys = list(sensordata.keys())
                    idata = sensordata
                keys.sort()
                keys_str = '-'.join(keys)
            datalogger, created = get_datalogger(device,
                                                 description=dl_descr,
                                                 update_activity=True)
            # TODO: log new devices (created == True), maybe send email to admin?
            ts = datetime.datetime.utcfromtimestamp(data['meta']['time'])
            ts = pytz.UTC.localize(ts)  # Make timestamp timezone aware at UTC
            measurement = create_influxdb_obj(device, keys_str, idata, ts)
            measurements = [measurement]
            dbname = request.GET.get('db')
            if dbname is None:
                dbname = EVERYNET_DB
            iclient = get_influxdb_client(database=dbname)
            iclient.create_database(dbname)
            try:
                iclient.write_points(measurements)
                response = HttpResponse("ok")
            except InfluxDBClientError as err:
                err_msg = '[EVERYNET] InfluxDB error: {}'.format(err)
                logger.error(err_msg)
                response = HttpResponse(err_msg, status=500)
            return response
        else:
            err_msg = '[EVERYNET] Unknown packet type {}'.format(packet_type)
            logger.warning(err_msg)
        return ok_response
Example #6
0
 def view_func(self, request):
     """
     Endpoint requires valid Digita formatted JSON payload.
     """
     err_msg = ''
     status = 200
     try:
         body_data = request.body
         data = json.loads(body_data.decode('utf-8'))
     except (json.decoder.JSONDecodeError, UnicodeDecodeError) as err:
         log_msg = '[DIGITA] Invalid data: "{}". Hint: should be UTF-8 json.'.format(
             body_data[:50])
         err_msg = 'Invalid data: "{}"... Hint: should be UTF-8 json.'.format(
             body_data[:50])
         logger.error(log_msg)
         return HttpResponse(err_msg, status=400)
     # meta and type keys should be always in request json
     try:
         d = data['DevEUI_uplink']
         device = d['DevEUI']
         times = str(d['Time'])
         rssi = d['LrrRSSI']
         payload_hex = d['payload_hex']
     except KeyError as err:
         log_msg = '[DIGITA] Invalid json structure: "{}". Missing key: {}.'.format(
             body_data, err)
         err_msg = 'Invalid json structure: "{}". Hint: missing key {}.'.format(
             body_data, err)
         logger.error(log_msg)
         return HttpResponse(err_msg, status=400)
     now = timezone.now().astimezone(pytz.utc)
     path = os.path.join(settings.MEDIA_ROOT, 'digita',
                         now.strftime('%Y-%m-%d'), device)
     os.makedirs(path, exist_ok=True)
     fpath = os.path.join(path, now.strftime('%Y%m%dT%H%M%S.%fZ.json'))
     with open(fpath, 'wt') as destination:
         destination.write(json.dumps(data, indent=1))
     response = HttpResponse("ok")
     # TODO: move this to a function
     if len(payload_hex) == 8:
         idata = {
             'wifi': int(payload_hex[0:4], 16),
             'ble': int(payload_hex[4:8], 16)
         }
         idata['rssi'] = rssi
         keys_str = 'wifi-ble'
         dl_descr = 'paxcounter'
         datalogger, created = get_datalogger(device,
                                              description=dl_descr,
                                              update_activity=True)
         ts = dateutil.parser.parse(times)
         measurement = create_influxdb_obj(device, keys_str, idata, ts)
         measurements = [measurement]
         # dbname = request.GET.get('db', DIGITA_DB)
         dbname = 'paxcounter'
         iclient = get_influxdb_client(database=dbname)
         iclient.create_database(dbname)
         try:
             iclient.write_points(measurements)
         except InfluxDBClientError as err:
             err_msg = '[DIGITA] InfluxDB error: {}'.format(err)
             status = 500
     elif payload_hex[:2] == '13':
         idata = handle_clickey_tempsens(payload_hex)
         idata['rssi'] = rssi
         keys_str = 'tempsens'
         datalogger, created = get_datalogger(
             device,
             description='Clickey Tempsens PRO',
             update_activity=True)
         ts = dateutil.parser.parse(times)
         measurement = create_influxdb_obj(device, keys_str, idata, ts)
         measurements = [measurement]
         # dbname = request.GET.get('db', DIGITA_DB)
         dbname = 'digita'
         iclient = get_influxdb_client(database=dbname)
         iclient.create_database(dbname)
         try:
             iclient.write_points(measurements)
         except InfluxDBClientError as err:
             err_msg = '[DIGITA] InfluxDB error: {}'.format(err)
             status = 500
     elif payload_hex[:2].lower(
     ) == '2a':  # payload_hex[:4].lower() == '2a2a':
         idata = handle_aqburk(payload_hex)
         idata['rssi'] = rssi
         keys_str = 'aqburk'
         datalogger, created = get_datalogger(device,
                                              description='FVH AQ burk',
                                              update_activity=True)
         ts = dateutil.parser.parse(times)
         measurement = create_influxdb_obj(device, keys_str, idata, ts)
         measurements = [measurement]
         DIGITA_DB = 'aqburk'
         dbname = request.GET.get('db', DIGITA_DB)
         iclient = get_influxdb_client(database=dbname)
         iclient.create_database(dbname)
         try:
             iclient.write_points(measurements)
         except InfluxDBClientError as err:
             err_msg = '[DIGITA] InfluxDB error: {}'.format(err)
             status = 500
     elif len(payload_hex) >= 2:  # Assume we have key-val data
         try:
             idata = handle_keyval(payload_hex)
         except (UnicodeDecodeError, IndexError) as err:
             err_msg = '[DIGITA] Payload error: {}'.format(err)
             status = 400
             logger.error(err_msg)
             dump_request(request, postfix='digita')
             response = HttpResponse(err_msg, status=status)
             return response
         idata['rssi'] = rssi
         ikeys = list(idata.keys())
         ikeys.sort()
         keys_str = '_'.join(ikeys)
         datalogger, created = get_datalogger(device,
                                              description='LoRaWAN device',
                                              update_activity=True)
         ts = dateutil.parser.parse(times)
         measurement = create_influxdb_obj(device, keys_str, idata, ts)
         measurements = [measurement]
         # dbname = request.GET.get('db', DIGITA_DB)
         dbname = 'digita'
         iclient = get_influxdb_client(database=dbname)
         iclient.create_database(dbname)
         try:
             iclient.write_points(measurements)
         except InfluxDBClientError as err:
             err_msg = '[DIGITA] InfluxDB error: {}'.format(err)
             status = 500
     else:
         err_msg = '[DIGITA] Not handled'
     if err_msg != '':
         logger.error(err_msg)
         dump_request(request, postfix='digita')
         response = HttpResponse(err_msg, status=status)
     return response