Commit 673c4e23 authored by Ikram Haq's avatar Ikram Haq
Browse files

Implemnt logic to send the userDistanceNotification

parent 851dac4b
Loading
Loading
Loading
Loading
+179 −0
Original line number Diff line number Diff line
@@ -380,6 +380,7 @@ func Run() (err error) {
			updateNotificationAreaCirclePeriodicTrigger()
			checkNotificationPeriodicTrigger()
			checkNotificationPeriodicTrigger1()
			checkNotificationDistancePeriodicTrigger1()
		}
	}()

@@ -802,6 +803,164 @@ func updateNotificationAreaCirclePeriodicTrigger() {
	}
}

func checkNotificationDistancePeriodicTrigger1() {

	//only check if there is at least one subscription
	mutex.Lock()
	defer mutex.Unlock()
	//check all that applies
	for subsId, distanceCheck := range distanceSubscriptionMap1 {
		if distanceCheck != nil && distanceCheck.Subscription != nil {
			// if distanceCheck.Subscription.Count == 0 || (distanceCheck.Subscription.Count != 0 && distanceCheck.NbNotificationsSent < distanceCheck.Subscription.Count) {
			// 	if distanceCheck.NextTts != 0 {
			// 		distanceCheck.NextTts--
			// 	}
			// 	if distanceCheck.NextTts == 0 {
			// 		distanceCheck.NotificationCheckReady = true
			// 	} else {
			// 		distanceCheck.NotificationCheckReady = false
			// 	}

			// 	if !distanceCheck.NotificationCheckReady {
			// 		continue
			// 	}

			//loop through every reference address
			returnAddr := make(map[string]*gisClient.Distance)
			skipThisSubscription := false

			//if reference address is specified, reference addresses are checked agains each monitored address
			//if reference address is nil, each pair of the monitored address should be checked
			//creating address pairs to check
			//e.g. refAddr = A, B ; monitoredAddr = C, D, E ; resultingPairs {A,C - A,D - A,E - B,C - B,D - B-E}
			//e.g. monitoredAddr = A, B, C ; resultingPairs {A,B - B,A - A,C - C,A - B,C - C,B}

			var addressPairs []Pair
			if distanceCheck.Subscription.ReferenceAddress != nil {
				for _, refAddr := range distanceCheck.Subscription.ReferenceAddress {
					//loop through every monitored address
					for _, monitoredAddr := range distanceCheck.Subscription.MonitoredAddress {
						pair := Pair{addr1: refAddr, addr2: monitoredAddr}
						addressPairs = append(addressPairs, pair)
					}
				}
			} else {
				nbIndex := len(distanceCheck.Subscription.MonitoredAddress)
				for i := 0; i < nbIndex-1; i++ {
					for j := i + 1; j < nbIndex; j++ {
						pair := Pair{addr1: distanceCheck.Subscription.MonitoredAddress[i], addr2: distanceCheck.Subscription.MonitoredAddress[j]}
						addressPairs = append(addressPairs, pair)
						//need pair to be symmetrical so that each is used as reference point and monitored address
						pair = Pair{addr1: distanceCheck.Subscription.MonitoredAddress[j], addr2: distanceCheck.Subscription.MonitoredAddress[i]}
						addressPairs = append(addressPairs, pair)
					}
				}
			}

			for _, pair := range addressPairs {
				refAddr := pair.addr1
				monitoredAddr := pair.addr2

				//check if one of the address if both addresses are connected, if not, disregard this pair
				if !addressConnectedMap[refAddr] || !addressConnectedMap[monitoredAddr] {
					//ignore that pair and continue processing
					continue
				}

				var distParam gisClient.TargetPoint
				distParam.AssetName = monitoredAddr

				distResp, httpResp, err := gisAppClient.GeospatialDataApi.GetDistanceGeoDataByName(context.TODO(), refAddr, distParam)
				if err != nil {
					//getting distance of an element that is not in the DB (not in scenario, not connected) returns error code 400 (bad parameters) in the API. Using that error code to track that request made it to GIS but no good result, so ignore that address (monitored or ref)
					if httpResp.StatusCode == http.StatusBadRequest {
						//ignore that pair and continue processing
						continue
					} else {
						log.Error("Failed to communicate with gis engine: ", err)
						return
					}
				}

				distance := int32(distResp.Distance)

				switch *distanceCheck.Subscription.Criteria {
				case ALL_WITHIN_DISTANCE_DistanceCriteria:
					if float32(distance) < distanceCheck.Subscription.Distance {
						returnAddr[monitoredAddr] = &distResp
					} else {
						skipThisSubscription = true
					}
				case ALL_BEYOND_DISTANCE_DistanceCriteria:
					if float32(distance) > distanceCheck.Subscription.Distance {
						returnAddr[monitoredAddr] = &distResp
					} else {
						skipThisSubscription = true
					}
				case ANY_WITHIN_DISTANCE_DistanceCriteria:
					if float32(distance) < distanceCheck.Subscription.Distance {
						returnAddr[monitoredAddr] = &distResp
					}
				case ANY_BEYOND_DISTANCE_DistanceCriteria:
					if float32(distance) > distanceCheck.Subscription.Distance {
						returnAddr[monitoredAddr] = &distResp
					}
				default:
				}
				if skipThisSubscription {
					break
				}
			}
			if skipThisSubscription {
				continue
			}
			if len(returnAddr) > 0 {
				//update nb of notification sent anch check if valid
				subsIdStr := strconv.Itoa(subsId)

				var distanceNotif UserDistanceNotification
				distanceNotif.DistanceEvent = distanceCheck.Subscription.Criteria
				// distanceNotif.IsFinalNotification = false
				// distanceNotif.Link = distanceCheck.Subscription.Link

				var userList UserList
				var userInfoList []UserInfo
				for terminalAddr, distanceInfo := range returnAddr {
					var userInfo UserInfo
					userInfo.Address = terminalAddr
					var locationInfo LocationInfo
					locationInfo.Latitude = nil
					locationInfo.Latitude = append(locationInfo.Latitude, distanceInfo.DstLatitude)
					locationInfo.Longitude = nil
					locationInfo.Longitude = append(locationInfo.Longitude, distanceInfo.DstLongitude)
					locationInfo.Shape = 2
					seconds := time.Now().Unix()
					var timestamp TimeStamp
					timestamp.Seconds = int32(seconds)
					locationInfo.Timestamp = &timestamp
					userInfo.LocationInfo = &locationInfo
					// retrievalStatus := RETRIEVED_RetrievalStatus
					// terminalLocation.LocationRetrievalStatus = &retrievalStatus
					userInfoList = append(userInfoList, userInfo)
				}
				userList.User = userInfoList
				distanceNotif.MonitoredUsers = &userList
				distanceNotif.NotificationType = "UserDistanceNotification"
				distanceNotif.CallbackData = distanceCheck.Subscription.CallbackReference.CallbackData
				var inlineDistanceSubscriptionNotification InlineUserDistanceNotification
				inlineDistanceSubscriptionNotification.UserDistanceNotification = &distanceNotif
				distanceCheck.NbNotificationsSent++
				sendSubscriptionNotification3(distanceCheck.Subscription.CallbackReference.NotifyURL, inlineDistanceSubscriptionNotification)
				log.Info("Distance Notification"+"("+subsIdStr+") For ", returnAddr)
				// distanceSubscriptionMap[subsId].NextTts = distanceCheck.Subscription.Frequency
				// distanceSubscriptionMap[subsId].NotificationCheckReady = false
			}
		}
	}
}

// }

func checkNotificationDistancePeriodicTrigger() {

	//only check if there is at least one subscription
@@ -1654,6 +1813,26 @@ func sendSubscriptionNotification1(notifyUrl string, notification InlineUserLoca
	defer resp.Body.Close()
}

func sendSubscriptionNotification3(notifyUrl string, notification InlineUserDistanceNotification) {
	startTime := time.Now()
	jsonNotif, err := json.Marshal(notification)
	if err != nil {
		log.Error(err)
		return
	}

	resp, err := http.Post(notifyUrl, "application/json", bytes.NewBuffer(jsonNotif))
	duration := float64(time.Since(startTime).Microseconds()) / 1000.0
	_ = httpLog.LogNotification(notifyUrl, "POST", "", "", string(jsonNotif), resp, startTime)
	if err != nil {
		log.Error(err)
		met.ObserveNotification(sandboxName, serviceName, notifSubscription, notifyUrl, nil, duration)
		return
	}
	met.ObserveNotification(sandboxName, serviceName, notifSubscription, notifyUrl, resp, duration)
	defer resp.Body.Close()
}

func sendSubscriptionNotification(notifyUrl string, notification InlineSubscriptionNotification) {
	startTime := time.Now()
	jsonNotif, err := json.Marshal(notification)
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (c) 2022  The AdvantEDGE Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * AdvantEDGE Location API
 *
 * Location Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC013 Location API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/013/02.02.01_60/gs_mec013v020201p.pdf) <p>The API is based on the Open Mobile Alliance's specification RESTful Network API for Zonal Presence <p>[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt) <p>**Micro-service**<br>[meep-loc-serv](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-loc-serv) <p>**Type & Usage**<br>Edge Service used by edge applications that want to get information about Users (UE) and Zone locations <p>**Note**<br>AdvantEDGE supports all of Location API endpoints (see below).
 *
 * API version: 2.2.1
 * Contact: AdvantEDGE@InterDigital.com
 * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
 */
package server

type InlineUserDistanceNotification struct {
	UserDistanceNotification *UserDistanceNotification `json:"distanceNotificationSubscription,omitempty"`
}
+21 −0
Original line number Diff line number Diff line
/*
 * AdvantEDGE Location API
 *
 * Location Service is AdvantEDGE's implementation of [ETSI MEC ISG MEC013 Location API](https://www.etsi.org/deliver/etsi_gs/MEC/001_099/013/02.02.01_60/gs_mec013v020201p.pdf) <p>The API is based on the Open Mobile Alliance's specification RESTful Network API for Zonal Presence <p>[Copyright (c) ETSI 2017](https://forge.etsi.org/etsi-forge-copyright-notice.txt) <p>**Micro-service**<br>[meep-loc-serv](https://github.com/InterDigitalInc/AdvantEDGE/tree/master/go-apps/meep-loc-serv) <p>**Type & Usage**<br>Edge Service used by edge applications that want to get information about Users (UE) and Zone locations <p>**Note**<br>AdvantEDGE supports all of Location API endpoints (see below).
 *
 * API version: 2.2.1
 * Contact: AdvantEDGE@InterDigital.com
 * Generated by: Swagger Codegen (https://github.com/swagger-api/swagger-codegen.git)
 */
package server

type UserDistanceNotification struct {
	CallbackData  string            `json:"callbackData,omitempty"`
	DistanceEvent *DistanceCriteria `json:"distanceEvent"`

	MonitoredUsers *UserList `json:"monitoredUsers"`
	// Shall be set to \"UserDistanceNotification\".
	NotificationType string `json:"notificationType"`

	TimeStamp *TimeStamp `json:"timeStamp,omitempty"`
}