remove cached files
This commit is contained in:
@@ -1,127 +0,0 @@
|
||||
/*
|
||||
* Serve GraphQL Backend
|
||||
*/
|
||||
|
||||
import express from 'express';
|
||||
import path from 'path';
|
||||
import webpack from 'webpack';
|
||||
import WebpackDevServer from 'webpack-dev-server';
|
||||
import bodyParser from 'body-parser';
|
||||
|
||||
|
||||
import DB from './config/database';
|
||||
import routes from './routes';
|
||||
|
||||
const API_PORT = 8080;
|
||||
const APP_PORT = 3000;
|
||||
|
||||
var api = express();
|
||||
|
||||
/*
|
||||
* Serve API App
|
||||
*/
|
||||
|
||||
DB.sync().then(()=>{
|
||||
|
||||
routes(api);
|
||||
|
||||
api.use(bodyParser.json());
|
||||
api.use(bodyParser.urlencoded({ extended: false }));
|
||||
|
||||
|
||||
api.listen(API_PORT, () => {
|
||||
console.log(`API is now running on http://localhost:${API_PORT}`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Development Server
|
||||
*/
|
||||
|
||||
var config = require('./config/webpack/development'),
|
||||
dev_server = new WebpackDevServer(webpack(config), {
|
||||
contentBase: __dirname + '/../client/build/development',
|
||||
publicPath: "/assets/",
|
||||
proxy: {
|
||||
'/data*': `http://localhost:${API_PORT}`,
|
||||
},
|
||||
stats: {colors: true}
|
||||
}),
|
||||
app = dev_server.app;
|
||||
|
||||
/*
|
||||
* Serve Vendor Scripts, CSS, and Templates
|
||||
*/
|
||||
|
||||
import favicon from 'serve-favicon';
|
||||
import logger from 'morgan';
|
||||
|
||||
// uncomment after placing your favicon in /public
|
||||
app.use(favicon(__dirname + '/public/favicon.ico'));
|
||||
app.use(logger('dev'));
|
||||
|
||||
// serve fonts in /assets/fonts
|
||||
import assets from "connect-assets";
|
||||
|
||||
// TODO: These routes need to match references in the bootstrap and font awesome files.
|
||||
app.use("/assets/fonts", express.static("bootstrap/dist/fonts"));
|
||||
app.use("/assets/fonts", express.static("font-awesome/fonts"));
|
||||
// serve compiled vendor assets and application.css.
|
||||
app.use(assets({
|
||||
paths: ["./../node_modules"],
|
||||
build: true,
|
||||
buildDir: false,
|
||||
//compile: false,
|
||||
compress: true
|
||||
}));
|
||||
// serve public static files.
|
||||
dev_server.app.use('/', express.static(path.resolve(__dirname, 'public')));
|
||||
|
||||
// view engine set up
|
||||
app.set('views', path.join(__dirname, 'views'));
|
||||
app.set('view engine', 'jade');
|
||||
app.get("/", (req, res, next)=>{
|
||||
res.render("index");
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
* Handle Errors
|
||||
*/
|
||||
|
||||
// catch 404 and forward to error handler
|
||||
app.use(function(req, res, next) {
|
||||
var err = new Error('Not Found');
|
||||
err.status = 404;
|
||||
next(err);
|
||||
});
|
||||
|
||||
// development error handler
|
||||
// will print stacktrace
|
||||
if (app.get('env') === 'development') {
|
||||
app.use(function(err, req, res, next) {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
message: err.message,
|
||||
error: err
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// production error handler
|
||||
// no stacktraces leaked to user
|
||||
app.use(function(err, req, res, next) {
|
||||
res.status(err.status || 500);
|
||||
res.render('error', {
|
||||
message: err.message,
|
||||
error: {}
|
||||
});
|
||||
});
|
||||
|
||||
dev_server.listen(APP_PORT, () => {
|
||||
console.log(`App is now running on http://localhost:${APP_PORT}`);
|
||||
});
|
||||
|
||||
module.exports = app;
|
||||
@@ -1,17 +0,0 @@
|
||||
import fs from 'fs';
|
||||
|
||||
const CONTROLLER_DIR = __dirname + '/../controllers';
|
||||
|
||||
class Controllers {
|
||||
|
||||
static sync(){
|
||||
fs.readdirSync(CONTROLLER_DIR).forEach(function(file) {
|
||||
var controller = require(CONTROLLER_DIR + '/' + file);
|
||||
Controllers[controller.NAME] = controller;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default Controllers;
|
||||
@@ -1,37 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
import fs from "fs";
|
||||
import Sequelize from 'sequelize';
|
||||
|
||||
var sequelize = new Sequelize("postgres://spikeuser:123456@localhost:5432/spike2", {
|
||||
pool: {
|
||||
max: 5,
|
||||
min: 0,
|
||||
idle: 10000
|
||||
}
|
||||
});
|
||||
const MODEL_DIR = __dirname + '/../models'
|
||||
|
||||
class Database {
|
||||
|
||||
static sync(){
|
||||
console.log("syncing db")
|
||||
fs.readdirSync(MODEL_DIR).forEach(function(file) {
|
||||
var model = require(MODEL_DIR + '/' + file);
|
||||
Database[model.NAME] = model;
|
||||
Database.models.push(model);
|
||||
});
|
||||
|
||||
// add associations
|
||||
for (var model of Database.models){
|
||||
model.set();
|
||||
}
|
||||
|
||||
return sequelize.sync().then(()=>{ console.log("done syncing db") });
|
||||
}
|
||||
}
|
||||
Database.sequelize = sequelize;
|
||||
Database.Sequelize = Sequelize;
|
||||
Database.models = [];
|
||||
|
||||
export default Database;
|
||||
@@ -1,7 +0,0 @@
|
||||
var config = {
|
||||
modules: 'es6',
|
||||
targetVersion: '0.14.0',
|
||||
suffix: '.rt'
|
||||
};
|
||||
|
||||
export default config;
|
||||
@@ -1 +0,0 @@
|
||||
design.js
|
||||
@@ -1,48 +0,0 @@
|
||||
import webpack from 'webpack';
|
||||
|
||||
const ROOT = __dirname + '/../../../';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: ROOT + 'client/app',
|
||||
style: ROOT + 'client/style'
|
||||
},
|
||||
output: {
|
||||
filename: '[name].js',
|
||||
path: ROOT + 'client/build/development'
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loaders: ['style', 'raw', 'sass']
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loaders: ['style', 'raw']
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'babel'
|
||||
}, {
|
||||
test: /\.json$/,
|
||||
loader: 'json-loader'
|
||||
}
|
||||
]
|
||||
},
|
||||
sassLoader: {
|
||||
includePaths: [ROOT + 'client', ROOT + 'node_modules']
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
"window.jQuery": "jquery"
|
||||
}),
|
||||
new webpack.ProvidePlugin({
|
||||
d3: "d3",
|
||||
"window.d3": "d3"
|
||||
})
|
||||
],
|
||||
node: {
|
||||
fs: "empty"
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import ExtractTextPlugin from 'extract-text-webpack-plugin';
|
||||
import webpack from 'webpack';
|
||||
|
||||
const ROOT = __dirname + '/../../../';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
app: ROOT + 'client/app',
|
||||
style: ROOT + 'client/style'
|
||||
},
|
||||
devtool: 'source-map',
|
||||
output: {
|
||||
filename: '[name].min.js',
|
||||
path: ROOT + 'client/build/production'
|
||||
},
|
||||
externals: {
|
||||
jquery: "$",
|
||||
d3: "d3"
|
||||
},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
test: /\.scss$/,
|
||||
loader: ExtractTextPlugin.extract("style-loader", "raw-loader!sass-loader")
|
||||
}, {
|
||||
test: /\.css$/,
|
||||
loader: ExtractTextPlugin.extract("style-loader", "raw-loader")
|
||||
}, {
|
||||
test: /\.js$/,
|
||||
loader: 'babel'
|
||||
}, {
|
||||
test: /\.woff(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
loader: "url-loader?limit=10000&minetype=application/font-woff"
|
||||
}, {
|
||||
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
|
||||
loader: "file-loader"
|
||||
}
|
||||
]
|
||||
},
|
||||
sassLoader: {
|
||||
includePaths: [ROOT + 'client', ROOT + 'node_modules']
|
||||
},
|
||||
// Use the plugin to specify the resulting filename (and add needed behavior to the compiler)
|
||||
plugins: [
|
||||
new ExtractTextPlugin("style.min.css", {
|
||||
allChunks: true
|
||||
}),
|
||||
new webpack.optimize.UglifyJsPlugin({minimize: true}),
|
||||
new webpack.ProvidePlugin({
|
||||
$: "jquery",
|
||||
jQuery: "jquery",
|
||||
"window.jQuery": "jquery"
|
||||
})
|
||||
],
|
||||
node: {
|
||||
fs: "empty"
|
||||
}
|
||||
};
|
||||
@@ -1,16 +0,0 @@
|
||||
import DB from './../config/database.js';
|
||||
|
||||
const NAME = 'EnergyController';
|
||||
|
||||
class EnergyController{
|
||||
|
||||
static index(req, res){
|
||||
DB.EnergyDatum.exposeForHouseAtDates(req.query.house_id, req.query.dates).then((energy_data)=>{
|
||||
res.json({data: energy_data});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EnergyController.NAME = NAME;
|
||||
module.exports = EnergyController;
|
||||
@@ -1,18 +0,0 @@
|
||||
import DB from './../config/database.js';
|
||||
|
||||
const NAME = 'HousesController';
|
||||
|
||||
class HousesController {
|
||||
|
||||
static index(req, res){
|
||||
var params = {};
|
||||
if (req.query.ids) query.id = ids;
|
||||
DB.House.findAll({where: params}).then((houses)=>{
|
||||
res.json({data: houses.map((house)=>{ return house.dataValues; })});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
HousesController.NAME = NAME;
|
||||
module.exports = HousesController;
|
||||
@@ -1,16 +0,0 @@
|
||||
import DB from './../config/database.js';
|
||||
|
||||
const NAME = 'PowerController';
|
||||
|
||||
class PowerController{
|
||||
|
||||
static index(req, res){
|
||||
DB.PowerDatum.exposeForHouseAtDates(req.query.house_id, req.query.dates).then((power_data)=>{
|
||||
res.json({data: power_data});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PowerController.NAME = NAME;
|
||||
module.exports = PowerController;
|
||||
@@ -1,29 +0,0 @@
|
||||
class ApiHelper {
|
||||
|
||||
// assume all dates from api coming as UNIX timestamps.
|
||||
static datesParamToSequelize(dates, field_name){
|
||||
if (!dates) return {};
|
||||
var params = {};
|
||||
|
||||
if (dates.length > 1){
|
||||
params['$or'] = [];
|
||||
dates.forEach((min_max)=>{
|
||||
var condition_n = {};
|
||||
condition_n[field_name] = {};
|
||||
if (min_max[0]) condition_n[field_name]['$gte'] = min_max[0];
|
||||
if (min_max[1]) condition_n[field_name]['$lte'] = min_max[1];
|
||||
if (Object.keys(condition_n).length) params['$or'].push(condition_n);
|
||||
});
|
||||
} else {
|
||||
var min_max = dates[0],
|
||||
condition = {}
|
||||
if (min_max[0]) condition['$gte'] = min_max[0];
|
||||
if (min_max[1]) condition['$lte'] = min_max[1];
|
||||
if (Object.keys(condition).length) params[field_name] = condition;
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default ApiHelper;
|
||||
@@ -1,57 +0,0 @@
|
||||
'use strict';
|
||||
// through2 is a thin wrapper around node transform streams
|
||||
import through from 'through2';
|
||||
import gutil from 'gulp-util';
|
||||
import rt from 'react-templates';
|
||||
import path from 'path';
|
||||
import extend from 'extend';
|
||||
|
||||
// Consts
|
||||
const PLUGIN_NAME = 'gulp-react-templates';
|
||||
var PluginError = gutil.PluginError;
|
||||
|
||||
function normalizeName(name) {
|
||||
return name.replace(/-/g, '_');
|
||||
}
|
||||
|
||||
export default function (opt) {
|
||||
function replaceExtension(filePath) {
|
||||
return filePath + '.js';
|
||||
}
|
||||
|
||||
function transform(file, enc, cb) {
|
||||
if (file.isNull()) {
|
||||
return cb(null, file);
|
||||
}
|
||||
if (file.isStream()) {
|
||||
return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'));
|
||||
}
|
||||
|
||||
var filePath = file.path,
|
||||
str = file.contents.toString('utf8'),
|
||||
data;
|
||||
|
||||
var options = extend({
|
||||
filename: file.path,
|
||||
sourceFiles: [file.relative],
|
||||
generatedFile: replaceExtension(file.relative)
|
||||
}, opt);
|
||||
|
||||
if (options.suffix && !options.name) {
|
||||
options.name = normalizeName(path.basename(filePath, path.extname(filePath))) + options.suffix;
|
||||
}
|
||||
|
||||
try {
|
||||
data = rt.convertTemplateToReact(str, options);
|
||||
} catch (err) {
|
||||
return cb(new PluginError(PLUGIN_NAME, err));
|
||||
}
|
||||
|
||||
file.contents = new Buffer(data);
|
||||
|
||||
file.path = replaceExtension(file.path);
|
||||
cb(null, file);
|
||||
}
|
||||
|
||||
return through.obj(transform);
|
||||
};
|
||||
@@ -1,103 +0,0 @@
|
||||
import extend from "extend";
|
||||
import moment from "moment";
|
||||
import csv from "fast-csv";
|
||||
import fs from 'fs';
|
||||
import MathUtils from "./../../../shared/utils/math"
|
||||
import DB from './../../config/database';
|
||||
|
||||
const DATA_PATH = __dirname + '/../../../shared/data/'
|
||||
|
||||
export class PowerDataSeed {
|
||||
|
||||
static saveCsv(opts, done){
|
||||
opts = extend({
|
||||
path: DATA_PATH + "power_data.csv"
|
||||
}, opts || {});
|
||||
var stream = fs.createReadStream(opts.path),
|
||||
csvStream = csv.fromStream(stream, {headers: ['house_id', 'time', 'consumption', 'production']}),
|
||||
rows = [];
|
||||
|
||||
csvStream.on("data", function(data){
|
||||
data.time = data.time;
|
||||
rows.push(data);
|
||||
if (rows.length % 100 === 0){
|
||||
DB.PowerDatum.bulkCreate(rows, {validate: true}).catch((error)=>{
|
||||
console.error(JSON.stringify(error));
|
||||
console.error(JSON.stringify(rows));
|
||||
});
|
||||
rows = [];
|
||||
}
|
||||
});
|
||||
csvStream.on("end", function(){
|
||||
console.log("all rows parsed")
|
||||
DB.PowerDatum.bulkCreate(rows, {validate: true}).then(()=>{
|
||||
return DB.House.findAll().then((houses)=>{
|
||||
var promises = [];
|
||||
for (var house of houses){
|
||||
var p = house.aggregatePowerToEnergyData();
|
||||
promises.push(p);
|
||||
}
|
||||
return Promise.all(promises);
|
||||
});
|
||||
}).then(()=>{
|
||||
console.log("DONE!")
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static generateCsv(opts, done){
|
||||
opts = extend({
|
||||
start_date: moment().subtract(120, "months").unix(),
|
||||
end_date: moment().unix(),
|
||||
interval: 900, // every 15 minutes (in s)
|
||||
average: 1400, // Wh
|
||||
path: DATA_PATH + "power_data.csv"
|
||||
}, opts || {});
|
||||
console.log(opts.start_date, opts.end_date)
|
||||
var row_date = opts.start_date,
|
||||
csvStream = csv.format({headers: true}),
|
||||
writableStream = fs.createWriteStream(opts.path),
|
||||
house_ids = opts.house_ids.split(",")
|
||||
|
||||
DB.House.findAll({where: {id: house_ids}}).then((houses)=>{
|
||||
|
||||
csvStream.pipe(writableStream);
|
||||
writableStream.on("finish", ()=>{
|
||||
console.log("DONE!")
|
||||
done();
|
||||
});
|
||||
|
||||
while (row_date <= opts.end_date){
|
||||
for (var house of houses){
|
||||
var consumption = MathUtils.normal(opts.average),
|
||||
production = MathUtils.normal(opts.average) * house.productionMultiplier(row_date * 1000);
|
||||
csvStream.write([house.id, row_date, consumption, production]);
|
||||
}
|
||||
row_date += opts.interval;
|
||||
}
|
||||
csvStream.end();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class HouseSeed {
|
||||
static saveCsv(opts, done){
|
||||
opts = extend({
|
||||
path: DATA_PATH + "houses.csv"
|
||||
}, opts || {});
|
||||
var stream = fs.createReadStream(opts.path),
|
||||
csvStream = csv.fromStream(stream, {headers: ['id', 'name', 'timezone']}),
|
||||
rows = [];
|
||||
|
||||
csvStream.on("data", function(data){
|
||||
rows.push(data);
|
||||
});
|
||||
csvStream.on("end", function(){
|
||||
console.log(rows);
|
||||
DB.House.bulkCreate(rows, {validate: true}).then(()=>{
|
||||
console.log("DONE!")
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
import DB from "./../config/database";
|
||||
import extend from 'extend';
|
||||
import ApiHelper from './../helpers/api_helper';
|
||||
|
||||
const NAME = 'EnergyDatum';
|
||||
|
||||
/**
|
||||
* Define your own types here
|
||||
*/
|
||||
|
||||
var EnergyDatum = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true // Automatically gets converted to SERIAL for postgres
|
||||
},
|
||||
day: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
},
|
||||
production: DB.Sequelize.FLOAT,
|
||||
consumption: DB.Sequelize.FLOAT
|
||||
}, {
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "energy_data",
|
||||
instanceMethods: {},
|
||||
classMethods: {
|
||||
set: ()=>{
|
||||
EnergyDatum.associate();
|
||||
},
|
||||
associate: ()=>{
|
||||
EnergyDatum.belongsTo(DB.House);
|
||||
},
|
||||
exposeForHouseAtDates: (house_id, dates)=>{
|
||||
var params = {house_id: house_id};
|
||||
extend(params, ApiHelper.datesParamToSequelize(dates, 'day'));
|
||||
console.log('EnergyDatum#exposeForHouseAtDates')
|
||||
console.log(params, dates)
|
||||
return EnergyDatum.findAll({
|
||||
where: params,
|
||||
attributes: ['id', 'production', 'consumption', 'day']
|
||||
}).then((energy_data)=>{
|
||||
return energy_data.map((energy_datum)=>{
|
||||
return energy_datum.dataValues;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
EnergyDatum.NAME = NAME;
|
||||
module.exports = EnergyDatum;
|
||||
@@ -1,93 +0,0 @@
|
||||
import moment from 'moment-timezone';
|
||||
import DB from "./../config/database";
|
||||
|
||||
const NAME = 'House';
|
||||
|
||||
/**
|
||||
* Sequelize Definition
|
||||
*/
|
||||
|
||||
var House = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true // Automatically gets converted to SERIAL for postgres
|
||||
},
|
||||
timezone: DB.Sequelize.STRING,
|
||||
name: DB.Sequelize.STRING,
|
||||
data_until: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
},
|
||||
data_from: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
}
|
||||
}, {
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "houses",
|
||||
instanceMethods: {
|
||||
productionMultiplier: function(timestamp){
|
||||
var house = this,
|
||||
minute = moment.tz(timestamp, house.timezone).hour() * 60 + moment.tz(timestamp, house.timezone).minute(),
|
||||
multiplier = 0;
|
||||
if (minute > 420 && minute < 1140){
|
||||
multiplier = 1 - Math.abs(780 - minute) / 360;
|
||||
}
|
||||
return multiplier;
|
||||
},
|
||||
unixToLocalDay: function(unix){
|
||||
var house = this;
|
||||
return moment.tz(unix * 1000, house.timezone).startOf('day').unix();
|
||||
},
|
||||
aggregatePowerToEnergyData: function(){
|
||||
var house = this;
|
||||
return DB.EnergyDatum.destroy({where: {house_id: house.id}})
|
||||
.then(()=>{
|
||||
return DB.PowerDatum.count({where: {house_id: house.id}})
|
||||
})
|
||||
.then((count)=>{
|
||||
var limit = 0,
|
||||
energy_data = new Map(),
|
||||
promises = [];
|
||||
while (limit < count){
|
||||
let complete = DB.PowerDatum.findAll({where: {house_id: house.id}, limit: 1000, offset: limit, order: 'id ASC'})
|
||||
.then((power_data)=>{
|
||||
power_data.forEach((power_datum)=>{
|
||||
var day = house.unixToLocalDay(power_datum.time),
|
||||
energy_datum = energy_data.get(day) || {production: 0, consumption: 0, day: day, house_id: house.id};
|
||||
energy_datum.production += power_datum.production / 1000; // convert Wh to kWh
|
||||
energy_datum.consumption += power_datum.consumption / 1000; // convert Wh to kWh
|
||||
energy_data.set(day, energy_datum);
|
||||
});
|
||||
});
|
||||
promises.push(complete);
|
||||
limit += 1000;
|
||||
}
|
||||
return Promise.all(promises).then(()=>{
|
||||
return DB.EnergyDatum.bulkCreate(Array.from(energy_data.values()), {validate: true});
|
||||
});
|
||||
})
|
||||
.then(()=>{
|
||||
return house.getPowerData({order: 'time DESC', limit: 1});
|
||||
})
|
||||
.then((max_data)=>{
|
||||
house.data_until = max_data[0].time;
|
||||
return house.getPowerData({order: 'time ASC', limit: 1});
|
||||
}).then((min_data)=>{
|
||||
house.data_from = min_data[0].time;
|
||||
return house.save();
|
||||
});
|
||||
}
|
||||
},
|
||||
classMethods: {
|
||||
set: ()=>{
|
||||
House.associate();
|
||||
},
|
||||
associate: ()=>{
|
||||
House.hasMany(DB.PowerDatum, {as: 'PowerData'});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
House.NAME = NAME;
|
||||
module.exports = House;
|
||||
@@ -1,59 +0,0 @@
|
||||
import DB from "./../config/database";
|
||||
import extend from 'extend';
|
||||
import ApiHelper from './../helpers/api_helper';
|
||||
|
||||
const NAME = 'PowerDatum';
|
||||
|
||||
/**
|
||||
* Define your own types here
|
||||
*/
|
||||
|
||||
var PowerDatum = DB.sequelize.define(NAME, {
|
||||
id: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
primaryKey: true,
|
||||
autoIncrement: true // Automatically gets converted to SERIAL for postgres
|
||||
},
|
||||
time: {
|
||||
type: DB.Sequelize.INTEGER,
|
||||
},
|
||||
consumption: DB.Sequelize.FLOAT,
|
||||
production: DB.Sequelize.FLOAT
|
||||
}, {
|
||||
paranoid: true,
|
||||
underscored: true,
|
||||
tableName: "power_data",
|
||||
instanceMethods: {
|
||||
exposeToApi: function(){
|
||||
var power_datum = this,
|
||||
data = power_datum.dataValues;
|
||||
data.consumption = data.consumption * 4; // convert Wh / 15 minutes, to W
|
||||
data.production = data.production * 4; // convert Wh / 15 minutes, to W
|
||||
return data;
|
||||
}
|
||||
},
|
||||
classMethods: {
|
||||
exposeForHouseAtDates: (house_id, dates)=>{
|
||||
var params = {house_id: house_id};
|
||||
params = extend(params, ApiHelper.datesParamToSequelize(dates, 'time'));
|
||||
console.log(params);
|
||||
return PowerDatum.findAll({
|
||||
where: params,
|
||||
attributes: ['id', 'production', 'consumption', 'time']
|
||||
}).then((power_data)=>{
|
||||
return power_data.map((power_datum)=>{
|
||||
return power_datum.exposeToApi();
|
||||
});
|
||||
});
|
||||
},
|
||||
set: ()=>{
|
||||
PowerDatum.associate();
|
||||
},
|
||||
associate: ()=>{
|
||||
PowerDatum.belongsTo(DB.House);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
PowerDatum.NAME = NAME;
|
||||
module.exports = PowerDatum;
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="/assets/css/vendor.css" rel="stylesheet" type="text/css">
|
||||
<link href="/assets/css/application.css" rel="stylesheet" type="text/css">
|
||||
<title>Spike Prototype</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="spike_container">
|
||||
<div id="spike_content">
|
||||
<nav style="margin-bottom:0px;" class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar" class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span><span class="icon-bar"></span></button><a href="/" class="navbar-brand">Spike</a>
|
||||
</div>
|
||||
<div id="navbar" class="collapse navbar-collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="/">Spike</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div id="root"></div>
|
||||
</div>
|
||||
<div id="spike_footer">
|
||||
<div class="container">Footer</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
// Force `fetch` polyfill to workaround Chrome not displaying request body
|
||||
// in developer tools for the native `fetch`.
|
||||
self.fetch = null;
|
||||
</script>
|
||||
<script src="http://localhost:3000/webpack-dev-server.js"></script>
|
||||
<script src="/assets/js/vendor.js"></script>
|
||||
<script src="/assets/js/application.js"></script>
|
||||
</html>
|
||||
@@ -1,11 +0,0 @@
|
||||
import Controllers from './config/controllers'
|
||||
|
||||
export default function(app){
|
||||
|
||||
Controllers.sync();
|
||||
|
||||
app.use('/data/v1/power', Controllers.PowerController.index);
|
||||
app.use('/data/v1/energy', Controllers.EnergyController.index);
|
||||
app.use('/data/v1/houses', Controllers.HousesController.index);
|
||||
|
||||
};
|
||||
@@ -1,6 +0,0 @@
|
||||
extends layout
|
||||
|
||||
block content
|
||||
h1= message
|
||||
h2= error.status
|
||||
pre #{error.stack}
|
||||
@@ -1,3 +0,0 @@
|
||||
extends layout
|
||||
block content
|
||||
div(id="root")
|
||||
@@ -1,34 +0,0 @@
|
||||
doctype html
|
||||
html
|
||||
head
|
||||
meta(charset='utf-8')
|
||||
meta(http-equiv='content-type', content='text/html; charset=UTF-8')
|
||||
meta(name='viewport', content='width=device-width, initial-scale=1')
|
||||
title Spike Prototype
|
||||
body
|
||||
#spike_container
|
||||
#spike_content
|
||||
nav.navbar.navbar-default(style='margin-bottom:0px;')
|
||||
.container
|
||||
.navbar-header
|
||||
button.navbar-toggle.collapsed(type='button', data-toggle='collapse', data-target='#navbar', aria-expanded='false', aria-controls='navbar')
|
||||
span.sr-only Toggle navigation
|
||||
span.icon-bar
|
||||
span.icon-bar
|
||||
span.icon-bar
|
||||
a.navbar-brand(href='/') Spike
|
||||
#navbar.collapse.navbar-collapse
|
||||
ul.nav.navbar-nav.navbar-right
|
||||
li
|
||||
a(href='/') Spike
|
||||
.container
|
||||
block content
|
||||
#spike_footer
|
||||
.container Footer
|
||||
script(type='text/javascript').
|
||||
// Force `fetch` polyfill to workaround Chrome not displaying request body
|
||||
// in developer tools for the native `fetch`.
|
||||
self.fetch = null;
|
||||
script(src='http://localhost:3000/webpack-dev-server.js')
|
||||
script(src='/assets/style.js')
|
||||
script(src='/assets/app.js')
|
||||
Reference in New Issue
Block a user