143 lines
5.5 KiB
Python
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)
|