mirror of
https://github.com/supanadit/geo-smart-system.git
synced 2024-11-22 00:26:21 +00:00
First Initialize
This commit is contained in:
commit
a5a5e459bd
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea
|
||||||
|
.vscode
|
35
README.md
Normal file
35
README.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# GEO Smart System
|
||||||
|
This is Tile38 Implementation for Golang, and also this software has a purpose to be real time tracking system
|
||||||
|
simulation such as Uber, Gojek, Grab, etc. The main feature of this software is that it must **lightweight**,
|
||||||
|
**less memory usage**, and **fast**, and for the live map it will integration with [Geo Smart Map](https://github.com/supanadit/geosmartmap)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
- [Tile38 Server](https://tile38.com/)
|
||||||
|
- [Golang](https://golang.org/)
|
||||||
|
|
||||||
|
## Todo
|
||||||
|
- Work with Socket.IO (OK)
|
||||||
|
- Connect With Tile38 (OK)
|
||||||
|
- CORS Support (OK)
|
||||||
|
- Get Data From Tile38 by Command SCAN (OK)
|
||||||
|
- Set HOOK by GeoFencing Trigger
|
||||||
|
- Receive New Point by HTTP GET also By Socket.IO and Trigger by Socket.IO Only
|
||||||
|
- Send Realtime Point by Socket.IO
|
||||||
|
- Support Nearby Trigger Feature
|
||||||
|
- Support Enter Area Trigger Feature
|
||||||
|
- Support Exit Area Trigger Feature
|
||||||
|
|
||||||
|
## License
|
||||||
|
Copyright 2019 Supan Adit Pratama
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
75
main.go
Normal file
75
main.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/gin-contrib/cors"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/go-redis/redis"
|
||||||
|
socketio "github.com/googollee/go-socket.io"
|
||||||
|
"github.com/supanadit/geosmartsystem/model"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Tile38
|
||||||
|
client := redis.NewClient(&redis.Options{
|
||||||
|
Addr: "localhost:9851",
|
||||||
|
})
|
||||||
|
|
||||||
|
router := gin.Default()
|
||||||
|
router.Use(cors.New(cors.Config{
|
||||||
|
AllowOrigins: []string{"http://localhost:4200"},
|
||||||
|
AllowMethods: []string{"PUT", "PATCH", "POST", "GET"},
|
||||||
|
AllowHeaders: []string{"Origin"},
|
||||||
|
ExposeHeaders: []string{"Content-Length"},
|
||||||
|
AllowWebSockets: true,
|
||||||
|
AllowCredentials: true,
|
||||||
|
AllowWildcard: true,
|
||||||
|
}))
|
||||||
|
router.GET("/point", func(c *gin.Context) {
|
||||||
|
data, _ := model.FromScan(client, "sales")
|
||||||
|
c.JSON(200, data)
|
||||||
|
})
|
||||||
|
// Socket.IO Start
|
||||||
|
server, err := socketio.NewServer(nil)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
server.OnConnect("/", func(s socketio.Conn) error {
|
||||||
|
s.SetContext("")
|
||||||
|
fmt.Println("Connected:", s.ID())
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
server.OnEvent("/", "message", func(s socketio.Conn, msg string) {
|
||||||
|
s.Emit("message", "have "+msg)
|
||||||
|
})
|
||||||
|
server.OnEvent("/", "bye", func(s socketio.Conn) string {
|
||||||
|
last := s.Context().(string)
|
||||||
|
s.Emit("bye", last)
|
||||||
|
_ = s.Close()
|
||||||
|
return last
|
||||||
|
})
|
||||||
|
server.OnError("/", func(e error) {
|
||||||
|
fmt.Println("Meet Error:", e)
|
||||||
|
})
|
||||||
|
server.OnDisconnect("/", func(s socketio.Conn, msg string) {
|
||||||
|
fmt.Println("Closed", msg)
|
||||||
|
})
|
||||||
|
router.GET("/socket.io/", gin.WrapH(server))
|
||||||
|
router.POST("/socket.io/", gin.WrapH(server))
|
||||||
|
router.Handle("WS", "/socket.io/", WebSocketIO(server))
|
||||||
|
router.Handle("WSS", "/socket.io/", WebSocketIO(server))
|
||||||
|
router.GET("/ws", func(c *gin.Context) {
|
||||||
|
server.ServeHTTP(c.Writer, c.Request)
|
||||||
|
})
|
||||||
|
go server.Serve()
|
||||||
|
defer server.Close()
|
||||||
|
// End Socket.IO
|
||||||
|
_ = router.Run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func WebSocketIO(server *socketio.Server) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
server.ServeHTTP(c.Writer, c.Request)
|
||||||
|
}
|
||||||
|
}
|
50
model/tile38data.go
Normal file
50
model/tile38data.go
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"github.com/go-redis/redis"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Tile38Data struct {
|
||||||
|
Object []Tile38Object `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func FromScan(client *redis.Client, name string) (Tile38Data, error) {
|
||||||
|
var tile38Data Tile38Data
|
||||||
|
var err error
|
||||||
|
v, err := client.Do("SCAN", name).Result()
|
||||||
|
if err == nil {
|
||||||
|
data, err := json.Marshal(v)
|
||||||
|
if err == nil {
|
||||||
|
jsonConverted := `{"data":` + string(data) + `}`
|
||||||
|
lengthData := gjson.Get(jsonConverted, "data.1.#")
|
||||||
|
if lengthData.Int() != 0 {
|
||||||
|
var x int64 = 0
|
||||||
|
for x = 0; x < lengthData.Int(); x++ {
|
||||||
|
name := "data.1." + strconv.FormatInt(int64(x), 10)
|
||||||
|
idName := name + ".0"
|
||||||
|
contentName := name + ".1"
|
||||||
|
id := gjson.Get(jsonConverted, idName)
|
||||||
|
content := gjson.Get(jsonConverted, contentName)
|
||||||
|
var tile38Object Tile38Object
|
||||||
|
var tile38SubObject Tile38SubObject
|
||||||
|
err = json.Unmarshal([]byte(content.String()), &tile38SubObject)
|
||||||
|
if err == nil {
|
||||||
|
tile38Object.Id = id.String()
|
||||||
|
tile38Object.Object = tile38SubObject
|
||||||
|
tile38Data.Object = append(tile38Data.Object, tile38Object)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tile38Data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tile38Data Tile38Data) ToJsonString() (string, error) {
|
||||||
|
var err error
|
||||||
|
data, err := json.Marshal(tile38Data)
|
||||||
|
return string(data), err
|
||||||
|
}
|
6
model/tile38object.go
Normal file
6
model/tile38object.go
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Tile38Object struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
Object Tile38SubObject `json:"object"`
|
||||||
|
}
|
14
model/tile38subobject.go
Normal file
14
model/tile38subobject.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Tile38SubObject struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Coordinates []float64 `json:"coordinates"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tile38SubObject Tile38SubObject) Lng() float64 {
|
||||||
|
return tile38SubObject.Coordinates[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tile38SubObject Tile38SubObject) Lat() float64 {
|
||||||
|
return tile38SubObject.Coordinates[1]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user