Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2dc1d19
Create README files for daemon and backend to begin documentation pro…
ethanwillis Jul 19, 2018
5818936
Implement mongoose schemas and add necessary mongoose and bluebird pa…
ethanwillis Jul 19, 2018
150d558
Refactor app to start listening when the mongodb in the docker contai…
ethanwillis Jul 19, 2018
6ef553f
- Created dockerfile for backend that takes in arguments for environm…
ethanwillis Jul 19, 2018
6ac3e70
Create placeholders for dockerfiles for other services.
ethanwillis Jul 19, 2018
2a101e4
Merge branch 'docs'
ethanwillis Jul 19, 2018
657526a
Merge branch 'docker'
ethanwillis Jul 19, 2018
4f987d4
Refactored schemas into separate files
ethanwillis Jul 19, 2018
024bc1d
Removed un-necessary fluff from app.js and added in some needed middl…
ethanwillis Jul 19, 2018
1751f36
Remove more un-necessary fluff from backend project
ethanwillis Jul 19, 2018
ee05112
Refactored API endpoints.
ethanwillis Jul 19, 2018
f343fc9
Fixed typos in the schemas files.
ethanwillis Jul 19, 2018
9d721a8
Added in loading of schemas for express app.
ethanwillis Jul 19, 2018
5c82984
Added cors and compression libraries and enabled them.
ethanwillis Jul 19, 2018
5a12beb
- Created Dockerfile for GUI frontend.
ethanwillis Jul 19, 2018
b4a7622
- Updated dockerfile and docker-compose for GUI/frontend so that we c…
ethanwillis Jul 19, 2018
2ac9b06
Wrote documentation for backend service that explains the REST API, h…
ethanwillis Jul 19, 2018
ea81030
Wrote README for backend service that details
ethanwillis Jul 19, 2018
df89b8a
Created docker compose file for production
ethanwillis Jul 19, 2018
a7f47e1
Merge branch 'master' into docs
ethanwillis Jul 19, 2018
e1ecfc8
Merge branch 'master' into schemas
ethanwillis Jul 19, 2018
e4b8d1d
Backend Readme
ethanwillis Jul 19, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,6 @@
*.app
Software/gui/.vscode/launch.json
Software/.vscode/launch.json

# Ignore docker data directories
docker
23 changes: 23 additions & 0 deletions Software/backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
FROM node:alpine

# Create a workdirectory in our container and copy all of our code to it.
WORKDIR /app
COPY . /app

# Setup inputs for arguments for environment variables.
ARG NODE_ENV
ARG PORT
ARG DATABASE_PROD
ARG DATABASE_TEST

# Set our environment variables from arguments.
ENV NODE_ENV ${NODE_ENV}
ENV PORT ${PORT}
ENV DATABASE_PROD ${DATABASE_PROD}
ENV DATABASE_TEST ${DATABASE_TEST}

# Install NPM dependencies for this project
RUN npm install --production

# Start API Backend.
CMD ["node", "app.js"]
134 changes: 134 additions & 0 deletions Software/backend/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# SpeedSeed 3 backend

## Setup
This program depends on docker and docker-compose. Please see install instructions [here](https://docs.docker.com/compose/install/).

***Once docker and docker-compose are installed***

### Setup as standalone server
If you want to run the API as a standalone either on the same hardware as the frontend code or on a remote server.

**Make sure you're in the correct directory.**
Directory: /SpeedSeed3/Software/backend
**Run the following command**
```sh
$ docker build -t speedseed3api \
--build-arg NODE_ENV=production \
--build-arg PORT=3001 \
--build-arg DATABASE_PROD=mongodb://db:27017/speedseed3 \
--build-arg DATABASE_TEST=mongodb://db:27017/speedseed3test .
$ docker run speedseed3api
```
**Explanation of build-args**
Each of the build-args, NODE_ENV, PORT, DATABASE_PROD, DATABASE_TEST, are used to configure the API at runtime.

***NODE_ENV:***
This can either be "production" or "test". If you use "production" then DATABASE_PROD will be used for the database connection. If you use "test" then DATABASE_TEST will be used for the database connection.
***PORT:***
This is simply the port that the application will bind itself to.
***DATABASE_PROD:***
This is the mongodb connection string used in production mode.
***DATABASE_TEST:***
This is the mongodb connection string used in test mode.

### Setup on same hardware as frontend/gui code.
If you want to run the API on the same hardware as the frontend code you can simply use the docker-compose file provided in Software/docker-compose-production.yml

**Make sure you're in the correct directory.**
Directory: /SpeedSeed3/Software
**Run the following command**
```sh
$ docker-compose -f docker-compose-production.yml up
```
Congratulations you are now running the full GUI, Backend, and Database servers.

## API Docs
The SpeedSeed 3 backend API provides access to two resources: Settings and Status.

### Settings Resource
The Settings resource controls the system schedule for controlling humidity levels, light levels, and temperature levels.
Currently there are two actions provided by this resource
1. Getting the current system Settings
2. Updating the system Settings.

The Settings resource's structure is defined in the schema at /SpeedSeed3/Software/backend/schemas/Settings.js

### GET /settings
This will return the current system settings object.

***Example Request:***
```curl
curl -X GET http://localhost:3001/settings
```

### POST /settings
This will set new system settings.

***Example Request:***

```curl
curl -X POST \
http://localhost:3001/settings \
-d '{
"temperature": [
{
"start_hour": 0,
"start_min": 0,
"end_hour": 5,
"end_min": 0,
"max": 16.0
},
{
"start_hour": 5,
"start_min": 0,
"end_hour": 6,
"end_min": 0,
"max": 30.0
},
{
"start_hour": 6,
"start_min": 0,
"end_hour": 24,
"end_min": 0,
"max": 16.0
}
],
"humidity": [
{
"start_hour": 0,
"start_min": 0,
"end_hour": 24,
"end_min": 0,
"max": 60.0
}
],
"light": [
{
"start_hour": 0,
"start_min": 0,
"end_hour": 4,
"end_min": 0,
"status": 0
},
{
"start_hour": 5,
"start_min": 0,
"end_hour": 24,
"end_min": 0,
"status": 1
}
]
}'
```

### Status Resource
The Status resource shows the system status over a period of time. E.G. what the humidity, temperature, and light status were at each time interval. Currently this resource is read-only.

The Status resource's structure is defined in the schema at /SpeedSeed3/Software/backend/schemas/Status.js

### GET /status

***Example Request:***
```curl
curl -X GET http://localhost:3001/status
```
135 changes: 83 additions & 52 deletions Software/backend/app.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var index = require('./routes/index');
var users = require('./routes/users');
var getMonitors = require('./routes/getMonitors');
var setSettings = require('./routes/setSettings');
var getSettings = require('./routes/getSettings');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);
app.use('/users', users);
app.use('/getMonitors', getMonitors);
app.use('/setSettings', setSettings);
app.use('/getSettings', getSettings);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
var err = new Error('Not Found');
err.status = 404;
next(err);
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;
#!/usr/bin/env node
let express = require('express');
let cors = require('cors');
let compression = require('compression');
let bodyParser = require('body-parser');
let logger = require('morgan');
let debug = require('debug')('backend:server');

// Create new express app.
let app = express();

// Add in mongoose and connect to database.
require('./mongoose')(app);

/**
* Normalize a port into a number, string, or false.
*/
function normalizePort(val) {
var port = parseInt(val, 10);

if (isNaN(port)) {
// named pipe
return val;
}

if (port >= 0) {
// port number
return port;
}

return false;
}

function onError(error) {
if (error.syscall !== 'listen') {
throw error;
}

var bind = typeof port === 'string'
? 'Pipe ' + port
: 'Port ' + port;

// handle specific listen errors with friendly messages
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
}

// When database in docker container is ready for connections...
app.on('mongo_ready', function() {
// Load in express app middleware.
console.log('Database ready, loading middleware...');
app.use(logger('dev'));
app.use(cors());
app.use(compression());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Pull in schemas
console.log("Loading schemas...");
require('./schemas/Errors')(app);
require('./schemas/Settings')(app);
require('./schemas/Status')(app);

// Start API endpoints
console.log("Loading API endpoints...");
require('./routes/Settings')(app);
require('./routes/Status')(app);

// Start app
var port = normalizePort(process.env.PORT || '3000');
app.listen(process.env.PORT);
console.log("Listening on: " + process.env.PORT)
})
90 changes: 0 additions & 90 deletions Software/backend/bin/www

This file was deleted.

Loading