Exemplo n.º 1
0
def last_reading_view(request, sensor_id=None, channel_name=None):
    user = djutils.get_requested_user(request)

    sensor = get_object_or_404(Sensor, id=sensor_id)
    try:
        channel = sensor.channels.get(name=channel_name)
    except Channel.DoesNotExist:
        raise Http404('Requested channel does not exist.')

    if user != sensor.user:
        return HttpResponse(
            "Tried to access data belonging to another user. Forbidden.",
            status=403)

    readings = SensorReading.objects.filter(channel=channel, sensor=sensor)

    if readings.exists():
        lastReadingTime = readings.order_by(
            "-timestamp")[0].timestamp.strftime(JS_FMT)
        return HttpResponse(lastReadingTime)
    else:
        msg = 'sensor: %s, channel: %s, readings.count(): %d' % (
            str(sensor), str(channel), readings.count())
        logger.info(msg)
        return HttpResponse(None)
Exemplo n.º 2
0
def total_energy_view(request):
    owner = djutils.get_requested_user(request)
    meter, channel = sdutils.get_meter(owner)

    form = IntervalForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest(get_json_error(dict(form.errors)))

    start = form.cleaned_data['start']
    end = form.cleaned_data['end']

    if start >= end:
        return HttpResponseBadRequest(
            get_json_error('invalid interval requested'))

    data_start = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Min('timestamp'))['timestamp__min']
    data_end = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Max('timestamp'))['timestamp__max']
    data_end += timedelta(seconds=channel.reading_frequency)

    start = max(start, data_start)
    end = min(end, data_end)

    #filter the reading list for the selection period
    reading_list = SensorReading.objects.filter(sensor=meter, channel=channel)
    reading_list = reading_list.filter(timestamp__gte=(start))
    reading_list = reading_list.filter(timestamp__lt=(end))

    total_energy = reading_list.aggregate(Sum('value'))['value__sum']

    return HttpResponse(json.dumps(total_energy))
Exemplo n.º 3
0
def meter_reading_view(request, data_type):
    djutils.log_request('meter_reading_view', request)

    form = SampledIntervalForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest(get_json_error(dict(form.errors)))

    meter_owner = djutils.get_requested_user(request)
    try:
        meter = Sensor.objects.get(id=request.GET['m_ID'])
    except KeyError:
        meter, _ = sdutils.get_meter(meter_owner)
    channel = Channel.objects.get(name='energy')

    requested_interval = form.cleaned_data['sampling_interval']
    start = form.cleaned_data['start']
    end = form.cleaned_data['end']

    if start >= end:
        return HttpResponseBadRequest(
            get_json_error('invalid interval requested'))

    #filter by interval

    #reading_list_gen = filter_according_to_interval_gen(meter, start, end, requested_interval, data_type)
    #reading_list_gen = list(reading_list_gen)
    #logger.debug('gen: ' + str([x.value for x in reading_list_gen[:4]]))
    #reading_list_sql = filter_according_to_interval_sql(meter, start, end, requested_interval, data_type)

    reading_list = sdutils.filter_according_to_interval(
        meter, channel, start, end, requested_interval, data_type)

    result = {}
    result['data'] = [{
        't': 1000 * mktime(x.timestamp.timetuple()),
        'value': x.value
    } for x in reading_list]

    if len(result['data']) == 0:
        #raise SensorReading.DoesNotExist('no sensor readings')
        result['max_datetime'] = 0
        result['min_datetime'] = 0
        return HttpResponse(json.dumps(result))

    min_datetime = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Min('timestamp'))['timestamp__min']
    min_datetime = min_datetime.strftime(djutils.DATE_FMTS[0])
    result['min_datetime'] = min_datetime

    max_datetime = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Max('timestamp'))['timestamp__max']
    max_datetime = max_datetime.strftime(djutils.DATE_FMTS[0])
    result['max_datetime'] = max_datetime

    return HttpResponse(json.dumps(result))
Exemplo n.º 4
0
def meter_view(request, meter_id=None):
    if request.method == "GET":
        if meter_id == None:
            owner = djutils.get_requested_user(request)
            meter_list = Meter.objects.filter(user=owner)

            return HttpResponse(json.dumps([to_dict(x) for x in meter_list]))
        else:
            meter_list = (Meter.objects.get(id=meter_id), )
            if meter_list[0].user != djutils.get_requested_user(request):
                return HttpResponse(
                    "Tried to access a meter from a different user than the authenticated user.",
                    status=403)
            return HttpResponse(json.dumps([to_dict(m) for m in meter_list]))
    elif request.method == "POST":
        raise NotImplementedError
    else:
        return HttpResponseBadRequest(
            djutils.get_json_error("NOT_GET_REQUEST"))
Exemplo n.º 5
0
def update_view(request):
    user = djutils.get_requested_user(request)
    meter, _ = sdutils.get_meter(user)

    url = settings.PROTECTED_SERVER_URL
    url += "update?fe_username="******"&meter_mac=" + meter.mac

    request = Request(url)
    try:
        response = urlopen(request).read()
        if response != 'ok':
            logger.error("error when updating from protected server")
    except URLError, e:
        logger.error("protected server not answering requests -- " + str(e))
Exemplo n.º 6
0
def event_names_view(request):
    djutils.log_request('event_names_view', request)

    owner = djutils.get_requested_user(request)

    # if the user is part of the control group return no events
    # if Group.objects.get(name='control') in request.user.groups.all():
    #     return HttpResponse(json.dumps([]))

    # filter by user
    events = Event.objects.filter(
        sensor__user=owner).values_list('name').distinct()

    events = [x[0] for x in events]

    return HttpResponse(json.dumps(events))
Exemplo n.º 7
0
def power_now_view(request):
    user = djutils.get_requested_user(request)
    meter, _ = sdutils.get_meter(user)

    url = settings.PROTECTED_SERVER_URL
    url += "power_now?fe_username="******"&meter_type=" + meter.sensor_type
    url += "&meter_mac=" + meter.mac
    #url += "&escrow_password="******"protected server not answering requests. Is it turned on? Is settings.PROTECTED_SERVER_URL correct?"
        )
        return HttpResponse(e, status="502")
Exemplo n.º 8
0
def always_on_view(request, data_type):
    meter_owner = djutils.get_requested_user(request)
    print("Request params:", request.GET.keys())

    if request.GET.get('m_ID', None) == None:
        meter, _ = sdutils.get_meter(meter_owner)
    else:
        meter = Sensor.objects.get(id=request.GET['m_ID'])

    channel = Channel.objects.get(name='energy')

    form = SampledIntervalForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest(get_json_error(dict(form.errors)))

    requested_interval = form.cleaned_data['sampling_interval']
    start = form.cleaned_data['start']
    end = form.cleaned_data['end']

    if start >= end:
        return HttpResponseBadRequest(
            get_json_error('invalid interval requested'))
    sr = SensorReading.objects.filter(sensor=meter, channel=channel)
    if not (sr.exists()):
        return HttpResponse(json.dumps([]))

    data_start = sr.aggregate(Min('timestamp'))['timestamp__min']
    data_end = sr.aggregate(Max('timestamp'))['timestamp__max']
    data_end += timedelta(seconds=channel.reading_frequency)

    start = max(start, data_start)
    end = min(end, data_end)

    baseline = sdutils.calculate_always_on(meter, channel, start, end,
                                           requested_interval, data_type)
    baseline = [{
        't': 1000 * mktime(x[0].timetuple()),
        'value': x[1]
    } for x in baseline]
    return HttpResponse(json.dumps(baseline))
Exemplo n.º 9
0
def live_stats_view(request):
    owner = djutils.get_requested_user(request)
    meter, channel = sdutils.get_meter(owner)
    prediction_weekly = 0

    # TODO: spawn separate thread?
    recentTime = datetime.now() - timedelta(minutes=25)
    testList = SensorReading.objects.filter(sensor=meter, channel=channel)
    testList = testList.filter(timestamp__gte=recentTime)
    testList = testList.filter(timestamp__lte=datetime.now())
    if testList.count() == 0:
        pass
        # TODO TODO TODO -- Work out what this code did and decide what needs to happen.
        #try:
        #amUser = AlertMeUser.objects.get(user=owner)
        #alertme.update_user(amUser, sensor=meter, quick=True)
        #except AlertMeUser.DoesNotExist:
        #pass
        #except URLError:
        #pass
        #except Exception, e:
        #logger.error(str(e))
        #logger.error(str(e.__class__.__name__))

    # Grab the data we need
    reading_list = SensorReading.objects.filter(sensor=meter, channel=channel)

    # Todays total energy
    today = date.fromtimestamp(time())
    startTime = datetime(today.year, today.month, today.day, 0, 0,
                         0)  # 12AM today

    reading_list_todays = reading_list
    reading_list_todays = reading_list_todays.filter(
        timestamp__gte=startTime).filter(timestamp__lte=datetime.now())

    if reading_list_todays.count() < 1:
        todays_total_energy = -1
    else:
        todays_total_energy = reading_list_todays.aggregate(
            Sum('value'))['value__sum']
    # End todays total energy

    # Average daily consumption (since the start of the users presence on system)
    min_date = reading_list.aggregate(Min('timestamp'))['timestamp__min']
    no_days = (datetime.now() - min_date).days

    if no_days == 0:
        average_energy_consumption = 0
    else:
        sum_daily_consumption = reading_list
        sum_daily_consumption = sum_daily_consumption.filter(
            timestamp__lte=datetime.now())

        if sum_daily_consumption.count() < 1:
            average_energy_consumption = -1
        else:
            sum_daily_consumption = sum_daily_consumption.aggregate(
                Sum('value'))['value__sum']
            average_energy_consumption = sum_daily_consumption / no_days
    # End average daily consumption

    # Consumed this week
    studyInfo = StudyInfo.objects.get(user=owner)
    delta = datetime.now() - studyInfo.start_date
    no_days_from_week_start = delta.days % 7
    startTime = date.today() - timedelta(days=no_days_from_week_start)

    week_consumption = reading_list
    week_consumption = week_consumption.filter(
        timestamp__gte=startTime).filter(timestamp__lte=datetime.now())

    if week_consumption.count() < 1:
        week_consumption = -1
    else:
        week_consumption = week_consumption.aggregate(
            Sum('value'))['value__sum']
    # End consumed this week

    # Prediction for the week
    if no_days_from_week_start > 0:
        prediction_weekly = (week_consumption / no_days_from_week_start) * 7
    else:
        # TODO: shall we say "n/a" ?
        #prediction_weekly = (week_consumption / startTime.hour) * 7 * 24
        prediction_weekly = -1
    # End prediction for the week.

    # Reference Consumption (i.e. StudyInfo baseline)
    baseline = studyInfo.baseline_consumption

    response = []
    jsonData = json.dumps(
        {
            'todays_total': todays_total_energy,
            'average_daily': average_energy_consumption,
            'consumed_weekly': week_consumption,
            'prediction_weekly': prediction_weekly,
            'baseline': baseline,
            'week_start': startTime.strftime('%A')
        },
        sort_keys=True,
        indent=4)
    response.append(jsonData)

    msg = '"user": "******", "view": "%s", "response": {%s}' % (
        owner, 'live_stats_view', jsonData)
    logger.info(msg)

    return HttpResponse(response)
Exemplo n.º 10
0
def savings_view(request):
    logger.debug('savings_view')

    owner = djutils.get_requested_user(request)
    meter, channel = sdutils.get_meter(owner)
    #Grab data we need
    #meter_data = SensorReading.objects.filter(meter = meter)
    study_data = StudyInfo.objects.filter(user=owner)

    baseline = study_data.values(
        'baseline_consumption')[0]['baseline_consumption']
    start_time = study_data.values('start_date')[0]['start_date']
    #end_time = datetime.today()

    #Identify the week we are in.
    no_days_since_start = (datetime.today() - start_time).days
    in_week = no_days_since_start / 7
    in_week = min(in_week, 4)

    no_days_from_week_start = no_days_since_start % 7
    start_from_sunday = date.today() - timedelta(days=no_days_from_week_start)

    end_from_yesterday = datetime.now()

    logger.debug("no_days_from_week_start, " + str(no_days_from_week_start))
    logger.debug("start_from_sunday, " + str(start_from_sunday))
    logger.debug("end_from_yesterday, " + str(end_from_yesterday))

    savings = ["na", "na", "na", "na"]
    rewards = [0, 0, 0, 0]

    for week in range(0, in_week):
        weekStart = start_time + timedelta(days=7 * week)
        weekEnd = start_time + timedelta(days=7 * (week + 1))
        weekEnd = min(weekEnd, datetime.now())
        # Calculate sum from start to now.
        weekSum = SensorReading.objects.filter(
            sensor=meter,
            channel=channel).filter(timestamp__gte=weekStart).filter(
                timestamp__lte=weekEnd).aggregate(Sum('value'))['value__sum']
        if weekSum is not None:
            week_savings = getSavings(weekSum, baseline)
            savings[week] = "%.2f" % (week_savings, )
            rewards[week] = getRewards(float(savings[week]), 1, 2, 3)
            logger.debug('savings[%d]: %s' % (week, savings[week]))
            logger.debug('weekSum: %3.2f, baseline: %3.2f' %
                         (weekSum, baseline))
            logger.debug('weekStart: %s, weekEnd: %s' % (weekStart, weekEnd))
        else:
            savings[week] = "n / a"
            rewards[week] = -1

        # TODO: integrate the rewards here..

    response = []
    jsonData = json.dumps(
        {
            'week1_savings': savings[0],
            'week2_savings': savings[1],
            'week3_savings': savings[2],
            'week4_savings': savings[3],
            'week1_rewards': rewards[0],
            'week2_rewards': rewards[1],
            'week3_rewards': rewards[2],
            'week4_rewards': rewards[3]
        },
        sort_keys=True,
        indent=4)
    response.append(jsonData)

    msg = '"user": "******", "view": "%s", "response": {%s}' % (
        owner, 'savings_view', jsonData)
    logger.info(msg)

    return HttpResponse(response)
Exemplo n.º 11
0
def total_energy_cost_view(request):
    owner = djutils.get_requested_user(request)
    meter, channel = sdutils.get_meter(owner)

    form = IntervalForm(request.GET)
    if not form.is_valid():
        return HttpResponseBadRequest(get_json_error(dict(form.errors)))

    start = form.cleaned_data['start']
    end = form.cleaned_data['end']

    if start >= end:
        return HttpResponseBadRequest(
            get_json_error('invalid interval requested'))

    data_start = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Min('timestamp'))['timestamp__min']
    data_end = SensorReading.objects.filter(
        sensor=meter,
        channel=channel).aggregate(Max('timestamp'))['timestamp__max']
    data_end += timedelta(seconds=channel.reading_frequency)

    start = max(start, data_start)
    end = min(end, data_end)

    #filter the reading list for the selection period
    reading_list = SensorReading.objects.filter(sensor=meter, channel=channel)
    reading_list = reading_list.filter(timestamp__gte=(start))
    reading_list = reading_list.filter(timestamp__lte=(end))

    total_energy = reading_list.aggregate(Sum('value'))['value__sum']

    always_on_readings = sdutils.calculate_always_on(meter, channel, start,
                                                     end, 120, 'energy')
    always_on = sum([x[1] for x in always_on_readings])

    #    logger.debug('energy count: %d, always_on count: %d' % (reading_list.count(), len(always_on_readings)))
    #    logger.debug('start: %s, end: %s' % (start, end))
    #    logger.debug('data_start: %s, data_end: %s' % (data_start, data_end))

    # TODO: this introduces a dependency -- this is to be considered
    # a temporary implementation and a cleaner solution should be found
    # to make the code more properly modular
    try:
        from pricing import combined  #@UnresolvedImport
        prices = combined.get_actual_prices(start, end, 0.5, 0.5)
        # TODO make this more precise
        avg_price = sum(prices) / float(len(prices))
        total_cost = total_energy * avg_price
        always_on_cost = always_on * avg_price
    except Exception as e:
        logger.error('pricing exception: ' + str(e))
        total_cost = 0
        always_on_cost = 0

    result = {}
    result['total_cost'] = total_cost
    result['always_on_cost'] = always_on_cost
    result[
        'variable_load_cost'] = result['total_cost'] - result['always_on_cost']

    return HttpResponse(json.dumps(result))
Exemplo n.º 12
0
def event_view(request, event_id=None):
    djutils.log_request('event_view %s' % (str(event_id)), request)

    logger.debug('event_view')

    owner = djutils.get_requested_user(request)
    #startTime = time.clock()
    if request.method == "GET":
        # if the user is part of the control group return no events
        # if Group.objects.get(name='control') in request.user.groups.all():
        #     return HttpResponse(json.dumps([]))

        if event_id != None:
            event = Event.objects.get(id=event_id)

            # augment json with baseline, max, consumption and data
            event_dict = sdutils.calculate_event(event)

            return HttpResponse(json.dumps(event_dict))
        else:
            logger.debug('entered else')
            # event_id not specified
            # get all events within interval
            form = IntervalForm(request.GET)
            if not form.is_valid():
                return HttpResponseBadRequest(get_json_error(dict(
                    form.errors)))

            start = form.cleaned_data['start']
            end = form.cleaned_data['end']

            if start >= end:
                return HttpResponseBadRequest(
                    get_json_error('invalid interval requested'))

            # filter by user
            events = Event.objects.filter(sensor__user=owner)
            events = events.filter(end__gte=start)
            events = events.filter(start__lte=end)

            # exclude suggestions overlapping events
            sugg_type = EventType.objects.get(name='question mark')
            # check that there are no overlapping events from the same user
            manual_events = Event.objects.filter(sensor__user=owner).filter(
                end__gte=start).filter(start__lte=end).exclude(
                    event_type=sugg_type)

            # TODO: fix this!
            logger.debug('about to enter for loop')
            for ev in manual_events:
                # start < sugg.start < end
                events = events.exclude(event_type=sugg_type,
                                        start__gte=ev.start,
                                        start__lte=ev.end)
                # start < sugg.end < end
                events = events.exclude(event_type=sugg_type,
                                        end__gte=ev.start,
                                        end__lte=ev.end)
                # start < sugg.start < sugg.end < end
                events = events.exclude(event_type=sugg_type,
                                        start__lte=ev.start,
                                        end__gte=ev.end)
                events = events.exclude(event_type=sugg_type,
                                        start__gte=ev.start,
                                        end__lte=ev.end)

            logger.debug('about to call sdutils.calculate_event')
            events = [sdutils.calculate_event(ev) for ev in events]
            logger.debug('sdutils.calculate_event returned')

            return HttpResponse(json.dumps(events))

    elif request.method == "POST":
        event = None
        if event_id != None:
            event = Event.objects.get(id=event_id)
        # TODO: use a form for validation
        form = EventForm(request.POST, instance=event)
        if not form.is_valid():
            return HttpResponseBadRequest(get_json_error(dict(form.errors)))

        event = form.save(commit=False)
        #event.user = owner
        #sensor = Sensor.objects.get(id=request)
        event.event_type = EventType.objects.get(
            id=form.cleaned_data['event_type_id'])

        # check that there are no overlapping events from the same user
        dupes = Event.objects.filter(sensor__user=owner).exclude(id=event.id)
        # except suggestions!
        dupes = dupes.exclude(event_type=EventType.objects.get(
            name='question mark'))
        dupes1 = dupes.filter(start__gte=event.start).filter(
            start__lte=event.end)
        dupes2 = dupes.filter(end__gte=event.start).filter(end__lte=event.end)
        if dupes1.count() + dupes2.count() > 0:
            return HttpResponseBadRequest(
                get_json_error('overlapping event exists'))
        event.save()

        #FigureEnergy.recognition.data_interface.extractFeaturesFromDBEvent(event)
        event_created.send(Event.objects, event=event)

        #event.start = datetime.utcfromtimestamp(int(float(request.POST['start'])))
        #event.end = datetime.utcfromtimestamp(int(float(request.POST['end'])))
        #event.name = request.POST['name']
        #event.description = request.POST['description']

        #typeID = request.POST.get('event_type')
        #event.type = EventType.objects.get(id=typeID)

        #event.consumption = 0
        #event.baseline = 0
        #event.save()
        #                if request.POST.get('metering_points_array', None) != None:
        #                    metering_point_ids = eval(request.POST.get('metering_points_array', None))
        #                    metering_points_found = []
        #                    for metering_point_id in metering_point_ids:
        #                        try:
        #                            metering_point = MeteringPoint.objects.get(id = metering_point_id)
        #                            metering_points_found.append(metering_point)
        #                        except MeteringPoint.DoesNotExist:
        #                            pass
        #                    event.metering_points = metering_points_found
        #                event.save()
        return HttpResponse(get_json_success(event.id))
    elif request.method == "DELETE":
        event = Event.objects.get(id=event_id)
        if event.sensor.user == owner:
            event_id = event.id
            event.delete()
            return HttpResponse(get_json_success(event_id))
        return HttpResponseForbidden(get_json_error("ACCESS_DENIED"))
    else:
        return HttpResponseBadRequest(
            get_json_error("NOT_GET_POST_OR_DELETE_REQUEST"))
Exemplo n.º 13
0
def annotation_view(request, annotation_id=None):
    owner = djutils.get_requested_user(request)
    if request.method == "GET":

        if annotation_id != None:
            annotation = Annotation.objects.get(id=annotation_id)
            return HttpResponse(json.dumps(to_dict(annotation)))
        else:
            # annotation_id not specified
            # get all annotations within interval
            form = IntervalForm(request.GET)
            if not form.is_valid():
                return HttpResponseBadRequest(get_json_error(dict(
                    form.errors)))

            start = form.cleaned_data['start']
            end = form.cleaned_data['end']

            if start >= end:
                return HttpResponseBadRequest(
                    get_json_error('invalid interval requested'))

            # filter by user
            annotations = Annotation.objects.filter(user=owner)
            annotations = annotations.filter(end__gte=start)
            annotations = annotations.filter(start__lte=end)
            result = [to_dict(annotation) for annotation in annotations]
            return HttpResponse(json.dumps(result))

    elif request.method == "POST":
        # print "In here..."
        username = request.POST.get('username')

        annotation = None
        if annotation_id != None:
            annotation = Annotation.objects.get(id=annotation_id)

        in_pairs = json.loads(request.POST.get('pairs'))
        pairs = []
        for in_pair in in_pairs:
            # print in_pair
            try:
                pair = SensorChannelPair.objects.get(
                    sensor=in_pair['sensor']['id'],
                    channel=in_pair['channel']['id'])
            except:
                return HttpResponseBadRequest(get_json_error("invalid pair"))
            pairs.append(pair)

        if len(pairs) == 0:
            return HttpResponseBadRequest(
                get_json_error("no pairs for annotation"))

        form = AnnotationForm(request.POST, instance=annotation)
        if not form.is_valid():
            return HttpResponseBadRequest(get_json_error(dict(form.errors)))
        # print "Now in here."
        annotation = form.save(commit=False)
        annotation.user = owner
        annotation.save()
        annotation.pairs = pairs
        annotation.save()

        return HttpResponse(get_json_success(annotation.id))
    elif request.method == "DELETE":
        annotation = Annotation.objects.get(id=annotation_id)
        if annotation.user == owner:
            annotation_id = annotation.id
            annotation.delete()
            return HttpResponse(get_json_success(annotation_id))
        return HttpResponseForbidden(get_json_error("ACCESS_DENIED"))
    else:
        return HttpResponseBadRequest(
            get_json_error("NOT_GET_POST_OR_DELETE_REQUEST"))
Exemplo n.º 14
0
def sensor_view(request, sensor_id=None):
    if request.method == "GET":
        if sensor_id == None:
            owner = djutils.get_requested_user(request)
            sensor_list = Sensor.objects.filter(user=owner)
            return HttpResponse(json.dumps([to_dict(x) for x in sensor_list]))
        else:
            try:
                sensor = Sensor.objects.get(id=sensor_id)
                if sensor.user != djutils.get_requested_user(request):
                    return HttpResponse(
                        "Tried to access a sensor from a different user than the authenticated user.",
                        status=403)
                return HttpResponse(json.dumps(to_dict(sensor)))
            except Sensor.DoesNotExist:
                return HttpResponseNotFound("Sensor with id %s not found." %
                                            (sensor_id, ))
    elif request.method == "POST":  # Ideally would have this PUT, but urllib sucks...
        # POST all require these three parameters. Check they are present, else 400
        try:
            mac = unicode(request.POST["mac"])
            name = unicode(request.POST["name"])
            sensor_type = unicode(request.POST["sensor_type"])
        except KeyError:
            return HttpResponseBadRequest(
                "The request to sensor_view with the following parameters is invalid: "
                + repr(request))
        except ValueError:
            return HttpResponseBadRequest(
                "The request to sensor_view had malformed parameters.")

        sensor_owner = djutils.get_requested_user(request)

        if sensor_id == None:
            # TODO: this should be replaced by dealing with Meter separately from Sensor

            # sensor_id being None may mean that the sensor was not created yet, or
            # a sync problem between the two servers.
            # get or create a sensor with these params:
            sensor, _ = Sensor.objects.get_or_create(mac=mac,
                                                     defaults={
                                                         'user': sensor_owner,
                                                         'name': name,
                                                         'sensor_type':
                                                         sensor_type
                                                     })

            profile = UserProfile.objects.get(user=sensor_owner)
            if profile.primary_sensor is None:
                if sensor.name.startswith(u'Meter Reader'):
                    profile.primary_sensor = sensor
                    profile.save()

            return HttpResponse(str(sensor.id), status=201)
        else:  # Request to specific sensor_id
            # If it exists already:
            try:
                sensor = Sensor.objects.get(id=sensor_id)
            except Sensor.DoesNotExist:  # If it doesn't exist, then throw 404
                return HttpResponseNotFound(
                    "The specified sensor does not exist: " + repr(sensor_id))

            # And doesn't belong to another user
            if sensor.user != sensor_owner:
                return HttpResponseForbidden(
                    "Tried to modify a sensor that doesn't belong the authenticated user."
                )
            else:
                # Then we need to update it according to the request
                sensor.mac = mac
                sensor.sensor_type = sensor_type
                sensor.name = name
                try:
                    sensor.save()
                except IntegrityError as e:
                    # TODO: is this the best response
                    logger.warn('IntegrityError: %s' % (str(e)))
                    return HttpResponseForbidden("Sensor already exists.")
                return HttpResponse(str(sensor.id), status=200)

    elif request.method == "DELETE":
        if sensor_id == None:
            return HttpResponse(
                "Not allowed to delete all sensors with a single call",
                status=403)
        user = djutils.get_requested_user(request)
        try:
            sensor = Sensor.objects.get(pk=sensor_id)
            if user != sensor.user:
                return HttpResponse("Cannot delete other users' meters!",
                                    status=403)
            else:
                with commit_on_success():
                    readings = SensorReading.objects.filter(sensor=sensor)
                    for reading in readings:
                        reading.delete()
                    sensor.delete()
                return HttpResponse("Sensor %s deleted." % (sensor_id, ),
                                    status=200)
        except Sensor.DoesNotExist:
            return HttpResponseNotFound("Meter with id %s not found." %
                                        (sensor_id, ))
    else:
        return HttpResponseBadRequest(
            "The sensor_view is unable to handle the given HTTP method: " +
            repr(request.method))
Exemplo n.º 15
0
def data_view(request, sensor_id=None, channel_name=None):
    if request.method == 'GET':
        # Get sensor and channel
        sensor = get_object_or_404(Sensor, id=sensor_id)
        try:
            channel = sensor.channels.get(name=channel_name)
        except Channel.DoesNotExist:
            return HttpResponseNotFound(
                "This sensor does not appear to contain that channel.")

        # Check user has permission
        if djutils.get_requested_user(request) != sensor.user:
            return HttpResponse(
                "Attempted to edit another user's sensor. Forbidden.",
                status=403)

        # check the interval form
        form = SampledIntervalForm(request.GET)
        if not form.is_valid():
            return HttpResponseBadRequest(
                djutils.get_json_error(dict(form.errors)))

        requested_interval = form.cleaned_data['sampling_interval']
        start = form.cleaned_data['start']
        end = form.cleaned_data['end']

        if start >= end:
            return HttpResponseBadRequest(
                djutils.get_json_error('invalid interval requested'))

        # TODO: using 'power' here as an argument is a hack, it should be fixed
        reading_list = sdutils.filter_according_to_interval(
            sensor, channel, start, end, requested_interval, 'generic')

        result = {}
        result['data'] = [{
            't': 1000 * mktime(x.timestamp.timetuple()),
            'value': x.value
        } for x in reading_list]

        if len(result['data']) == 0:
            #raise SensorReading.DoesNotExist('no sensor readings')
            result['max_datetime'] = 0
            result['min_datetime'] = 0
            return HttpResponse(json.dumps(result))

        min_datetime = SensorReading.objects.filter(
            sensor=sensor,
            channel=channel).aggregate(Min('timestamp'))['timestamp__min']
        min_datetime = min_datetime.strftime(djutils.DATE_FMTS[0])
        result['min_datetime'] = min_datetime

        max_datetime = SensorReading.objects.filter(
            sensor=sensor,
            channel=channel).aggregate(Max('timestamp'))['timestamp__max']
        max_datetime = max_datetime.strftime(djutils.DATE_FMTS[0])
        result['max_datetime'] = max_datetime

        return HttpResponse(json.dumps(result))

    elif request.method == 'POST':
        # TODO: this could be made more clean, using a multi-part post..
        # Check inputs are present and deserialisable
        try:
            data = json.loads(request.POST['data'])
        except KeyError:
            return HttpResponseBadRequest("The data is missing.")
        except TypeError:
            return HttpResponseBadRequest(
                "The data is not a well formed JSON string.")

        # Get sensor and channel
        sensor = get_object_or_404(Sensor, id=sensor_id)
        try:
            channel = sensor.channels.get(name=channel_name)
        except Channel.DoesNotExist:
            return HttpResponseNotFound(
                "This sensor does not appear to contain that channel.")

        # Check user has permission
        if djutils.get_requested_user(request) != sensor.user:
            return HttpResponse(
                "Attempted to edit another user's sensor. Forbidden.",
                status=403)

        # Add data - checking validity
        newCount = 0
        with commit_on_success():
            if type(data) != list:
                return HttpResponseBadRequest(
                    "data_view requires a list of data points.")
            for datum in data:
                try:
                    timestamp = datetime.strptime(str(datum['timestamp']),
                                                  JS_FMT)
                    value = float(datum['value'])
                except KeyError:
                    logger.error('error in data posted to sd_store')
                    return HttpResponseBadRequest(
                        "data_view requires data points to have a 'timestamp' and 'value' key."
                    )
                except ValueError:
                    logger.error(
                        'error in data posted to sd_store (timestamp formatting?)'
                    )
                    return HttpResponseBadRequest(
                        "Timestamps must be formatted:" + JS_FMT +
                        ', and values must be floats.')

                reading, created = SensorReading.objects.get_or_create(
                    sensor=sensor,
                    channel=channel,
                    timestamp=timestamp,
                    defaults={'value': value})
                if not created:
                    reading.value = value
                    reading.save()
                if created:
                    newCount += 1
        return HttpResponse(str(newCount), status=200)
    else:
        return HttpResponseNotAllowed(['GET', 'POST'])
Exemplo n.º 16
0
def channel_view(request, sensor_id=None, channel_name=None):
    if request.method == 'GET':
        user = djutils.get_requested_user(request)
        try:
            sensor = Sensor.objects.get(id=sensor_id)
            channel = sensor.channels.get(name=channel_name)
            if user != sensor.user:
                return HttpResponse(
                    "Tried to access another user's data. Forbidden.",
                    status=403)
            return HttpResponse(json.dumps(to_dict(channel)))

        except Sensor.DoesNotExist:
            return HttpResponseNotFound()
        except Channel.DoesNotExist:
            return HttpResponseNotFound()

    elif request.method == 'POST':
        user = djutils.get_requested_user(request)

        try:
            unit = unicode(request.POST['unit'])
            interval = int(request.POST['reading_frequency'])
        except KeyError:
            return HttpResponseBadRequest(
                "POST to channel_view with missing parameters.")
        except ValueError:
            return HttpResponseBadRequest(
                "POST to channel_view with malformed parameters.")

        try:
            sensor = Sensor.objects.get(id=sensor_id)
        except Sensor.DoesNotExist:
            return HttpResponse(
                "Tried to append a channel to a non-existent sensor.",
                status=404)

        if user != sensor.user:
            logger.warn(
                "Tried to add a channel to a different user's sensor. " +
                'user: %s, sensor: %s, channel_name: %s' %
                (str(user), str(sensor), str(channel_name)))
            return HttpResponse(
                "Tried to add a channel to a different user's sensor. Forbidden.",
                status=403)

        # Create the channel if needed.
        channel, _ = Channel.objects.get_or_create(name=channel_name,
                                                   unit=unit,
                                                   reading_frequency=interval)

        # If the sensor doesn't have a channel by that name, create it:
        if not bool(sensor.channels.filter(name=channel_name)):
            try:
                sensor.channels.add(channel)
                sensor.save()
                return HttpResponse("Added channel to sensor.", status=201)
            except IntegrityError as e:
                #msg = "exception from sensor.channels.add(channel): %s; " % str(e)
                #msg += "sensor.channels.all(): %s; " % str(sensor.channels.all())
                #msg += "IDs: %s; " % str([x.id for x in sensor.channels.all()])
                #msg += "new channel id: %s; " % str(channel.id)
                #msg += "bool(sensor.channels.filter(name=%s)): %s" % (
                #      channel_name, str(bool(sensor.channels.filter(name=channel_name))) )
                #logger.error(msg)
                return HttpResponse("Could not add channel to sensor.",
                                    status=201)
        else:
            oldChannel = sensor.channels.get(name=channel_name)
            sensor.channels.remove(oldChannel)
            sensor.save()
            sensor.channels.add(channel)
            sensor.save()
            return HttpResponse("Modified existing channel on sensor.",
                                status=200)

    elif request.method == 'DELETE':
        user = djutils.get_requested_user(request)
        try:
            sensor = Sensor.objects.get(id=sensor_id)
            channel = sensor.channels.get(name=channel_name)

            if user != sensor.user:
                return HttpResponse(
                    "Tried to delete another user's data. Forbidden.",
                    status=403)

            with commit_on_success():
                for reading in SensorReading.objects.filter(sensor=sensor,
                                                            channel=channel):
                    reading.delete()
                sensor.channels.remove(channel)
            return HttpResponse("Successfully removed channel.", status=200)
        except Sensor.DoesNotExist:
            return HttpResponse(
                "Tried to delete a channel on a non-existent sensor.",
                status=404)
        except Channel.DoesNotExist:
            return HttpResponse("Tried to delete a non-existent channel.",
                                status=404)
    else:
        return HttpResponseBadRequest("channel_view cannot serve HTTP %s." %
                                      (request.method, ))