diff --git a/helper.go b/helper.go index a910758..dadac0e 100644 --- a/helper.go +++ b/helper.go @@ -2,12 +2,12 @@ package main import ( "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/dynamodb" + d "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/expression" ) // GetDevices is to get all devices we know -func GetDevices(svc *dynamodb.DynamoDB) (*dynamodb.ScanOutput, error) { +func GetDevices(svc *d.DynamoDB) (*d.ScanOutput, error) { proj := expression.NamesList( expression.Name("device"), @@ -16,7 +16,7 @@ func GetDevices(svc *dynamodb.DynamoDB) (*dynamodb.ScanOutput, error) { expr, _ := expression.NewBuilder().WithProjection(proj).Build() // Build the query input parameters - params := &dynamodb.ScanInput{ + params := &d.ScanInput{ ExpressionAttributeNames: expr.Names(), ExpressionAttributeValues: expr.Values(), ProjectionExpression: expr.Projection(), @@ -26,14 +26,17 @@ func GetDevices(svc *dynamodb.DynamoDB) (*dynamodb.ScanOutput, error) { } // GetHistory is a query history for any device -func GetHistory(svc *dynamodb.DynamoDB, deviceID string, limit int64) (*dynamodb.QueryOutput, error) { +func GetHistory(svc *d.DynamoDB, deviceID string, limit int64) (*d.QueryOutput, error) { keyCond := expression.Key("device").Equal(expression.Value(deviceID)) - qProj := expression.NamesList(expression.Name("device"), expression.Name("timestamp"), expression.Name("data")) + qProj := expression.NamesList( + expression.Name("device"), + expression.Name("timestamp"), + expression.Name("data")) qBuilder := expression.NewBuilder().WithKeyCondition(keyCond).WithProjection(qProj) qExpression, _ := qBuilder.Build() - queryInput := &dynamodb.QueryInput{ + queryInput := &d.QueryInput{ KeyConditionExpression: qExpression.KeyCondition(), ProjectionExpression: qExpression.Projection(), ExpressionAttributeNames: qExpression.Names(), diff --git a/model.go b/model.go index 4df2c3c..f0b56d2 100644 --- a/model.go +++ b/model.go @@ -11,13 +11,15 @@ type Device struct { Name string `json:"name"` } -// Create structs to hold info about new item +// ItemInfo - create structs to hold info about new item type ItemInfo struct { Firmware string `json:"firmware"` Sensor string `json:"sensor"` + Model string `json:"model"` } -type ItemFloraData struct { +// SensorData to store all sensor's data +type SensorData struct { Battery int `json:"battery"` Light int `json:"light"` Conductivity float32 `json:"conductivity"` @@ -26,13 +28,15 @@ type ItemFloraData struct { Humidity float32 `json:"humidity"` } +// Item is an item to generalize every IoT devices type Item struct { - Device string `json:"device"` - Timestamp string `json:"timestamp"` - Info ItemInfo `json:"info"` - Data ItemFloraData `json:"data"` + Device string `json:"device"` + Timestamp string `json:"timestamp"` + Info ItemInfo `json:"info"` + Data SensorData `json:"data"` } +// History returns data in []Item func (d Device) History(svc *dynamodb.DynamoDB, limit int64) ([]Item, error) { result, err := GetHistory(svc, d.Device, limit) var ev []Item diff --git a/read_item.go b/read_item.go index ae673ec..fa2555c 100644 --- a/read_item.go +++ b/read_item.go @@ -3,8 +3,7 @@ package main import ( "encoding/json" "fmt" - "io" - "log" + "html/template" "net/http" "os" @@ -13,7 +12,8 @@ import ( "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute" "github.com/flosch/pongo2" - "github.com/gorilla/mux" + "github.com/labstack/echo" + "github.com/labstack/echo/middleware" ) var tplHome = pongo2.Must(pongo2.FromFile("home.html")) @@ -21,25 +21,31 @@ var sess *session.Session var err error var svc *dynamodb.DynamoDB -func indexHandler(w http.ResponseWriter, r *http.Request) { +// 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) + // err := tplHome.ExecuteWriter(pongo2.Context{"query": "dddd"}, w) + out, err := tplHome.Execute(pongo2.Context{"query": "dddd"}) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) + return err + // http.Error(w, err.Error(), http.StatusInternalServerError) } + return c.Render(http.StatusOK, "home", template.HTML(out)) } -func healthCheckHandler(w http.ResponseWriter, r *http.Request) { +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") + // 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}`) + // io.WriteString(w, `{"alive": true}`) + return c.JSON(http.StatusOK, `{"alive": true}`) } -func overallHandler(w http.ResponseWriter, r *http.Request) { +func overallHandler(c echo.Context) error { devices, _ := GetDevices(svc) var result []Item @@ -47,25 +53,43 @@ func overallHandler(w http.ResponseWriter, r *http.Request) { device := Device{} err := dynamodbattribute.UnmarshalMap(i, &device) if err != nil { - fmt.Println("Device error unmarshalling:") - fmt.Println(err.Error()) - os.Exit(1) + return err } data, _ := device.History(svc, 1) result = append(result, data[0]) } - b, _ := json.Marshal(result) - - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") - io.WriteString(w, string(b)) + // b, _ := json.Marshal(result) + return c.JSON(http.StatusOK, result) } -func oneDeviceHandler(w http.ResponseWriter, r *http.Request) { - - w.WriteHeader(http.StatusOK) - w.Header().Set("Content-Type", "application/json") +// func oneDeviceHandler(w http.ResponseWriter, r *http.Request) { +func oneDeviceHandler(c echo.Context) error { + id := c.Param("id") + result, err := GetHistory(svc, id, 5) + 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) + 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) } func main() { @@ -99,14 +123,37 @@ func main() { // http.Handle("/", router) // http.ListenAndServe(":4000", nil) - r := mux.NewRouter() - // 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", r)) + // 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()) + e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ + AllowOrigins: []string{"*"}, + AllowMethods: []string{"GET", "OPTIONS"}, + AllowHeaders: []string{echo.HeaderOrigin, echo.HeaderContentType, echo.HeaderAccept}, + })) + + e.GET("/health", healthCheckHandler) + e.GET("/id/:id", oneDeviceHandler) + e.GET("/all", overallHandler) + e.GET("/", indexHandler) + e.Logger.Fatal(e.Start(":8000")) }