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)
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))
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))
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"))
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))
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))
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")
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))
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)
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)
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))
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"))
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"))
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))
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'])
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, ))