updated readme and usability
This commit is contained in:
49
README.md
49
README.md
@@ -1,4 +1,24 @@
|
|||||||
# Quick Documentation
|
# Climate Dashboard and Server
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
Linux packages (apt)
|
||||||
|
> python3 libgpiod2 npm mariadb-server
|
||||||
|
|
||||||
|
Python3 packages (pip3)
|
||||||
|
> adafruit-circuitpython-dht mh-z19
|
||||||
|
|
||||||
|
The setup script installs these for you.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
1. Pull the repository.
|
||||||
|
1. Fill out your specific config options in `./server/.env`
|
||||||
|
1. Ensure `./app-dist/scripts/climate-pinger.py` has the correct pin for your adafruit-dht22 device and/or edit the script for your specific setup.
|
||||||
|
1. Run `./setup.sh` as administrator
|
||||||
|
1. Start the server:
|
||||||
|
> node ./app-dist/main.js
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
In the following, a datetime parameter is always a unix timestamp in milliseconds and an ISO string in UTC.
|
In the following, a datetime parameter is always a unix timestamp in milliseconds and an ISO string in UTC.
|
||||||
|
|
||||||
@@ -19,7 +39,7 @@ In the following, a datetime parameter is always a unix timestamp in millisecond
|
|||||||
|
|
||||||
All API endpoints that return a snapshot can specify the `timeFormat` parameter, with the value `unix` or `iso` to override default behaviour.
|
All API endpoints that return a snapshot can specify the `timeFormat` parameter, with the value `unix` or `iso` to override default behaviour.
|
||||||
|
|
||||||
A request to the API whose parameters are all given in a particular time format (either an ISO string or a unix timetamp) are all consistent will always return with all timestamps in the corresponding fomat unless the request specifies the "timeFormat" parameter to override.
|
A request to the API whose parameters are all given in a particular time format (either an ISO string or a unix timetamp) are all consistent will always return with all timestamps in the corresponding format unless the request specifies the "timeFormat" parameter to override.
|
||||||
If the request has mixed use of the time formats, the default will be an ISO string in UTC.
|
If the request has mixed use of the time formats, the default will be an ISO string in UTC.
|
||||||
|
|
||||||
|
|
||||||
@@ -56,8 +76,10 @@ If the request has mixed use of the time formats, the default will be an ISO str
|
|||||||
| last-minutes | number | alone, in order to return snapshots from the last number of minutes specified|
|
| last-minutes | number | alone, in order to return snapshots from the last number of minutes specified|
|
||||||
| from | datetime | alone or with `to` in order to return snapshots within a range|
|
| from | datetime | alone or with `to` in order to return snapshots within a range|
|
||||||
| to | datetime | always with `from` in order to return snapshots within a range|
|
| to | datetime | always with `from` in order to return snapshots within a range|
|
||||||
|
| time-format | string: `unix` or `iso` | optional usage, default is 'iso', if set will override the inferred format from `from` and `to`
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
`GET http://<host>/<project-root>/api/snapshots?from=2021-03-06T07:21:50.862Z&to=1615015610862`
|
`GET http://<host>/<project-root>/api/snapshots?from=2021-03-06T07:21:50.862Z&to=1615015610862`
|
||||||
|
|
||||||
- `GET /api/snapshots/latest`
|
- `GET /api/snapshots/latest`
|
||||||
@@ -79,4 +101,25 @@ If the request has mixed use of the time formats, the default will be an ISO str
|
|||||||
// ...
|
// ...
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
- `GET /api/timeseries/<data-type>`
|
||||||
|
- This endpoint returns an octet stream of 32 bit integers. `data-type` must be `co2`, `temp`, or `humidity`. The integer stream is an alternating array of data points and unix timestamps.
|
||||||
|
|
||||||
|
- Available parameters
|
||||||
|
|
||||||
|
| Name | Type | Usage |
|
||||||
|
|--------|------|---------|
|
||||||
|
| last-minutes | number | alone, in order to return snapshots from the last number of minutes specified|
|
||||||
|
| from | datetime | alone or with `to` in order to return snapshots within a range|
|
||||||
|
| to | datetime | always with `from` in order to return snapshots within a range|
|
||||||
|
|
||||||
|
### Sensor script:
|
||||||
|
|
||||||
|
The script in `./app-dist/scripts/climate-pinger.py` is provided as an example. You can replace this script with your own, provided it outputs in the following format:
|
||||||
|
```
|
||||||
|
Time: <time as iso string>
|
||||||
|
Temp: <temp>
|
||||||
|
Humidity: <humidity>
|
||||||
|
CO2: <co2>
|
||||||
|
```
|
||||||
|
with label and data separated by tabs.
|
||||||
3
build.sh
3
build.sh
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
(cd ./server && tsc) & (cd ./dashboard && npm run build)
|
|
||||||
@@ -10,11 +10,19 @@ export async function establishDatabaseConnection() {
|
|||||||
host: process.env.MYSQL_ADDRESS,
|
host: process.env.MYSQL_ADDRESS,
|
||||||
user: process.env.MYSQL_USERNAME,
|
user: process.env.MYSQL_USERNAME,
|
||||||
password: process.env.MYSQL_PW,
|
password: process.env.MYSQL_PW,
|
||||||
database: "climate",
|
|
||||||
connectTimeout: 30000,
|
connectTimeout: 30000,
|
||||||
});
|
});
|
||||||
|
await dbConnection.query("CREATE DATABASE IF NOT EXISTS `climate`;");
|
||||||
|
dbConnection.changeUser({database: "climate"});
|
||||||
|
await dbConnection.query(`CREATE TABLE IF NOT EXISTS \`snapshots\` (
|
||||||
|
\`id\` INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
|
\`temp\` INT NOT NULL,
|
||||||
|
\`humidity\` INT NOT NULL,
|
||||||
|
\`co2\` INT NOT NULL,
|
||||||
|
\`time\` DATETIME NOT NULL);`
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new Error(`Couldn't establish a connection with the database: ${e.message}`);
|
throw new Error(`Error setting up the database: ${e.message}`);
|
||||||
}
|
}
|
||||||
return dbConnection;
|
return dbConnection;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,12 @@ import newByteSeriesRouter from "./byteSeriesRouter";
|
|||||||
|
|
||||||
export function newMainRouter(collections: CollectionRegistry) {
|
export function newMainRouter(collections: CollectionRegistry) {
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
const snapshotRouter = newSnapshotRouter(collections);
|
|
||||||
const byteSeriesRouter = newByteSeriesRouter(collections);
|
|
||||||
|
|
||||||
router.get("/dashboard", (req, res) => {
|
router.get("/dashboard", (req, res) => {
|
||||||
res.render("index.ejs", { rootUrl: req.app.locals.rootUrl });
|
res.render("index.ejs", { rootUrl: req.app.locals.rootUrl });
|
||||||
});
|
});
|
||||||
router.use("/api/snapshots", snapshotRouter);
|
router.use("/api/snapshots", newSnapshotRouter(collections));
|
||||||
router.use("/api/timeseries", byteSeriesRouter);
|
router.use("/api/timeseries", newByteSeriesRouter(collections));
|
||||||
router.use(topLevelErrorHandler);
|
router.use(topLevelErrorHandler);
|
||||||
|
|
||||||
return router;
|
return router;
|
||||||
|
|||||||
Reference in New Issue
Block a user