Newer
Older
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
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
3234
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
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
}
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
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
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
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
}
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
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
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
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
}
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))
}