public void Handle(string json) { Console.WriteLine("Measurement handler invoked " + DateTime.UtcNow); var obj = JsonConvert.DeserializeObject <Measurement>(json, settings); string END_USER_URI = obj.user; int userId = storeAPI.GetIdFromURI(obj.user); Tuple <string, string> userLocales = storeAPI.GetUserLocale(END_USER_URI, userId); var LANG = userLocales.Item1; var tZone = userLocales.Item2; //var LANG = storeAPI.GetLang(obj.user); if (obj.measurement_type == "weight") { var weightValInfo = (WeightValueInfo)obj.value_info; var val = weightValInfo.Value; var kg = storeAPI.GetLatestWeightMeasurement(userId); var trend = "normal"; obj.ok = true; if (kg != 0) { if (Math.Abs(val - kg) > 2) { trend = val > kg ? "up" : "down"; obj.ok = false; } } storeAPI.PushMeasurement(JsonConvert.SerializeObject(obj)); if (trend == "down" || trend == "up") { var category = trend == "up" ? Loc.WEIGHT_INC : Loc.WEIGHT_DEC; var endUserMsg = string.Format(Loc.Get(LANG, Loc.MSG, category, Loc.USR), Math.Floor(Math.Abs(val - kg))); var caregiverMsg = string.Format(Loc.Get(LANG, Loc.MSG, category, Loc.CAREGVR), Math.Floor(Math.Abs(val - kg))); InformUser(END_USER_URI, "weight", "medium", endUserMsg, Loc.Get(LANG, Loc.DES, category, Loc.USR)); InformCaregivers(END_USER_URI, "weight", "medium", caregiverMsg, Loc.Get(LANG, Loc.DES, category, Loc.CAREGVR)); } } else if (obj.measurement_type == "pulse") { var pulseValInfo = (PulseValueInfo)obj.value_info; var val = pulseValInfo.Value; var min = 50; var midLow = 60; var midHigh = 100; var max = 120; if (val < min || val > max) { obj.ok = false; } else { obj.ok = true; } storeAPI.PushMeasurement(JsonConvert.SerializeObject(obj)); TimeZoneInfo localTz = TimeZoneInfo.FindSystemTimeZoneById(tZone); DateTime pulseDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0).AddSeconds(obj.timestamp); DateTime localizedPulseDateTime = UnixTimeStampToDateTime(obj.timestamp, localTz); if (pulseDateTime.AddHours(1) > DateTime.UtcNow && localizedPulseDateTime.Hour >= 6) { AnalyzePulseValue(val, min, midLow, midHigh, max, END_USER_URI); } /* * if (val < min || val > max) * { * obj.ok = false; * * * // For the AAL Forum we will analyse each pulse measurement individually because we do not expect them to arrive very often * // In any case, we will need a mechanism to switch between an individual and an aggregated analysis, based on context * // (e.g. how frequently do the measurements arrive and what is their source) * * if(storeAPI.AreLastNHeartRateCritical(3, min, max)) * { * var anEvent = new RMQ.INS.Event() { category = "HEART_RATE", content = new RMQ.INS.Content() { num_value = val } }; * insertionAPI.InsertEvent( JsonConvert.SerializeObject(anEvent)); * } * * //storeAPI.PushJournalEntry("Pulse is abnormal", "Pulse is abnormal", "pulse"); * } * else * { * obj.ok = true; * } */ } else if (obj.measurement_type == "blood_pressure") { // TODO: for now we are treating the pulse values from blood_pressure measurements (if they contain one) in the same // way in which we would handle pulse measurements from the FitBit. This is mostly for demo purposes and will change in the future. // First, just save the blood_pressure measurement in the CAMI Store, marking it as ok, because we perform no analysis on BP values obj.ok = true; storeAPI.PushMeasurement(JsonConvert.SerializeObject(obj)); // Then perform analysis on Pulse value, if there is any var bpValInfo = (BloodPressureValueInfo)obj.value_info; var val = bpValInfo.pulse; // if it has pulse information if (val != 0) { var min = 50; var midLow = 60; var midHigh = 100; var max = 120; // create a new measurement object of type Pulse, copying over meta data from the BP obj var pulseObj = new Measurement(); pulseObj.measurement_type = "pulse"; pulseObj.unit_type = "bpm"; pulseObj.timestamp = obj.timestamp; pulseObj.user = obj.user; pulseObj.device = obj.device; pulseObj.gateway_id = obj.gateway_id; var pulseValInfo = new PulseValueInfo(); pulseValInfo.Value = val; pulseObj.value_info = pulseValInfo; if (val < min || val > max) { pulseObj.ok = false; } else { pulseObj.ok = true; } // first store the measurement in the CAMI Store storeAPI.PushMeasurement(JsonConvert.SerializeObject(pulseObj)); // TODO: currently we know that notification are handled client side only for the CamiDemo user (id = 2), so if we are not // handling data for that user, do not send alerts AnalyzePulseValue(val, min, midLow, midHigh, max, END_USER_URI); } } else if (obj.measurement_type == "steps") { Console.WriteLine("Steps invoked!"); obj.ok = true; storeAPI.PushMeasurement(JsonConvert.SerializeObject(obj)); // start the step count timer for this user if not already done so StartStepsTimer(obj.user); } else { // for measurements for which there is no analysis, just mark the measurement as ok and insert it in the CAMI Store obj.ok = true; storeAPI.PushMeasurement(JsonConvert.SerializeObject(obj)); } }