Skip to content

Commit

Permalink
Merge pull request #412 from dmsl/develop-server
Browse files Browse the repository at this point in the history
minor bugfix
  • Loading branch information
paschalis-mpeis authored Oct 25, 2021
2 parents fd44b66 + 3df45dd commit e2ce48b
Show file tree
Hide file tree
Showing 49 changed files with 1,972 additions and 1,214 deletions.
2 changes: 1 addition & 1 deletion server/API_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
| /anyplace/position/predictFloorAlgo1 | /api/position/predictFloorAlgo1 | |
| /anyplace/position/estimate_position | /api/position/estimate | |
| /anyplace/position/radio/delete | /api/radiomap/delete | |
| /anyplace/position/radio_by_building_floor_all | /api/radiomap/floor/all | |
| /anyplace/position/radio_by_building_floor_all | /api/radiomap/floors | |
| /anyplace/position/radio_by_floor_bbox | /api/radiomap/floor/bbox | |
| /anyplace/position/radio_upload | /api/radiomap/upload | |
| /anyplace/position/radio_download_floor | /api/radiomap/floor | |
Expand Down
30 changes: 30 additions & 0 deletions server/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,34 @@
# CHANGELOG

# Version 4.2.6
- search bar (pac-input):
- accepts coordinates in google maps format: LAT, LON
- moves map to that location
- previous functionality is not working due to GMap.js update
- uploading floorplans
- `OverlayMode`:
- keep the previous floor's floorplan when uploading a new one to aid in aligning
- no longer rotating when zooming in. the `rotatable` plugin was also updated
- while zooming, rotating and panning a floorplan:
- most of the gmaps functionality is disabled (e.g, rotation, zoom, etc)
- using the proper callbacks now (from rotatable, resizable, etc)
- not required to zoom at full level to improve quality
- image is uploaded at max quality
- canvas is re-drawn before saving at full resolution

- share urls (and everything based on BASE_URL) is now relative
- e.g. sharing a building on ap-dev will generate an endpoint for ap-dev

- BUGFIX: MDB issue when storing new documents
- affected vessel/building, floor creation, etc
- BUGFIX: architect no longer loads 3x on `angular init`
- BUGFIX: better handling of the cases where architect requests fingerprints/heatmaps/APs of unmapped floors.
- BUGFIX: backup now works:
- related bugs: (endpoints updated)
- `/api/floorplans64/all/{buid}/{floors}`
- `/api/radiomap/floors`
- BUGFIX: POI Connection delete

#### Archive: [changelog](changelog/README.md)

---
Expand Down
54 changes: 52 additions & 2 deletions server/FAQ.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,54 @@
# FAQ:

##### 1. Swagger documentation not generated correctly:
Try the sbt `swagger` command that the `iheart/sbt-swagger-play` plugin adds.
### A. Documentation
Documentation is automatically generated using `iheart-radio/swagger`.
The additions are in `conf/swagger.yml` and `conf/api.routes`

##### A1. Swagger documentation not generated correctly:
Try the sbt `swagger` command that the `iheart/sbt-swagger-play` plugin adds.

##### A2. An endpoint on `/developers` does not get the response.
<details close>
<summary>
Reply example in swagger
</summary>

Either it's a bug or it's missing the response tag.
Update the relevant `api.routes` entry with:
```bash
# responses:
# '200':
# description: Successful operation
```
See other examples on how to put a sample response.
</details>

##### A3. How to put a reply example in swagger:
<details close>
<summary>
Reply example in swagger
</summary>

Way 1:
```bash
# examples:
# application/json: |
# {
# "all_floors": [
# "<floor1 BASE64>",
# "<floor2 BASE64>"
# ]
# }
```

Way 2:
```bash
# responses:
# 200:
# description: success
# schema:
# $ref: '#/definitions/Version'
```
This requires a definition in `conf/swagger.yml`, under `definitions:`.
</details>

10 changes: 9 additions & 1 deletion server/app/controllers/HeatmapController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,12 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
val json = anyReq.getJsonBody()
LOG.D2("Heatmap: floorWifiAVG1: " + Utils.stripJsValueStr(json))

val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor)
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
try {
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage1(buid, floor)
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
Expand Down Expand Up @@ -71,6 +73,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
try {
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage2(buid, floor)
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
Expand Down Expand Up @@ -105,6 +108,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
try {
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage3(buid, floor)
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
Expand Down Expand Up @@ -138,6 +142,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
val tileX = (json \ SCHEMA.fX).as[Int]
val tileY = (json \ SCHEMA.fY).as[Int]
val zoomLevel = (json \ "z").as[Int]
Expand Down Expand Up @@ -181,6 +186,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
try {
Expand Down Expand Up @@ -211,6 +217,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
try {
Expand Down Expand Up @@ -248,6 +255,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
val timestampY = (json \ SCHEMA.fTimestampY).as[String]

Expand Down Expand Up @@ -284,6 +292,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val floor = (json \ SCHEMA.fFloor).as[String]
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
val x = (json \ SCHEMA.fX).as[Int]
Expand Down Expand Up @@ -313,7 +322,6 @@ class HeatmapController @Inject()(cc: ControllerComponents,
case e: DatasourceException => return RESPONSE.ERROR(e)
}
}

inner(request)
}

Expand Down
3 changes: 2 additions & 1 deletion server/app/controllers/MapCampusController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,8 @@ class MapCampusController @Inject()(cc: ControllerComponents,
case e: DatasourceException =>
return RESPONSE.ERROR(e)
}
return RESPONSE.OK("Successfully deleted everything related to building.")

RESPONSE.OK("Deleted indoor campus (cascading).")
}

inner(request)
Expand Down
42 changes: 25 additions & 17 deletions server/app/controllers/MapFloorplanController.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package controllers

import controllers.FloorplanSettings.MIN_ZOOM_UPLOAD
import datasources.{DatasourceException, ProxyDataSource, SCHEMA}
import models._
import models.oauth.OAuth2Request
Expand All @@ -13,6 +14,12 @@ import java.io._
import java.util
import javax.inject.{Inject, Singleton}
import scala.jdk.CollectionConverters.CollectionHasAsScala

object FloorplanSettings {
/** It no longer affects upload quality (fixed JS), but it might affect accuracy. */
var MIN_ZOOM_UPLOAD=18
}

@Singleton
class MapFloorplanController @Inject()(cc: ControllerComponents,
tilerHelper: AnyPlaceTilerHelper,
Expand Down Expand Up @@ -152,15 +159,15 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
* @param floorNum
* @return
*/
def getAllBase64(buid: String, floorNum: String): Action[AnyContent] = Action {
def getAllBase64(buid: String, requestedFloors: String): Action[AnyContent] = Action {
implicit request =>
def inner(request: Request[AnyContent]): Result = {
val anyReq = new OAuth2Request(request)
if (!anyReq.assertJsonBody())
return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
val json = anyReq.getJsonBody()
LOG.D2("Floorplan: getAllBase64: " + Utils.stripJsValueStr(json) + " " + floorNum)
val floors = floorNum.split(" ")
LOG.D2("Floorplan: getAllBase64: " + Utils.stripJsValueStr(json) + " " + requestedFloors)
val floors = requestedFloors.split(" ")
val all_floors = new util.ArrayList[String]
var z = 0
while (z < floors.length) {
Expand All @@ -174,20 +181,21 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
all_floors.add(s)
} catch {
case _: IOException =>
return RESPONSE.BAD("Requested floorplan cannot be encoded in base64 properly: " + floors(z))
return RESPONSE.BAD("Cannot encode floorplan: " + floors(z))
}
catch {
case _: Exception =>
return RESPONSE.ERROR_INTERNAL("Unknown server error during floorplan delivery.")
case e: Exception =>
return RESPONSE.ERROR_INTERNAL("Error while getting floorplans: " + requestedFloors +" : "
+ e.getMessage)
}
z += 1
}
val res: JsValue = Json.obj("all_floors" -> all_floors.asScala)
try
try {
RESPONSE.gzipJsonOk(res.toString)
catch {
} catch {
case _: IOException =>
return RESPONSE.OK(res, "Successfully retrieved all floors.")
RESPONSE.OK(res, "Floors retrieved.")
}
}

Expand Down Expand Up @@ -286,9 +294,8 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
if (checkRequirements != null) return checkRequirements
val buid = (json \ SCHEMA.fBuid).as[String]
val zoom = (json \ SCHEMA.fZoom).as[String]
val zoom_number = zoom.toInt
if (zoom_number < 20)
return RESPONSE.BAD("You have provided zoom level " + zoom + ". You have to zoom at least to level 20 to upload the floorplan.")
if (zoom.toInt < MIN_ZOOM_UPLOAD) return RESPONSE.BAD_FLOORPLAN_ZOOM_LEVEL(zoom)

val floorNum = (json \ SCHEMA.fFloorNumber).as[String]
val bottom_left_lat = (json \ SCHEMA.fLatBottomLeft).as[String]
val bottom_left_lng = (json \ SCHEMA.fLonBottomLeft).as[String]
Expand All @@ -304,26 +311,27 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
storedFloor = storedFloor.as[JsObject] + (SCHEMA.fLatTopRight -> JsString(top_right_lat))
storedFloor = storedFloor.as[JsObject] + (SCHEMA.fLonTopRight -> JsString(top_right_lng))
if (!pds.db.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, storedFloor.toString)) {
return RESPONSE.BAD("floorplan could not be updated in the database.")
return RESPONSE.BAD("Could not update floorplan.")
}
} catch {
case e: DatasourceException => return RESPONSE.ERROR_INTERNAL("Error while reading from our backend service.")
case _: DatasourceException => return RESPONSE.ERROR_INTERNAL("Error while reading from backend.")
}
var floor_file: File = null
try {
floor_file = tilerHelper.storeFloorPlanToServer(buid, floorNum, floorplan.ref.path.toFile)
} catch {
case e: AnyPlaceException => return RESPONSE.BAD("Cannot save floorplan on the server.")
case _: AnyPlaceException => return RESPONSE.BAD("Cannot save floorplan.")
}
val top_left_lat = top_right_lat
val top_left_lng = bottom_left_lng
try {
tilerHelper.tileImageWithZoom(floor_file, top_left_lat, top_left_lng, zoom)
} catch {
case _: AnyPlaceException => return RESPONSE.BAD("Could not create floorplan tiles on the server.")
case _: AnyPlaceException => return RESPONSE.BAD("Cannot create floorplan tiles.")
}
LOG.I("Successfully tiled: " + floor_file.toString)
return RESPONSE.OK("Successfully updated floorplan.")

RESPONSE.OK("Uploaded floorplan.")
}

inner(request)
Expand Down
6 changes: 3 additions & 3 deletions server/app/controllers/MapPoiConnectionController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import java.text.{NumberFormat, ParseException}
import java.util.Locale
import javax.inject.{Inject, Singleton}
import scala.jdk.CollectionConverters.CollectionHasAsScala

@Singleton
class MapPoiConnectionController @Inject()(cc: ControllerComponents,
pds: ProxyDataSource,
Expand Down Expand Up @@ -151,13 +152,12 @@ class MapPoiConnectionController @Inject()(cc: ControllerComponents,
def delete(): Action[AnyContent] = Action {
implicit request =>
def inner(request: Request[AnyContent]): Result = {

LOG.D2("PoiConnection: delete")
val anyReq = new OAuth2Request(request)
val apiKey = anyReq.getAccessToken()
if (apiKey == null) return anyReq.NO_ACCESS_TOKEN()
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
var json = anyReq.getJsonBody()
LOG.D2("PoiConnection: delete: " + Utils.stripJsValueStr(json))
val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fPoisA, SCHEMA.fPoisB, SCHEMA.fBuidA, SCHEMA.fBuidB)
if (checkRequirements != null) return checkRequirements
val owner_id = user.authorize(apiKey)
Expand Down Expand Up @@ -300,4 +300,4 @@ class MapPoiConnectionController @Inject()(cc: ControllerComponents,
}
GeoPoint.getDistanceBetweenPoints(lat_a, lon_a, lat_b, lon_b, "K")
}
}
}
20 changes: 10 additions & 10 deletions server/app/controllers/MapSpaceController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,8 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
val json = anyReq.getJsonBody()
LOG.D2("spaceGetOne: " + Utils.stripJsValueStr(json))
val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid)
if (checkRequirements != null) return checkRequirements
val check = VALIDATE.checkRequirements(json, SCHEMA.fBuid)
if (check!= null) return check
val buid = (json \ SCHEMA.fBuid).as[String]
try {
var space = pds.db.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid)
Expand All @@ -276,14 +276,14 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
(space \ SCHEMA.fName) != JsDefined(JsNull) &&
(space \ SCHEMA.fDescription) != JsDefined(JsNull)) {
space = space.as[JsObject] - SCHEMA.fOwnerId - SCHEMA.fCoOwners - SCHEMA.fId - SCHEMA.fSchema
val res: JsValue = Json.obj("space" -> space)
try {
return RESPONSE.gzipJsonOk(res.toString)
return RESPONSE.gzipJsonOk(space.toString)
} catch {
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved the space!")
case _: IOException => return RESPONSE.OK(space, "Space retrieved.")
}
}
return RESPONSE.NOT_FOUND("Space not found.")

RESPONSE.NOT_FOUND("Space not found.")
} catch {
case e: DatasourceException => return RESPONSE.ERROR(e)
}
Expand All @@ -301,7 +301,7 @@ class MapSpaceController @Inject()(cc: ControllerComponents,

if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
val json = anyReq.getJsonBody()
LOG.D2("spaceAccessible: " + Utils.stripJsValueStr(json))
LOG.D2("userAccessible: " + Utils.stripJsValueStr(json))
val checkRequirements = VALIDATE.checkRequirements(json) // , SCHEMA.fAccessToken
if (checkRequirements != null) return checkRequirements

Expand All @@ -314,7 +314,7 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
try {
RESPONSE.gzipJsonOk(res.toString)
} catch {
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved all spaces.")
case ioe: IOException => return RESPONSE.OK(res, "Retrieved user spaces.")
}
} catch {
case e: DatasourceException => return RESPONSE.ERROR(e)
Expand Down Expand Up @@ -415,10 +415,10 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
try {
RESPONSE.gzipJsonOk(res.toString)
} catch {
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved all spaces near your position!")
case _: IOException => RESPONSE.OK(res, "Retrieved all spaces near user position")
}
} catch {
case e: DatasourceException => return RESPONSE.ERROR(e)
case e: DatasourceException => RESPONSE.ERROR(e)
}
}

Expand Down
Loading

0 comments on commit e2ce48b

Please sign in to comment.