Merge branch 'new-docs'

This commit is contained in:
Starbeamrainbowlabs 2019-03-17 13:29:43 +00:00
commit 21c3b0c0e5
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
11 changed files with 383 additions and 264 deletions

2
.gitignore vendored
View file

@ -1,5 +1,7 @@
*.backup
app/
data/
__nightdocs/
# Created by https://www.gitignore.io/api/git
# Edit at https://www.gitignore.io/?templates=git

213
README.md
View file

@ -11,219 +11,6 @@ The client-side browser application is powered by [Leaflet](https://leafletjs.co
Note that this project is _not_ responsible for entering data into the database. This project's purpose is simply to display the data.
## System Requirements
In order to run this program, you'll need the following:
- Git
- Bash (if on Windows, try [Git Bash](https://gitforwindows.org/)) - the build script is written in Bash
- [composer](https://getcomposer.org/) - For the server-side packages
- [Node.JS](https://nodejs.org/)
- [npm](https://npmjs.org/) - comes with Node.JS - used for building the client-side code
- A [MariaDB](https://mariadb.com/) server with a database already setup with the schema data in it. Please get in contact with [ConnectedHumber](https://connectedhumber.org/) for information about the database schema and structure.
## Getting Started
The client-side code requires building. Currently, no pre-built versions are available (though these can be provided upon request), so this must be done from source. A build script is available, however, which automates the process - as explained below.
### System Requirements
- PHP-enabled web server
- _Nginx_ + _PHP-FPM_ is recommended
- Apache works too
- MariaDB database with the appropriate table structure pre-loaded
- PHP 7+
- Node.JS (preferably 10+) + npm 6+ (for installing & building the client-side app code)
- [Composer](https://getcomposer.org/) (for installing server-side dependencies)
- PHP modules:
- `pdo-mysql` (for the database connection)
### Installation
1. Start by cloning this repository:
```bash
git clone https://github.com/ConnectedHumber/Air-Quality-Web.git
```
2. `cd` into the root of the cloned repository. Then install the dependencies (these are installed locally):
```bash
./build setup setup-dev
```
3. Build the client-side application:
```bash
# For development, run this:
./build client
# For production, run this:
NODE_ENV=production ./build client
# If you're actively working on the codebase and need to auto-recompile on every change, run this:
./build client-watch
```
4. Change the ownership to allow your web server user to access the created directory. Usually, the web server will be running under the `www-data` user:
```bash
sudo chown -R www-data:www-data path/to/Air-Quality-Web
```
5. Edit `data/settings.toml` to enter your database credentials.
You can edit other settings here too. See `settings.default.toml` for the settings you can change, but do **not** edit `settings.default.toml`! Edit `data/settings.toml` instead. You'll probably want to give the entire default settings file a careful read.
6. Configure your web server to serve the root of the repository you've cloned if you haven't already. Skip this step if you cloned the repository into a directory that your web server already serves.
7. Disallow public access to the private `data` directory.
In Nginx:
```nginx
# Put this inside the "server { }" website definition block:
# The "server { }" block can usually be found somewhere in /etc/nginx on Linux machines, and may have a "server_name" directive specifying the domain name it's serving if multiple websites are configured.
location ^~ /path/to/data/directory {
deny all;
}
```
In Apache:
```htaccess
# Create a file called ".htaccess" with this content inside the data/ directory
Require all denied
```
8. Test the application with an API call. If this returns valid JSON, then you've set it up correctly
```
http://example.com/path/to/Air-Quality-Web/api.php?action=list-devices
```
9. (Optional) Setup HTTPS:
```bash
sudo apt install certbot
# On Nginx:
sudo certbot --nginx --domain example.com
# On Apache:
sudo certbot --apache --domain example.com
```
## API
The server-side API is accessed through `api.php`, and supports a number of GET parameters. The most important of these is the `action` parameter, Which determines what the API will do. The following values are supported:
### version
> Returns the version of the application.
_No parameters are currently supported by this action._
Examples:
```
https://example.com/path/to/api.php?action=version
```
### fetch-data
> Fetches air quality data from the system for a specific data type at a specific date and time.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`datetime` | date/time | Required. Specifies the date and time for which readings are desired. For current data use the special keyword `now`.
`reading_type` | string | Required. Specifies the type of reading desired.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
Examples:
```
https://example.com/path/to/api.php?action=fetch-data&datetime=2019-01-03%2007:52:10&reading_type=PM10
https://example.com/path/to/api.php?action=fetch-data&datetime=now&reading_type=PM10
```
### list-devices
> Fetches a list of devices currently in the system.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`only-with-location`| bool | Optional. If present only devices with a defined location will be returned. Useful for getting a list of devices to place on a map.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
Examples:
```
https://example.com/path/to/api.php?action=list-devices
https://example.com/path/to/api.php?action=list-devices&only-with-location=yes
```
### device-info
> Gets (lots of) information about a single device.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Required. The id of the device to get extended information for. See the `list-device` action for how to get a hold of one.
Examples:
### list-reading-types
> Lists the different types of readings that can be specified.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Optional. If specified, this filters the list of measurement types to list only those reported by the device with the specified id.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
```
https://example.com/path/to/api.php?action=list-reading-types
https://example.com/path/to/api.php?action=list-reading-types&device-id=22
https://example.com/path/to/api.php?action=list-reading-types&device-id=54
```
### device-data-bounds
> Gets the start and end DateTime bounds for the data recorded for a specific device.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Required. The id of the device to get the data DateTime bounds for.
```
https://example.com/path/to/api.php?action=device-data-bounds&device-id=18
https://example.com/path/to/api.php?action=device-data-bounds&device-id=11
```
### device-data
> Gets data by device given a start and end time.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | The id of the device to get data for.
`reading-type` | string | The type of reading to obtain data for.
`start` | datetime | The starting datetime.
`end` | datetime | The ending datetime.
`average-seconds` | int | Optional. If specified, readings will be grouped into lumps of this many seconds and averaged. For example a value of 3600 (1 hour) will return 1 data point per hour, with the value of each point an average of all the readings for that hour.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
```
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=2019-01-20T18:14:59.992Z
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=2019-01-20T18:14:59.992Z&average-seconds=3600
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=now&average-seconds=3600&format=csv
```
### changelog
> Gets the changelog as a fragment of HTML.
_No parameters are currently supported by this action._
```
https://example.com/path/to/api.php?action=changelog
```
## Notes

61
build
View file

@ -55,6 +55,8 @@ if [[ "$#" -lt 1 ]]; then
echo -e " ${CACTION}dev-server-stop${RS} - Stop the currently running development server";
echo -e " ${CACTION}client${RS} - Build the client web app";
echo -e " ${CACTION}client-watch${RS} - Watch for changes to the client code & rebuild automatically";
echo -e " ${CACTION}docs${RS} - Render the documentation";
echo -e " ${CACTION}ci${RS} - Perform CI tasks";
echo -e "";
exit 1;
@ -62,7 +64,15 @@ fi
###############################################################################
function task_setup {
# ███████ ███████ ████████ ██ ██ ██████
# ██ ██ ██ ██ ██ ██ ██
# ███████ █████ ██ ██ ██ ██████
# ██ ██ ██ ██ ██ ██
# ███████ ███████ ██ ██████ ██
task_setup() {
stage_begin "Setting up";
task_begin "Checking environment";
@ -112,7 +122,7 @@ function task_setup {
stage_end $?;
}
function task_setup-dev {
task_setup-dev() {
task_begin "Checking environment";
check_command mysql true optional;
task_end $?;
@ -126,7 +136,14 @@ function task_setup-dev {
task_end $?;
}
function task_database {
# ██████ ███████ ██ ██
# ██ ██ ██ ██ ██
# ██ ██ █████ ██ ██
# ██ ██ ██ ██ ██
# ██████ ███████ ████
task_database() {
task_begin "Connecting to the database";
set-title "Database";
ssh -TN "${database_host}" -L 3306:localhost:3306 &
@ -138,7 +155,7 @@ function task_database {
task_end $?;
}
function task_dev-server {
task_dev-server() {
task_begin "Starting development server";
php -S [::1]:40482 &
exit_code=$?;
@ -147,7 +164,7 @@ function task_dev-server {
sleep 1;
}
function task_dev-server-stop {
task_dev-server-stop() {
task_begin "Stopping development server";
kill "$(cat /tmp/micro-lantern-dev-server.pid)";
@ -157,7 +174,13 @@ function task_dev-server-stop {
}
function task_client {
# ██████ ██ ██ ███████ ███ ██ ████████
# ██ ██ ██ ██ ████ ██ ██
# ██ ██ ██ █████ ██ ██ ██ ██
# ██ ██ ██ ██ ██ ██ ██ ██
# ██████ ███████ ██ ███████ ██ ████ ██
task_client() {
task_begin "Packaging Javascript";
node_modules/rollup/bin/rollup --sourcemap --config rollup.config.js;
task_end $? "Error: rollup packing failed!";
@ -172,7 +195,7 @@ function task_client {
# task_end $?;
}
function task_client-watch {
task_client-watch() {
set-title "Client Watcher";
echo -e "Watching for changes.";
@ -189,6 +212,30 @@ function task_client-watch {
done
}
# ██████ ██████ ██████ ███████
# ██ ██ ██ ██ ██ ██
# ██ ██ ██ ██ ██ ███████
# ██ ██ ██ ██ ██ ██
# ██████ ██████ ██████ ███████
task_docs() {
task_begin "Rendering docs";
node_modules/.bin/nightdocs --config nightdocs.toml;
task_end $?;
}
# ██████ ██
# ██ ██
# ██ ██
# ██ ██
# ██████ ██
task_ci() {
tasks_run setup setup-dev client docs;
}
#########################################################################
tasks_run $@;

7
docs/00-Welcome.md Normal file
View file

@ -0,0 +1,7 @@
# Welcome!
> The Web Interface for the _Monitair_ project.
This is the documentation for [Air Quality Web](https://github.com/ConnectedHumber/Air-Quality-Web/), the air quality web interface that displays data from sensors scattered about the globe.
Check out the sections in the sidebar for documentation on the installation process, configuring an installation, and the HTTP API provided.

102
docs/01-Getting-Started.md Normal file
View file

@ -0,0 +1,102 @@
# Getting Started
To get started, there are 3 main steps:
1. Cloning & building the application
2. Configuring the application
3. Configuration a web server
The process is outlined in detail below.
## System Requirements
- Git
- Bash (if on Windows, try [Git Bash](https://gitforwindows.org/)) - the build script is written in Bash
- PHP 7+ enabled web server
- _Nginx_ + _PHP-FPM_ is recommended
- Apache works too
- MariaDB database with the appropriate table structure pre-loaded
- Node.JS (preferably 10+) + [npm](https://npmjs.org/) 6+ (for installing & building the client-side app code)
- [Node.JS](https://nodejs.org/)
- [Composer](https://getcomposer.org/) (for installing server-side dependencies)
- PHP modules:
- `pdo-mysql` (for the database connection)
- A [MariaDB](https://mariadb.com/) server with a database already setup with the schema data in it. Please get in contact with [ConnectedHumber](https://connectedhumber.org/) for information about the database schema and structure.
## Installation
1. Start by cloning this repository:
```bash
git clone https://github.com/ConnectedHumber/Air-Quality-Web.git
```
2. `cd` into the root of the cloned repository. Then install the dependencies (these are installed locally):
```bash
./build setup setup-dev
```
3. Build the client-side application:
```bash
# For development, run this:
./build client
# For production, run this:
NODE_ENV=production ./build client
# If you're actively working on the codebase and need to auto-recompile on every change, run this:
./build client-watch
```
4. Change the ownership to allow your web server user to access the created directory. Usually, the web server will be running under the `www-data` user:
```bash
sudo chown -R www-data:www-data path/to/Air-Quality-Web
```
5. Edit `data/settings.toml` to enter your database credentials.
You can edit other settings here too. See `settings.default.toml` for the settings you can change, but do **not** edit `settings.default.toml`! Edit `data/settings.toml` instead. You'll probably want to give the entire default settings file a careful read.
6. Configure your web server to serve the root of the repository you've cloned if you haven't already. Skip this step if you cloned the repository into a directory that your web server already serves.
7. Disallow public access to the private `data` directory.
In Nginx:
```nginx
# Put this inside the "server { }" website definition block:
# The "server { }" block can usually be found somewhere in /etc/nginx on Linux machines, and may have a "server_name" directive specifying the domain name it's serving if multiple websites are configured.
location ^~ /path/to/data/directory {
deny all;
}
```
In Apache:
```htaccess
# Create a file called ".htaccess" with this content inside the data/ directory
Require all denied
```
8. Test the application with an API call. If this returns valid JSON, then you've set it up correctly
```
http://example.com/path/to/Air-Quality-Web/api.php?action=list-devices
```
9. (Optional) Setup HTTPS:
```bash
sudo apt install certbot
# On Nginx:
sudo certbot --nginx --domain example.com
# On Apache:
sudo certbot --apache --domain example.com
```

110
docs/05-API-Docs.md Normal file
View file

@ -0,0 +1,110 @@
# API
The server-side API is accessed through `api.php`, and supports a number of GET parameters. The most important of these is the `action` parameter, Which determines what the API will do. The following values are supported:
## version
> Returns the version of the application.
_No parameters are currently supported by this action._
Examples:
```
https://example.com/path/to/api.php?action=version
```
## fetch-data
> Fetches air quality data from the system for a specific data type at a specific date and time.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`datetime` | date/time | Required. Specifies the date and time for which readings are desired. For current data use the special keyword `now`.
`reading_type` | string | Required. Specifies the type of reading desired.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
Examples:
```
https://example.com/path/to/api.php?action=fetch-data&datetime=2019-01-03%2007:52:10&reading_type=PM10
https://example.com/path/to/api.php?action=fetch-data&datetime=now&reading_type=PM10
```
## list-devices
> Fetches a list of devices currently in the system.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`only-with-location`| bool | Optional. If present only devices with a defined location will be returned. Useful for getting a list of devices to place on a map.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
Examples:
```
https://example.com/path/to/api.php?action=list-devices
https://example.com/path/to/api.php?action=list-devices&only-with-location=yes
```
## device-info
> Gets (lots of) information about a single device.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Required. The id of the device to get extended information for. See the `list-device` action for how to get a hold of one.
Examples:
## list-reading-types
> Lists the different types of readings that can be specified.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Optional. If specified, this filters the list of measurement types to list only those reported by the device with the specified id.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
```
https://example.com/path/to/api.php?action=list-reading-types
https://example.com/path/to/api.php?action=list-reading-types&device-id=22
https://example.com/path/to/api.php?action=list-reading-types&device-id=54
```
## device-data-bounds
> Gets the start and end DateTime bounds for the data recorded for a specific device.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | Required. The id of the device to get the data DateTime bounds for.
```
https://example.com/path/to/api.php?action=device-data-bounds&device-id=18
https://example.com/path/to/api.php?action=device-data-bounds&device-id=11
```
## device-data
> Gets data by device given a start and end time.
Parameter | Type | Meaning
--------------------|-----------|---------------------
`device-id` | int | The id of the device to get data for.
`reading-type` | string | The type of reading to obtain data for.
`start` | datetime | The starting datetime.
`end` | datetime | The ending datetime.
`average-seconds` | int | Optional. If specified, readings will be grouped into lumps of this many seconds and averaged. For example a value of 3600 (1 hour) will return 1 data point per hour, with the value of each point an average of all the readings for that hour.
`format` | string | Optional. Specifies the format that the response will be returned in. Valid values: `json`, `csv`. Default: `json`.
```
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=2019-01-20T18:14:59.992Z
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=2019-01-20T18:14:59.992Z&average-seconds=3600
https://example.com/path/to/api.php?action=device-data&device-id=18&reading-type=PM25&start=2019-01-19T18:14:59.992Z&end=now&average-seconds=3600&format=csv
```
## changelog
> Gets the changelog as a fragment of HTML.
_No parameters are currently supported by this action._
```
https://example.com/path/to/api.php?action=changelog
```

7
docs/README.md Normal file
View file

@ -0,0 +1,7 @@
# Air Quality Web
* [Welcome!](./00-Welcome.md)
* [Production Instance](https://aq.connectedhumber.org/app/)
* [Getting Started](01-Getting-Started.md)
* [Changelog](https://github.com/ConnectedHumber/Air-Quality-Web/blob/master/Changelog.md#changelog)
* [API Docs](05-API-Docs.md)

0
docs/theme.css Normal file
View file

2
nightdocs.toml Normal file
View file

@ -0,0 +1,2 @@
[template]
project_name = "Air Quality Web Docs"

45
package-lock.json generated
View file

@ -144,6 +144,12 @@
"integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
"dev": true
},
"await-fs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/await-fs/-/await-fs-1.0.0.tgz",
"integrity": "sha1-QAnTAIYz/WYlqgCfCm8aujY38wE=",
"dev": true
},
"base": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
@ -1406,6 +1412,12 @@
"integrity": "sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ==",
"dev": true
},
"html-entities": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.1.tgz",
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
"dev": true
},
"icss-replace-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
@ -1805,6 +1817,12 @@
"object-visit": "^1.0.0"
}
},
"marked": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/marked/-/marked-0.6.1.tgz",
"integrity": "sha512-+H0L3ibcWhAZE02SKMqmvYsErLo4EAVJxu5h3bHBBDvvjeWXtl92rGUSBYHL2++5Y+RSNgl8dYOAXcYe7lp1fA==",
"dev": true
},
"mdn-data": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
@ -1949,6 +1967,27 @@
"resolved": "https://registry.npmjs.org/nanomodal/-/nanomodal-5.1.1.tgz",
"integrity": "sha1-qiEiUSr49vpr3G8y1nqm3whvfK0="
},
"nightdocs": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/nightdocs/-/nightdocs-1.0.1.tgz",
"integrity": "sha512-JRX8iOjvW0wbYFNWH16deb8KFAQq9lM74IBT1SdtEjAyqetDs3DmsAsJNc/HRqft8QRcRDQmWsWeLbV4nrW0QQ==",
"dev": true,
"requires": {
"marked": "^0.6.1",
"nightink": "^0.1.2",
"toml": "^3.0.0"
}
},
"nightink": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/nightink/-/nightink-0.1.2.tgz",
"integrity": "sha512-nAyyf1EvghaFtmwD4ox2rFiY0eWqAsW6rulIPaPC5IMv3YaNKYdQ4F7zUZ6E7eONEVQGtiCGTv6YksY9wHHs1g==",
"dev": true,
"requires": {
"await-fs": "^1.0.0",
"html-entities": "^1.2.1"
}
},
"node-releases": {
"version": "1.1.10",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.10.tgz",
@ -4210,6 +4249,12 @@
}
}
},
"toml": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz",
"integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==",
"dev": true
},
"union-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",

View file

@ -33,6 +33,7 @@
"@types/leaflet": "^1.4.3",
"@types/leaflet-fullscreen": "^1.0.4",
"leaflet-heatmap": "^1.0.0",
"nightdocs": "^1.0.1",
"postcss-copy": "^7.1.0",
"postcss-import": "^12.0.1",
"rollup": "^1.6.0",
@ -41,5 +42,14 @@
"rollup-plugin-postcss": "^2.0.3",
"rollup-plugin-replace": "^2.1.0",
"rollup-plugin-terser": "^4.0.4"
},
"docpress": {
"github": "ConnectedHumber/Air-Quality-Web",
"markdown": {
"xhtmlOut": true
},
"css": [
"docs/theme.css"
]
}
}