class SensorResource(Resource): model = Sensor display_field = 'metric' resource_name = 'sensors' resource_type = 'sensor' required_fields = ['metric', 'unit'] # for now, name is hardcoded as the only attribute of metric and unit stub_fields = {'metric': 'name', 'unit': 'name'} queryset = Sensor.objects related_fields = { 'ch:dataHistory': CollectionField(SensorDataResource, reverse_name='sensor'), 'ch:device': ResourceField('chain.core.resources.DeviceResource', 'device') } def serialize_single(self, embed, cache, *args, **kwargs): data = super(SensorResource, self).serialize_single(embed, cache, *args, **kwargs) if embed: data['dataType'] = 'float' last_data = self._obj.scalar_data.order_by( 'timestamp').reverse()[:1] if last_data: data['value'] = last_data[0].value data['updated'] = last_data[0].timestamp.isoformat() return data def get_tags(self): return ['sensor-%s' % self._obj.id, 'device-%s' % self._obj.device_id, 'site-%s' % self._obj.device.site_id]
class DeviceResource(Resource): model = Device display_field = 'name' resource_name = 'devices' resource_type = 'device' required_fields = ['name'] model_fields = [ 'name', 'description', 'building', 'floor', 'room', 'active' ] ''''ch:sensors': CollectionField(ScalarSensorResource, reverse_name='device'), 'ch:sensors': CollectionField(PresenceSensorResource, reverse_name='device'),''' related_fields = { 'ch:sensors': CollectionField(MixedSensorResource, reverse_name='device'), 'ch:site': ResourceField('chain.core.resources.SiteResource', 'site'), 'ch:metadata': MetadataCollectionField(MetadataResource) } queryset = Device.objects def get_tags(self): # sometimes the site_id field is unicode? weird return ['device-%d' % self._obj.id, 'site-%s' % self._obj.site_id]
class ScalarSensorResource(Resource): model = ScalarSensor display_field = 'metric' resource_name = 'scalar_sensors' resource_type = 'scalar_sensor' required_fields = ['metric', 'unit'] model_fields = ['active'] # for now, name is hardcoded as the only attribute of metric and unit stub_fields = {'metric': 'name', 'unit': 'name'} queryset = ScalarSensor.objects related_fields = { 'ch:dataHistory': CollectionField(ScalarSensorDataResource, reverse_name='sensor'), 'ch:aggregateData': CollectionField(AggregateScalarSensorDataResource, reverse_name='sensor'), 'ch:device': ResourceField('chain.core.resources.DeviceResource', 'device'), 'ch:metadata': MetadataCollectionField(MetadataResource) } def serialize_single(self, embed, cache, *args, **kwargs): data = super( ScalarSensorResource, self).serialize_single( embed, cache, *args, **kwargs) data['sensor-type'] = "scalar" if embed: data['dataType'] = 'float' # this is hammering the influx server, we should switch it # over to doing a single bulk query. For now disabling the # data to get things up and running if not kwargs.get('include_data', True): return data else: last_data = influx_client.get_last_sensor_data(self._obj.id) if last_data: # column name returned by last() selector is last data['value'] = last_data[0]['last'] data['updated'] = last_data[0]['time'] return data def get_tags(self): return ['sensor-%s' % self._obj.id, 'scalar_sensor-%s' % self._obj.id, 'device-%s' % self._obj.device_id, 'site-%s' % self._obj.device.site_id]
class MixedSensorResource(Resource): model = ScalarSensor display_field = 'metric' resource_name = 'sensors' resource_type = 'sensor' # for now, name is hardcoded as the only attribute of metric and unit stub_fields = {'metric': 'name'} queryset = ScalarSensor.objects available_sensor_types = { 'scalar': { 'model': ScalarSensor, 'resource': ScalarSensorResource }, 'presence': { 'model': PresenceSensor, 'resource': PresenceSensorResource } } related_fields = { 'ch:device': ResourceField('chain.core.resources.DeviceResource', 'device') } @classmethod def get_schema(cls, filters=None): schema = { 'required': ['sensor-type'], 'type': 'object', 'properties': { 'sensor-type': { 'type': 'string', 'title': 'sensor-type', 'enum': cls.available_sensor_types.keys() } }, 'title': 'Create Sensor' } for sensor_type in cls.available_sensor_types: sub_schema = cls.available_sensor_types[sensor_type][ 'resource'].get_schema(filters) schema = json_merge(schema, sub_schema) return schema @classmethod def create_list(cls, data, req): raise Exception("Not yet implemented.") @classmethod def create_single(cls, data, req): if u'sensor-type' not in data: # raise Exception("'type' property not found") # For temporary back-compatability, assume it # is a ScalarSensor: return ScalarSensorResource.create_single(data, req) for sensor_type in cls.available_sensor_types: if data['sensor-type'] == sensor_type: del data['sensor-type'] return cls.available_sensor_types[sensor_type][ 'resource'].create_single(data, req) # TODO: Return 400 rather than raising an exception raise Exception("Unrecognized sensor type.") def serialize_single(self, embed, cache, *args, **kwargs): data = super(MixedSensorResource, self).serialize_single(embed, cache, *args, **kwargs) if embed: pass if '_links' in data: data['_links'].update(self.get_links()) data['totalCount'] = len(data['_links']['items']) return data def serialize_list(self, embed, cache, *args, **kwargs): data = super(MixedSensorResource, self).serialize_list(embed=embed, cache=cache, *args, **kwargs) if embed: pass if '_links' in data: data['_links'].update(self.get_links()) data['totalCount'] = len(data['_links']['items']) return data def get_links(self): mapped_model_to_res = self.map_model_to_resource() sensors = self.query_models() items = [] for sensor in sensors: items.append({ 'href': (mapped_model_to_res[type(sensor)]( obj=sensor, request=self._request)).get_single_href(), 'title': "%s" % sensor }) return {'items': items} def map_model_to_resource(self): mapped = {} for sensor_type in self.available_sensor_types: sensor_details = self.available_sensor_types[sensor_type] mapped[sensor_details['model']] = sensor_details['resource'] return mapped def query_models(self): results = [] for sensor_type in self.available_sensor_types: modelResults = self.available_sensor_types[sensor_type][ 'model'].objects.filter(**self._filters) results.extend(modelResults) return results def get_tags(self): return [ 'sensor-%s' % self._obj.id, 'device-%s' % self._obj.device_id, 'site-%s' % self._obj.device.site_id ]
class PersonResource(Resource): model = Person display_field = 'last_name' resource_name = 'people' resource_type = 'person' required_fields = ['first_name', 'last_name'] model_fields = ['first_name', 'last_name', 'twitter_handle', 'rfid'] related_fields = { 'ch:presence-data': CollectionField(PresenceDataResource, reverse_name='person'), 'ch:site': ResourceField('chain.core.resources.SiteResource', 'site') } queryset = Person.objects def serialize_single(self, embed, cache, *args, **kwargs): data = super(PersonResource, self).serialize_single(embed, cache, *args, **kwargs) if embed: if '_embedded' not in data: data['_embedded'] = {} data['_embedded'].update(self.get_additional_embedded()) if '_links' in data: data['_links'].update(self.get_additional_links()) return data def get_presence_data(self): filters = {'person': self._obj} return PresenceData.objects.filter(**filters).order_by('timestamp')[:1] def get_additional_links(self): links = {} last_data = self.get_presence_data() if last_data: links['last-visit'] = { 'href': self.get_presense_data_url(last_data[0]), 'title': "at %s->%s at time %s" % (last_data[0].sensor.device, last_data[0].sensor.metric, last_data[0].timestamp.isoformat()) } if self._obj.picture_url: links['picture'] = { 'href': self._obj.picture_url, 'title': 'Picture URL (external)' } return links def get_additional_embedded(self): embedded = {} last_data = self.get_presence_data() if last_data: embedded['last-visit'] = PresenceDataResource(obj=last_data[0], request=self._request)\ .serialize_single(False, {}) return embedded def get_presense_data_url(self, obj): if self._request is None: # No way to form URL, just return the person's ID return obj.id pdata_resource = PresenceDataResource(obj=obj, request=self._request) return pdata_resource.get_single_href() def get_tags(self): # sometimes the site_id field is unicode? weird return ['person-%d' % self._obj.id, 'site-%s' % self._obj.site_id]
class PresenceSensorResource(Resource): model = PresenceSensor display_field = 'metric' resource_name = 'presence_sensors' resource_type = 'presence_sensor' required_fields = ['metric'] # for now, name is hardcoded as the only attribute of metric and unit stub_fields = {'metric': 'name'} queryset = PresenceSensor.objects related_fields = { 'ch:dataHistory': CollectionField(PresenceDataResource, reverse_name='sensor'), 'ch:device': ResourceField('chain.core.resources.DeviceResource', 'device') } def serialize_single(self, embed, cache, *args, **kwargs): data = super(PresenceSensorResource, self).serialize_single(embed, cache, *args, **kwargs) data['sensor-type'] = "presence" data['dataType'] = "presence" if embed: if '_embedded' not in data: data['_embedded'] = {} data['_embedded'].update(self.get_additional_embedded()) if '_links' not in data: data['_links'] = {} data['_links'].update(self.get_additional_links()) return data def get_additional_links(self): links = {} last_data = self._obj.presence_data.order_by('timestamp').reverse()[:1] if last_data: links['last-visit'] = { 'href': self.get_presense_data_url(last_data[0]), 'title': "%s at %s" % (last_data[0].person, last_data[0].timestamp.isoformat()) } return links def get_additional_embedded(self): embedded = {} last_data = self._obj.presence_data.order_by('timestamp').reverse()[:1] if last_data: embedded['last-visit'] = PresenceDataResource(obj=last_data[0], request=self._request)\ .serialize_single(False, {}) return embedded def get_person_url(self, obj): if self._request is None: # No way to form URL, just return the person's ID return obj.id person_resource = PersonResource(obj=obj, request=self._request) return person_resource.get_single_href() def get_presense_data_url(self, obj): if self._request is None: # No way to form URL, just return the person's ID return obj.id pdata_resource = PresenceDataResource(obj=obj, request=self._request) return pdata_resource.get_single_href() def get_sensor_url(self, obj): if self._request is None: # No way to form URL, just return the person's ID return obj.id psensor_resource = PresenceSensorResource(obj=obj, request=self._request) return psensor_resource.get_single_href() def get_tags(self): return [ 'sensor-%s' % self._obj.id, 'presense_sensor-%s' % self._obj.id, 'device-%s' % self._obj.device_id, 'site-%s' % self._obj.device.site_id ]