mirror of
https://github.com/supanadit/geo-smart-system.git
synced 2024-12-04 07:06:21 +00:00
Organize and Optimize Code
This commit is contained in:
parent
4f2a9128ed
commit
bca8a676e5
145
main.go
145
main.go
@ -3,150 +3,21 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gin-contrib/cors"
|
"github.com/gin-contrib/cors"
|
||||||
"github.com/gin-contrib/sse"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-redis/redis"
|
"github.com/go-redis/redis"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/supanadit/geo-smart-system/system"
|
||||||
"github.com/rs/xid"
|
|
||||||
"github.com/supanadit/geo-smart-system/model"
|
|
||||||
"github.com/supanadit/geo-smart-system/model/tile38"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
port := "8080"
|
// Create Connection with Tile 38
|
||||||
|
|
||||||
client := redis.NewClient(&redis.Options{
|
client := redis.NewClient(&redis.Options{
|
||||||
Addr: "192.168.99.100:9851",
|
Addr: system.GetTile38ConnectionAddress(),
|
||||||
})
|
})
|
||||||
|
// Create Gin Engine
|
||||||
r := gin.Default()
|
r := gin.Default()
|
||||||
r.Use(cors.Default())
|
r.Use(cors.Default())
|
||||||
|
// Call Router
|
||||||
r.GET("/id/get/unique", func(c *gin.Context) {
|
system.Router(r, client)
|
||||||
id := xid.New()
|
// Run Server
|
||||||
c.JSON(200, gin.H{"id": id.String()})
|
_ = r.Run(fmt.Sprintf(":%s", system.ServerPort))
|
||||||
})
|
|
||||||
|
|
||||||
r.POST("/point/set", func(c *gin.Context) {
|
|
||||||
var location model.Location
|
|
||||||
err := c.BindJSON(&location)
|
|
||||||
client.Do("SET", location.Type, location.Id, "POINT", location.Lat, location.Lng)
|
|
||||||
var status map[string]interface{}
|
|
||||||
var httpStatus int
|
|
||||||
if err != nil {
|
|
||||||
status = gin.H{"status": "Unknown Error"}
|
|
||||||
httpStatus = http.StatusInternalServerError
|
|
||||||
} else {
|
|
||||||
status = gin.H{"status": "Ok"}
|
|
||||||
httpStatus = http.StatusOK
|
|
||||||
}
|
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
|
||||||
c.JSON(httpStatus, status)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.POST("/point/unset", func(c *gin.Context) {
|
|
||||||
var location model.Location
|
|
||||||
err := c.BindJSON(&location)
|
|
||||||
client.Do("DEL", location.Type, location.Id)
|
|
||||||
var status map[string]interface{}
|
|
||||||
var httpStatus int
|
|
||||||
if err != nil {
|
|
||||||
status = gin.H{"status": "Unknown Error"}
|
|
||||||
httpStatus = http.StatusInternalServerError
|
|
||||||
} else {
|
|
||||||
status = gin.H{"status": "Ok"}
|
|
||||||
httpStatus = http.StatusOK
|
|
||||||
}
|
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
|
||||||
c.JSON(httpStatus, status)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/point/get", func(c *gin.Context) {
|
|
||||||
t := c.DefaultQuery("type", "user")
|
|
||||||
data, _ := tile38.FromScan(client, t)
|
|
||||||
c.JSON(http.StatusOK, data)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/point/get/stream", func(c *gin.Context) {
|
|
||||||
w := c.Writer
|
|
||||||
t := c.DefaultQuery("type", "user")
|
|
||||||
data, _ := tile38.FromScan(client, t)
|
|
||||||
|
|
||||||
_ = sse.Encode(w, sse.Event{
|
|
||||||
Event: "message",
|
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
r.POST("/detection/set", func(c *gin.Context) {
|
|
||||||
var detection model.Detection
|
|
||||||
err := c.BindJSON(&detection)
|
|
||||||
hookID := "HOOK-" + xid.New().String()
|
|
||||||
hookURL := "http://192.168.99.1:" + port + "/detection/call?hook=" + hookID
|
|
||||||
trigger := strings.Join(detection.TriggerType, ",")
|
|
||||||
var status map[string]interface{}
|
|
||||||
var httpStatus int
|
|
||||||
if trigger == "" {
|
|
||||||
status = gin.H{"status": "Please include trigger type such as 'enter','cross','exit','inside' or 'outside'"}
|
|
||||||
httpStatus = http.StatusBadRequest
|
|
||||||
} else {
|
|
||||||
client.Do("SETHOOK", hookID, hookURL, "NEARBY", detection.Type, "FENCE", "DETECT", trigger, "COMMANDS", "set", "POINT", detection.Lat, detection.Lng)
|
|
||||||
if err != nil {
|
|
||||||
status = gin.H{"status": "Unknown Error"}
|
|
||||||
httpStatus = http.StatusInternalServerError
|
|
||||||
} else {
|
|
||||||
status = gin.H{"status": "Ok"}
|
|
||||||
httpStatus = http.StatusOK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.Writer.Header().Set("Content-Type", "application/json")
|
|
||||||
c.JSON(httpStatus, status)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/detection/call", func(c *gin.Context) {
|
|
||||||
hookID := c.Query("hook")
|
|
||||||
if hookID == "" {
|
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"status": "Wrong Request"})
|
|
||||||
} else {
|
|
||||||
client.Do("DELHOOK", hookID)
|
|
||||||
c.JSON(http.StatusOK, gin.H{"status": "OK"})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
r.GET("/ws", func(c *gin.Context) {
|
|
||||||
websocketHandler(c.Writer, c.Request)
|
|
||||||
})
|
|
||||||
|
|
||||||
r.Static("/public", "./public")
|
|
||||||
r.Static("/assets", "./assets")
|
|
||||||
|
|
||||||
_ = r.Run(":" + port)
|
|
||||||
}
|
|
||||||
|
|
||||||
var websocketUpgrade = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func websocketHandler(w http.ResponseWriter, r *http.Request) {
|
|
||||||
conn, err := websocketUpgrade.Upgrade(w, r, nil)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
t, msg, err := conn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
fmt.Printf("Received : %s \n", msg)
|
|
||||||
_ = conn.WriteMessage(t, []byte("OK"))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,12 +7,12 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tile38Data struct {
|
type Data struct {
|
||||||
Object []Tile38Object `json:"data"`
|
Object []Object `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromScan(client *redis.Client, name string) (Tile38Data, error) {
|
func FromScan(client *redis.Client, name string) (Data, error) {
|
||||||
var tile38Data Tile38Data
|
var tile38Data Data
|
||||||
var err error
|
var err error
|
||||||
v, err := client.Do("SCAN", name).Result()
|
v, err := client.Do("SCAN", name).Result()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
@ -28,8 +28,8 @@ func FromScan(client *redis.Client, name string) (Tile38Data, error) {
|
|||||||
contentName := name + ".1"
|
contentName := name + ".1"
|
||||||
id := gjson.Get(jsonConverted, idName)
|
id := gjson.Get(jsonConverted, idName)
|
||||||
content := gjson.Get(jsonConverted, contentName)
|
content := gjson.Get(jsonConverted, contentName)
|
||||||
var tile38Object Tile38Object
|
var tile38Object Object
|
||||||
var tile38SubObject Tile38SubObject
|
var tile38SubObject SubObject
|
||||||
err = json.Unmarshal([]byte(content.String()), &tile38SubObject)
|
err = json.Unmarshal([]byte(content.String()), &tile38SubObject)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
tile38Object.Id = id.String()
|
tile38Object.Id = id.String()
|
||||||
@ -43,7 +43,7 @@ func FromScan(client *redis.Client, name string) (Tile38Data, error) {
|
|||||||
return tile38Data, err
|
return tile38Data, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tile38Data Tile38Data) ToJsonString() (string, error) {
|
func (tile38Data Data) ToJsonString() (string, error) {
|
||||||
var err error
|
var err error
|
||||||
data, err := json.Marshal(tile38Data)
|
data, err := json.Marshal(tile38Data)
|
||||||
return string(data), err
|
return string(data), err
|
6
model/tile38/object.go
Normal file
6
model/tile38/object.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package tile38
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Object SubObject `json:"object"`
|
||||||
|
}
|
@ -8,21 +8,21 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Tile38SubObject struct {
|
type SubObject struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Coordinates []float64 `json:"coordinates"`
|
Coordinates []float64 `json:"coordinates"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tile38SubObject Tile38SubObject) Lng() float64 {
|
func (tile38SubObject SubObject) Lng() float64 {
|
||||||
return tile38SubObject.Coordinates[0]
|
return tile38SubObject.Coordinates[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tile38SubObject Tile38SubObject) Lat() float64 {
|
func (tile38SubObject SubObject) Lat() float64 {
|
||||||
return tile38SubObject.Coordinates[1]
|
return tile38SubObject.Coordinates[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func FromLocation(location model.Location) Tile38SubObject {
|
func FromLocation(location model.Location) SubObject {
|
||||||
var tile38SubObject Tile38SubObject
|
var tile38SubObject SubObject
|
||||||
tile38SubObject.Type = "Point"
|
tile38SubObject.Type = "Point"
|
||||||
lng, _ := strconv.ParseFloat(location.Lng, 64)
|
lng, _ := strconv.ParseFloat(location.Lng, 64)
|
||||||
lat, _ := strconv.ParseFloat(location.Lat, 64)
|
lat, _ := strconv.ParseFloat(location.Lat, 64)
|
||||||
@ -33,8 +33,8 @@ func FromLocation(location model.Location) Tile38SubObject {
|
|||||||
return tile38SubObject
|
return tile38SubObject
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDataLocation(client *redis.Client, typeLocation string, id string) (Tile38Object, error) {
|
func GetDataLocation(client *redis.Client, typeLocation string, id string) (Object, error) {
|
||||||
var tile38Object Tile38Object
|
var tile38Object Object
|
||||||
var err error
|
var err error
|
||||||
data, err := client.Do("GET", typeLocation, id).Result()
|
data, err := client.Do("GET", typeLocation, id).Result()
|
||||||
if err == nil {
|
if err == nil {
|
@ -1,6 +0,0 @@
|
|||||||
package tile38
|
|
||||||
|
|
||||||
type Tile38Object struct {
|
|
||||||
Id string `json:"id"`
|
|
||||||
Object Tile38SubObject `json:"object"`
|
|
||||||
}
|
|
19
system/constants.go
Normal file
19
system/constants.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Tile 38
|
||||||
|
Tile38Address = "127.0.0.1"
|
||||||
|
Tile38Port = "9851"
|
||||||
|
// Server Port
|
||||||
|
ServerPort = "8080"
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetTile38ConnectionAddress() string {
|
||||||
|
return fmt.Sprintf("%s:%s", Tile38Address, Tile38Port)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTile38HookURL(hookID string) string {
|
||||||
|
return fmt.Sprintf("http://%s/detection/call?hook=%s", GetTile38ConnectionAddress(), hookID)
|
||||||
|
}
|
140
system/router.go
Normal file
140
system/router.go
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
package system
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-contrib/sse"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-redis/redis"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/rs/xid"
|
||||||
|
"github.com/supanadit/geo-smart-system/model"
|
||||||
|
"github.com/supanadit/geo-smart-system/model/tile38"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Router(r *gin.Engine, client *redis.Client) {
|
||||||
|
r.GET("/id/get/unique", func(c *gin.Context) {
|
||||||
|
id := xid.New()
|
||||||
|
c.JSON(200, gin.H{"id": id.String()})
|
||||||
|
})
|
||||||
|
|
||||||
|
r.POST("/point/set", func(c *gin.Context) {
|
||||||
|
var location model.Location
|
||||||
|
err := c.BindJSON(&location)
|
||||||
|
client.Do("SET", location.Type, location.Id, "POINT", location.Lat, location.Lng)
|
||||||
|
var status map[string]interface{}
|
||||||
|
var httpStatus int
|
||||||
|
if err != nil {
|
||||||
|
status = gin.H{"status": "Unknown Error"}
|
||||||
|
httpStatus = http.StatusInternalServerError
|
||||||
|
} else {
|
||||||
|
status = gin.H{"status": "Ok"}
|
||||||
|
httpStatus = http.StatusOK
|
||||||
|
}
|
||||||
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
|
c.JSON(httpStatus, status)
|
||||||
|
})
|
||||||
|
|
||||||
|
r.POST("/point/unset", func(c *gin.Context) {
|
||||||
|
var location model.Location
|
||||||
|
err := c.BindJSON(&location)
|
||||||
|
client.Do("DEL", location.Type, location.Id)
|
||||||
|
var status map[string]interface{}
|
||||||
|
var httpStatus int
|
||||||
|
if err != nil {
|
||||||
|
status = gin.H{"status": "Unknown Error"}
|
||||||
|
httpStatus = http.StatusInternalServerError
|
||||||
|
} else {
|
||||||
|
status = gin.H{"status": "Ok"}
|
||||||
|
httpStatus = http.StatusOK
|
||||||
|
}
|
||||||
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
|
c.JSON(httpStatus, status)
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/point/get", func(c *gin.Context) {
|
||||||
|
t := c.DefaultQuery("type", "user")
|
||||||
|
data, _ := tile38.FromScan(client, t)
|
||||||
|
c.JSON(http.StatusOK, data)
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/point/get/stream", func(c *gin.Context) {
|
||||||
|
w := c.Writer
|
||||||
|
t := c.DefaultQuery("type", "user")
|
||||||
|
data, _ := tile38.FromScan(client, t)
|
||||||
|
|
||||||
|
_ = sse.Encode(w, sse.Event{
|
||||||
|
Event: "message",
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
r.POST("/detection/set", func(c *gin.Context) {
|
||||||
|
var detection model.Detection
|
||||||
|
err := c.BindJSON(&detection)
|
||||||
|
hookID := "HOOK-" + xid.New().String()
|
||||||
|
hookURL := system.GetTile38HookURL(hookID)
|
||||||
|
trigger := strings.Join(detection.TriggerType, ",")
|
||||||
|
var status map[string]interface{}
|
||||||
|
var httpStatus int
|
||||||
|
if trigger == "" {
|
||||||
|
status = gin.H{"status": "Please include trigger type such as 'enter','cross','exit','inside' or 'outside'"}
|
||||||
|
httpStatus = http.StatusBadRequest
|
||||||
|
} else {
|
||||||
|
client.Do("SETHOOK", hookID, hookURL, "NEARBY", detection.Type, "FENCE", "DETECT", trigger, "COMMANDS", "set", "POINT", detection.Lat, detection.Lng)
|
||||||
|
if err != nil {
|
||||||
|
status = gin.H{"status": "Unknown Error"}
|
||||||
|
httpStatus = http.StatusInternalServerError
|
||||||
|
} else {
|
||||||
|
status = gin.H{"status": "Ok"}
|
||||||
|
httpStatus = http.StatusOK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.Writer.Header().Set("Content-Type", "application/json")
|
||||||
|
c.JSON(httpStatus, status)
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/detection/call", func(c *gin.Context) {
|
||||||
|
hookID := c.Query("hook")
|
||||||
|
if hookID == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"status": "Wrong Request"})
|
||||||
|
} else {
|
||||||
|
client.Do("DELHOOK", hookID)
|
||||||
|
c.JSON(http.StatusOK, gin.H{"status": "OK"})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
r.GET("/ws", func(c *gin.Context) {
|
||||||
|
websocketHandler(c.Writer, c.Request)
|
||||||
|
})
|
||||||
|
|
||||||
|
r.Static("/public", "./public")
|
||||||
|
r.Static("/assets", "./assets")
|
||||||
|
}
|
||||||
|
|
||||||
|
var websocketUpgrade = websocket.Upgrader{
|
||||||
|
ReadBufferSize: 1024,
|
||||||
|
WriteBufferSize: 1024,
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func websocketHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
conn, err := websocketUpgrade.Upgrade(w, r, nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
t, msg, err := conn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fmt.Printf("Received : %s \n", msg)
|
||||||
|
_ = conn.WriteMessage(t, []byte("OK"))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user