Skip to content
loc-serv.go 55.3 KiB
Newer Older
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory Address parameter not present")
		http.Error(w, "Mandatory Address parameter not present", http.StatusBadRequest)
	newSubsId := nextUserSubscriptionIdAvailable
	nextUserSubscriptionIdAvailable++
	subsIdStr := strconv.Itoa(newSubsId)

	registerUser(userTrackingSub.Address, userTrackingSub.UserEventCriteria, subsIdStr)
	userTrackingSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/userTracking/" + subsIdStr
	_ = rc.JSONSetEntry(baseKey+typeUserSubscription+":"+subsIdStr, ".", convertUserSubscriptionToJson(userTrackingSub))
	response.UserTrackingSubscription = userTrackingSub
	jsonResponse, err := json.Marshal(response)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusCreated)
	fmt.Fprintf(w, string(jsonResponse))
}

Simon Pastor's avatar
Simon Pastor committed
func userTrackingSubPut(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	vars := mux.Vars(r)

	var response InlineUserTrackingSubscription
	var body InlineUserTrackingSubscription
	decoder := json.NewDecoder(r.Body)
Simon Pastor's avatar
Simon Pastor committed
	err := decoder.Decode(&body)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
Simon Pastor's avatar
Simon Pastor committed
	userTrackingSub := body.UserTrackingSubscription

	if userTrackingSub == nil {
		log.Error("Body not present")
		http.Error(w, "Body not present", http.StatusBadRequest)
	//checking for mandatory properties
	if userTrackingSub.CallbackReference == nil || userTrackingSub.CallbackReference.NotifyURL == "" {
		log.Error("Mandatory CallbackReference parameter not present")
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory Address parameter not present")
		http.Error(w, "Mandatory Address parameter not present", http.StatusBadRequest)
	if userTrackingSub.ResourceURL == "" {
		log.Error("Mandatory ResourceURL parameter not present")
		http.Error(w, "Mandatory ResourceURL parameter not present", http.StatusBadRequest)
Simon Pastor's avatar
Simon Pastor committed
	subsIdParamStr := vars["subscriptionId"]

	selfUrl := strings.Split(userTrackingSub.ResourceURL, "/")
	subsIdStr := selfUrl[len(selfUrl)-1]

Simon Pastor's avatar
Simon Pastor committed
	//Body content not matching parameters
Simon Pastor's avatar
Simon Pastor committed
	if subsIdStr != subsIdParamStr {
		log.Error("SubscriptionId in endpoint and in body not matching")
		http.Error(w, "SubscriptionId in endpoint and in body not matching", http.StatusBadRequest)
	userTrackingSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/userTracking/" + subsIdStr
	subsId, err := strconv.Atoi(subsIdStr)
	if err != nil {
		log.Error(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
Simon Pastor's avatar
Simon Pastor committed

Simon Pastor's avatar
Simon Pastor committed
	if userSubscriptionMap[subsId] == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	_ = rc.JSONSetEntry(baseKey+typeUserSubscription+":"+subsIdStr, ".", convertUserSubscriptionToJson(userTrackingSub))

	deregisterUser(subsIdStr)
	registerUser(userTrackingSub.Address, userTrackingSub.UserEventCriteria, subsIdStr)
	response.UserTrackingSubscription = userTrackingSub
	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))
func populateUserTrackingList(key string, jsonInfo string, userData interface{}) error {
Simon Pastor's avatar
Simon Pastor committed
	userList := userData.(*NotificationSubscriptionList)
	var userInfo UserTrackingSubscription

	// Format response
	err := json.Unmarshal([]byte(jsonInfo), &userInfo)
	if err != nil {
		return err
	}
	userList.UserTrackingSubscription = append(userList.UserTrackingSubscription, userInfo)
	return nil
}

Simon Pastor's avatar
Simon Pastor committed
func zonalTrafficSubDelete(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	vars := mux.Vars(r)

	err := rc.JSONDelEntry(baseKey+typeZonalSubscription+":"+vars["subscriptionId"], ".")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	deregisterZonal(vars["subscriptionId"])
	w.WriteHeader(http.StatusNoContent)
Simon Pastor's avatar
Simon Pastor committed
func zonalTrafficSubListGet(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	var response InlineNotificationSubscriptionList
Simon Pastor's avatar
Simon Pastor committed
	var zonalTrafficSubList NotificationSubscriptionList
	zonalTrafficSubList.ResourceURL = hostUrl.String() + basePath + "subscriptions/zonalTraffic"
	response.NotificationSubscriptionList = &zonalTrafficSubList
	keyName := baseKey + typeZonalSubscription + "*"
	err := rc.ForEachJSONEntry(keyName, populateZonalTrafficList, &zonalTrafficSubList)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	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))
}

Simon Pastor's avatar
Simon Pastor committed
func zonalTrafficSubGet(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	vars := mux.Vars(r)

	var response InlineZonalTrafficSubscription
	var zonalTrafficSub ZonalTrafficSubscription
	response.ZonalTrafficSubscription = &zonalTrafficSub
	jsonZonalTrafficSub, _ := rc.JSONGetEntry(baseKey+typeZonalSubscription+":"+vars["subscriptionId"], ".")
	if jsonZonalTrafficSub == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	err := json.Unmarshal([]byte(jsonZonalTrafficSub), &zonalTrafficSub)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	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))
}

func zonalTrafficSubPost(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	var response InlineZonalTrafficSubscription
	var body InlineZonalTrafficSubscription
	decoder := json.NewDecoder(r.Body)
Simon Pastor's avatar
Simon Pastor committed
	err := decoder.Decode(&body)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
Simon Pastor's avatar
Simon Pastor committed
	zonalTrafficSub := body.ZonalTrafficSubscription

	if zonalTrafficSub == nil {
		log.Error("Body not present")
		http.Error(w, "Body not present", http.StatusBadRequest)
	//checking for mandatory properties
	if zonalTrafficSub.CallbackReference == nil || zonalTrafficSub.CallbackReference.NotifyURL == "" {
		log.Error("Mandatory CallbackReference parameter not present")
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory ZoneId parameter not present")
		http.Error(w, "Mandatory ZoneId parameter not present", http.StatusBadRequest)
	newSubsId := nextZonalSubscriptionIdAvailable
	nextZonalSubscriptionIdAvailable++
	subsIdStr := strconv.Itoa(newSubsId)
	/*
		if zonalTrafficSub.Duration > 0 {
			//TODO start a timer mecanism and expire subscription
		}
		//else, lasts forever or until subscription is deleted
	*/
Simon Pastor's avatar
Simon Pastor committed
	if zonalTrafficSub.Duration != 0 { //used to be string -> zonalTrafficSub.Duration != "" && zonalTrafficSub.Duration != "0" {
		//TODO start a timer mecanism and expire subscription
		log.Info("Non zero duration")
	}
	//else, lasts forever or until subscription is deleted

	zonalTrafficSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/zonalTraffic/" + subsIdStr
	_ = rc.JSONSetEntry(baseKey+typeZonalSubscription+":"+subsIdStr, ".", convertZonalSubscriptionToJson(zonalTrafficSub))
	registerZonal(zonalTrafficSub.ZoneId, zonalTrafficSub.UserEventCriteria, subsIdStr)
	response.ZonalTrafficSubscription = zonalTrafficSub
	jsonResponse, err := json.Marshal(response)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	w.WriteHeader(http.StatusCreated)
	fmt.Fprintf(w, string(jsonResponse))
}

Simon Pastor's avatar
Simon Pastor committed
func zonalTrafficSubPut(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	vars := mux.Vars(r)

	var response InlineZonalTrafficSubscription
	var body InlineZonalTrafficSubscription
	decoder := json.NewDecoder(r.Body)
Simon Pastor's avatar
Simon Pastor committed
	err := decoder.Decode(&body)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
Simon Pastor's avatar
Simon Pastor committed
	zonalTrafficSub := body.ZonalTrafficSubscription

	if zonalTrafficSub == nil {
		log.Error("Body not present")
		http.Error(w, "Body not present", http.StatusBadRequest)
	//checking for mandatory properties
	if zonalTrafficSub.CallbackReference == nil || zonalTrafficSub.CallbackReference.NotifyURL == "" {
		log.Error("Mandatory CallbackReference parameter not present")
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory ZoneId parameter not present")
		http.Error(w, "Mandatory ZoneId parameter not present", http.StatusBadRequest)
	if zonalTrafficSub.ResourceURL == "" {
		log.Error("Mandatory ResourceURL parameter not present")
		http.Error(w, "Mandatory ResourceURL parameter not present", http.StatusBadRequest)
Simon Pastor's avatar
Simon Pastor committed
	subsIdParamStr := vars["subscriptionId"]

	selfUrl := strings.Split(zonalTrafficSub.ResourceURL, "/")
	subsIdStr := selfUrl[len(selfUrl)-1]

Simon Pastor's avatar
Simon Pastor committed
	//body content not matching parameters
Simon Pastor's avatar
Simon Pastor committed
	if subsIdStr != subsIdParamStr {
		log.Error("SubscriptionId in endpoint and in body not matching")
		http.Error(w, "SubscriptionId in endpoint and in body not matching", http.StatusBadRequest)
	zonalTrafficSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/zonalTraffic/" + subsIdStr
Simon Pastor's avatar
Simon Pastor committed
	subsId, err := strconv.Atoi(subsIdStr)
	if err != nil {
		log.Error(err)
		w.WriteHeader(http.StatusBadRequest)
		return
	}
Simon Pastor's avatar
Simon Pastor committed

Simon Pastor's avatar
Simon Pastor committed
	if zonalSubscriptionMap[subsId] == "" {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	_ = rc.JSONSetEntry(baseKey+typeZonalSubscription+":"+subsIdStr, ".", convertZonalSubscriptionToJson(zonalTrafficSub))

	deregisterZonal(subsIdStr)
	registerZonal(zonalTrafficSub.ZoneId, zonalTrafficSub.UserEventCriteria, subsIdStr)
	response.ZonalTrafficSubscription = zonalTrafficSub
	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))
func populateZonalTrafficList(key string, jsonInfo string, userData interface{}) error {
Simon Pastor's avatar
Simon Pastor committed
	zoneList := userData.(*NotificationSubscriptionList)
	var zoneInfo ZonalTrafficSubscription

	// Format response
	err := json.Unmarshal([]byte(jsonInfo), &zoneInfo)
	if err != nil {
		return err
	}
	zoneList.ZonalTrafficSubscription = append(zoneList.ZonalTrafficSubscription, zoneInfo)
	return nil
}

Simon Pastor's avatar
Simon Pastor committed
func zoneStatusSubDelete(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	err := rc.JSONDelEntry(baseKey+typeZoneStatusSubscription+":"+vars["subscriptionId"], ".")
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	deregisterZoneStatus(vars["subscriptionId"])
	w.WriteHeader(http.StatusNoContent)
Simon Pastor's avatar
Simon Pastor committed
func zoneStatusSubListGet(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")

	var response InlineNotificationSubscriptionList
Simon Pastor's avatar
Simon Pastor committed
	var zoneStatusSubList NotificationSubscriptionList
	zoneStatusSubList.ResourceURL = hostUrl.String() + basePath + "subscriptions/zoneStatus"
	response.NotificationSubscriptionList = &zoneStatusSubList
	keyName := baseKey + typeZoneStatusSubscription + "*"
	err := rc.ForEachJSONEntry(keyName, populateZoneStatusList, &zoneStatusSubList)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	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))
}

Simon Pastor's avatar
Simon Pastor committed
func zoneStatusSubGet(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	var response InlineZoneStatusSubscription
	var zoneStatusSub ZoneStatusSubscription
	response.ZoneStatusSubscription = &zoneStatusSub
	jsonZoneStatusSub, _ := rc.JSONGetEntry(baseKey+typeZoneStatusSubscription+":"+vars["subscriptionId"], ".")
	if jsonZoneStatusSub == "" {
	err := json.Unmarshal([]byte(jsonZoneStatusSub), &zoneStatusSub)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	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))
Simon Pastor's avatar
Simon Pastor committed
func zoneStatusSubPost(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	var response InlineZoneStatusSubscription
	var body InlineZoneStatusSubscription
	decoder := json.NewDecoder(r.Body)
Simon Pastor's avatar
Simon Pastor committed
	err := decoder.Decode(&body)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
Simon Pastor's avatar
Simon Pastor committed
	zoneStatusSub := body.ZoneStatusSubscription

	if zoneStatusSub == nil {
		log.Error("Body not present")
		http.Error(w, "Body not present", http.StatusBadRequest)
	//checking for mandatory properties
	if zoneStatusSub.CallbackReference == nil || zoneStatusSub.CallbackReference.NotifyURL == "" {
		log.Error("Mandatory CallbackReference parameter not present")
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory ZoneId parameter not present")
		http.Error(w, "Mandatory ZoneId parameter not present", http.StatusBadRequest)
	newSubsId := nextZoneStatusSubscriptionIdAvailable
	nextZoneStatusSubscriptionIdAvailable++
	subsIdStr := strconv.Itoa(newSubsId)

	zoneStatusSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/zoneStatus/" + subsIdStr
	_ = rc.JSONSetEntry(baseKey+typeZoneStatusSubscription+":"+subsIdStr, ".", convertZoneStatusSubscriptionToJson(zoneStatusSub))
	registerZoneStatus(zoneStatusSub.ZoneId, zoneStatusSub.NumberOfUsersZoneThreshold, zoneStatusSub.NumberOfUsersAPThreshold,
		zoneStatusSub.OperationStatus, subsIdStr)
	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.StatusCreated)
Simon Pastor's avatar
Simon Pastor committed
func zoneStatusSubPut(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json; charset=UTF-8")
	var response InlineZoneStatusSubscription
	var body InlineZoneStatusSubscription
Simon Pastor's avatar
Simon Pastor committed
	err := decoder.Decode(&body)
	if err != nil {
		log.Error(err.Error())
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
Simon Pastor's avatar
Simon Pastor committed
	zoneStatusSub := body.ZoneStatusSubscription

	if zoneStatusSub == nil {
		log.Error("Body not present")
		http.Error(w, "Body not present", http.StatusBadRequest)
	//checking for mandatory properties
	if zoneStatusSub.CallbackReference == nil || zoneStatusSub.CallbackReference.NotifyURL == "" {
		log.Error("Mandatory CallbackReference parameter not present")
		http.Error(w, "Mandatory CallbackReference parameter not present", http.StatusBadRequest)
		log.Error("Mandatory ZoneId parameter not present")
		http.Error(w, "Mandatory ZoneId parameter not present", http.StatusBadRequest)
	if zoneStatusSub.ResourceURL == "" {
		log.Error("Mandatory ResourceURL parameter not present")
		http.Error(w, "Mandatory ResourceURL parameter not present", http.StatusBadRequest)
Simon Pastor's avatar
Simon Pastor committed
	subsIdParamStr := vars["subscriptionId"]

	selfUrl := strings.Split(zoneStatusSub.ResourceURL, "/")
	subsIdStr := selfUrl[len(selfUrl)-1]

Simon Pastor's avatar
Simon Pastor committed
	//body content not matching parameters
Simon Pastor's avatar
Simon Pastor committed
	if subsIdStr != subsIdParamStr {
		log.Error("SubscriptionId in endpoint and in body not matching")
		http.Error(w, "SubscriptionId in endpoint and in body not matching", http.StatusBadRequest)
	zoneStatusSub.ResourceURL = hostUrl.String() + basePath + "subscriptions/zoneStatus/" + subsIdStr
Simon Pastor's avatar
Simon Pastor committed
	subsId, err := strconv.Atoi(subsIdStr)
	if err != nil {
		log.Error(err)
		w.WriteHeader(http.StatusBadRequest)
Simon Pastor's avatar
Simon Pastor committed
	if zoneStatusSubscriptionMap[subsId] == nil {
		w.WriteHeader(http.StatusNotFound)
		return
	}

	_ = rc.JSONSetEntry(baseKey+typeZoneStatusSubscription+":"+subsIdStr, ".", convertZoneStatusSubscriptionToJson(zoneStatusSub))
	registerZoneStatus(zoneStatusSub.ZoneId, zoneStatusSub.NumberOfUsersZoneThreshold, zoneStatusSub.NumberOfUsersAPThreshold,
		zoneStatusSub.OperationStatus, subsIdStr)
	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))
func populateZoneStatusList(key string, jsonInfo string, userData interface{}) error {
Simon Pastor's avatar
Simon Pastor committed
	zoneList := userData.(*NotificationSubscriptionList)
	var zoneInfo ZoneStatusSubscription

	// Format response
	err := json.Unmarshal([]byte(jsonInfo), &zoneInfo)
	if err != nil {
		return err
	}
	zoneList.ZoneStatusSubscription = append(zoneList.ZoneStatusSubscription, zoneInfo)
	return nil
}

Simon Pastor's avatar
Simon Pastor committed
func cleanUp() {
	log.Info("Terminate all")
Simon Pastor's avatar
Simon Pastor committed
	nextZonalSubscriptionIdAvailable = 1
	nextUserSubscriptionIdAvailable = 1
	nextZoneStatusSubscriptionIdAvailable = 1
	previousNbUsersInAp = 0
	previousNbUsersInZone = 0
Simon Pastor's avatar
Simon Pastor committed

	mutex.Lock()
	defer mutex.Unlock()
Simon Pastor's avatar
Simon Pastor committed
	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{}
Simon Pastor's avatar
Simon Pastor committed

	updateStoreName("")
}

func updateStoreName(storeName string) {
Simon Pastor's avatar
Simon Pastor committed
	if currentStoreName != storeName {
		currentStoreName = storeName
		_ = httpLog.ReInit(logModuleLocServ, sandboxName, storeName, redisAddr, influxAddr)
	}
Simon Pastor's avatar
Simon Pastor committed
}

func updateUserInfo(address string, zoneId string, accessPointId string, longitude *float32, latitude *float32) {
	jsonUserInfo, _ := rc.JSONGetEntry(baseKey+typeUser+":"+address, ".")
Simon Pastor's avatar
Simon Pastor committed

	// Create new user info if necessary
	if userInfo == nil {
		userInfo = new(UserInfo)
		userInfo.Address = address
Simon Pastor's avatar
Simon Pastor committed
		userInfo.ResourceURL = hostUrl.String() + basePath + "queries/users?address=" + address
Simon Pastor's avatar
Simon Pastor committed
		oldZoneId = userInfo.ZoneId
		oldApId = userInfo.AccessPointId
	}
	userInfo.ZoneId = zoneId
	userInfo.AccessPointId = accessPointId
Simon Pastor's avatar
Simon Pastor committed

	// Update position
	if longitude == nil || latitude == nil {
		userInfo.LocationInfo = nil
	} else {
		if userInfo.LocationInfo == nil {
			userInfo.LocationInfo = new(LocationInfo)
		}
Simon Pastor's avatar
Simon Pastor committed
		//we only support shape == 2 in locationInfo, so we ignore any conditional parameters based on shape
		userInfo.LocationInfo.Shape = 2
Simon Pastor's avatar
Simon Pastor committed
		userInfo.LocationInfo.Longitude = nil
		userInfo.LocationInfo.Longitude = append(userInfo.LocationInfo.Longitude, *longitude)
		userInfo.LocationInfo.Latitude = nil
		userInfo.LocationInfo.Latitude = append(userInfo.LocationInfo.Latitude, *latitude)

		seconds := time.Now().Unix()
		var timeStamp TimeStamp
		timeStamp.Seconds = int32(seconds)

		userInfo.LocationInfo.Timestamp = &timeStamp
	// Update User info in DB & Send notifications
	_ = rc.JSONSetEntry(baseKey+typeUser+":"+address, ".", convertUserInfoToJson(userInfo))
Simon Pastor's avatar
Simon Pastor committed
	checkNotificationRegistrations(USER_TRACKING_AND_ZONAL_TRAFFIC, oldZoneId, zoneId, oldApId, accessPointId, address)
Simon Pastor's avatar
Simon Pastor committed
func updateZoneInfo(zoneId string, nbAccessPoints int, nbUnsrvAccessPoints int, nbUsers int) {
	jsonZoneInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+zoneId, ".")
Simon Pastor's avatar
Simon Pastor committed

	// Create new zone info if necessary
	if zoneInfo == nil {
		zoneInfo = new(ZoneInfo)
		zoneInfo.ZoneId = zoneId
Simon Pastor's avatar
Simon Pastor committed
		zoneInfo.ResourceURL = hostUrl.String() + basePath + "queries/zones/" + zoneId
		zoneInfo.NumberOfAccessPoints = int32(nbAccessPoints)
Simon Pastor's avatar
Simon Pastor committed
		zoneInfo.NumberOfUnserviceableAccessPoints = int32(nbUnsrvAccessPoints)
		zoneInfo.NumberOfUsers = int32(nbUsers)
Simon Pastor's avatar
Simon Pastor committed

	// Update Zone info in DB & Send notifications
	_ = rc.JSONSetEntry(baseKey+typeZone+":"+zoneId, ".", convertZoneInfoToJson(zoneInfo))
Simon Pastor's avatar
Simon Pastor committed
	checkNotificationRegistrations(ZONE_STATUS, zoneId, "", "", strconv.Itoa(nbUsers), "")
func updateAccessPointInfo(zoneId string, apId string, conTypeStr string, opStatusStr string, nbUsers int, longitude *float32, latitude *float32) {
	jsonApInfo, _ := rc.JSONGetEntry(baseKey+typeZone+":"+zoneId+":"+typeAccessPoint+":"+apId, ".")
Simon Pastor's avatar
Simon Pastor committed

	// Create new AP info if necessary
	if apInfo == nil {
		apInfo = new(AccessPointInfo)
		apInfo.AccessPointId = apId
Simon Pastor's avatar
Simon Pastor committed
		apInfo.ResourceURL = hostUrl.String() + basePath + "queries/zones/" + zoneId + "/accessPoints/" + apId
		opStatus := convertStringToOperationStatus(opStatusStr)
		apInfo.OperationStatus = &opStatus
Simon Pastor's avatar
Simon Pastor committed
	if conTypeStr != "" {
		conType := convertStringToConnectionType(conTypeStr)
		apInfo.ConnectionType = &conType
	}
		apInfo.NumberOfUsers = int32(nbUsers)
	// Update position
	if longitude == nil || latitude == nil {
		apInfo.LocationInfo = nil
	} else {
		if apInfo.LocationInfo == nil {
			apInfo.LocationInfo = new(LocationInfo)
			apInfo.LocationInfo.Accuracy = 1
		}
Simon Pastor's avatar
Simon Pastor committed
		//we only support shape != 7 in locationInfo
		apInfo.LocationInfo.Shape = 2
Simon Pastor's avatar
Simon Pastor committed
		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
	// Update AP info in DB & Send notifications
	_ = rc.JSONSetEntry(baseKey+typeZone+":"+zoneId+":"+typeAccessPoint+":"+apId, ".", convertAccessPointInfoToJson(apInfo))
Simon Pastor's avatar
Simon Pastor committed
	checkNotificationRegistrations(ZONE_STATUS, zoneId, apId, strconv.Itoa(nbUsers), "", "")
func zoneStatusReInit() {
	//reusing the object response for the get multiple zoneStatusSubscription
Simon Pastor's avatar
Simon Pastor committed
	var zoneList NotificationSubscriptionList
	keyName := baseKey + typeZoneStatusSubscription + "*"
	_ = rc.ForEachJSONEntry(keyName, populateZoneStatusList, &zoneList)
	mutex.Lock()
	defer mutex.Unlock()
	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 = (int)(zone.NumberOfUsersZoneThreshold)
			zoneStatus.NbUsersInAPThreshold = (int)(zone.NumberOfUsersAPThreshold)
			zoneStatus.ZoneId = zone.ZoneId
			zoneStatusSubscriptionMap[subscriptionId] = &zoneStatus
		}
	}
	nextZoneStatusSubscriptionIdAvailable = maxZoneStatusSubscriptionId + 1
}

func zonalTrafficReInit() {
	//reusing the object response for the get multiple zonalSubscription
Simon Pastor's avatar
Simon Pastor committed
	var zoneList NotificationSubscriptionList
	keyName := baseKey + typeZonalSubscription + "*"
	_ = rc.ForEachJSONEntry(keyName, populateZonalTrafficList, &zoneList)

	maxZonalSubscriptionId := 0
	mutex.Lock()
	defer mutex.Unlock()
	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] {
Simon Pastor's avatar
Simon Pastor committed
				case ENTERING_EVENT:
					zonalSubscriptionEnteringMap[subscriptionId] = zone.ZoneId
Simon Pastor's avatar
Simon Pastor committed
				case LEAVING_EVENT:
					zonalSubscriptionLeavingMap[subscriptionId] = zone.ZoneId
Simon Pastor's avatar
Simon Pastor committed
				case TRANSFERRING_EVENT:
					zonalSubscriptionTransferringMap[subscriptionId] = zone.ZoneId
			zonalSubscriptionMap[subscriptionId] = zone.ZoneId
		}
	}
	nextZonalSubscriptionIdAvailable = maxZonalSubscriptionId + 1
}

func userTrackingReInit() {
	//reusing the object response for the get multiple zonalSubscription
Simon Pastor's avatar
Simon Pastor committed
	var userList NotificationSubscriptionList
	keyName := baseKey + typeUserSubscription + "*"
	_ = rc.ForEachJSONEntry(keyName, populateUserTrackingList, &userList)

	maxUserSubscriptionId := 0
	mutex.Lock()
	defer mutex.Unlock()

	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] {
Simon Pastor's avatar
Simon Pastor committed
				case ENTERING_EVENT:
					userSubscriptionEnteringMap[subscriptionId] = user.Address
Simon Pastor's avatar
Simon Pastor committed
				case LEAVING_EVENT:
					userSubscriptionLeavingMap[subscriptionId] = user.Address
Simon Pastor's avatar
Simon Pastor committed
				case TRANSFERRING_EVENT:
					userSubscriptionTransferringMap[subscriptionId] = user.Address
			userSubscriptionMap[subscriptionId] = user.Address
		}
	}
	nextUserSubscriptionIdAvailable = maxUserSubscriptionId + 1
}