server/fgs/model.py

143 lines
5.5 KiB
Python

from . import db
import bcrypt
class Collar(db.Model):
"""
Table representing a collar device.
The collar has the following columns:
name - the collar's human-readable name.
active - whether or not the collar should be shown to users.
data_points - the list of coordinates transmitted by this collar.
boundary - the collar's valid grazing boundary (can be null)
"""
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
active = db.Column(db.Boolean)
data_points = db.relationship('DataPoint')
boundary = db.relationship("BoundingBox", uselist=False)
class DataPoint(db.Model):
"""
A data point transmitted by the collar.
The data point has the following attributes; though they
were specified in the design document, currently, only the latitude,
longitude, and datetime (along with the collar ID) are used.
collar_id - the identifier of the collar that generated this point.
longitude - the collar's longitude.
latitude - the collar's latitude.
battery_level - the collar's battery level, between 0 and 1.
datetime - the time when this data point was collected.
outside - whether or not the collar is outside the grazing boundary.
"""
id = db.Column(db.Integer, primary_key=True)
collar_id = db.Column(db.Integer, db.ForeignKey('collar.id'))
longitude = db.Column(db.Float(precision=10))
latitude = db.Column(db.Float(precision=10))
battery_level = db.Column(db.Integer)
datetime = db.Column(db.DateTime)
outside = db.Column(db.Boolean)
def to_dict(self):
return {'longitude': self.longitude,
'latitude': self.latitude,
'battery_level': self.battery_level,
'datetime': self.datetime,
'outside': self.outside
}
class StimulusActivation(db.Model):
"""
A report made by the collar when it attempts
to get the animal to move back into the grazing area.
The report has the following attributes:
collar_id - the collar that reported the attempt.
longitude - the collar's longitude at the time of the attempt.
latitude - the collar's latitude at the time of the attempt.
volume_level - the volume level of the sound the collar emitted.
voltage_level - the voltage of the electric shock the collar emitted.
datetime - the time at which the attempt was made.
"""
id = db.Column(db.Integer, primary_key=True)
collar_id = db.Column(db.Integer, db.ForeignKey('collar.id'))
longitude = db.Column(db.Float(precision=10))
latitude = db.Column(db.Float(precision=10))
volume_level = db.Column(db.Integer)
voltage_level = db.Column(db.Integer)
datetime = db.Column(db.DateTime)
class BoundingBox(db.Model):
"""
A polygon bounding box represent the valid grazing area.
To more closely match the collar's hardware limitation,
this table has exactly 10 vertex points. These points
are converted to and from lists of coordinates
by the unflatten and flatten functions, respectively.
Other than the coodinates, the polygon has the following
attributes:
collar_id - the identifier of the collar whose grazing area this is.
num_points - the number of points (from 0) that are actually used in this polygon.
"""
id = db.Column(db.Integer, primary_key=True)
collar_id = db.Column(db.Integer, db.ForeignKey('collar.id'))
num_points = db.Column(db.Integer)
needs_push = db.Column(db.Boolean)
coord0x = db.Column(db.Float(precision=10))
coord0y = db.Column(db.Float(precision=10))
coord1x = db.Column(db.Float(precision=10))
coord1y = db.Column(db.Float(precision=10))
coord2x = db.Column(db.Float(precision=10))
coord2y = db.Column(db.Float(precision=10))
coord3x = db.Column(db.Float(precision=10))
coord3y = db.Column(db.Float(precision=10))
coord4x = db.Column(db.Float(precision=10))
coord4y = db.Column(db.Float(precision=10))
coord5x = db.Column(db.Float(precision=10))
coord5y = db.Column(db.Float(precision=10))
coord6x = db.Column(db.Float(precision=10))
coord6y = db.Column(db.Float(precision=10))
coord7x = db.Column(db.Float(precision=10))
coord7y = db.Column(db.Float(precision=10))
coord8x = db.Column(db.Float(precision=10))
coord8y = db.Column(db.Float(precision=10))
coord9x = db.Column(db.Float(precision=10))
coord9y = db.Column(db.Float(precision=10))
class User(db.Model):
"""
Database model representing the user. The user's password is stored
as a Bcrypt hash, and accessed via the password property.
The user has the following attributes:
username - the username of the user
password_hash - the Bcrypt hash stored in the database. This can be set using the password property.
"""
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String)
password_hash = db.Column(db.String)
def get_password(self):
"""
Returns the user's encrypted password.
"""
return self.password_hash
def set_password(self, password):
"""
Encrypts and updates the user's password.
"""
self.password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt())
def check_password(self, password):
"""
Checks if the given (unencrypted) password
matches the user's password hash.
"""
return bcrypt.checkpw(password.encode(), self.password_hash)
password = property(get_password, set_password)