diff --git a/apps/airquality/__init__.py b/apps/airquality/__init__.py new file mode 100755 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/apps/airquality/models.py b/apps/airquality/models.py new file mode 100755 index 0000000000000000000000000000000000000000..34d58d72f3d849fbb9866f9a4f02e8cb0b650bae --- /dev/null +++ b/apps/airquality/models.py @@ -0,0 +1,176 @@ +# -*- coding: utf-8 -*- +''' +Copyright (c) 2016, Virginia Tech +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the + following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those of the authors and should not be +interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. + +This material was prepared as an account of work sponsored by an agency of the United States Government. Neither the +United States Government nor the United States Department of Energy, nor Virginia Tech, nor any of their employees, +nor any jurisdiction or organization that has cooperated in the development of these materials, makes any warranty, +express or implied, or assumes any legal liability or responsibility for the accuracy, completeness, or usefulness or +any information, apparatus, product, software, or process disclosed, or represents that its use would not infringe +privately owned rights. + +Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or +otherwise does not necessarily constitute or imply its endorsement, recommendation, favoring by the United States +Government or any agency thereof, or Virginia Tech - Advanced Research Institute. The views and opinions of authors +expressed herein do not necessarily state or reflect those of the United States Government or any agency thereof. + +VIRGINIA TECH – ADVANCED RESEARCH INSTITUTE +under Contract DE-EE0006352 + +#__author__ = "BEMOSS Team" +#__credits__ = "" +#__version__ = "2.0" +#__maintainer__ = "BEMOSS Team" +#__email__ = "aribemoss@gmail.com" +#__website__ = "www.bemoss.org" +#__created__ = "2014-09-12 12:04:50" +#__lastUpdated__ = "2016-03-14 11:23:33" +''' + + +from django.core.validators import MinValueValidator, MaxValueValidator +from django.db import models +from apps.dashboard.models import Building_Zone, DeviceMetadata + + +#Air Quality Sensor information - for awair sensors in BEMOSS +#TODO make necessary changes in web_ui code to add tables and displays for airquality devices +class AirQuality(models.Model): + airquality = models.ForeignKey(DeviceMetadata,max_length=50, primary_key=True) + co2 = models.FloatField(max_length=6, null=True, blank=True) + voc = models.FloatField(max_length=6, null=True, blank=True) + dust = models.FloatField(max_length=6, null=True, blank=True) + temperature = models.FloatField(max_length=5, null=True, blank=True) + humidity = models.FloatField(max_length=4, null=True, blank=True) + ip_address = models.IPAddressField(null=True, blank=True) + token = models.CharField(max_length=120, null=True, blank=True) + nickname = models.CharField(max_length=30, null=True, blank=True) + zone = models.ForeignKey(Building_Zone, null=True, blank=True) + network_status = models.CharField(max_length=7, null=True, blank=True) + other_parameters = models.CharField(max_length=200, null=True, blank=True) + last_scanned_time = models.DateTimeField(null=True, blank=True) + last_offline_time = models.DateTimeField(null=True, blank=True) + override = models.NullBooleanField() + + class Meta: + db_table = "airquality" + + #TODO update functions to airquality from thermostat + def __unicode__(self): + return self.thermostat_id + + def get_zone(self): + zone_req = Building_Zone.as_json(self.zone) + return zone_req + + #TODO update functions to airquality from thermostat + def data_as_json(self): + zone_req = Building_Zone.as_json(self.zone) + device_info = DeviceMetadata.objects.get(device_id=self.thermostat_id) + metadata = DeviceMetadata.data_as_json(device_info) + return dict( + id=self.thermostat_id, + temperature=self.temperature, + heat_setpoint=self.heat_setpoint, + cool_setpoint=self.cool_setpoint, + thermostat_mode=self.thermostat_mode.encode('utf-8') if self.thermostat_mode else '', + fan_mode=self.fan_mode.encode('utf-8') if self.fan_mode else '', + device_model_id=metadata['device_model_id'], + device_type=metadata['device_type'].encode('utf-8') if metadata['device_type'] else '', + identifiable=metadata['identifiable'], + mac_address=metadata['mac_address'].encode('utf-8') if metadata['mac_address'] else '', + vendor_name=metadata['vendor_name'].encode('utf-8') if metadata['vendor_name'] else '', + device_model=metadata['device_model'].encode('utf-8') if metadata['device_model'] else '', + battery=self.battery, + override=self.override, + hold=self.hold, + # bemoss=metadata['bemoss'], + zone=zone_req, + zone_id=zone_req['id'], + nickname=self.nickname.encode('utf-8').title() if self.nickname else '', + approval_status=metadata['approval_status'], + approval_status_choices=metadata['approval_status_choices']) + + #TODO update functions to airquality from thermostat + def device_status(self): + zone_req = Building_Zone.as_json(self.zone) + device_info = DeviceMetadata.objects.get(device_id=self.thermostat_id) + metadata = DeviceMetadata.data_as_json(device_info) + return dict( + id=self.thermostat_id, + nickname=self.nickname.encode('utf-8').title() if self.nickname else '', + device_model=metadata['device_model'], + date_added=metadata['date_added'], + zone_id=zone_req['id'], + #bemoss=metadata['bemoss'], + zone_nickname=zone_req['zone_nickname'], + battery=self.battery, + override=self.override, + hold=self.hold, + network_status=self.network_status.capitalize(), + last_scanned=self.last_scanned_time, + last_offline=self.last_offline_time, + approval_status=metadata['approval_status'], + approval_status_choices=metadata['approval_status_choices']) + + #TODO update functions to airquality from thermostat + def data_dashboard(self): + zone_req = Building_Zone.as_json(self.zone) + device_info = DeviceMetadata.objects.get(device_id=self.thermostat_id) + metadata = DeviceMetadata.data_as_json(device_info) + return dict( + device_id=self.thermostat_id, + device_type=metadata['device_type'].encode('utf-8') if metadata['device_type'] else '', + vendor_name=metadata['vendor_name'].encode('utf-8') if metadata['vendor_name'] else '', + device_model=metadata['device_model'].encode('utf-8') if metadata['device_model'] else '', + device_model_id=metadata['device_model_id'], + identifiable=metadata['identifiable'], + mac_address=metadata['mac_address'].encode('utf-8') if metadata['mac_address'] else '', + nickname=self.nickname.encode('utf-8').title() if self.nickname else '', + date_added=metadata['date_added'], + zone_id=zone_req['id'], + #bemoss=metadata['bemoss'], + battery=self.battery, + override=self.override, + hold=self.hold, + zone_nickname=zone_req['zone_nickname'], + network_status=self.network_status.capitalize(), + last_scanned=self.last_scanned_time, + approval_status=metadata['approval_status'], + approval_status_choices=metadata['approval_status_choices']) + + #TODO update functions to airquality from thermostat + def data_side_nav(self): + zone_req = Building_Zone.as_json(self.zone) + device_info = DeviceMetadata.objects.get(device_id=self.thermostat_id) + metadata = DeviceMetadata.data_as_json(device_info) + return dict( + device_id=self.thermostat_id, + device_model_id=metadata['device_model_id'], + mac_address=metadata['mac_address'].encode('utf-8') if metadata['mac_address'] else '', + nickname=self.nickname.encode('utf-8').title() if self.nickname else '', + zone_id=zone_req['id'], + #bemoss=metadata['bemoss'], + zone_nickname=zone_req['zone_nickname'], + network_status=self.network_status.capitalize(), + approval_status=metadata['approval_status'], + approval_status_choices=metadata['approval_status_choices']) diff --git a/apps/dashboard/models.py b/apps/dashboard/models.py index 2a349d53b85fd4758318de0def59f8e2523f41c2..c60687bb21e31bad7d97f192805d09148f1d9f6c 100755 --- a/apps/dashboard/models.py +++ b/apps/dashboard/models.py @@ -121,6 +121,7 @@ class DeviceMetadata(models.Model): ('3WSP', 'wemo smart plug'), ('3MOD', 'modlet smart plug'), ('3WP', 'wattstopper plugload'), + ('4AIR', 'awair sensor') ) APPROVAL_STATUS_CHOICES = ( diff --git a/apps/dashboard/views.py b/apps/dashboard/views.py index 0ae6634e2f41ca47bc7fcd7bf942a52dcb928daa..25cd7d5610c78eaf99ba0fe475e1f3d38e806f9f 100755 --- a/apps/dashboard/views.py +++ b/apps/dashboard/views.py @@ -228,7 +228,8 @@ def identify_status(request): device_type = 'lighting' elif device_type_id == '3WSP' or device_type_id == '3WP' or device_type_id == '3WIS': device_type = 'plugload' - + elif device_type_id == '4AIR': + device_type = 'airquality' json_result = {'status': 'success'} if request.is_ajax(): diff --git a/run/defaultDB.py b/run/defaultDB.py index d1c4455ef37abdc3307689ca2aa7d700d71fa823..6e4f1a4398f436dc099e29134f36d3b2b6be1893 100755 --- a/run/defaultDB.py +++ b/run/defaultDB.py @@ -73,7 +73,8 @@ DEVICE_TYPE_CHOICES = ( ('2WSL', 'wattstopper lighting'), ('3WSP', 'wemo smart plug'), ('3WIS', 'wemo insight switch'), - ('3WP', 'wattstopper plugload')) + ('3WP', 'wattstopper plugload'), + ('4AIR', 'awair sensor')) thermostat = DeviceModel(device_model_id='1TH', device_model_name='Thermostat') thermostat.save() @@ -102,6 +103,9 @@ wemo_smart_plug.save() wattstopper_plugload = DeviceModel(device_model_id='3WP', device_model_name='Wattstopper Plugload') wattstopper_plugload.save() +awair_sensor = DeviceModel(device_model_id='4AIR', device_model_name='Awair Sensor') +awair_sensor.save() + print "device_model table updated with device model information." zone_999 = Building_Zone(zone_id=999, zone_nickname="BEMOSS Core") diff --git a/settings.py b/settings.py index bc8096d6808cef566ecdf81bc5dace0423c364b8..f47d095d04d3aaa0ba204b93ec1a07ea11db4e44 100755 --- a/settings.py +++ b/settings.py @@ -209,6 +209,7 @@ INSTALLED_APPS = ( 'apps.smartplug', 'apps.admin', 'apps.lighting', + 'apps.airquality', 'clock', 'volttron', 'apps.error', diff --git a/settings_tornado.py b/settings_tornado.py index b80d179f68d9131ebb932ba14c70603fe3c012e3..5a66e8d1a83c2b6f30e55ab77c7b7bc6c9ef3ed7 100755 --- a/settings_tornado.py +++ b/settings_tornado.py @@ -215,6 +215,7 @@ INSTALLED_APPS = ( 'apps.smartplug', 'apps.admin', 'apps.lighting', + 'apps.airquality', 'clock', 'volttron', 'apps.error',