Newer
Older
if zoneStatusSub.ResourceURL == "" {
log.Error("Mandatory ResourceURL parameter not present")
http.Error(w, "Mandatory ResourceURL parameter not present", http.StatusBadRequest)
subsIdParamStr := vars["subscriptionId"]
selfUrl := strings.Split(zoneStatusSub.ResourceURL, "/")
subsIdStr := selfUrl[len(selfUrl)-1]
log.Error("SubscriptionId in endpoint and in body not matching")
http.Error(w, "SubscriptionId in endpoint and in body not matching", http.StatusBadRequest)
Simon Pastor
committed
Kevin Di Lallo
committed
zoneStatusSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/zoneStatus/" + subsIdStr
Simon Pastor
committed
subsId, err := strconv.Atoi(subsIdStr)
if err != nil {
log.Error(err)
w.WriteHeader(http.StatusBadRequest)
if zoneStatusSubscriptionMap[subsId] == nil {
w.WriteHeader(http.StatusNotFound)
return
}
Kevin Di Lallo
committed
_ = rc.JSONSetEntry(baseKey+typeZoneStatusSubscription+":"+subsIdStr, ".", convertZoneStatusSubscriptionToJson(zoneStatusSub))
Simon Pastor
committed
deregisterZoneStatus(subsIdStr)
registerZoneStatus(zoneStatusSub.ZoneId, zoneStatusSub.NumberOfUsersZoneThreshold, zoneStatusSub.NumberOfUsersAPThreshold,
zoneStatusSub.OperationStatus, subsIdStr)
Simon Pastor
committed
response.ZoneStatusSubscription = zoneStatusSub
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
Kevin Di Lallo
committed
func populateZoneStatusList(key string, jsonInfo string, userData interface{}) error {
var zoneInfo ZoneStatusSubscription
// Format response
err := json.Unmarshal([]byte(jsonInfo), &zoneInfo)
if err != nil {
return err
}
zoneList.ZoneStatusSubscription = append(zoneList.ZoneStatusSubscription, zoneInfo)
return nil
}
Kevin Di Lallo
committed
rc.DBFlush(baseKey)
nextZonalSubscriptionIdAvailable = 1
nextUserSubscriptionIdAvailable = 1
nextZoneStatusSubscriptionIdAvailable = 1
nextDistanceSubscriptionIdAvailable = 1
nextAreaCircleSubscriptionIdAvailable = 1
zonalSubscriptionEnteringMap = map[int]string{}
zonalSubscriptionLeavingMap = map[int]string{}
zonalSubscriptionTransferringMap = map[int]string{}
zonalSubscriptionMap = map[int]string{}
userSubscriptionEnteringMap = map[int]string{}
userSubscriptionLeavingMap = map[int]string{}
userSubscriptionTransferringMap = map[int]string{}
userSubscriptionMap = map[int]string{}
zoneStatusSubscriptionMap = map[int]*ZoneStatusCheck{}
distanceSubscriptionMap = map[int]*DistanceCheck{}
areaCircleSubscriptionMap = map[int]*AreaCircleCheck{}
periodicSubscriptionMap = map[int]*PeriodicCheck{}
updateStoreName("")
}
func updateStoreName(storeName string) {
if currentStoreName != storeName {
currentStoreName = storeName
_ = httpLog.ReInit(logModuleLocServ, sandboxName, storeName, redisAddr, influxAddr)
}
Kevin Di Lallo
committed
func updateUserInfo(address string, zoneId string, accessPointId string, longitude *float32, latitude *float32) {
Kevin Di Lallo
committed
var oldZoneId string
var oldApId string
Kevin Di Lallo
committed
// Get User Info from DB
Kevin Di Lallo
committed
jsonUserInfo, _ := rc.JSONGetEntry(baseKey+typeUser+":"+address, ".")
Kevin Di Lallo
committed
userInfo := convertJsonToUserInfo(jsonUserInfo)
Kevin Di Lallo
committed
// Create new user info if necessary
if userInfo == nil {
userInfo = new(UserInfo)
userInfo.Address = address
userInfo.ResourceURL = hostUrl.String() + basePath + "queries/users?address=" + address
Kevin Di Lallo
committed
} else {
// Get old zone & AP IDs
oldZoneId = userInfo.ZoneId
oldApId = userInfo.AccessPointId
Kevin Di Lallo
committed
}
userInfo.ZoneId = zoneId
userInfo.AccessPointId = accessPointId
//dtermine if ue is connected or not based on POA connectivity
if accessPointId != "" {
addressConnectedMap[address] = true
} else {
addressConnectedMap[address] = false
}
seconds := time.Now().Unix()
var timeStamp TimeStamp
timeStamp.Seconds = int32(seconds)
userInfo.Timestamp = &timeStamp
Kevin Di Lallo
committed
// Update position
if longitude == nil || latitude == nil {
userInfo.LocationInfo = nil
} else {
if userInfo.LocationInfo == nil {
userInfo.LocationInfo = new(LocationInfo)
}
//we only support shape == 2 in locationInfo, so we ignore any conditional parameters based on shape
userInfo.LocationInfo.Shape = 2
userInfo.LocationInfo.Longitude = nil
userInfo.LocationInfo.Longitude = append(userInfo.LocationInfo.Longitude, *longitude)
userInfo.LocationInfo.Latitude = nil
userInfo.LocationInfo.Latitude = append(userInfo.LocationInfo.Latitude, *latitude)
userInfo.LocationInfo.Timestamp = &timeStamp
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
// Update User info in DB & Send notifications
_ = rc.JSONSetEntry(baseKey+typeUser+":"+address, ".", convertUserInfoToJson(userInfo))
checkNotificationRegisteredUsers(oldZoneId, zoneId, oldApId, accessPointId, address)
checkNotificationRegisteredZones(oldZoneId, zoneId, oldApId, accessPointId, address)
func updateZoneInfo(zoneId string, nbAccessPoints int, nbUnsrvAccessPoints int, nbUsers int) {
Kevin Di Lallo
committed
// Get Zone Info from DB
Kevin Di Lallo
committed
jsonZoneInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+zoneId, ".")
Kevin Di Lallo
committed
zoneInfo := convertJsonToZoneInfo(jsonZoneInfo)
Kevin Di Lallo
committed
// Create new zone info if necessary
if zoneInfo == nil {
zoneInfo = new(ZoneInfo)
zoneInfo.ZoneId = zoneId
zoneInfo.ResourceURL = hostUrl.String() + basePath + "queries/zones/" + zoneId
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
// Update info
if nbAccessPoints != -1 {
zoneInfo.NumberOfAccessPoints = int32(nbAccessPoints)
Kevin Di Lallo
committed
}
if nbUnsrvAccessPoints != -1 {
zoneInfo.NumberOfUnserviceableAccessPoints = int32(nbUnsrvAccessPoints)
Kevin Di Lallo
committed
}
if nbUsers != -1 {
zoneInfo.NumberOfUsers = int32(nbUsers)
Kevin Di Lallo
committed
// Update Zone info in DB & Send notifications
_ = rc.JSONSetEntry(baseKey+typeZone+":"+zoneId, ".", convertZoneInfoToJson(zoneInfo))
checkNotificationRegisteredZoneStatus(zoneId, "", int32(-1), int32(nbUsers), int32(-1), previousNbUsers)
Kevin Di Lallo
committed
func updateAccessPointInfo(zoneId string, apId string, conTypeStr string, opStatusStr string, nbUsers int, longitude *float32, latitude *float32) {
Kevin Di Lallo
committed
// Get AP Info from DB
Kevin Di Lallo
committed
jsonApInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+zoneId+":"+typeAccessPoint+":"+apId, ".")
Kevin Di Lallo
committed
apInfo := convertJsonToAccessPointInfo(jsonApInfo)
Kevin Di Lallo
committed
// Create new AP info if necessary
if apInfo == nil {
apInfo = new(AccessPointInfo)
apInfo.AccessPointId = apId
apInfo.ResourceURL = hostUrl.String() + basePath + "queries/zones/" + zoneId + "/accessPoints/" + apId
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
// Update info
if opStatusStr != "" {
opStatus := convertStringToOperationStatus(opStatusStr)
apInfo.OperationStatus = &opStatus
Kevin Di Lallo
committed
}
if conTypeStr != "" {
conType := convertStringToConnectionType(conTypeStr)
apInfo.ConnectionType = &conType
}
Kevin Di Lallo
committed
if nbUsers != -1 {
apInfo.NumberOfUsers = int32(nbUsers)
Kevin Di Lallo
committed
Kevin Di Lallo
committed
// Update position
if longitude == nil || latitude == nil {
apInfo.LocationInfo = nil
} else {
if apInfo.LocationInfo == nil {
apInfo.LocationInfo = new(LocationInfo)
}
//Accuracy supported for shape 4, 5, 6 only, so ignoring it in our case (only support shape == 2)
//apInfo.LocationInfo.Accuracy = 1
apInfo.LocationInfo.Longitude = nil
apInfo.LocationInfo.Longitude = append(apInfo.LocationInfo.Longitude, *longitude)
apInfo.LocationInfo.Latitude = nil
apInfo.LocationInfo.Latitude = append(apInfo.LocationInfo.Latitude, *latitude)
seconds := time.Now().Unix()
var timeStamp TimeStamp
timeStamp.Seconds = int32(seconds)
apInfo.LocationInfo.Timestamp = &timeStamp
Kevin Di Lallo
committed
}
Kevin Di Lallo
committed
// Update AP info in DB & Send notifications
_ = rc.JSONSetEntry(baseKey+typeZone+":"+zoneId+":"+typeAccessPoint+":"+apId, ".", convertAccessPointInfoToJson(apInfo))
checkNotificationRegisteredZoneStatus(zoneId, apId, int32(nbUsers), int32(-1), previousNbUsers, int32(-1))
Simon Pastor
committed
func zoneStatusReInit() {
//reusing the object response for the get multiple zoneStatusSubscription
Simon Pastor
committed
Kevin Di Lallo
committed
keyName := baseKey + typeZoneStatusSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populateZoneStatusList, &zoneList)
Simon Pastor
committed
maxZoneStatusSubscriptionId := 0
Simon Pastor
committed
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
for _, zone := range zoneList.ZoneStatusSubscription {
resourceUrl := strings.Split(zone.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxZoneStatusSubscriptionId {
maxZoneStatusSubscriptionId = subscriptionId
}
var zoneStatus ZoneStatusCheck
opStatus := zone.OperationStatus
if opStatus != nil {
for i := 0; i < len(opStatus); i++ {
switch opStatus[i] {
case SERVICEABLE:
zoneStatus.Serviceable = true
case UNSERVICEABLE:
zoneStatus.Unserviceable = true
case OPSTATUS_UNKNOWN:
zoneStatus.Unknown = true
default:
}
}
}
zoneStatus.NbUsersInZoneThreshold = zone.NumberOfUsersZoneThreshold
zoneStatus.NbUsersInAPThreshold = zone.NumberOfUsersAPThreshold
Simon Pastor
committed
zoneStatus.ZoneId = zone.ZoneId
zoneStatusSubscriptionMap[subscriptionId] = &zoneStatus
}
}
nextZoneStatusSubscriptionIdAvailable = maxZoneStatusSubscriptionId + 1
}
func zonalTrafficReInit() {
//reusing the object response for the get multiple zonalSubscription
Kevin Di Lallo
committed
keyName := baseKey + typeZonalSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populateZonalTrafficList, &zoneList)
maxZonalSubscriptionId := 0
for _, zone := range zoneList.ZonalTrafficSubscription {
resourceUrl := strings.Split(zone.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxZonalSubscriptionId {
maxZonalSubscriptionId = subscriptionId
}
for i := 0; i < len(zone.UserEventCriteria); i++ {
switch zone.UserEventCriteria[i] {
zonalSubscriptionEnteringMap[subscriptionId] = zone.ZoneId
zonalSubscriptionLeavingMap[subscriptionId] = zone.ZoneId
zonalSubscriptionTransferringMap[subscriptionId] = zone.ZoneId
zonalSubscriptionMap[subscriptionId] = zone.ZoneId
}
}
nextZonalSubscriptionIdAvailable = maxZonalSubscriptionId + 1
}
func userTrackingReInit() {
//reusing the object response for the get multiple zonalSubscription
Kevin Di Lallo
committed
keyName := baseKey + typeUserSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populateUserTrackingList, &userList)
maxUserSubscriptionId := 0
for _, user := range userList.UserTrackingSubscription {
resourceUrl := strings.Split(user.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxUserSubscriptionId {
maxUserSubscriptionId = subscriptionId
}
for i := 0; i < len(user.UserEventCriteria); i++ {
switch user.UserEventCriteria[i] {
userSubscriptionEnteringMap[subscriptionId] = user.Address
userSubscriptionLeavingMap[subscriptionId] = user.Address
userSubscriptionTransferringMap[subscriptionId] = user.Address
userSubscriptionMap[subscriptionId] = user.Address
}
}
nextUserSubscriptionIdAvailable = maxUserSubscriptionId + 1
}
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
func distanceReInit() {
//reusing the object response for the get multiple zonalSubscription
var distanceList NotificationSubscriptionList
keyName := baseKey + typeDistanceSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populateDistanceList, &distanceList)
maxDistanceSubscriptionId := 0
mutex.Lock()
defer mutex.Unlock()
for _, distanceSub := range distanceList.DistanceNotificationSubscription {
resourceUrl := strings.Split(distanceSub.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxDistanceSubscriptionId {
maxDistanceSubscriptionId = subscriptionId
}
var distanceCheck DistanceCheck
distanceCheck.Subscription = &distanceSub
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
if distanceSub.CheckImmediate {
distanceCheck.NextTts = 0 //next time periodic trigger hits, will be forced to trigger
} else {
distanceCheck.NextTts = distanceSub.Frequency
}
distanceSubscriptionMap[subscriptionId] = &distanceCheck
}
}
nextDistanceSubscriptionIdAvailable = maxDistanceSubscriptionId + 1
}
func areaCircleReInit() {
//reusing the object response for the get multiple zonalSubscription
var areaCircleList NotificationSubscriptionList
keyName := baseKey + typeAreaCircleSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populateAreaCircleList, &areaCircleList)
maxAreaCircleSubscriptionId := 0
mutex.Lock()
defer mutex.Unlock()
for _, areaCircleSub := range areaCircleList.CircleNotificationSubscription {
resourceUrl := strings.Split(areaCircleSub.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxAreaCircleSubscriptionId {
maxAreaCircleSubscriptionId = subscriptionId
}
var areaCircleCheck AreaCircleCheck
areaCircleCheck.Subscription = &areaCircleSub
areaCircleCheck.AddrInArea = map[string]bool{}
if areaCircleSub.CheckImmediate {
areaCircleCheck.NextTts = 0 //next time periodic trigger hits, will be forced to trigger
} else {
areaCircleCheck.NextTts = areaCircleSub.Frequency
}
areaCircleSubscriptionMap[subscriptionId] = &areaCircleCheck
}
}
nextAreaCircleSubscriptionIdAvailable = maxAreaCircleSubscriptionId + 1
}
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
func periodicReInit() {
//reusing the object response for the get multiple zonalSubscription
var periodicList NotificationSubscriptionList
keyName := baseKey + typePeriodicSubscription + "*"
_ = rc.ForEachJSONEntry(keyName, populatePeriodicList, &periodicList)
maxPeriodicSubscriptionId := 0
mutex.Lock()
defer mutex.Unlock()
for _, periodicSub := range periodicList.PeriodicNotificationSubscription {
resourceUrl := strings.Split(periodicSub.ResourceURL, "/")
subscriptionId, err := strconv.Atoi(resourceUrl[len(resourceUrl)-1])
if err != nil {
log.Error(err)
} else {
if subscriptionId > maxPeriodicSubscriptionId {
maxPeriodicSubscriptionId = subscriptionId
}
var periodicCheck PeriodicCheck
periodicCheck.Subscription = &periodicSub
periodicCheck.NextTts = periodicSub.Frequency
periodicSubscriptionMap[subscriptionId] = &periodicCheck
}
}
nextPeriodicSubscriptionIdAvailable = maxPeriodicSubscriptionId + 1
}
func distanceGet(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
// Retrieve query parameters
u, _ := url.Parse(r.URL.String())
log.Info("url: ", u.RequestURI())
q := u.Query()
//requester := q.Get("requester")
latitudeStr := q.Get("latitude")
longitudeStr := q.Get("longitude")
address := q["address"]
if len(address) == 0 {
log.Error("Query should have at least 1 'address' parameter")
http.Error(w, "Query should have at least 1 'address' parameter", http.StatusBadRequest)
return
}
if len(address) > 2 {
log.Error("Query cannot have more than 2 'address' parameters")
http.Error(w, "Query cannot have more than 2 'address' parameters", http.StatusBadRequest)
return
}
if len(address) == 2 && (latitudeStr != "" || longitudeStr != "") {
log.Error("Query cannot have 2 'address' parameters and 'latitude'/'longitude' parameters")
http.Error(w, "Query cannot have 2 'address' parameters and 'latitude'/'longitude' parameters", http.StatusBadRequest)
return
}
if (latitudeStr != "" && longitudeStr == "") || (latitudeStr == "" && longitudeStr != "") {
log.Error("Query must provide a latitude and a longitude for a point to be valid")
http.Error(w, "Query must provide a latitude and a longitude for a point to be valid", http.StatusBadRequest)
return
}
if len(address) == 1 && latitudeStr == "" && longitudeStr == "" {
log.Error("Query must provide either 2 'address' parameters or 1 'address' parameter and 'latitude'/'longitude' parameters")
http.Error(w, "Query must provide either 2 'address' parameters or 1 'address' parameter and 'latitude'/'longitude' parameters", http.StatusBadRequest)
return
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
}
validQueryParams := []string{"requester", "address", "latitude", "longitude"}
//look for all query parameters to reject if any invalid ones
found := false
for queryParam := range q {
found = false
for _, validQueryParam := range validQueryParams {
if queryParam == validQueryParam {
found = true
break
}
}
if !found {
log.Error("Query param not valid: ", queryParam)
w.WriteHeader(http.StatusBadRequest)
return
}
}
srcAddress := address[0]
dstAddress := ""
if len(address) > 1 {
dstAddress = address[1]
}
var distParam gisClient.TargetPoint
distParam.AssetName = dstAddress
if longitudeStr != "" {
longitude, err := strconv.ParseFloat(longitudeStr, 32)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
distParam.Longitude = float32(longitude)
}
if latitudeStr != "" {
latitude, err := strconv.ParseFloat(latitudeStr, 32)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
distParam.Latitude = float32(latitude)
}
distResp, _, err := gisAppClient.GeospatialDataApi.GetDistanceGeoDataByName(context.TODO(), srcAddress, distParam)
if err != nil {
errCodeStr := strings.Split(err.Error(), " ")
if len(errCodeStr) > 0 {
errCode, errStr := strconv.Atoi(errCodeStr[0])
if errStr == nil {
log.Error("Error code from gis-engine API : ", err)
http.Error(w, err.Error(), errCode)
} else {
log.Error("Failed to communicate with gis engine: ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
} else {
log.Error("Failed to communicate with gis engine: ", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
}
return
}
var response InlineTerminalDistance
var terminalDistance TerminalDistance
terminalDistance.Distance = int32(distResp.Distance)
seconds := time.Now().Unix()
var timestamp TimeStamp
timestamp.Seconds = int32(seconds)
terminalDistance.Timestamp = ×tamp
response.TerminalDistance = &terminalDistance
// Send response
jsonResponse, err := json.Marshal(response)
if err != nil {
log.Error(err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, string(jsonResponse))
}