Commit 36c48d75 authored by Alan Mitchell's avatar Alan Mitchell

Added Sensors endpoint to v2 API.

parent 7fe83312
......@@ -322,7 +322,9 @@ class BMSdata:
def sensor_id_list(self):
"""Returns a list of Sensor IDs that are present in the Reading
database. The returned list is sorted by ID."""
database. The returned list is sorted by ID. This includes unassigned sensors
(sensors that are in the Django Sensor object list.
# Don't return IDs that start with underbar.
id_list = [sens_id for sens_id in self.sensor_ids if sens_id[0]!='_']
return sorted(id_list)
......@@ -40,7 +40,7 @@ urlpatterns = [
# Views related to the API, version 2
re_path(r'^api/v2/version/$', views_api_v2.api_version),
re_path(r'^api/v2/readings/$', views_api_v2.sensor_readings_multiple),
re_path(r'^api/v2/readings/$', views_api_v2.sensor_readings),
re_path(r'^api/v2/sensors/$', views_api_v2.sensors),
re_path(r'^api/v2/buildings/$', views_api_v2.buildings),
"""Version 2.x of the API. Relies on views from API v1.
"""Version 2.x of the API. Relies on functions in API v1.
import logging
from collections import Counter
......@@ -11,7 +11,7 @@ from bmsapp import models
from bmsapp.readingdb import bmsdata
from bmsapp.views_api_v1 import (
......@@ -34,7 +34,7 @@ def api_version(request):
return JsonResponse(result)
def sensor_readings_multiple(request):
def sensor_readings(request):
"""API Method. Returns readings from multiple sensors, perhaps time-averaged
and filtered by a date/time range.
......@@ -177,7 +177,120 @@ def sensor_readings_multiple(request):
return JsonResponse(result, status=500)
def sensors(request):
"""Returns information about one or more sensors.
request: Django request object
The 'request' object can have the following query parameters:
sensor_id: The Sensor ID of a sensor to include. This parameter can occur
multiple times to request data from multiple sensors. If the sensor_id
parameter is not present, information for **all** sensors is returned.
A JSON response containing an indicator of success or failure, a list of
sensors including sensor properties and building association information
if available.
# TO DO: fill out unit_id with a string from Units table
# TO DO: create list: (building_id, sensor_group, sort_order)
#------ Check the query parameters
messages = invalid_query_params(request, ['sensor_id'])
# get a list of all the Sensor IDs in the reading database
db = bmsdata.BMSdata() # reading database
all_sensor_ids = db.sensor_id_list()
# determine the list of Sensor IDs requested by this call
sensor_ids = request.GET.getlist('sensor_id')
if len(sensor_ids) == 0:
# no sensors were in the request, which means this should
# return all sensors.
sensor_ids = all_sensor_ids
# check to make sure all the Sensor IDs are valid.
invalid_ids = set(sensor_ids) - set(all_sensor_ids)
if len(invalid_ids):
messages['sensor_id'] = f"Invalid Sensor IDs: {', '.join(list(invalid_ids))}"
if messages:
return fail_payload(messages)
fields_to_exclude = ['_state']
def clean_sensor(s):
"""Function to clean up Sensor object property dictionary and
add some additional info.
Parameter 's' is the dictionary of the Django Sensor object, gotten
from sensor.__dict__
# remove fields to exclude
for fld in fields_to_exclude:
s.pop(fld, None)
# look up the sensor units if present
unit_id = s.pop('unit_id')
if unit_id:
unit = models.Unit.objects.get(pk=unit_id)
s['unit'] = unit.label
s['unit'] = ''
# Add a list of buildings that this sensor is associated with.
if s['id'] is not None:
bldgs = []
for link in models.BldgToSensor.objects.filter(sensor=s['id']):
'sensor_group': link.sensor_group.title,
'sort_order': link.sort_order}
s['buildings'] = bldgs
# no buildings
s['buildings'] = []
return s
sensors = [] # list holding sensor information to return
# get a default dictionary to use if the Sensor ID is not in the Django model
# object list.
default_props = models.Sensor().__dict__
for sensor_id in sensor_ids:
sensor = models.Sensor.objects.get(sensor_id=sensor_id)
sensor_props = sensor.__dict__
# No Django sensor object yet (this is an unassigned sensor).
# Use default values
sensor_props = default_props.copy()
sensor_props['sensor_id'] = sensor_id
result = {
'status': 'success',
'data': {
'sensors': sensors,
return JsonResponse(result)
except Exception as e:
# A processing error occurred.
_logger.exception('Error retrieving sensor information')
result = {
'status': 'error',
'message': str(e)
return JsonResponse(result, status=500)
def buildings(request):
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment