house, power, energy data generators, savers
This commit is contained in:
@@ -1,4 +0,0 @@
|
|||||||
var getbabelRelayPlugin = require('babel-relay-plugin'),
|
|
||||||
schema = require('../config/graphql/schema.json');
|
|
||||||
|
|
||||||
module.exports = getbabelRelayPlugin(schema.data, {abortOnError: true});
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
1,Johnson
|
|
||||||
2,Beverley
|
|
||||||
3,Thompson
|
|
||||||
|
89283
data/power_data.csv
89283
data/power_data.csv
File diff suppressed because it is too large
Load Diff
@@ -1,5 +0,0 @@
|
|||||||
tom,1
|
|
||||||
fred,1
|
|
||||||
bethany,2
|
|
||||||
sally,3
|
|
||||||
saray,2
|
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
import gulp from 'gulp';
|
import gulp from 'gulp';
|
||||||
import yargs from 'yargs';
|
import yargs from 'yargs';
|
||||||
|
|
||||||
import DB from './config/database';
|
import DB from './server/config/database';
|
||||||
import {PowerDataSeed, HouseSeed, UserSeed} from './lib/tasks/seed_data';
|
import {PowerDataSeed, HouseSeed} from './server/lib/tasks/seed_data';
|
||||||
import updateSchema from './lib/tasks/update_schema';
|
|
||||||
|
|
||||||
gulp.task('generate_power_csv', function(done){
|
gulp.task('generate_power_csv', function(done){
|
||||||
DB.sync().then(()=>{
|
DB.sync().then(()=>{
|
||||||
@@ -22,9 +21,3 @@ gulp.task('save_house_csv', function(done){
|
|||||||
HouseSeed.saveCsv(yargs.argv, done);
|
HouseSeed.saveCsv(yargs.argv, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('save_user_csv', function(done){
|
|
||||||
DB.sync().then(()=>{
|
|
||||||
UserSeed.saveCsv(yargs.argv, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,28 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import Relay from 'react-relay';
|
|
||||||
|
|
||||||
class App extends React.Component {
|
|
||||||
render() {
|
|
||||||
var viewer = this.props.viewer,
|
|
||||||
house = viewer.house;
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Hi, {viewer.username}</h1>
|
|
||||||
<p>You are living in the {house.name} house!!!!</p>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Relay.createContainer(App, {
|
|
||||||
fragments: {
|
|
||||||
viewer: () => Relay.QL`
|
|
||||||
fragment on User {
|
|
||||||
username
|
|
||||||
house {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import Relay from 'react-relay';
|
|
||||||
|
|
||||||
export default class extends Relay.Route {
|
|
||||||
static queries = {
|
|
||||||
viewer: () => Relay.QL`
|
|
||||||
query {
|
|
||||||
viewer
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
};
|
|
||||||
static routeName = 'AppHomeRoute';
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
import fs from 'fs';
|
|
||||||
import path from 'path';
|
|
||||||
import { graphql, GraphQLSchema } from 'graphql';
|
|
||||||
import { introspectionQuery, printSchema } from 'graphql/utilities';
|
|
||||||
|
|
||||||
import DB from './../../config/database';
|
|
||||||
import schema from './../../config/graphql/schema';
|
|
||||||
|
|
||||||
DB.sync().then(()=>{
|
|
||||||
|
|
||||||
var Schema = schema();
|
|
||||||
|
|
||||||
// Save JSON of full schema introspection for Babel Relay Plugin to use
|
|
||||||
(async () => {
|
|
||||||
var result = await (graphql(Schema, introspectionQuery));
|
|
||||||
if (result.errors) {
|
|
||||||
console.error(
|
|
||||||
'ERROR introspecting schema: ',
|
|
||||||
JSON.stringify(result.errors, null, 2)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(__dirname, './../../config/graphql/schema.json'),
|
|
||||||
JSON.stringify(result, null, 2)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
// Save user readable type system shorthand of schema
|
|
||||||
fs.writeFileSync(
|
|
||||||
path.join(__dirname, './../../config/graphql/schema.graphql'),
|
|
||||||
printSchema(Schema)
|
|
||||||
);
|
|
||||||
|
|
||||||
});
|
|
||||||
100
models/house.js
100
models/house.js
@@ -1,100 +0,0 @@
|
|||||||
import {
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLObjectType,
|
|
||||||
GraphQLInt,
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLList
|
|
||||||
} from 'graphql';
|
|
||||||
|
|
||||||
import {
|
|
||||||
globalIdField,
|
|
||||||
connectionDefinitions,
|
|
||||||
connectionArgs
|
|
||||||
} from 'graphql-relay';
|
|
||||||
|
|
||||||
import extend from 'extend';
|
|
||||||
import DB from "./../config/database";
|
|
||||||
import {nodeInterface} from './../config/graphql/node';
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
name: DB.Sequelize.STRING
|
|
||||||
}, {
|
|
||||||
paranoid: true,
|
|
||||||
underscored: true,
|
|
||||||
tableName: "houses",
|
|
||||||
instanceMethods: {
|
|
||||||
|
|
||||||
},
|
|
||||||
classMethods: {
|
|
||||||
set: ()=>{
|
|
||||||
House.associate();
|
|
||||||
House.defineGraphQLType();
|
|
||||||
},
|
|
||||||
associate: ()=>{
|
|
||||||
House.hasMany(DB.PowerDatum, {as: 'PowerData'});
|
|
||||||
House.hasMany(DB.User, {as: 'Habitants'});
|
|
||||||
},
|
|
||||||
defineGraphQLType: ()=>{
|
|
||||||
House.graphql_type = new GraphQLObjectType({
|
|
||||||
name: NAME,
|
|
||||||
description: 'A house',
|
|
||||||
fields: () => {
|
|
||||||
return {
|
|
||||||
id: globalIdField(NAME),
|
|
||||||
name: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
power_data: {
|
|
||||||
type: new GraphQLList(DB.PowerDatum.graphql_type),
|
|
||||||
description: "Returns house's power data.",
|
|
||||||
args: connectionArgs,
|
|
||||||
resolve: (house, args) => {
|
|
||||||
return house.getPowerDataByTime(args);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
habitants: {
|
|
||||||
type: new GraphQLList(DB.User.graphql_type),
|
|
||||||
description: "Returns list of house's habitants.",
|
|
||||||
args: connectionArgs,
|
|
||||||
resolve: (house, args) => {
|
|
||||||
var params = extend({
|
|
||||||
order: 'name ASC',
|
|
||||||
limit: 50,
|
|
||||||
offset: 0,
|
|
||||||
}, args);
|
|
||||||
delete params.where; // don't allow any additional query params.
|
|
||||||
return house.getHabitants(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
interfaces: [nodeInterface]
|
|
||||||
});
|
|
||||||
},
|
|
||||||
getPowerDataByTime: (start_date, end_date, page)=>{
|
|
||||||
var params = extend({
|
|
||||||
order: 'time ASC',
|
|
||||||
limit: 500
|
|
||||||
}, args.page);
|
|
||||||
params.where = {time: {}};
|
|
||||||
if (start_date) params.where.time.$gt = moment.utc(start_date).toDate();
|
|
||||||
if (end_date) params.where.time.$lt = moment.utc(end_date).toDate();
|
|
||||||
|
|
||||||
return House.getPowerData(params);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
House.name = NAME;
|
|
||||||
module.exports = House;
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
import {
|
|
||||||
GraphQLFloat,
|
|
||||||
GraphQLInt,
|
|
||||||
GraphQLObjectType
|
|
||||||
} from 'graphql';
|
|
||||||
|
|
||||||
import {
|
|
||||||
globalIdField
|
|
||||||
} from 'graphql-relay';
|
|
||||||
|
|
||||||
import DB from "./../config/database";
|
|
||||||
import {nodeInterface} from './../config/graphql/node';
|
|
||||||
|
|
||||||
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: DB.Sequelize.DATE,
|
|
||||||
power: DB.Sequelize.FLOAT
|
|
||||||
}, {
|
|
||||||
paranoid: true,
|
|
||||||
underscored: true,
|
|
||||||
tableName: "power_data",
|
|
||||||
instanceMethods: {
|
|
||||||
|
|
||||||
},
|
|
||||||
classMethods: {
|
|
||||||
set: ()=>{
|
|
||||||
PowerDatum.associate();
|
|
||||||
PowerDatum.defineGraphQLType();
|
|
||||||
},
|
|
||||||
associate: ()=>{
|
|
||||||
PowerDatum.belongsTo(DB.House);
|
|
||||||
},
|
|
||||||
defineGraphQLType: ()=>{
|
|
||||||
PowerDatum.graphql_type = new GraphQLObjectType({
|
|
||||||
name: NAME,
|
|
||||||
description: 'A person who uses our app',
|
|
||||||
fields: () => ({
|
|
||||||
id: globalIdField(NAME),
|
|
||||||
power: {
|
|
||||||
type: GraphQLFloat,
|
|
||||||
},
|
|
||||||
time: {
|
|
||||||
type: GraphQLInt,
|
|
||||||
description: "Time the power was recorded.",
|
|
||||||
resolve: (power_datum, _) => {
|
|
||||||
return power_datum.time.getTime();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
interfaces: [nodeInterface]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
PowerDatum.name = NAME;
|
|
||||||
module.exports = PowerDatum;
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import {
|
|
||||||
GraphQLString,
|
|
||||||
GraphQLNonNull,
|
|
||||||
GraphQLObjectType
|
|
||||||
} from 'graphql';
|
|
||||||
|
|
||||||
import {
|
|
||||||
globalIdField,
|
|
||||||
connectionDefinitions,
|
|
||||||
connectionArgs
|
|
||||||
} from 'graphql-relay';
|
|
||||||
|
|
||||||
import DB from "./../config/database";
|
|
||||||
import {nodeInterface} from './../config/graphql/node';
|
|
||||||
|
|
||||||
const NAME = 'User';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sequelize Definition
|
|
||||||
*/
|
|
||||||
|
|
||||||
var User = DB.sequelize.define(NAME, {
|
|
||||||
id: {
|
|
||||||
type: DB.Sequelize.INTEGER,
|
|
||||||
primaryKey: true,
|
|
||||||
autoIncrement: true // Automatically gets converted to SERIAL for postgres
|
|
||||||
},
|
|
||||||
username: {
|
|
||||||
type: DB.Sequelize.STRING,
|
|
||||||
unique: true
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
paranoid: true,
|
|
||||||
underscored: true,
|
|
||||||
tableName: "users",
|
|
||||||
instanceMethods: {
|
|
||||||
|
|
||||||
},
|
|
||||||
classMethods: {
|
|
||||||
set: ()=>{
|
|
||||||
User.associate();
|
|
||||||
User.defineGraqhQLType()
|
|
||||||
},
|
|
||||||
associate: ()=>{
|
|
||||||
User.belongsTo(DB.House);
|
|
||||||
},
|
|
||||||
defineGraqhQLType: ()=>{
|
|
||||||
User.graphql_type = new GraphQLObjectType({
|
|
||||||
name: NAME,
|
|
||||||
description: 'A house',
|
|
||||||
fields: () => {
|
|
||||||
return {
|
|
||||||
id: globalIdField(NAME),
|
|
||||||
username: {
|
|
||||||
type: new GraphQLNonNull(GraphQLString)
|
|
||||||
},
|
|
||||||
house: {
|
|
||||||
type: DB.House.graphql_type,
|
|
||||||
description: "Returns user's house.",
|
|
||||||
resolve: (user, args) => {
|
|
||||||
return user.getHouse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
interfaces: [nodeInterface]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
User.name = NAME;
|
|
||||||
module.exports = User;
|
|
||||||
16
package.json
16
package.json
@@ -3,8 +3,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "babel-node ./app.express.js",
|
"start": "babel-node ./app.express.js"
|
||||||
"update-schema": "babel-node ./lib/tasks/update_schema.js"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "~1.12.0",
|
"body-parser": "~1.12.0",
|
||||||
@@ -26,21 +25,15 @@
|
|||||||
"babel-preset-es2015": "6.3.13",
|
"babel-preset-es2015": "6.3.13",
|
||||||
"babel-preset-react": "6.3.13",
|
"babel-preset-react": "6.3.13",
|
||||||
"babel-preset-stage-0": "6.3.13",
|
"babel-preset-stage-0": "6.3.13",
|
||||||
"babel-relay-plugin": "0.6.0",
|
|
||||||
"babel-core": "6.3.21",
|
"babel-core": "6.3.21",
|
||||||
"babel-loader": "6.2.0",
|
"babel-loader": "6.2.0",
|
||||||
"babel-polyfill": "6.3.14",
|
"babel-polyfill": "6.3.14",
|
||||||
"babel-preset-es2015": "6.3.13",
|
"babel-preset-es2015": "6.3.13",
|
||||||
"babel-preset-react": "6.3.13",
|
"babel-preset-react": "6.3.13",
|
||||||
"babel-preset-stage-0": "6.3.13",
|
"babel-preset-stage-0": "6.3.13",
|
||||||
"babel-relay-plugin": "0.6.0",
|
|
||||||
"express": "4.13.3",
|
"express": "4.13.3",
|
||||||
"express-graphql": "0.4.5",
|
|
||||||
"graphql": "0.4.14",
|
|
||||||
"graphql-relay": "0.3.6",
|
|
||||||
"react": "0.14.3",
|
"react": "0.14.3",
|
||||||
"react-dom": "0.14.3",
|
"react-dom": "0.14.3",
|
||||||
"react-relay": "0.6.0",
|
|
||||||
"webpack": "1.12.9",
|
"webpack": "1.12.9",
|
||||||
"webpack-dev-server": "1.14.0",
|
"webpack-dev-server": "1.14.0",
|
||||||
"jquery": "2.2.0",
|
"jquery": "2.2.0",
|
||||||
@@ -51,13 +44,14 @@
|
|||||||
"style-loader": "^0.12.3",
|
"style-loader": "^0.12.3",
|
||||||
"connect-assets":"~4.7.0",
|
"connect-assets":"~4.7.0",
|
||||||
"node-sass": "3.4.2",
|
"node-sass": "3.4.2",
|
||||||
"moment": "2.11.1",
|
"moment-timezone":"0.5.0",
|
||||||
"yargs": "3.32.0",
|
"yargs": "3.32.0",
|
||||||
"extend": "3.0.0"
|
"extend": "3.0.0"
|
||||||
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"gulp": "^3.9.0",
|
"gulp": "^3.9.0",
|
||||||
"babel-cli": "^6.3.17"
|
"babel-cli": "^6.3.17",
|
||||||
|
"babel-standalone": "6.4.4",
|
||||||
|
"react-templates": "0.4.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,19 +14,10 @@ import DB from './config/database';
|
|||||||
const APP_PORT = 3000;
|
const APP_PORT = 3000;
|
||||||
const GRAPHQL_PORT = 8080;
|
const GRAPHQL_PORT = 8080;
|
||||||
|
|
||||||
var graphql_server = express();
|
var rest_api = express();
|
||||||
|
|
||||||
DB.sync().then(()=>{
|
DB.sync().then(()=>{
|
||||||
console.log("db done syncing")
|
rest_api
|
||||||
// Expose a GraphQL endpoint
|
|
||||||
graphql_server.use('/', graphQLHTTP({
|
|
||||||
graphiql: true,
|
|
||||||
pretty: true,
|
|
||||||
schema: schema(),
|
|
||||||
}));
|
|
||||||
graphql_server.listen(GRAPHQL_PORT, () => console.log(
|
|
||||||
`GraphQL Server is now running on http://localhost:${GRAPHQL_PORT}`
|
|
||||||
));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import Sequelize from 'sequelize';
|
import Sequelize from 'sequelize';
|
||||||
|
|
||||||
var sequelize = new Sequelize("postgres://spikeuser:123456@localhost:5432/spike_proto", {
|
var sequelize = new Sequelize("postgres://spikeuser:123456@localhost:5432/spike2", {
|
||||||
pool: {
|
pool: {
|
||||||
max: 5,
|
max: 5,
|
||||||
min: 0,
|
min: 0,
|
||||||
13
server/controllers/energy_controller.js
Normal file
13
server/controllers/energy_controller.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import DB from './../config/database.js';
|
||||||
|
|
||||||
|
class EnergyController{
|
||||||
|
|
||||||
|
static index(req, res){
|
||||||
|
DB.House.findOne({where: {name: req.housename}}).then((house)=>{
|
||||||
|
house.getEnergyDataByTime(req.params.start_time, req.params.end_time).then((energy_data){
|
||||||
|
req.json(energy_data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
11
server/controllers/houses_controller.js
Normal file
11
server/controllers/houses_controller.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import DB from './../config/database.js';
|
||||||
|
|
||||||
|
class HousesController{
|
||||||
|
|
||||||
|
static index(req, res){
|
||||||
|
DB.House.findAll({attributes: ['id', 'name']}).then((houses){
|
||||||
|
res.json(houses);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
13
server/controllers/power_controller.js
Normal file
13
server/controllers/power_controller.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import DB from './../config/database.js';
|
||||||
|
|
||||||
|
class PowerController{
|
||||||
|
|
||||||
|
static index(req, res){
|
||||||
|
DB.House.findOne({where: {name: req.housename}}).then((house)=>{
|
||||||
|
house.getPowerDataByTime(req.params.start_time, req.params.end_time).then((power_data){
|
||||||
|
res.json(power_data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,21 +2,23 @@ import extend from "extend";
|
|||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import csv from "fast-csv";
|
import csv from "fast-csv";
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import MathUtils from "./../utils/math"
|
import MathUtils from "./../../../shared/utils/math"
|
||||||
import DB from './../../config/database';
|
import DB from './../../config/database';
|
||||||
|
|
||||||
|
const DATA_PATH = __dirname + '/../../../shared/data/'
|
||||||
|
|
||||||
export class PowerDataSeed {
|
export class PowerDataSeed {
|
||||||
|
|
||||||
static saveCsv(opts, done){
|
static saveCsv(opts, done){
|
||||||
opts = extend({
|
opts = extend({
|
||||||
path: __dirname + "/../../data/power_data.csv"
|
path: DATA_PATH + "power_data.csv"
|
||||||
}, opts || {});
|
}, opts || {});
|
||||||
var stream = fs.createReadStream(opts.path),
|
var stream = fs.createReadStream(opts.path),
|
||||||
csvStream = csv.fromStream(stream, {headers: ['house_id', 'time', 'power']}),
|
csvStream = csv.fromStream(stream, {headers: ['house_id', 'time', 'consumption', 'production']}),
|
||||||
rows = [];
|
rows = [];
|
||||||
|
|
||||||
csvStream.on("data", function(data){
|
csvStream.on("data", function(data){
|
||||||
data.time = moment.utc(parseInt(data.time)).format();
|
data.time = moment.utc(parseInt(data.time * 1000)).format();
|
||||||
rows.push(data);
|
rows.push(data);
|
||||||
if (rows.length % 100 === 0){
|
if (rows.length % 100 === 0){
|
||||||
DB.PowerDatum.bulkCreate(rows, {validate: true}).then(()=>{
|
DB.PowerDatum.bulkCreate(rows, {validate: true}).then(()=>{
|
||||||
@@ -25,9 +27,20 @@ export class PowerDataSeed {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
csvStream.on("end", function(){
|
csvStream.on("end", function(){
|
||||||
|
console.log("all rows parsed")
|
||||||
DB.PowerDatum.bulkCreate(rows, {validate: true}).then(()=>{
|
DB.PowerDatum.bulkCreate(rows, {validate: true}).then(()=>{
|
||||||
|
return DB.House.findAll().then((houses)=>{
|
||||||
|
var promise = Promise.resolve();
|
||||||
|
|
||||||
|
for (var house of houses){
|
||||||
|
promise = promise.then(()=>{
|
||||||
|
return house.aggregatePowerToEnergyData();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return promise;
|
||||||
|
});
|
||||||
|
}).then(()=>{
|
||||||
console.log("DONE!")
|
console.log("DONE!")
|
||||||
done();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -36,9 +49,9 @@ export class PowerDataSeed {
|
|||||||
opts = extend({
|
opts = extend({
|
||||||
start_date: moment().subtract(2, "months").unix(),
|
start_date: moment().subtract(2, "months").unix(),
|
||||||
end_date: moment().unix(),
|
end_date: moment().unix(),
|
||||||
interval: 180, // every 3 minutes (in s)
|
interval: 900, // every 15 minutes (in s)
|
||||||
average: 1400, // Wh
|
average: 1400, // Wh
|
||||||
path: __dirname + "/../../data/power_data.csv"
|
path: DATA_PATH + "power_data.csv"
|
||||||
}, opts || {});
|
}, opts || {});
|
||||||
|
|
||||||
var row_date = opts.start_date,
|
var row_date = opts.start_date,
|
||||||
@@ -46,29 +59,34 @@ export class PowerDataSeed {
|
|||||||
writableStream = fs.createWriteStream(opts.path),
|
writableStream = fs.createWriteStream(opts.path),
|
||||||
house_ids = opts.house_ids.split(",")
|
house_ids = opts.house_ids.split(",")
|
||||||
|
|
||||||
csvStream.pipe(writableStream);
|
DB.House.findAll({where: {id: house_ids}}).then((houses)=>{
|
||||||
writableStream.on("finish", ()=>{
|
|
||||||
console.log("DONE!")
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
while (row_date <= opts.end_date){
|
csvStream.pipe(writableStream);
|
||||||
for (var house_id of house_ids){
|
writableStream.on("finish", ()=>{
|
||||||
csvStream.write([house_id, row_date, MathUtils.normal(opts.average)]);
|
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;
|
||||||
}
|
}
|
||||||
row_date += opts.interval;
|
csvStream.end();
|
||||||
}
|
});
|
||||||
csvStream.end();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class HouseSeed {
|
export class HouseSeed {
|
||||||
static saveCsv(opts, done){
|
static saveCsv(opts, done){
|
||||||
opts = extend({
|
opts = extend({
|
||||||
path: __dirname + "/../../data/houses.csv"
|
path: DATA_PATH + "houses.csv"
|
||||||
}, opts || {});
|
}, opts || {});
|
||||||
var stream = fs.createReadStream(opts.path),
|
var stream = fs.createReadStream(opts.path),
|
||||||
csvStream = csv.fromStream(stream, {headers: ['id', 'name']}),
|
csvStream = csv.fromStream(stream, {headers: ['id', 'name', 'timezone']}),
|
||||||
rows = [];
|
rows = [];
|
||||||
|
|
||||||
csvStream.on("data", function(data){
|
csvStream.on("data", function(data){
|
||||||
@@ -84,26 +102,3 @@ export class HouseSeed {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UserSeed {
|
|
||||||
static saveCsv(opts, done){
|
|
||||||
opts = extend({
|
|
||||||
path: __dirname + "/../../data/users.csv"
|
|
||||||
}, opts || {});
|
|
||||||
var stream = fs.createReadStream(opts.path),
|
|
||||||
csvStream = csv.fromStream(stream, {headers: ['username', 'house_id']}),
|
|
||||||
rows = [];
|
|
||||||
|
|
||||||
csvStream.on("data", function(data){
|
|
||||||
console.log(JSON.stringify(data))
|
|
||||||
rows.push(data);
|
|
||||||
});
|
|
||||||
csvStream.on("end", function(){
|
|
||||||
console.log(rows);
|
|
||||||
DB.User.bulkCreate(rows, {validate: true}).then(()=>{
|
|
||||||
console.log("DONE!")
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
server/models/energy_datum.js
Normal file
36
server/models/energy_datum.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import DB from "./../config/database";
|
||||||
|
|
||||||
|
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: DB.Sequelize.DATEONLY,
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
EnergyDatum.name = NAME;
|
||||||
|
module.exports = EnergyDatum;
|
||||||
80
server/models/house.js
Normal file
80
server/models/house.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
import moment from 'moment-timezone';
|
||||||
|
import DB from "./../config/database";
|
||||||
|
import {nodeInterface} from './../config/graphql/node';
|
||||||
|
|
||||||
|
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
|
||||||
|
}, {
|
||||||
|
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;
|
||||||
|
},
|
||||||
|
timeToDateString: function(timestamp){
|
||||||
|
var house = this;
|
||||||
|
return moment.tz(timestamp, house.timezone).format("YYYY-MM-DD");
|
||||||
|
},
|
||||||
|
aggregatePowerToEnergyData: function(){
|
||||||
|
var house = this;
|
||||||
|
return DB.EnergyDatum.destroy({where: {house_id: house.id}})
|
||||||
|
.then(()=>{
|
||||||
|
return house.getPowerData();
|
||||||
|
})
|
||||||
|
.then((power_data)=>{
|
||||||
|
var energy_data = new Map();
|
||||||
|
power_data.forEach((power_datum)=>{
|
||||||
|
var day = house.timeToDateString(power_datum.time),
|
||||||
|
energy_datum = energy_data.get(day) || {production: 0, consumption: 0, day: day, house_id: house.id};
|
||||||
|
console.log(power_datum.time)
|
||||||
|
console.log(day)
|
||||||
|
energy_datum.production += power_datum.production;
|
||||||
|
energy_datum.consumption += power_datum.consumption;
|
||||||
|
energy_data.set(day, energy_datum);
|
||||||
|
});
|
||||||
|
console.log(Array.from(energy_data.values()))
|
||||||
|
return DB.EnergyDatum.bulkCreate(Array.from(energy_data.values()), {validate: true});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
classMethods: {
|
||||||
|
set: ()=>{
|
||||||
|
House.associate();
|
||||||
|
},
|
||||||
|
associate: ()=>{
|
||||||
|
House.hasMany(DB.PowerDatum, {as: 'PowerData'});
|
||||||
|
},
|
||||||
|
getPowerDataByTime: (start_date, end_date)=>{
|
||||||
|
var params = {
|
||||||
|
where: {time: {}},
|
||||||
|
attributes: ['time', 'consumption', 'production']
|
||||||
|
};
|
||||||
|
if (start_date) params.where.time.$gt = moment.utc(start_date).toDate();
|
||||||
|
if (end_date) params.where.time.$lt = moment.utc(end_date).toDate();
|
||||||
|
|
||||||
|
return House.getPowerData(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
House.name = NAME;
|
||||||
|
module.exports = House;
|
||||||
36
server/models/power_datum.js
Normal file
36
server/models/power_datum.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import DB from "./../config/database";
|
||||||
|
|
||||||
|
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: DB.Sequelize.DATE,
|
||||||
|
consumption: DB.Sequelize.FLOAT,
|
||||||
|
production: DB.Sequelize.FLOAT
|
||||||
|
}, {
|
||||||
|
paranoid: true,
|
||||||
|
underscored: true,
|
||||||
|
tableName: "power_data",
|
||||||
|
instanceMethods: {
|
||||||
|
|
||||||
|
},
|
||||||
|
classMethods: {
|
||||||
|
set: ()=>{
|
||||||
|
PowerDatum.associate();
|
||||||
|
},
|
||||||
|
associate: ()=>{
|
||||||
|
PowerDatum.belongsTo(DB.House);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
PowerDatum.name = NAME;
|
||||||
|
module.exports = PowerDatum;
|
||||||
9
server/routes.js
Normal file
9
server/routes.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import Controllers from 'controllers'
|
||||||
|
|
||||||
|
export default function(app){
|
||||||
|
|
||||||
|
app.use('/data/v1/savings/:housename', Controllers.Energy.savings);
|
||||||
|
app.use('/data/v1/production/:housename', Controllers.Energy.production);
|
||||||
|
app.use('/data/v1/houses/:housename');
|
||||||
|
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user