Skip to content

Commit e2ce48b

Browse files
Merge pull request #412 from dmsl/develop-server
minor bugfix
2 parents fd44b66 + 3df45dd commit e2ce48b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1972
-1214
lines changed

server/API_CHANGES.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
| /anyplace/position/predictFloorAlgo1 | /api/position/predictFloorAlgo1 | |
4545
| /anyplace/position/estimate_position | /api/position/estimate | |
4646
| /anyplace/position/radio/delete | /api/radiomap/delete | |
47-
| /anyplace/position/radio_by_building_floor_all | /api/radiomap/floor/all | |
47+
| /anyplace/position/radio_by_building_floor_all | /api/radiomap/floors | |
4848
| /anyplace/position/radio_by_floor_bbox | /api/radiomap/floor/bbox | |
4949
| /anyplace/position/radio_upload | /api/radiomap/upload | |
5050
| /anyplace/position/radio_download_floor | /api/radiomap/floor | |

server/CHANGELOG.md

+30
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
11
# CHANGELOG
2+
3+
# Version 4.2.6
4+
- search bar (pac-input):
5+
- accepts coordinates in google maps format: LAT, LON
6+
- moves map to that location
7+
- previous functionality is not working due to GMap.js update
8+
- uploading floorplans
9+
- `OverlayMode`:
10+
- keep the previous floor's floorplan when uploading a new one to aid in aligning
11+
- no longer rotating when zooming in. the `rotatable` plugin was also updated
12+
- while zooming, rotating and panning a floorplan:
13+
- most of the gmaps functionality is disabled (e.g, rotation, zoom, etc)
14+
- using the proper callbacks now (from rotatable, resizable, etc)
15+
- not required to zoom at full level to improve quality
16+
- image is uploaded at max quality
17+
- canvas is re-drawn before saving at full resolution
18+
19+
- share urls (and everything based on BASE_URL) is now relative
20+
- e.g. sharing a building on ap-dev will generate an endpoint for ap-dev
21+
22+
- BUGFIX: MDB issue when storing new documents
23+
- affected vessel/building, floor creation, etc
24+
- BUGFIX: architect no longer loads 3x on `angular init`
25+
- BUGFIX: better handling of the cases where architect requests fingerprints/heatmaps/APs of unmapped floors.
26+
- BUGFIX: backup now works:
27+
- related bugs: (endpoints updated)
28+
- `/api/floorplans64/all/{buid}/{floors}`
29+
- `/api/radiomap/floors`
30+
- BUGFIX: POI Connection delete
31+
232
#### Archive: [changelog](changelog/README.md)
333

434
---

server/FAQ.md

+52-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,54 @@
11
# FAQ:
22

3-
##### 1. Swagger documentation not generated correctly:
4-
Try the sbt `swagger` command that the `iheart/sbt-swagger-play` plugin adds.
3+
### A. Documentation
4+
Documentation is automatically generated using `iheart-radio/swagger`.
5+
The additions are in `conf/swagger.yml` and `conf/api.routes`
6+
7+
##### A1. Swagger documentation not generated correctly:
8+
Try the sbt `swagger` command that the `iheart/sbt-swagger-play` plugin adds.
9+
10+
##### A2. An endpoint on `/developers` does not get the response.
11+
<details close>
12+
<summary>
13+
Reply example in swagger
14+
</summary>
15+
16+
Either it's a bug or it's missing the response tag.
17+
Update the relevant `api.routes` entry with:
18+
```bash
19+
# responses:
20+
# '200':
21+
# description: Successful operation
22+
```
23+
See other examples on how to put a sample response.
24+
</details>
25+
26+
##### A3. How to put a reply example in swagger:
27+
<details close>
28+
<summary>
29+
Reply example in swagger
30+
</summary>
31+
32+
Way 1:
33+
```bash
34+
# examples:
35+
# application/json: |
36+
# {
37+
# "all_floors": [
38+
# "<floor1 BASE64>",
39+
# "<floor2 BASE64>"
40+
# ]
41+
# }
42+
```
43+
44+
Way 2:
45+
```bash
46+
# responses:
47+
# 200:
48+
# description: success
49+
# schema:
50+
# $ref: '#/definitions/Version'
51+
```
52+
This requires a definition in `conf/swagger.yml`, under `definitions:`.
53+
</details>
54+

server/app/controllers/HeatmapController.scala

+9-1
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,12 @@ class HeatmapController @Inject()(cc: ControllerComponents,
3939
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
4040
val json = anyReq.getJsonBody()
4141
LOG.D2("Heatmap: floorWifiAVG1: " + Utils.stripJsValueStr(json))
42+
4243
val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid, SCHEMA.fFloor)
4344
if (checkRequirements != null) return checkRequirements
4445
val buid = (json \ SCHEMA.fBuid).as[String]
4546
val floor = (json \ SCHEMA.fFloor).as[String]
47+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
4648
try {
4749
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage1(buid, floor)
4850
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
@@ -71,6 +73,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
7173
if (checkRequirements != null) return checkRequirements
7274
val buid = (json \ SCHEMA.fBuid).as[String]
7375
val floor = (json \ SCHEMA.fFloor).as[String]
76+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
7477
try {
7578
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage2(buid, floor)
7679
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
@@ -105,6 +108,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
105108
if (checkRequirements != null) return checkRequirements
106109
val buid = (json \ SCHEMA.fBuid).as[String]
107110
val floor = (json \ SCHEMA.fFloor).as[String]
111+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
108112
try {
109113
val radioPoints = pds.db.getRadioHeatmapByBuildingFloorAverage3(buid, floor)
110114
if (radioPoints == null) return RESPONSE.BAD_CANNOT_RETRIEVE_SPACE
@@ -138,6 +142,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
138142
if (checkRequirements != null) return checkRequirements
139143
val buid = (json \ SCHEMA.fBuid).as[String]
140144
val floor = (json \ SCHEMA.fFloor).as[String]
145+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
141146
val tileX = (json \ SCHEMA.fX).as[Int]
142147
val tileY = (json \ SCHEMA.fY).as[Int]
143148
val zoomLevel = (json \ "z").as[Int]
@@ -181,6 +186,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
181186
if (checkRequirements != null) return checkRequirements
182187
val buid = (json \ SCHEMA.fBuid).as[String]
183188
val floor = (json \ SCHEMA.fFloor).as[String]
189+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
184190
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
185191
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
186192
try {
@@ -211,6 +217,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
211217
if (checkRequirements != null) return checkRequirements
212218
val buid = (json \ SCHEMA.fBuid).as[String]
213219
val floor = (json \ SCHEMA.fFloor).as[String]
220+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
214221
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
215222
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
216223
try {
@@ -248,6 +255,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
248255
if (checkRequirements != null) return checkRequirements
249256
val buid = (json \ SCHEMA.fBuid).as[String]
250257
val floor = (json \ SCHEMA.fFloor).as[String]
258+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
251259
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
252260
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
253261

@@ -284,6 +292,7 @@ class HeatmapController @Inject()(cc: ControllerComponents,
284292
if (checkRequirements != null) return checkRequirements
285293
val buid = (json \ SCHEMA.fBuid).as[String]
286294
val floor = (json \ SCHEMA.fFloor).as[String]
295+
if (!pds.db.floorHasFingerprints(buid, floor)) return RESPONSE.BAD_NO_FINGERPRINTS
287296
val timestampX = (json \ SCHEMA.fTimestampX).as[String]
288297
val timestampY = (json \ SCHEMA.fTimestampY).as[String]
289298
val x = (json \ SCHEMA.fX).as[Int]
@@ -313,7 +322,6 @@ class HeatmapController @Inject()(cc: ControllerComponents,
313322
case e: DatasourceException => return RESPONSE.ERROR(e)
314323
}
315324
}
316-
317325
inner(request)
318326
}
319327

server/app/controllers/MapCampusController.scala

+2-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,8 @@ class MapCampusController @Inject()(cc: ControllerComponents,
247247
case e: DatasourceException =>
248248
return RESPONSE.ERROR(e)
249249
}
250-
return RESPONSE.OK("Successfully deleted everything related to building.")
250+
251+
RESPONSE.OK("Deleted indoor campus (cascading).")
251252
}
252253

253254
inner(request)

server/app/controllers/MapFloorplanController.scala

+25-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package controllers
22

3+
import controllers.FloorplanSettings.MIN_ZOOM_UPLOAD
34
import datasources.{DatasourceException, ProxyDataSource, SCHEMA}
45
import models._
56
import models.oauth.OAuth2Request
@@ -13,6 +14,12 @@ import java.io._
1314
import java.util
1415
import javax.inject.{Inject, Singleton}
1516
import scala.jdk.CollectionConverters.CollectionHasAsScala
17+
18+
object FloorplanSettings {
19+
/** It no longer affects upload quality (fixed JS), but it might affect accuracy. */
20+
var MIN_ZOOM_UPLOAD=18
21+
}
22+
1623
@Singleton
1724
class MapFloorplanController @Inject()(cc: ControllerComponents,
1825
tilerHelper: AnyPlaceTilerHelper,
@@ -152,15 +159,15 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
152159
* @param floorNum
153160
* @return
154161
*/
155-
def getAllBase64(buid: String, floorNum: String): Action[AnyContent] = Action {
162+
def getAllBase64(buid: String, requestedFloors: String): Action[AnyContent] = Action {
156163
implicit request =>
157164
def inner(request: Request[AnyContent]): Result = {
158165
val anyReq = new OAuth2Request(request)
159166
if (!anyReq.assertJsonBody())
160167
return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
161168
val json = anyReq.getJsonBody()
162-
LOG.D2("Floorplan: getAllBase64: " + Utils.stripJsValueStr(json) + " " + floorNum)
163-
val floors = floorNum.split(" ")
169+
LOG.D2("Floorplan: getAllBase64: " + Utils.stripJsValueStr(json) + " " + requestedFloors)
170+
val floors = requestedFloors.split(" ")
164171
val all_floors = new util.ArrayList[String]
165172
var z = 0
166173
while (z < floors.length) {
@@ -174,20 +181,21 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
174181
all_floors.add(s)
175182
} catch {
176183
case _: IOException =>
177-
return RESPONSE.BAD("Requested floorplan cannot be encoded in base64 properly: " + floors(z))
184+
return RESPONSE.BAD("Cannot encode floorplan: " + floors(z))
178185
}
179186
catch {
180-
case _: Exception =>
181-
return RESPONSE.ERROR_INTERNAL("Unknown server error during floorplan delivery.")
187+
case e: Exception =>
188+
return RESPONSE.ERROR_INTERNAL("Error while getting floorplans: " + requestedFloors +" : "
189+
+ e.getMessage)
182190
}
183191
z += 1
184192
}
185193
val res: JsValue = Json.obj("all_floors" -> all_floors.asScala)
186-
try
194+
try {
187195
RESPONSE.gzipJsonOk(res.toString)
188-
catch {
196+
} catch {
189197
case _: IOException =>
190-
return RESPONSE.OK(res, "Successfully retrieved all floors.")
198+
RESPONSE.OK(res, "Floors retrieved.")
191199
}
192200
}
193201

@@ -286,9 +294,8 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
286294
if (checkRequirements != null) return checkRequirements
287295
val buid = (json \ SCHEMA.fBuid).as[String]
288296
val zoom = (json \ SCHEMA.fZoom).as[String]
289-
val zoom_number = zoom.toInt
290-
if (zoom_number < 20)
291-
return RESPONSE.BAD("You have provided zoom level " + zoom + ". You have to zoom at least to level 20 to upload the floorplan.")
297+
if (zoom.toInt < MIN_ZOOM_UPLOAD) return RESPONSE.BAD_FLOORPLAN_ZOOM_LEVEL(zoom)
298+
292299
val floorNum = (json \ SCHEMA.fFloorNumber).as[String]
293300
val bottom_left_lat = (json \ SCHEMA.fLatBottomLeft).as[String]
294301
val bottom_left_lng = (json \ SCHEMA.fLonBottomLeft).as[String]
@@ -304,26 +311,27 @@ class MapFloorplanController @Inject()(cc: ControllerComponents,
304311
storedFloor = storedFloor.as[JsObject] + (SCHEMA.fLatTopRight -> JsString(top_right_lat))
305312
storedFloor = storedFloor.as[JsObject] + (SCHEMA.fLonTopRight -> JsString(top_right_lng))
306313
if (!pds.db.replaceJsonDocument(SCHEMA.cFloorplans, SCHEMA.fFuid, fuid, storedFloor.toString)) {
307-
return RESPONSE.BAD("floorplan could not be updated in the database.")
314+
return RESPONSE.BAD("Could not update floorplan.")
308315
}
309316
} catch {
310-
case e: DatasourceException => return RESPONSE.ERROR_INTERNAL("Error while reading from our backend service.")
317+
case _: DatasourceException => return RESPONSE.ERROR_INTERNAL("Error while reading from backend.")
311318
}
312319
var floor_file: File = null
313320
try {
314321
floor_file = tilerHelper.storeFloorPlanToServer(buid, floorNum, floorplan.ref.path.toFile)
315322
} catch {
316-
case e: AnyPlaceException => return RESPONSE.BAD("Cannot save floorplan on the server.")
323+
case _: AnyPlaceException => return RESPONSE.BAD("Cannot save floorplan.")
317324
}
318325
val top_left_lat = top_right_lat
319326
val top_left_lng = bottom_left_lng
320327
try {
321328
tilerHelper.tileImageWithZoom(floor_file, top_left_lat, top_left_lng, zoom)
322329
} catch {
323-
case _: AnyPlaceException => return RESPONSE.BAD("Could not create floorplan tiles on the server.")
330+
case _: AnyPlaceException => return RESPONSE.BAD("Cannot create floorplan tiles.")
324331
}
325332
LOG.I("Successfully tiled: " + floor_file.toString)
326-
return RESPONSE.OK("Successfully updated floorplan.")
333+
334+
RESPONSE.OK("Uploaded floorplan.")
327335
}
328336

329337
inner(request)

server/app/controllers/MapPoiConnectionController.scala

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import java.text.{NumberFormat, ParseException}
1414
import java.util.Locale
1515
import javax.inject.{Inject, Singleton}
1616
import scala.jdk.CollectionConverters.CollectionHasAsScala
17+
1718
@Singleton
1819
class MapPoiConnectionController @Inject()(cc: ControllerComponents,
1920
pds: ProxyDataSource,
@@ -151,13 +152,12 @@ class MapPoiConnectionController @Inject()(cc: ControllerComponents,
151152
def delete(): Action[AnyContent] = Action {
152153
implicit request =>
153154
def inner(request: Request[AnyContent]): Result = {
154-
155+
LOG.D2("PoiConnection: delete")
155156
val anyReq = new OAuth2Request(request)
156157
val apiKey = anyReq.getAccessToken()
157158
if (apiKey == null) return anyReq.NO_ACCESS_TOKEN()
158159
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
159160
var json = anyReq.getJsonBody()
160-
LOG.D2("PoiConnection: delete: " + Utils.stripJsValueStr(json))
161161
val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fPoisA, SCHEMA.fPoisB, SCHEMA.fBuidA, SCHEMA.fBuidB)
162162
if (checkRequirements != null) return checkRequirements
163163
val owner_id = user.authorize(apiKey)
@@ -300,4 +300,4 @@ class MapPoiConnectionController @Inject()(cc: ControllerComponents,
300300
}
301301
GeoPoint.getDistanceBetweenPoints(lat_a, lon_a, lat_b, lon_b, "K")
302302
}
303-
}
303+
}

server/app/controllers/MapSpaceController.scala

+10-10
Original file line numberDiff line numberDiff line change
@@ -264,8 +264,8 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
264264
if (!anyReq.assertJsonBody()) return RESPONSE.BAD(RESPONSE.ERROR_JSON_PARSE)
265265
val json = anyReq.getJsonBody()
266266
LOG.D2("spaceGetOne: " + Utils.stripJsValueStr(json))
267-
val checkRequirements = VALIDATE.checkRequirements(json, SCHEMA.fBuid)
268-
if (checkRequirements != null) return checkRequirements
267+
val check = VALIDATE.checkRequirements(json, SCHEMA.fBuid)
268+
if (check!= null) return check
269269
val buid = (json \ SCHEMA.fBuid).as[String]
270270
try {
271271
var space = pds.db.getFromKeyAsJson(SCHEMA.cSpaces, SCHEMA.fBuid, buid)
@@ -276,14 +276,14 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
276276
(space \ SCHEMA.fName) != JsDefined(JsNull) &&
277277
(space \ SCHEMA.fDescription) != JsDefined(JsNull)) {
278278
space = space.as[JsObject] - SCHEMA.fOwnerId - SCHEMA.fCoOwners - SCHEMA.fId - SCHEMA.fSchema
279-
val res: JsValue = Json.obj("space" -> space)
280279
try {
281-
return RESPONSE.gzipJsonOk(res.toString)
280+
return RESPONSE.gzipJsonOk(space.toString)
282281
} catch {
283-
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved the space!")
282+
case _: IOException => return RESPONSE.OK(space, "Space retrieved.")
284283
}
285284
}
286-
return RESPONSE.NOT_FOUND("Space not found.")
285+
286+
RESPONSE.NOT_FOUND("Space not found.")
287287
} catch {
288288
case e: DatasourceException => return RESPONSE.ERROR(e)
289289
}
@@ -301,7 +301,7 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
301301

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

@@ -314,7 +314,7 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
314314
try {
315315
RESPONSE.gzipJsonOk(res.toString)
316316
} catch {
317-
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved all spaces.")
317+
case ioe: IOException => return RESPONSE.OK(res, "Retrieved user spaces.")
318318
}
319319
} catch {
320320
case e: DatasourceException => return RESPONSE.ERROR(e)
@@ -415,10 +415,10 @@ class MapSpaceController @Inject()(cc: ControllerComponents,
415415
try {
416416
RESPONSE.gzipJsonOk(res.toString)
417417
} catch {
418-
case ioe: IOException => return RESPONSE.OK(res, "Successfully retrieved all spaces near your position!")
418+
case _: IOException => RESPONSE.OK(res, "Retrieved all spaces near user position")
419419
}
420420
} catch {
421-
case e: DatasourceException => return RESPONSE.ERROR(e)
421+
case e: DatasourceException => RESPONSE.ERROR(e)
422422
}
423423
}
424424

0 commit comments

Comments
 (0)