/// <summary> /// Gets the status of on an intersection without acquiring a lock. /// This should only be called if the lock has already been acquired /// </summary> /// <param name="id">The ID the intersection to query</param> /// <returns>The intersection status</returns> private List <IntersectionStatus> GetIntersectionStatusNoLock(string[] id) { var client = new TmddEnhancedServiceClient(); List <IntersectionStatus> returnStatus = new List <IntersectionStatus>(); IntersectionSignalStatus[] status = PerformStatusQuery(id, client); foreach (IntersectionSignalStatus s in status) { IntersectionStatus curStatus = new IntersectionStatus(); curStatus.ID = s.devicestatusheader.deviceid; IntersectionSignalTimingInventory inventory = PerformTimingInventoryQuery(s.devicestatusheader.deviceid, client); curStatus.Name = ""; curStatus.GroupGreens = s.phasestatus.phasestatusgroup[0].phasestatusgroupgreens; curStatus.AllPhases = new List <PhaseInfo>(); curStatus.ActivePhases = GetActivePhases(s.phasestatus.phasestatusgroup[0].phasestatusgroupgreens); foreach (var phase in inventory.phases.phases) { PhaseInfo item = new PhaseInfo(); item.PhaseID = phase.phaseidentifier; item.MinGreen = phase.MinGreen; item.MaxGreen = phase.MaxLimit; item.LastActiveTime = 0; item.CurrentlyActive = curStatus.ActivePhases.Contains(item.PhaseID); curStatus.AllPhases.Add(item); } returnStatus.Add(curStatus); } return(returnStatus); }
/// <summary> /// Gets the status of an intersection. The status is returned from the statusDictionary if it is getting continuous updates /// </summary> /// <param name="id">ID of the intersection to get the status of</param> /// <param name="forceQuery">If true the status will not be returned from the statusDictionary even if it exists in it</param> /// <returns>The intersection status</returns> public IntersectionStatus GetIntersectionStatus(string id, bool forceQuery = false) { lock (statusLock) { // If we are already tracking the status of the intersection return that value if (statusDictionary.ContainsKey(id) && !forceQuery && statusDictionary[id] != null) { IntersectionStatus status = new IntersectionStatus(); status.ActivePhases = statusDictionary[id].ActivePhases; status.AllPhases = statusDictionary[id].AllPhases; status.GroupGreens = statusDictionary[id].GroupGreens; status.ID = statusDictionary[id].ID; status.Name = statusDictionary[id].Name; return(status); } // If we are not tracking still return the intersection status else { var client = new TmddEnhancedServiceClient(); IntersectionStatus returnStatus = new IntersectionStatus(); IntersectionSignalStatus status = PerformStatusQuery(new string[] { id }, client)[0]; IntersectionSignalTimingInventory inventory = PerformTimingInventoryQuery(id, client); returnStatus.ID = status.devicestatusheader.deviceid; returnStatus.Name = ""; returnStatus.GroupGreens = status.phasestatus.phasestatusgroup[0].phasestatusgroupgreens; returnStatus.AllPhases = new List <PhaseInfo>(); returnStatus.ActivePhases = GetActivePhases(status.phasestatus.phasestatusgroup[0].phasestatusgroupgreens); foreach (var phase in inventory.phases.phases) { PhaseInfo item = new PhaseInfo(); item.PhaseID = phase.phaseidentifier; item.MinGreen = phase.MinGreen; item.MaxGreen = phase.MaxLimit; item.LastActiveTime = 0; item.CurrentlyActive = returnStatus.ActivePhases.Contains(item.PhaseID); returnStatus.AllPhases.Add(item); } return(returnStatus); } } }
/// <summary> /// This function will run in a seperate thread constantly updaing the status of each intersection registered for status updates /// </summary> private void UpdatePhaseStatuses() { while (running) { lock (statusLock) { var keys = new List <string>(statusDictionary.Keys); List <IntersectionStatus> statuses = GetIntersectionStatusNoLock(keys.ToArray()); foreach (IntersectionStatus status in statuses) { if (statusDictionary.ContainsKey(status.ID)) { IntersectionStatus oldStatus = statusDictionary[status.ID]; bool logChange = false; // If this isn't the first update for this intersection if (oldStatus != null) { for (int i = 0; i < status.AllPhases.Count; i++) { PhaseInfo oldPhase = oldStatus.AllPhases.Find(x => x.PhaseID == status.AllPhases[i].PhaseID); // Phase has become inactive if (oldPhase.CurrentlyActive && !status.AllPhases[i].CurrentlyActive) { status.AllPhases[i].CurrentActiveTime = 0f; status.AllPhases[i].LastActiveTime = (float)(DateTime.Now - oldPhase.BecameActiveTimestamp).TotalSeconds; logChange = true; } // Phase has just become active else if (!oldPhase.CurrentlyActive && status.AllPhases[i].CurrentlyActive) { status.AllPhases[i].LastActiveTime = oldPhase.LastActiveTime; status.AllPhases[i].BecameActiveTimestamp = DateTime.Now; logChange = true; } // No change in phase state and active else if (status.AllPhases[i].CurrentlyActive) { status.AllPhases[i].LastActiveTime = oldPhase.LastActiveTime; status.AllPhases[i].BecameActiveTimestamp = oldPhase.BecameActiveTimestamp; status.AllPhases[i].CurrentActiveTime = (float)(DateTime.Now - status.AllPhases[i].BecameActiveTimestamp).TotalSeconds; } // No change in phase state and not active else { status.AllPhases[i] = oldPhase; } } } else { foreach (int activePhase in status.ActivePhases) { status.AllPhases.Find(x => x.PhaseID == activePhase).BecameActiveTimestamp = DateTime.Now; } } statusDictionary[status.ID] = status; if (logChange) { string text = DateTime.Now.ToString("MM/dd/yyyy\tHH:mm:ss") + '\t'; foreach (int i in status.ActivePhases) { text += i.ToString() + '\t'; } text += '\n'; try { if (!Directory.Exists(LOGFILE_PATH)) { Directory.CreateDirectory(LOGFILE_PATH); } File.AppendAllText(LOGFILE_PATH + status.ID + ".lg", text); } catch (Exception e) { LogError(e.Message); } } } } } // Wait one second before checking status Thread.Sleep(1000); } }