dual offline/online, map info

* Server provides map info with zoom, default center and paths to both downloadable pack and tile url template.
This commit is contained in:
zegkljan 2022-02-05 17:56:13 +01:00
parent caeb5c9198
commit 08a203e4a6
5 changed files with 69 additions and 28 deletions

16
main.go
View File

@ -8,6 +8,7 @@ import (
"os/signal"
"syscall"
"cernobor.cz/oko-server/models"
"cernobor.cz/oko-server/server"
"github.com/sirupsen/logrus"
)
@ -17,6 +18,9 @@ func main() {
tilepackFileArg := flag.String("tilepack", "", "File that will be sent to clients when they request a tile pack. Required.")
apkFileArg := flag.String("apk", "", "APK file with the client app. If not specified, no APK will be available (404).")
reinitDBArg := flag.Bool("reinit-db", false, "Reinitializes the DB, which means all the tables will be recreated, deleting all data.")
minZoomArg := flag.Int("min-zoom", 1, "Minimum zoom that will be sent to clients.")
defaultCenterLatArg := flag.Float64("default-center-lat", 0, "Latitude of the default map center.")
defaultCenterLngArg := flag.Float64("default-center-lng", 0, "Longitude of the default map center.")
flag.Parse()
@ -26,7 +30,17 @@ func main() {
os.Exit(1)
}
s := server.New(*dbFileArg, *tilepackFileArg, *apkFileArg, *reinitDBArg)
s := server.New(server.ServerConfig{
DbPath: *dbFileArg,
TilepackPath: *tilepackFileArg,
ApkPath: *apkFileArg,
ReinitDB: *reinitDBArg,
MinZoom: *minZoomArg,
DefaultCenter: models.Coords{
Lat: *defaultCenterLatArg,
Lng: *defaultCenterLngArg,
},
})
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGTERM, syscall.SIGINT, syscall.SIGQUIT)

View File

@ -33,6 +33,19 @@ type Feature struct {
// transport objects
type Coords struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
type MapInfo struct {
MapPackPath string `json:"map_pack_path"`
MapPackSize int64 `json:"map_pack_size"`
TilePathTemplate string `json:"tile_path_template"`
MinZoom int `json:"min_zoom"`
DefaultCenter Coords `json:"default_center"`
}
type Update struct {
Create []Feature `json:"create"`
CreatedPhotos map[FeatureID][]string `json:"created_photos"`
@ -50,7 +63,7 @@ type HandshakeChallenge struct {
type HandshakeResponse struct {
ID UserID `json:"id"`
Name string `json:"name"`
TilePackPath string `json:"tile_pack_path"`
MapInfo MapInfo `json:"map_info"`
}
type Data struct {

View File

@ -4,13 +4,13 @@ const (
URIPing = "/ping"
URIHardFail = "/hard-fail"
URISoftFail = "/soft-fail"
URITilepack = "/tilepack"
URIMapPack = "/mappack"
URIHandshake = "/handshake"
URIData = "/data"
URIDataPeople = "/data/people"
URIDataExtra = "/data/extra"
URIDataFeatures = "/data/features"
URIDataFeaturesPhoto = "/data/features/:feature/photos/:photo"
URITileserverRoot = "/tileserver"
URITileserver = URITileserverRoot + "/*x"
URITileTemplate = URITileserverRoot + "/map/tiles/{z}/{x}/{y}.pbf"
)

View File

@ -86,7 +86,7 @@ func (s *Server) setupRouter() *gin.Engine {
})
// resources
router.GET(URITilepack, s.handleGETTilepack)
router.GET(URIMapPack, s.handleGETTilepack)
// API
router.POST(URIHandshake, s.handlePOSTHandshake)
@ -131,7 +131,13 @@ func (s *Server) handlePOSTHandshake(gc *gin.Context) {
gc.JSON(http.StatusOK, models.HandshakeResponse{
ID: id,
Name: hs.Name,
TilePackPath: URITilepack,
MapInfo: models.MapInfo{
MapPackPath: URIMapPack,
MapPackSize: s.mapPackSize,
TilePathTemplate: URITileTemplate,
MinZoom: s.config.MinZoom,
DefaultCenter: s.config.DefaultCenter,
},
})
}

View File

@ -7,6 +7,7 @@ import (
"io"
"net/http"
"net/url"
"os"
"time"
_ "embed"
@ -29,6 +30,7 @@ type Server struct {
log *logrus.Logger
ctx context.Context
tileserverSvSet *mbsh.ServiceSet
mapPackSize int64
}
type ServerConfig struct {
@ -36,16 +38,13 @@ type ServerConfig struct {
TilepackPath string
ApkPath string
ReinitDB bool
MinZoom int
DefaultCenter models.Coords
}
func New(dbPath, tilepackPath, apkPath string, reinitDB bool) *Server {
func New(config ServerConfig) *Server {
return &Server{
config: ServerConfig{
DbPath: dbPath,
TilepackPath: tilepackPath,
ApkPath: apkPath,
ReinitDB: reinitDB,
},
config: config,
}
}
@ -63,6 +62,7 @@ func (s *Server) Run(ctx context.Context) {
Addr: fmt.Sprintf(":%d", 8080),
Handler: router,
}
s.log.Infof("Running on %s", server.Addr)
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
s.log.Infof("listen: %s\n", err)
@ -99,6 +99,7 @@ func (s *Server) setupDB() {
s.dbpool = dbpool
if s.config.ReinitDB {
s.log.Info("Reinitializing DB.")
conn := s.getDbConn()
defer s.dbpool.Put(conn)
@ -124,24 +125,30 @@ func (s *Server) setupTiles() {
if err != nil {
s.log.WithError(err).Fatal("Failed to create tileserver service set.")
}
err = svs.AddTileset(s.config.TilepackPath, "main")
err = svs.AddTileset(s.config.TilepackPath, "map")
if err != nil {
s.log.WithError(err).Fatal("Failed to register main tileset.")
s.log.WithError(err).Fatal("Failed to register tileset.")
}
s.tileserverSvSet = svs
info, err := os.Stat(s.config.TilepackPath)
if err != nil {
s.log.WithError(err).Fatal("Failed to get info about tile pack file.")
}
s.mapPackSize = info.Size()
}
func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error) {
conn := s.getDbConn()
defer s.dbpool.Put(conn)
userID, err := func() (uid int, err error) {
userID, err := func() (uid int64, err error) {
defer sqlitex.Save(conn)(&err)
var id *int
var id *int64
if hc.Exists {
err = sqlitex.Exec(conn, "select id from users where name = ?", func(stmt *sqlite.Stmt) error {
id = ptrInt(stmt.ColumnInt(0))
id = ptrInt64(stmt.ColumnInt64(0))
return nil
}, hc.Name)
if sqlite.ErrCode(err) != sqlite.SQLITE_OK {
@ -154,8 +161,8 @@ func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error)
return 0, errs.ErrAttemptedSystemUser
}
} else {
err = sqlitex.Exec(conn, "insert into users(name) values(?) returning id", func(stmt *sqlite.Stmt) error {
id = ptrInt(stmt.ColumnInt(0))
err = sqlitex.Exec(conn, "insert into users(name) values(?)", func(stmt *sqlite.Stmt) error {
id = ptrInt64(stmt.ColumnInt64(0))
return nil
}, hc.Name)
if sqlite.ErrCode(err) == sqlite.SQLITE_CONSTRAINT_UNIQUE {
@ -164,6 +171,7 @@ func (s *Server) handshake(hc models.HandshakeChallenge) (models.UserID, error)
if sqlite.ErrCode(err) != sqlite.SQLITE_OK {
return 0, err
}
id = ptrInt64(conn.LastInsertRowID())
}
return *id, nil
}()