Browse Source

Alpha

master
sipp11 7 years ago
parent
commit
78a9924c63
  1. 4
      .gitignore
  2. 24
      helper.go
  3. 135
      html/home.html
  4. 79
      main.go
  5. 4
      model.go

4
.gitignore vendored

@ -0,0 +1,4 @@
.DS_Store
helper
my-iot

24
helper.go

@ -3,9 +3,32 @@ package main
import (
"github.com/aws/aws-sdk-go/aws"
d "github.com/aws/aws-sdk-go/service/dynamodb"
da "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
"github.com/aws/aws-sdk-go/service/dynamodb/expression"
)
// GetDevice is to get a device from id
func GetDevice(svc *d.DynamoDB, deviceID string) (Device, error) {
var device Device
input := &d.GetItemInput{
Key: map[string]*d.AttributeValue{
"device": {
S: aws.String(deviceID),
},
},
TableName: aws.String("iot-item"),
}
result, err := svc.GetItem(input)
if err != nil {
return device, err
}
err = da.UnmarshalMap(result.Item, &device)
if err != nil {
return device, err
}
return device, nil
}
// GetDevices is to get all devices we know
func GetDevices(svc *d.DynamoDB) (*d.ScanOutput, error) {
@ -31,6 +54,7 @@ func GetHistory(svc *d.DynamoDB, deviceID string, limit int64) (*d.QueryOutput,
qProj := expression.NamesList(
expression.Name("device"),
expression.Name("timestamp"),
expression.Name("info"),
expression.Name("data"))
qBuilder := expression.NewBuilder().WithKeyCondition(keyCond).WithProjection(qProj)

135
html/home.html

@ -27,17 +27,38 @@
<script src="http://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7/html5shiv.js"></script>
<![endif]-->
<style>
path {
stroke: rgb(237, 40, 1);
stroke-width: 2;
fill: none;
}
.dash {
padding: 1em;
font-size: 16px;
}
.dash-container {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
.graph {
position: relative;
width: 250px;
height: 50px;
}
.dash-one {
width: 250px;
text-align: center;
font-size: 1.2em;
font-size: 1em;
background: #33333322;
padding: 10px;
padding: 10px 0;
overflow: wrap;
}
.dash-one p {
font-size: 4em;
margin: 0em;
}
.dash-one h2 {
font-size: 1.1em;
margin: 2px 5px;
@ -47,20 +68,78 @@
<body>
<div id="layout" class="pure-g">
<div class="sidebar pure-u-1 pure-u-md-1-4">
<!-- <div class="sidebar pure-u-1 pure-u-md-1-4">
<ul class="device-list"></ul>
</div>
<div class="content pure-u-1 pure-u-md-3-4"></div>
</div> -->
<div id="content" class="pure-u-1"></div>
</div>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="https://d3js.org/d3.v4.js"></script>
<script>
function displayGraph(id, data, width, height, interpolation) {
//, animate, updateDelay, transitionDelay) {
var animate = true, updateDelay = 1000, transitionDelay = 1000;
// create an SVG element inside the #graph div that fills 100% of the div
var graph = d3.select(id).append("svg:svg");
// X scale will fit values from 0-10 within pixels 0-100
var x = d3.scaleLinear().domain([0, 152]).range([0, width]); // starting point is -5 so the first value doesn't show and slides off the edge as part of the transition
// Y scale will fit values from 0-10 within pixels 0-100
var y = d3.scaleLinear().domain([0, 80]).range([0, height]);
// create a line object that represents the SVN line we're creating
var line = d3.line()
// assign the X function to plot our line as we wish
.x(function (d, i) {
// verbose logging to show what's actually being done
//console.log('Plotting X value for data point: ' + d + ' using index: ' + i + ' to be at: ' + x(i) + ' using our xScale.');
// return the X coordinate where we want to plot this datapoint
return x(i);
})
.y(function (d) {
// verbose logging to show what's actually being done
//console.log('Plotting Y value for data point: ' + d + ' to be at: ' + y(d) + " using our yScale.");
// return the Y coordinate where we want to plot this datapoint
return y(d);
})
if (interpolation == "basis") {
line.curve(d3.curveCatmullRom.alpha(0.5))
}
// display the line by appending an svg:path element with the data line we created above
graph.append("svg:path").attr("d", line(data));
// or it can be done like this
//graph.selectAll("path").data([data]).enter().append("svg:path").attr("d", line);
function redrawWithAnimation() {
// update with animation
graph.selectAll("path")
.attr("transform", "translate(" + x(1) + ")") // set the transform to the right by x(1) pixels (6 for the scale we've set) to hide the new value
.data([data]) // set the new data
.attr("d", line) // apply the new data values ... but the new value is hidden at this point off the right of the canvas
.transition() // start a transition to bring the new value into view
.ease(d3.easeLinear)
.duration(transitionDelay * 0.95) // for this demo we want a continual slide so set this to the same as the setInterval amount below
.attr("transform", "translate(" + x(0) + ")"); // animate a slide to the left back to x(0) pixels to reveal the new value
/* thanks to 'barrym' for examples of transform: https://gist.github.com/1137131 */
}
function redrawWithoutAnimation() {
// static update without animation
graph.selectAll("path")
.data([data]) // set the new data
.attr("d", line); // apply the new data values
}
redrawWithoutAnimation();
}
(function () {
var baseUrl = 'http://localhost:8000',
var baseUrl = '',
allUrl = baseUrl + '/all',
$sidebar = $('.sidebar'),
$list = $sidebar.find('.device-list'),
$content = $('.content');
$content = $('#content');
var addToList = function(item) {
$list.append(
@ -70,19 +149,49 @@
var addEleToDashBoard = function(item) {
var data = item['data'];
var str = `<div class="pure-u-md-1-2 dash">` +
`<h1>${item['device']}</h1>` +
`<div class="pure-u-md-1-3 dash-one"><h2>Temp</h2>${data['temperature']}</div>` +
`<div class="pure-u-md-1-3 dash-one"><h2>Moisture</h2>${data['moisture']}</div>` +
var xid = item['device'].replace(/:/g, '_')
var str = `<div class="pure-u-md-1-2 dash" id="${xid}">` +
`<h1>${item['info']['name']}</h1>` +
`<div class="dash-container">` +
`<div class="dash-one temperature"><h2>Temp</h2><p>${data['temperature']}</p> <div class="graph" id="${xid}-temperature"></div></div>` +
`<div class="dash-one moisture"><h2>Moisture</h2><p>${data['moisture']}</p> <div class="graph" id="${xid}-moisture"></div></div>` +
`<div class="dash-one humidity"><h2>Humidity</h2><p>${data['humidity']}</p> <div class="graph" id="${xid}-humidity"></div></div>` +
`</div>` +
`</div>`;
$content.append(str);
};
var reloadListener = function() {
$('.dash').on('click', function () {
var that = $(this),
id = that.attr('id').replace(/_/g, ':'),
oneUrl = `${baseUrl}/id/${id}?limit=150`;
that.off('click');
$.getJSON(oneUrl, function(data, textStatus, xhr) {
var extra = (data[0]['info']['sensor'] === "dht11" ? "humidity" : "moisture");
var ks = ['temperature', extra];
for (var ik in ks) {
var key = ks[ik];
var ll = data.map(function(ele, i) {
return ele['data'][key]
});
var tid = `#${that.attr('id')}-${key}`;
displayGraph(tid, ll, 250, 50, "basic");
}
});
});
}
$.getJSON(allUrl, function(data, textStatus, xhr) {
for (var i=0; i<data.length; i++) {
addToList(data[i]);
addEleToDashBoard(data[i]);
var x = data[i];
addToList(x);
addEleToDashBoard(x);
var toHide = (x['info']['sensor'] === "dht11" ? 'moisture' : 'humidity');
$('#' + x['device'].replace(/:/g, '_')).find('.'+ toHide).hide();
}
reloadListener();
});
})(jQuery);
</script>

79
read_item.go → main.go

@ -1,10 +1,12 @@
// +build linux darwin
package main
import (
"encoding/json"
"fmt"
"net/http"
"os"
"strconv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
@ -23,7 +25,6 @@ var svc *dynamodb.DynamoDB
// func indexHandler(w http.ResponseWriter, r *http.Request) {
func indexHandler(c echo.Context) error {
// Execute the template per HTTP request
// err := tplHome.ExecuteWriter(pongo2.Context{"query": "dddd"}, w)
out, err := tplHome.Execute(pongo2.Context{"query": "dddd"})
if err != nil {
return err
@ -32,14 +33,7 @@ func indexHandler(c echo.Context) error {
}
func healthCheckHandler(c echo.Context) error {
// func healthCheckHandler(w http.ResponseWriter, r *http.Request) {
// A very simple health check.
// w.WriteHeader(http.StatusOK)
// w.Header().Set("Content-Type", "application/json")
// In the future we could report back on the status of our DB, or our cache
// (e.g. Redis) by performing a simple PING, and include them in the response.
// io.WriteString(w, `{"alive": true}`)
return c.JSON(http.StatusOK, `{"alive": true}`)
}
@ -54,40 +48,42 @@ func overallHandler(c echo.Context) error {
return err
}
data, _ := device.History(svc, 1)
one := data[0]
one.Info.Name = device.Name
one.Info.Model = device.Model
result = append(result, data[0])
}
// b, _ := json.Marshal(result)
return c.JSON(http.StatusOK, result)
}
// func oneDeviceHandler(w http.ResponseWriter, r *http.Request) {
func oneDeviceHandler(c echo.Context) error {
id := c.Param("id")
result, err := GetHistory(svc, id, 5)
// default limit is 5
limit, _ := strconv.ParseInt(c.QueryParam("limit"), 10, 64)
if limit == 0 {
limit = 5
}
device, err := GetDevice(svc, id)
if err != nil {
return c.String(http.StatusInternalServerError, "Error unmarshalling")
}
result, err := GetHistory(svc, id, limit)
var ev []Item
if err != nil {
// w.WriteHeader(http.StatusInternalServerError)
// w.Header().Set("Content-Type", "application/json")
// io.WriteString(w, fmt.Sprintf(`{"msg":"%+v"}`, err))
return c.String(http.StatusInternalServerError, "Error unmarshalling")
}
for _, i := range result.Items {
item := Item{}
err = dynamodbattribute.UnmarshalMap(i, &item)
item.Info.Name = device.Name
item.Info.Model = device.Model
if err != nil {
// w.WriteHeader(http.StatusInternalServerError)
// w.Header().Set("Content-Type", "application/json")
// io.WriteString(w, fmt.Sprintf(`{"msg":"%+v"}`, err))
return c.String(http.StatusInternalServerError, "Error unmarshalling")
}
ev = append(ev, item)
}
// w.WriteHeader(http.StatusOK)
// w.Header().Set("Content-Type", "application/json")
b, _ := json.Marshal(ev)
// io.WriteString(w, string(b))
return c.JSON(http.StatusOK, b)
return c.JSON(http.StatusOK, ev)
}
func main() {
@ -105,41 +101,6 @@ func main() {
// Create DynamoDB client
svc = dynamodb.New(sess)
// func main() {
// session, err := r.Connect(r.ConnectOpts{
// Address: "localhost:28015",
// Database: "rtcom",
// })
// if err != nil {
// log.Panic(err.Error())
// }
// router := NewRouter()
// router.Handle("channel add", addChannel)
// router.Handle("channel subscribe", subscribeChannel)
// http.Handle("/", router)
// http.ListenAndServe(":4000", nil)
// r := mux.NewRouter()
// // r := http.NewServeMux()
// // r.HandleFunc("/", HomeHandler)
// // r.HandleFunc("/products", ProductsHandler)
// // r.HandleFunc("/articles/{id}", handler).Methods("GET", "PUT")
// // r.HandleFunc("/authors", handler).Queries("surname", "{surname}")
// r.HandleFunc("/health", healthCheckHandler)
// r.HandleFunc("/id/{id}", oneDeviceHandler)
// r.HandleFunc("/all", overallHandler)
// r.HandleFunc("/", indexHandler)
// log.Fatal(http.ListenAndServe(":8000",
// handlers.CORS(
// handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}),
// handlers.AllowedMethods([]string{"GET", "POST", "PUT", "HEAD", "OPTIONS"}),
// handlers.AllowedOrigins([]string{"*"}),
// handlers.IgnoreOptions(),
// )(r)),
// )
e := echo.New()
e.Use(middleware.Logger())
e.Use(middleware.Recover())
@ -153,5 +114,5 @@ func main() {
e.GET("/id/:id", oneDeviceHandler)
e.GET("/all", overallHandler)
e.GET("/", indexHandler)
e.Logger.Fatal(e.Start(":8000"))
e.Logger.Fatal(e.Start(":31101"))
}

4
model.go

@ -9,6 +9,7 @@ import (
type Device struct {
Device string `json:"device"`
Name string `json:"name"`
Model string `json:"model"`
}
// ItemInfo - create structs to hold info about new item
@ -16,6 +17,7 @@ type ItemInfo struct {
Firmware string `json:"firmware"`
Sensor string `json:"sensor"`
Model string `json:"model"`
Name string `json:"name"`
}
// SensorData to store all sensor's data
@ -46,6 +48,8 @@ func (d Device) History(svc *dynamodb.DynamoDB, limit int64) ([]Item, error) {
for _, i := range result.Items {
item := Item{}
err = dynamodbattribute.UnmarshalMap(i, &item)
item.Info.Name = d.Name
item.Info.Model = d.Model
if err != nil {
return ev, err
}

Loading…
Cancel
Save