mirror of
https://github.com/mgerb/mywebsite
synced 2026-01-10 09:52:51 +00:00
server set up with app engine
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,7 +1,6 @@
|
|||||||
\.c9
|
\.c9
|
||||||
\.DS_Store
|
\.DS_Store
|
||||||
config.json
|
config.json
|
||||||
mywebsite
|
|
||||||
mywebsite.exe
|
|
||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
|
public
|
||||||
|
|||||||
6
app.yaml
Normal file
6
app.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
runtime: go
|
||||||
|
api_version: go1
|
||||||
|
|
||||||
|
handlers:
|
||||||
|
- url: /.*
|
||||||
|
script: _go_app
|
||||||
@@ -11,13 +11,13 @@ function initPreview(posts){
|
|||||||
//in this case we can send the http request here rather in the react component
|
//in this case we can send the http request here rather in the react component
|
||||||
export function fetchPreview(){
|
export function fetchPreview(){
|
||||||
return (dispatch) => {
|
return (dispatch) => {
|
||||||
return fetch('/metadata.json')
|
return fetch('/public/metadata.json')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(json => {
|
.then(json => {
|
||||||
dispatch(initPreview(json));
|
dispatch(initPreview(json));
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
9
config.template.json
Normal file
9
config.template.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"database": {
|
||||||
|
"url": "",
|
||||||
|
"database": ""
|
||||||
|
},
|
||||||
|
"api": {
|
||||||
|
"key": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
36
index.html
36
index.html
@@ -1,21 +1,31 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<meta name="author" content="Mitchell Gerber">
|
<meta name="author" content="Mitchell Gerber">
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:300,400" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab:300,400" rel="stylesheet">
|
||||||
<title>mitchel.io</title>
|
<title>mitchel.io</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<script>
|
<script>
|
||||||
(function(i, s, o, g, r, a, m) {i['GoogleAnalyticsObject'] = r;i[r] = i[r] || function() {
|
(function(i, s, o, g, r, a, m) {
|
||||||
(i[r].q = i[r].q || []).push(arguments)}, i[r].l = 1 * new Date();
|
i['GoogleAnalyticsObject'] = r;
|
||||||
a = s.createElement(o),m = s.getElementsByTagName(o)[0];a.async = 1;a.src = g;m.parentNode.insertBefore(a, m)})
|
i[r] = i[r] || function() {
|
||||||
|
(i[r].q = i[r].q || []).push(arguments)
|
||||||
|
}, i[r].l = 1 * new Date();
|
||||||
|
a = s.createElement(o), m = s.getElementsByTagName(o)[0];
|
||||||
|
a.async = 1;
|
||||||
|
a.src = g;
|
||||||
|
m.parentNode.insertBefore(a, m)
|
||||||
|
})
|
||||||
(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
|
||||||
</script>
|
</script>
|
||||||
<!--it's happening!!!-->
|
<!--it's happening!!!-->
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
14
metadata.js
14
metadata.js
@@ -3,7 +3,7 @@
|
|||||||
folder/files within posts are scanned recursively
|
folder/files within posts are scanned recursively
|
||||||
each post is contained within category, which is supplied by the direct parent folder
|
each post is contained within category, which is supplied by the direct parent folder
|
||||||
Posts are sorted by date
|
Posts are sorted by date
|
||||||
Stores all metadata in ./dist/metadata.json
|
Stores all metadata in ./public/metadata.json
|
||||||
Client uses metadata to display posts on preview page
|
Client uses metadata to display posts on preview page
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -27,10 +27,10 @@ const json = {
|
|||||||
//do everything synchronously to keep posts ordered
|
//do everything synchronously to keep posts ordered
|
||||||
function parse_dir(dir, folder_name){
|
function parse_dir(dir, folder_name){
|
||||||
const posts = fs.readdirSync(dir);
|
const posts = fs.readdirSync(dir);
|
||||||
|
|
||||||
for(let post of posts){
|
for(let post of posts){
|
||||||
const stats = fs.statSync(dir + post);
|
const stats = fs.statSync(dir + post);
|
||||||
|
|
||||||
if(stats.isDirectory()){
|
if(stats.isDirectory()){
|
||||||
parse_dir(dir + post + '/', post);
|
parse_dir(dir + post + '/', post);
|
||||||
} else {
|
} else {
|
||||||
@@ -58,15 +58,15 @@ json.posts.sort((a, b) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
//output to public path
|
//output to public path
|
||||||
fs.writeFile('./dist/metadata.json', JSON.stringify(json,null,4), (err) => {
|
fs.writeFile('./public/metadata.json', JSON.stringify(json,null,4), (err) => {
|
||||||
if (err) throw err;
|
if (err) throw err;
|
||||||
console.log("Saved metadata.json");
|
console.log("Saved metadata.json");
|
||||||
})
|
})
|
||||||
|
|
||||||
//copy posts folder to dist
|
//copy posts folder to public
|
||||||
ncp('./posts', './dist/posts', (err) => {
|
ncp('./posts', './public/posts', (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
return console.error(err);
|
return console.error(err);
|
||||||
}
|
}
|
||||||
console.log('copied');
|
console.log('copied');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack && babel-node metadata.js",
|
"build": "webpack && babel-node metadata.js",
|
||||||
"c9": "webpack-dev-server --port $PORT --host $IP --hot --content-base dist --history-api-fallback",
|
"c9": "webpack-dev-server --port $PORT --host $IP --hot --content-base public --history-api-fallback",
|
||||||
"dev": "webpack-dev-server --content-base dist --inline --hot --history-api-fallback",
|
"dev": "webpack-dev-server --content-base public --inline --hot --history-api-fallback",
|
||||||
"prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js",
|
"prod": "export NODE_ENV=production && webpack -p && babel-node metadata.js",
|
||||||
"prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js",
|
"prod-win": "set NODE_ENV=production && webpack -p && babel-node metadata.js",
|
||||||
"deploy": "goapp deploy",
|
"deploy": "goapp deploy",
|
||||||
|
|||||||
12
readme.md
12
readme.md
@@ -6,4 +6,14 @@
|
|||||||
`npm run build` - builds the application using webpack and runs metadata.js
|
`npm run build` - builds the application using webpack and runs metadata.js
|
||||||
|
|
||||||
- metadata.js recursivly scans the posts folder for markdown files and then parses each into into a json object
|
- metadata.js recursivly scans the posts folder for markdown files and then parses each into into a json object
|
||||||
- the posts folder is then copied into the dist folder
|
- the posts folder is then copied into the dist folder
|
||||||
|
|
||||||
|
## TODO
|
||||||
|
- fix goapp serve and webpack-dev-server so paths work correctly
|
||||||
|
- posts page
|
||||||
|
- add sensor page
|
||||||
|
- finally do writeups on my projects
|
||||||
|
- clean go code up
|
||||||
|
- host on app engine (run mongodb on compute engine???)
|
||||||
|
- pull everything off digital ocean
|
||||||
|
- add paging
|
||||||
|
|||||||
23
server.go
Normal file
23
server.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"mywebsite/server/controller/api"
|
||||||
|
"mywebsite/server/db"
|
||||||
|
"mywebsite/server/route"
|
||||||
|
"mywebsite/server/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
configurations := utils.ReadConfig()
|
||||||
|
|
||||||
|
db.Configure(configurations.Database)
|
||||||
|
api.Configure(configurations.Api)
|
||||||
|
|
||||||
|
db.Mongo.Connect()
|
||||||
|
|
||||||
|
router := route.Routes()
|
||||||
|
|
||||||
|
http.Handle("/", router)
|
||||||
|
}
|
||||||
13
server/controller/api/config.go
Normal file
13
server/controller/api/config.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import ()
|
||||||
|
|
||||||
|
var Api ApiInfo
|
||||||
|
|
||||||
|
type ApiInfo struct {
|
||||||
|
Key string `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Configure(a ApiInfo) {
|
||||||
|
Api = a
|
||||||
|
}
|
||||||
211
server/controller/api/sensor.go
Normal file
211
server/controller/api/sensor.go
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mywebsite/server/model/daily_sensor"
|
||||||
|
"mywebsite/server/model/raw_sensor"
|
||||||
|
)
|
||||||
|
|
||||||
|
// handle http request from sensors
|
||||||
|
func HandleSensorRequest(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
//store data from sensor in raw_sensor collection
|
||||||
|
//**********************************************************************************
|
||||||
|
key := r.URL.Query().Get("key")
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
var message string
|
||||||
|
|
||||||
|
if key == Api.Key {
|
||||||
|
|
||||||
|
//get request parameters - convert temp to float64
|
||||||
|
temperature, _ := strconv.ParseFloat(r.URL.Query().Get("temperature"), 64)
|
||||||
|
location := r.URL.Query().Get("location")
|
||||||
|
t := time.Now()
|
||||||
|
|
||||||
|
store := raw_sensor.Data{"", temperature, location, t}
|
||||||
|
|
||||||
|
err := store.StoreData()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
message = "Failed to insert into database"
|
||||||
|
} else {
|
||||||
|
message = "Data inserted into database"
|
||||||
|
}
|
||||||
|
|
||||||
|
//compare current readings with dialy_sensor readings
|
||||||
|
//update daily_sensor readings if out of bounds
|
||||||
|
//**********************************************************************************
|
||||||
|
|
||||||
|
storedData, err := daily_sensor.GetDailySensorInfo(location)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
//store data if nothing exists for the day
|
||||||
|
if storedData.Location == "" {
|
||||||
|
|
||||||
|
storedData.ID = ""
|
||||||
|
storedData.Location = location
|
||||||
|
storedData.MaxTemp = temperature
|
||||||
|
storedData.MinTemp = temperature
|
||||||
|
storedData.Day = t.Day()
|
||||||
|
storedData.Month = int(t.Month())
|
||||||
|
storedData.MonthName = t.Month().String()
|
||||||
|
storedData.Year = t.Year()
|
||||||
|
|
||||||
|
err := storedData.StoreData()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
performUpdate := false
|
||||||
|
|
||||||
|
//check if values exceed max or min
|
||||||
|
if temperature > storedData.MaxTemp {
|
||||||
|
storedData.MaxTemp = temperature
|
||||||
|
performUpdate = true
|
||||||
|
}
|
||||||
|
if temperature < storedData.MinTemp {
|
||||||
|
storedData.MinTemp = temperature
|
||||||
|
performUpdate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
//store or update information if values have been changed
|
||||||
|
if performUpdate == true {
|
||||||
|
|
||||||
|
err := storedData.UpdateData()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message = "Incorrect api key"
|
||||||
|
}
|
||||||
|
|
||||||
|
//send response back
|
||||||
|
fmt.Fprint(w, "{ message : \""+message+"\"}")
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleAllSensors(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
s, err := raw_sensor.GetAllSensors()
|
||||||
|
|
||||||
|
var response string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
js, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
response = string(js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleSensorByLocation(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
location := ps.ByName("location")
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
s, err := daily_sensor.GetAllSensorInfo(location)
|
||||||
|
|
||||||
|
var response string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
js, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
response = string(js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleSensorByLocationYear(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
location := ps.ByName("location")
|
||||||
|
year, _ := strconv.Atoi(ps.ByName("year"))
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
s, err := daily_sensor.GetAllSensorInfoByYear(location, year)
|
||||||
|
|
||||||
|
var response string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
js, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
response = string(js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, response)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleSensorByLocationMonth(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
|
||||||
|
|
||||||
|
location := ps.ByName("location")
|
||||||
|
year, _ := strconv.Atoi(ps.ByName("year"))
|
||||||
|
monthname := ps.ByName("monthname")
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
|
s, err := daily_sensor.GetAllSensorInfoByMonth(location, year, monthname)
|
||||||
|
|
||||||
|
var response string
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
js, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
response = "{message : \"Error loading data from database\""
|
||||||
|
} else {
|
||||||
|
response = string(js)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(w, response)
|
||||||
|
}
|
||||||
22
server/controller/redirect.go
Normal file
22
server/controller/redirect.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// redirects for personal use
|
||||||
|
// Redirect to discord
|
||||||
|
func DiscordRedirect(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
http.Redirect(w, r, "https://discordapp.com/invite/0Z2tzxKECEj2BHwj", 301)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to discord
|
||||||
|
func VPNRedirect(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
http.Redirect(w, r, "https://mitchel.io:943", 301)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to security cameras
|
||||||
|
func CameraRedirect(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
|
||||||
|
http.Redirect(w, r, "http://24.118.44.161:8080/html/", 301)
|
||||||
|
}
|
||||||
54
server/db/db.go
Normal file
54
server/db/db.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package db
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/mgo.v2"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Mongo Driver
|
||||||
|
|
||||||
|
type Driver struct {
|
||||||
|
Session *mgo.Session
|
||||||
|
Info DatabaseInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type DatabaseInfo struct {
|
||||||
|
URL string `json:"url"`
|
||||||
|
Database string `json:"database"`
|
||||||
|
Username string `json:"username,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Configure(d DatabaseInfo) {
|
||||||
|
Mongo.Info = d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Connect() {
|
||||||
|
// Connect to MongoDB
|
||||||
|
s, err := mgo.DialWithTimeout(d.Info.URL, 5*time.Second)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("MongoDB Driver Error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Session = s
|
||||||
|
|
||||||
|
// Prevents these errors: read tcp 127.0.0.1:27017: i/o timeout
|
||||||
|
d.Session.SetSocketTimeout(10 * time.Second)
|
||||||
|
|
||||||
|
// Check if is alive
|
||||||
|
if err = d.Session.Ping(); err != nil {
|
||||||
|
log.Println("Database Error", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Println("Connected to database")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Driver) Connected() bool {
|
||||||
|
if d.Session != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
200
server/model/daily_sensor/daily_sensor.go
Normal file
200
server/model/daily_sensor/daily_sensor.go
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
package daily_sensor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mywebsite/server/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
collection = "daily_sensor"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Data struct {
|
||||||
|
ID bson.ObjectId `bson:"_id,omitempty"`
|
||||||
|
MaxTemp float64 `json:"maxtemp" bson:"maxtemp"`
|
||||||
|
MinTemp float64 `json:"mintemp" bson:"mintemp"`
|
||||||
|
Location string `json:"location" bson:"location"`
|
||||||
|
Month int `json:"month" bson:"month"`
|
||||||
|
MonthName string `json:"monthname" bson:"monthname"`
|
||||||
|
Day int `json:"day" bson:"day"`
|
||||||
|
Year int `json:"year" bson:"year"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert struct to json string
|
||||||
|
func (s *Data) toJson() string {
|
||||||
|
|
||||||
|
b, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Data) StoreData() error {
|
||||||
|
|
||||||
|
if db.Mongo.Connected() {
|
||||||
|
|
||||||
|
log.Println("Inserting data into " + collection)
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
// Insert Datas
|
||||||
|
err := c.Insert(s)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//function to update the daily temperature max or min for a location
|
||||||
|
func (s *Data) UpdateData() error {
|
||||||
|
|
||||||
|
if db.Mongo.Connected() {
|
||||||
|
|
||||||
|
log.Println("Updating data")
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
colQuerier := bson.M{"location": s.Location, "month": s.Month, "monthname": s.MonthName, "day": s.Day, "year": s.Year}
|
||||||
|
change := bson.M{"$set": bson.M{"maxtemp": s.MaxTemp, "mintemp": s.MinTemp}}
|
||||||
|
|
||||||
|
err := c.Update(colQuerier, change)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the current daily sensor reading to compare
|
||||||
|
//if the max or min temp needs to be updated
|
||||||
|
func GetDailySensorInfo(sensor_location string) (Data, error) {
|
||||||
|
|
||||||
|
d := Data{}
|
||||||
|
t := time.Now()
|
||||||
|
|
||||||
|
day := t.Day()
|
||||||
|
month := int(t.Month())
|
||||||
|
monthname := t.Month().String()
|
||||||
|
year := t.Year()
|
||||||
|
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
err := c.Find(bson.M{"location": sensor_location, "day": day, "month": month, "monthname": monthname, "year": year}).One(&d)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return d, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllSensorInfo(sensor_location string) ([]Data, error) {
|
||||||
|
d := []Data{}
|
||||||
|
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
//err := c.Find(bson.M{"location": sensor_location}).Sort("-year, -month").All(&d)
|
||||||
|
err := c.Pipe([]bson.M{{"$match": bson.M{"location": sensor_location}},
|
||||||
|
{"$sort": bson.M{"year": -1, "month": 1}}}).All(&d)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return d, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//return all daily temperature readings per year for a location
|
||||||
|
//sort by most recent year and oldest month
|
||||||
|
func GetAllSensorInfoByYear(sensor_location string, year int) ([]Data, error) {
|
||||||
|
d := []Data{}
|
||||||
|
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
err := c.Pipe([]bson.M{{"$match": bson.M{"location": sensor_location, "year": year}},
|
||||||
|
{"$sort": bson.M{"year": -1, "month": 1}}}).All(&d)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return d, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//return all temperature readings for a specific month and location
|
||||||
|
func GetAllSensorInfoByMonth(sensor_location string, year int, monthname string) ([]Data, error) {
|
||||||
|
d := []Data{}
|
||||||
|
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
err := c.Pipe([]bson.M{{"$match": bson.M{"location": sensor_location, "year": year, "monthname": monthname}},
|
||||||
|
{"$sort": bson.M{"year": -1, "month": 1}}}).All(&d)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return d, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return d, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return d, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
139
server/model/raw_sensor/raw_sensor.go
Normal file
139
server/model/raw_sensor/raw_sensor.go
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
package raw_sensor
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"gopkg.in/mgo.v2/bson"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"mywebsite/server/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
collection = "raw_sensor"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Data struct {
|
||||||
|
ID bson.ObjectId `bson:"_id,omitempty"`
|
||||||
|
Temperature float64 `json:"temperature" bson:"temperature"`
|
||||||
|
Location string `json:"location" bson:"location"`
|
||||||
|
Updated time.Time `json:"updated" bson:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//convert struct to json string
|
||||||
|
func (s *Data) toJson() string {
|
||||||
|
|
||||||
|
b, err := json.MarshalIndent(s, "", " ")
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err.Error)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Data) StoreData() error {
|
||||||
|
|
||||||
|
if db.Mongo.Connected() {
|
||||||
|
|
||||||
|
log.Println("Inserting data into " + collection)
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
// Insert Datas
|
||||||
|
err := c.Insert(s)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//handle queries for all sensors page
|
||||||
|
//********************************************************************************
|
||||||
|
type DataStore_AllSensors struct {
|
||||||
|
ID string `json:"location" bson:"_id"`
|
||||||
|
Temperature float64 `json:"temperature" bson:"temperature"`
|
||||||
|
Updated time.Time `json:"updated" bson:"updated"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllSensors() ([]DataStore_AllSensors, error) {
|
||||||
|
|
||||||
|
s := []DataStore_AllSensors{}
|
||||||
|
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
|
||||||
|
err := c.Pipe([]bson.M{{"$group": bson.M{"_id": "$location", "temperature": bson.M{"$last": "$temperature"},
|
||||||
|
"updated": bson.M{"$last": "$updated"}}},
|
||||||
|
bson.M{"$sort": bson.M{"_id": 1}}}).All(&s)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return s, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//********************************************************************************
|
||||||
|
|
||||||
|
//get sensor information by location
|
||||||
|
//********************************************************************************
|
||||||
|
type DataStore_SensorByLocation struct {
|
||||||
|
Id sensorByLocation `json:"_id" bson:"_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type sensorByLocation struct {
|
||||||
|
Year int `json:"year" bson:"year"`
|
||||||
|
Month int `json:"month" bson:"month"`
|
||||||
|
Location string `json:"location" bson:"location"`
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func GetSensorInfoByLocation(sensor_location string) ([]DataStore_SensorByLocation, error) {
|
||||||
|
s := []DataStore_SensorByLocation{}
|
||||||
|
if db.Mongo.Connected() == true {
|
||||||
|
session := db.Mongo.Session.Copy()
|
||||||
|
defer session.Close()
|
||||||
|
c := session.DB(db.Mongo.Info.Database).C(collection)
|
||||||
|
err := c.Pipe([]bson.M{{"$project": bson.M{"location": "$location", "year": bson.M{"$year": "$updated"}, "month": bson.M{"$month": "$updated"}}},
|
||||||
|
bson.M{"$match": bson.M{"location": sensor_location}},
|
||||||
|
bson.M{"$group": bson.M{"_id": bson.M{"year": "$year", "month": "$month", "location": "$location"}}},
|
||||||
|
bson.M{"$sort": bson.M{"_id.year": -1, "_id.month": -1}}}).All(&s)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
} else {
|
||||||
|
return s, errors.New("Query failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
//********************************************************************************
|
||||||
|
|
||||||
|
/*************************
|
||||||
|
testStore := model.SensorData{
|
||||||
|
ID: bson.NewObjectId(),
|
||||||
|
Temperature: 34.2,
|
||||||
|
Humidity: 33.22,
|
||||||
|
Location: "Grand Meadow",
|
||||||
|
Updated: time.Now(),
|
||||||
|
}
|
||||||
|
**************************/
|
||||||
54
server/route/route.go
Normal file
54
server/route/route.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package route
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/julienschmidt/httprouter"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"mywebsite/server/controller"
|
||||||
|
"mywebsite/server/controller/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Routes() *httprouter.Router {
|
||||||
|
|
||||||
|
log.Println("Server Started")
|
||||||
|
|
||||||
|
r := httprouter.New()
|
||||||
|
|
||||||
|
r.GET("/api/storedata", api.HandleSensorRequest)
|
||||||
|
r.GET("/api/allsensors", api.HandleAllSensors)
|
||||||
|
r.GET("/api/sensor/:location", api.HandleSensorByLocation)
|
||||||
|
r.GET("/api/sensor/:location/:year", api.HandleSensorByLocationYear)
|
||||||
|
r.GET("/api/sensor/:location/:year/:monthname", api.HandleSensorByLocationMonth)
|
||||||
|
|
||||||
|
r.GET("/discord", controller.DiscordRedirect)
|
||||||
|
r.GET("/vpn", controller.VPNRedirect)
|
||||||
|
r.GET("/camera", controller.CameraRedirect)
|
||||||
|
|
||||||
|
//set up public folder path
|
||||||
|
r.ServeFiles("/public/*filepath", http.Dir("./public/"))
|
||||||
|
|
||||||
|
//route every invalid request to template file
|
||||||
|
//routing is all handled on the client side with angular
|
||||||
|
r.NotFound = http.HandlerFunc(fileHandler("./public/index.html"))
|
||||||
|
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
//route requests to static files
|
||||||
|
func routerFileHandler(path string) httprouter.Handle {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
|
||||||
|
|
||||||
|
http.ServeFile(w, r, path)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//function to serve files with standard net/http library
|
||||||
|
func fileHandler(path string) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
|
http.ServeFile(w, r, path)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
44
server/utils/config.go
Normal file
44
server/utils/config.go
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"mywebsite/server/controller/api"
|
||||||
|
"mywebsite/server/db"
|
||||||
|
)
|
||||||
|
|
||||||
|
//structure for application configurations
|
||||||
|
type Config struct {
|
||||||
|
Database db.DatabaseInfo `json:"database"`
|
||||||
|
Api api.ApiInfo `json:"api"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//read the config file and return JsonObject struct
|
||||||
|
func ReadConfig() Config {
|
||||||
|
|
||||||
|
log.Println("Reading config file...")
|
||||||
|
|
||||||
|
file, e := ioutil.ReadFile("./config.json")
|
||||||
|
|
||||||
|
if e != nil {
|
||||||
|
log.Printf("File error: %v\n", e)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("%s\n", string(file))
|
||||||
|
|
||||||
|
//m := new(Dispatch)
|
||||||
|
//var m interface{}
|
||||||
|
var result Config
|
||||||
|
|
||||||
|
err := json.Unmarshal(file, &result)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
@@ -33,8 +33,8 @@ module.exports = {
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
output: {
|
output: {
|
||||||
path: __dirname + "/dist/",
|
path: __dirname + "/public/",
|
||||||
publicPath: "/dist/",
|
publicPath: "/public/",
|
||||||
filename: "client.min.js"
|
filename: "client.min.js"
|
||||||
},
|
},
|
||||||
plugins: debug ? [] : [
|
plugins: debug ? [] : [
|
||||||
@@ -48,6 +48,6 @@ module.exports = {
|
|||||||
template: 'index.html',
|
template: 'index.html',
|
||||||
inject: 'body',
|
inject: 'body',
|
||||||
hash: true
|
hash: true
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user