from datetime import datetime from sqlalchemy import ( TIMESTAMP, BigInteger, Boolean, Column, Float, ForeignKey, Integer, SmallInteger, String, UniqueConstraint, ) from sqlalchemy.dialects.postgresql import ARRAY as PSQL_ARRAY from sqlalchemy.dialects.postgresql import INTEGER as PSQL_INTEGER from sqlalchemy.dialects.postgresql import JSONB as PSQL_JSONB from sqlalchemy.dialects.postgresql import TEXT as PSQL_TEXT from sqlalchemy.ext.declarative import declarative_base, declared_attr from sqlalchemy.orm import relationship Base = declarative_base() class Participant(Base): __tablename__ = "participants" id = Column(Integer, primary_key=True) username = Column(String(64), index=True, unique=True) password_hash = Column(String(128)) token = Column(String(32), index=True, unique=True) token_expiration_utc = Column(TIMESTAMP(timezone=False)) collection_start_utc = Column(TIMESTAMP(timezone=False)) last_upload_utc = Column(TIMESTAMP(timezone=False)) day_count_uploaded = Column(SmallInteger) last_known_device_id = Column(String(length=36), nullable=False, default="") active = Column(Boolean, index=True, nullable=False, default=False) marked_active_utc = Column(TIMESTAMP(timezone=False)) day_count_active = Column(SmallInteger) tester = Column(Boolean, index=True, nullable=False, default=False) def __repr__(self): return "Participant()" def __str__(self): return "".format(self.username) class AWAREsensor(object): id = Column(BigInteger, primary_key=True, nullable=False) _id = Column(BigInteger, nullable=False) timestamp = Column(BigInteger, nullable=False) device_id = Column(String(length=36), nullable=False) @declared_attr def __tablename__(self): return self.__name__.lower() @declared_attr def participant_id(self): return Column( Integer, ForeignKey("participants.id"), nullable=False, index=True ) @declared_attr def participant(self): return relationship("Participant", lazy="select", backref=self.__tablename__) @declared_attr def __table_args__(self): return ( UniqueConstraint("device_id", "_id", name=self.__tablename__ + "_twice"), ) # I think it makes more sense to create a Constraint # on device_id and _id rather than relate it to participant_id. # _id is a primary key, auto incremented by AWARE. # However, I would expect it to reset back to 1 # if the application was reinstalled, # similarly to how device_id resets. class Accelerometer(Base, AWAREsensor): double_values_0 = Column(Float, nullable=False) double_values_1 = Column(Float, nullable=False) double_values_2 = Column(Float, nullable=False) accuracy = Column(SmallInteger, nullable=True) label = Column(String, nullable=True) class GoogleAR(Base, AWAREsensor): __tablename__ = "google_ar" activity_name = Column(String(32), nullable=True) activity_type = Column(SmallInteger, nullable=True) confidence = Column(SmallInteger, nullable=True) activities = Column(PSQL_JSONB(none_as_null=False), nullable=True) class Application(Base, AWAREsensor): __tablename__ = "applications" # package_name = Column(String, nullable=False) # application_name = Column(String) package_hash = Column(String(64), nullable=False) play_store_genre = Column(String, nullable=True) is_system_app = Column(Boolean) class Barometer(Base, AWAREsensor): double_values_0 = Column(Float, nullable=False) accuracy = Column(SmallInteger, nullable=True) label = Column(String, nullable=True) class BarometerSensor(Base, AWAREsensor): __tablename__ = "barometer_sensor" # Since this table is not really important, # I will leave all columns as nullable. (nullable=True by default.) double_sensor_maximum_range = Column(Float) double_sensor_minimum_delay = Column(Float) sensor_name = Column(String) double_sensor_power_ma = Column(Float) double_sensor_resolution = Column(Float) sensor_type = Column(String) sensor_vendor = Column(String) sensor_version = Column(String) class Battery(Base, AWAREsensor): battery_status = Column(SmallInteger, nullable=False) battery_level = Column(SmallInteger, nullable=False) battery_scale = Column(SmallInteger, nullable=False) battery_voltage = Column(Integer, nullable=True) battery_temperature = Column(Integer, nullable=True) battery_adaptor = Column(SmallInteger, nullable=True) battery_health = Column(SmallInteger, nullable=True) battery_technology = Column(String, nullable=True) class Bluetooth(Base, AWAREsensor): bt_address = Column(String(length=40), nullable=False) bt_name = Column(String, nullable=True) bt_rssi = Column(Integer, nullable=True) label = Column(String, nullable=True) class Call(Base, AWAREsensor): call_type = Column(SmallInteger, nullable=False) call_duration = Column(Integer, nullable=False) trace = Column(String(length=40), nullable=True) class ESM(Base, AWAREsensor): esm_status = Column(SmallInteger, nullable=False) esm_user_answer = Column(String, nullable=True) esm_notification_timeout = Column(SmallInteger) esm_json = Column(PSQL_JSONB(none_as_null=False), nullable=False) double_esm_user_answer_timestamp = Column(BigInteger, nullable=False) esm_trigger = Column(String, nullable=True) esm_session = Column(Integer, nullable=False) esm_notification_id = Column(Integer, nullable=False) esm_expiration_threshold = Column(SmallInteger) class Imperfection(Base): __tablename__ = "imperfection" id = Column(BigInteger, primary_key=True, nullable=False) timestamp = Column(BigInteger, nullable=False) error = Column(String) data_type = Column(String) data = Column(String) class LightSensor(Base, AWAREsensor): __tablename__ = "light_sensor" double_light_lux = Column(Float, nullable=False) accuracy = Column(Integer, nullable=True) label = Column(String, nullable=True) class Location(Base, AWAREsensor): __tablename__ = "locations" double_latitude = Column(Float, nullable=False) double_longitude = Column(Float, nullable=False) double_bearing = Column(Float) double_speed = Column(Float) double_altitude = Column(Float) provider = Column(String) accuracy = Column(Integer) label = Column(String, nullable=True) category = Column(PSQL_ARRAY(PSQL_TEXT), nullable=True) category_short = Column(PSQL_ARRAY(PSQL_TEXT), nullable=True) distance = Column(PSQL_ARRAY(PSQL_INTEGER), nullable=True) api_response_code = Column(SmallInteger, nullable=False) api_response = Column(String, nullable=True) class Mic(Base, AWAREsensor): half_s_speech = Column(Boolean, nullable=False) rnnoutp = Column(Float, nullable=False) flatness = Column(Float, nullable=False) absmax = Column(Float, nullable=False) max = Column(Float, nullable=False) min = Column(Float, nullable=False) # mfcc = Column(PSQL_ARRAY(PSQL_REAL, dimensions=13), nullable=False) mfcc_0 = Column(Float, nullable=False) mfcc_1 = Column(Float, nullable=False) mfcc_2 = Column(Float, nullable=False) mfcc_3 = Column(Float, nullable=False) mfcc_4 = Column(Float, nullable=False) mfcc_5 = Column(Float, nullable=False) mfcc_6 = Column(Float, nullable=False) mfcc_7 = Column(Float, nullable=False) mfcc_8 = Column(Float, nullable=False) mfcc_9 = Column(Float, nullable=False) mfcc_10 = Column(Float, nullable=False) mfcc_11 = Column(Float, nullable=False) mfcc_12 = Column(Float, nullable=False) class Speech(Base, AWAREsensor): speech_proportion = Column(Float, nullable=False) class NetworkData(Base, AWAREsensor): __tablename__ = "network_data" network_type = Column(SmallInteger, nullable=False) network_subtype = Column(String(10), nullable=False) network_state = Column(SmallInteger, nullable=True) class NetworkTraffic(Base, AWAREsensor): __tablename__ = "network_traffic_data" network_type = Column(SmallInteger, nullable=False) double_received_bytes = Column(Float, nullable=True) double_sent_bytes = Column(Float, nullable=True) double_received_packets = Column(Float, nullable=True) double_sent_packets = Column(Float, nullable=True) class Notification(Base, AWAREsensor): __tablename__ = "notifications" # package_name = Column(String, nullable=False) # application_name = Column(String, nullable=False) package_hash = Column(String(64), nullable=False) play_store_genre = Column(String, nullable=True) sound = Column(String, nullable=False) vibrate = Column(String, nullable=False) sound_app = Column(String, nullable=False) vibrate_app = Column(String, nullable=False) led_app = Column(String, nullable=False) category = Column(String, nullable=False) is_ongoing = Column(SmallInteger, nullable=False) is_clearable = Column(SmallInteger, nullable=False) is_group = Column(SmallInteger, nullable=True) class Processor(Base, AWAREsensor): double_last_user = Column(Float, nullable=False) double_last_system = Column(Float, nullable=False) double_last_idle = Column(Float, nullable=False) double_user_load = Column(Float, nullable=False) double_system_load = Column(Float, nullable=False) double_idle_load = Column(Float, nullable=False) class Proximity(Base, AWAREsensor): double_proximity = Column(Float, nullable=False) accuracy = Column(SmallInteger, nullable=True) label = Column(String, nullable=True) class Screen(Base, AWAREsensor): screen_status = Column(SmallInteger) class SMS(Base, AWAREsensor): message_type = Column(SmallInteger, nullable=False) trace = Column(String(length=40), nullable=False) class Temperature(Base, AWAREsensor): temperature_celsius = Column(Float, nullable=False) accuracy = Column(SmallInteger, nullable=True) label = Column(String, nullable=True) class TemperatureSensor(Base, AWAREsensor): # I left all of these nullable, # as we haven't seen any data from this sensor anyway. __tablename__ = "temperature_sensor" double_sensor_maximum_range = Column(Float) double_sensor_minimum_delay = Column(Float) sensor_name = Column(String) double_sensor_power_ma = Column(Float) double_sensor_resolution = Column(Float) sensor_type = Column(String) sensor_vendor = Column(String) sensor_version = Column(String) class Timezone(Base, AWAREsensor): timezone = Column(String, nullable=False) class WiFi(Base, AWAREsensor): bssid = Column(String(length=40), nullable=False) ssid = Column(String, nullable=True) rssi = Column(Integer, nullable=False) security = Column(String, nullable=True) frequency = Column(Integer, nullable=True) label = Column(String, nullable=True) all_AWARE_tables = [ ESM, Location, Screen, LightSensor, Call, SMS, Application, Notification, Battery, WiFi, Proximity, Timezone, Processor, NetworkData, NetworkTraffic, Barometer, BarometerSensor, Temperature, TemperatureSensor, Bluetooth, Accelerometer, GoogleAR, Speech, ] all_AWARE_table_names = [table.__tablename__ for table in all_AWARE_tables] def increment_one(ii): return ii + 1 class AppCategories(Base): __tablename__ = "app_categories" id = Column(Integer, primary_key=True) application_name = Column(String, nullable=True) package_name = Column(String, nullable=False) package_hash = Column(String(64), index=True, nullable=False, unique=True) play_store_genre = Column(String, nullable=True) play_store_response = Column(SmallInteger, nullable=False) number_of_attempts = Column( SmallInteger, nullable=False, default=0, onupdate=increment_one ) last_attempt = Column( TIMESTAMP(timezone=False), nullable=False, default=datetime.utcnow, onupdate=datetime.utcnow, )