12 KiB
DATABASE
This is the server side component for the robot hands system.
This is going to be split into a few parts:
- The database, which stores the data
- The receiver/responder, which receives data from the base stations and puts it into the database and responds with settings if appropriate
- The frond-end, which reads from the database and serves the front-end (in another repo)
The idea is to make this in node quickly and then transfer it into go later.
Database stuff
In the database there are two unifying concepts: The node and the temperature site. Data is received from nodes and can be retrieved by node id. Some nodes are assigned temperature sites, with each temperature site having at most one node, data can be retrieed by temperature site.
Tables
Users table
This table is probably going to be handled by django, if not we need to figure out what else we have to add here.
namethe usernamecreation_timewhen the entry was added, this is automatically set.
CREATE TABLE IF NOT EXISTS Users (
name TEXT UNIQUE NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Nodes table
This table lists all of the nodes and names for the nodes.
This does not give any type to the nodes, that is all done using groups.
author is a foreign key to the users table.
hardware_idthe node id, currently we use the mac addressfriendly_namea human readable namecreation_timewhen the entry was added, this is automatically set.authorthe user that added the entry, must match an entry in the Users table
CREATE TABLE IF NOT EXISTS Nodes (
hardware_id VARCHAR(255) UNIQUE NOT NULL,
friendly_name TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
author TEXT NOT NULL,
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name)
);
Groups table
This table defines different groups that exist
namethe group namecreation_timewhen the entry was added, this is automatically set.authorthe user that added the entry, must match an entry in the Users table
CREATE TABLE IF NOT EXISTS Groups (
name TEXT UNIQUE NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name)
);
Node2Group table
This table associates each node with its groups
nodeis the hardware id of the node, it must match an entry in theNodestable.groupis the group name, it must match an entry is theGroupstable.authorthe user that added the entry, must match an entry in the Users tablecreation_timewhen the entry was added, this is automatically set.
CREATE TABLE IF NOT EXISTS Node2Group (
node VARCHAR(255) NOT NULL,
node_group TEXT NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_pairing UNIQUE(node, node_group),
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name),
CONSTRAINT FOREIGN KEY (node) REFERENCES Nodes(hardware_id),
CONSTRAINT FOREIGN KEY (node_group) REFERENCES Groups(name)
);
GroupType table
This defines the different group types
namethe group type nameauthorthe user that added the entry, must match an entry in the Users tablecreation_timewhen the entry was added, this is automatically set.
CREATE TABLE IF NOT EXISTS GroupType (
name VARCHAR(255) UNIQUE NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name)
);
GroupParent table
This gives groups a hierarachy.
Make sure that we enforce that parent != child
childthe child group, must match an entry in theGroupstableparentthe parent group, must match an entry in the `Groups' tableauthorthe user that added the entry, must match an entry in the Users tablecreation_timewhen the entry was added, this is automatically set.
CREATE TABLE IF NOT EXISTS GroupParent (
child TEXT NOT NULL,
parent TEXT NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_relation UNIQUE(child, parent),
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name),
CONSTRAINT FOREIGN KEY (child) REFERENCES Nodes(hardware_id),
CONSTRAINT FOREIGN KEY (parent) REFERENCES Nodes(hardware_id)
);
Group2Type table
This associates each group with a type
groupis the group name, it must match an entry is theGroupstable.typethe group type, it must match an entry in theGroupTypetableauthorthe user that added the entry, must match an entry in the Users tablecreation_timewhen the entry was added, this is automatically set.
CREATE TABLE IF NOT EXISTS Group2Type (
group_name TEXT NOT NULL,
type TEXT NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_grouptype UNIQUE(group_name, type),
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name),
CONSTRAINT FOREIGN KEY (group_name) REFERENCES Groups(name),
CONSTRAINT FOREIGN KEY (type) REFERENCES GroupType(name)
);
Measurement table
This stores all of the measurement data
source_nodethe hardware id of the node that took the measurement, must match an entry in theNodestablereporting_nodethe hardware id of the node that sent the data to the server, generally a basestation, must match an entry in theNodestableassociated_groupthe group associated with the node, generally a temperature site, must match an entry in theGroupstablecollection_timethe time that the node took the measurement as reported by the nodeserver_received_timethe time that the server received the measurement datatemperature_18_inchthe temperature at the 18 inch probe in degrees Ctemperature_36_inchthe temperature at the 36 inch probe in degrees Cdevice_temperaturethe internal temperature of the controller on the node, in degrees Cambient_temperaturethe ambient temperature as measured by the on-board sensor (SHT40 or BME280 for now). This isn't really ambient temperature if the probe is in sunlight due to the case heating up.relative_humiditythe relative humidity as measured by the on-board sensor. This is humidity inside the case, not necessarily the external humiditybarometric_pressurethe measured barometric pressure in hpa, measured using a BME280 at the base stationaccelerometer_xthe measured acceleration along the x axis- on the probe the x axis is along the pipe, the point is in the +x direction and the brain case is -x
- on the base station the x axis is left and right with +x pointing to the right and -x pointing to the left
accelerometer_ythe measured acceleration along the y axis- on the probe the y axis is left and right from the board, +y is to the right, -y is to the left
- on the base station y is front to back (pitch), with +y at the back and -y at the front
accelerometer_zthe measured acceleration along the z axis- on the probe the +z axis points out of the front of the board, -z out the back
- on the base station +z is toward the top, -z is down
battery_charge_percentis the measured remaining battery change is %, where 100% is full charge and 0% is our defined lowest acceptable chargebattery_voltageis the measured battery voltageremaining_battery_capacityis the estimated remaining battery capacity is mAh
CREATE TABLE IF NOT EXISTS Measurement (
source_node VARCHAR(255) NOT NULL,
reporting_node VARCHAR(255) NOT NULL,
associated_group TEXT NOT NULL,
collection_time TIMESTAMP NOT NULL,
server_received_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
temperature_18_inch FLOAT,
temperature_36_inch FLOAT,
device_temperature FLOAT NOT NULL,
ambient_temperature FLOAT NOT NULL,
relative_humidity FLOAT,
barometric_pressure FLOAT,
accelerometer_x FLOAT NOT NULL,
accelerometer_y FLOAT NOT NULL,
accelerometer_z FLOAT NOT NULL,
battery_charge_percent FLOAT NOT NULL,
battery_voltage FLOAT NOT NULL,
remaining_battery_capacity FLOAT NOT NULL,
CONSTRAINT device_measurement UNIQUE(source_node, collection_time),
CONSTRAINT FOREIGN KEY (source_node) REFERENCES Nodes(hardware_id),
CONSTRAINT FOREIGN KEY (reporting_node) REFERENCES Nodes(hardware_id),
CONSTRAINT FOREIGN KEY (associated_group) REFERENCES Groups(name)
);
NodeRssiRecord table
This stores RSSI data
nodeis the hardware id of the node measuring the rssi, must match an entry in theNodestableneighbouris the hardware id of the node that sent the message used to get the rssi, must match an entry in theNodestablerssiis the rssi valuecollection_timethe time that the node took the measurement as reported by the nodeserver_received_timethe time that the server received the measurement data
CREATE TABLE IF NOT EXISTS NodeRssiRecord (
node VARCHAR(255) NOT NULL,
neighbor VARCHAR(255) NOT NULL,
rssi INT NOT NULL,
collection_time TIMESTAMP NOT NULL,
server_received_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT unique_thing UNIQUE(node, neighbor, collection_time),
CONSTRAINT FOREIGN KEY (node) REFERENCES Nodes(hardware_id),
CONSTRAINT FOREIGN KEY (neighbor) REFERENCES Nodes(hardware_id)
);
NodeFileManifest table
This holds the file manifests for each node
nodeis the hardware id of the reporting node, must match an entry in theNodestablecollection_timethe time that the node took the measurement as reported by the nodeserver_received_timethe time that the server received the measurement dataprogram_idthe id of the fileprogram_versionthe file version
CREATE TABLE IF NOT EXISTS NodeFileManifest (
node VARCHAR(255) NOT NULL,
collection_time TIMESTAMP NOT NULL,
server_received_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
program_id INT NOT NULL,
program_version INT NOT NULL,
CONSTRAINT unique_version UNIQUE(node, collection_time, program_id),
CONSTRAINT FOREIGN KEY (node) REFERENCES Nodes(hardware_id)
);
NodeReportedStatus table
This holds the reported status from nodes.
nodeis the hardware id of the reporting node, must match an entry in theNodestablecollection_timethe time that the node sent the data, as reported by the nodeserver_received_timethe time that the server received the datameasurement_interval_minutesthe time between measurements in minuteswake_window_length_minutesthe time that the node stays awake (basestation only)offset_from_midnight_minutesthe time offset from midnight for that measurement times are aligned tosleep_duration_minutesthe amonut of time that the node is set to sleep fornumber_saved_measurementsthe number of measurements saved in the nodes local memorywhen_time_was_last_updatedthe time when the node last received a time update
CREATE TABLE IF NOT EXISTS NodeReportedStatus (
node VARCHAR(255) NOT NULL,
collection_time TIMESTAMP NOT NULL,
server_received_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
measurement_interval_minutes INT NOT NULL,
wake_window_length_minutes INT NOT NULL,
offset_from_midnight_minutes INT NOT NULL,
sleep_duration_minutes INT NOT NULL,
number_saved_measurements INT NOT NULL,
when_time_was_last_updated TIMESTAMP NOT NULL,
CONSTRAINT unique_status UNIQUE(node, collection_time),
CONSTRAINT FOREIGN KEY (node) REFERENCES Nodes(hardware_id)
);
NodeConfiguration table
This holds the configuration data for the nodes. This sets the configuration, it doesn't report it.
nodeis the hardware id of the node the settings are for, must match an entry in theNodestableauthorthe user that added the entry, must match an entry in theUserstablecreation_timethe time when the entry was addedmeasurement_interval_minutesthe time the node should wait between measurementsoffset_from_midnight_minutesthe offset from midnight that the measurements are aligned towake_window_length_minuteshow long the node stays awake, only relevant for basestations
CREATE TABLE IF NOT EXISTS NodeConfiguration (
node VARCHAR(255) NOT NULL,
author TEXT NOT NULL,
creation_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
measurement_interval_minutes INT NOT NULL,
offset_from_midnight_minutes INT NOT NULL,
wake_window_length_minutes INT NOT NULL,
CONSTRAINT FOREIGN KEY (author) REFERENCES Users(name),
CONSTRAINT FOREIGN KEY (node) REFERENCES Nodes(hardware_id)
);