using System.Threading.Channels; using System.Timers; using UI_SequentMicrosystems.Components; using UI_SequentMicrosystems.Models; using Wrapper_Api_SequentMicrosystems.RTD8TM; namespace UI_SequentMicrosystems.Services { public class RTD8TMService { private SortedList ChanelNames = new SortedList(); private SortedList ActualValues = new SortedList(); private SortedList ValuesType = new SortedList(); private SortedList Calibrations = new SortedList(); public SortedList>> GraphData = new(); public SortedList>> GraphFiltered = new(); private byte GraphDataCounterCount = 10; private byte GraphDataCounter = 9; private string? Address { get; set; } private RTD8TM _RTD8TM = new RTD8TM(); private System.Timers.Timer _timer = new(1000); public delegate Task AsyncEventHandler(object? sender, TEventArgs? e); public event AsyncEventHandler? EventUpdateValues; public event AsyncEventHandler? EventUpdateGraph; public RTD8TMService() { _timer.AutoReset = true; _timer.Elapsed += TimerElapsed; _timer.Start(); } //Main Parameters Work /// /// Set Device Address /// /// Address [Base url] (http://1.2.3.4) public void SetAddress(string address) { Address = address; GetChanelsNames(); GetValueTypes(); GetCalibrations(); } /// /// Get used device Address /// /// Address or empty string public string GetAddress() { if (Address == null) { return ""; } else { return Address; } } //Actual Data /// /// Read Actual values from Device /// private async void GetActualValues() { if (Address == null) { return; } ActualValues = await _RTD8TM.Get(Address); foreach (byte stack in ActualValues.Keys) { if (Calibrations.ContainsKey(stack)) { for (byte chanel = 0; chanel < 8; chanel++) { ActualValues[stack][chanel] += Calibrations[stack][chanel]; } } } if (GraphDataCounter >= GraphDataCounterCount) { GraphDataCounter = 0; ReadChartData(); if (EventUpdateGraph != null) { await EventUpdateGraph.Invoke(this, true); } } else { GraphDataCounter++; } } /// /// Request for actual data /// /// public SortedList GetActualData() { return ActualValues; } /// /// Get actual data Value /// /// Stack ID /// Chanel ID /// Measure Resistance public float GetActualData(byte stack, byte chanel) { if (ActualValues.ContainsKey(stack)) { return ActualValues[stack][chanel]; } else { return 0; } } //ChanelsNames /// /// Read configured chanels Names from Device /// public async void GetChanelsNames() { if (Address == null) return; ChanelNames = await _RTD8TM.GetNames(Address); AutoUpdateChanelsName(); } /// /// Set new Chanels Names /// /// chanels names sorted list #pragma warning disable CS1998 // V této asynchronní metodě chybí operátory await a spustí se synchronně. public async Task SetChanelsNames() #pragma warning restore CS1998 // V této asynchronní metodě chybí operátory await a spustí se synchronně. { if (Address == null) return; _RTD8TM.PostNames(Address, ChanelNames); } /// /// Update Chanels Names for not null loading names /// private void AutoUpdateChanelsName() { if (ActualValues.Count <= 0) return; foreach (byte key in ActualValues.Keys) { if (!ChanelNames.ContainsKey(key)) { ChanelNames.Add(key, new string[8]); } for (int i = 0; i < 8; i++) { if (ChanelNames[key][i] == null) { ChanelNames[key][i] = "----------"; } } } } /// /// Get chanel names /// /// Chanels names object public SortedList GetChanelNames() { return ChanelNames; } /// /// Set chanel Name /// /// Stack ID /// Chanel ID /// New Name public void SetChanelNames(byte stack, byte chanel, string name) { if (!ChanelNames.ContainsKey(stack)) { ChanelNames.Add(stack, new string[8]); } ChanelNames[stack][chanel] = name; } /// /// Read chanel name /// /// Stack ID /// Chanel ID /// Chanel name public string GetChanelName(byte stack, byte chanel) { if (ChanelNames.ContainsKey(stack)) { return ChanelNames[stack][chanel]; } else { return "----------"; } } /// /// Clear chanels Names to default /// public void ClearChanelNames() { ChanelNames.Clear(); AutoUpdateChanelsName(); } //Timer private async void TimerElapsed(object? o, ElapsedEventArgs? e) { GetActualValues(); AutoUpdateChanelsName(); if (EventUpdateValues != null) { await EventUpdateValues.Invoke(this, true); } } //Graph Data /// /// Get Chart data /// public void ReadChartData() { DateTime time = DateTime.Now; foreach (byte stack in ActualValues.Keys) { if (!GraphData.ContainsKey(stack)) { GraphData.Add(stack, new()); for (int chanel = 0; chanel < 8; chanel++) { GraphData[stack].Add(new()); } } for (byte chanel = 0; chanel < 8; chanel++) { GraphData[stack][chanel].Add(new RTD8TMPointModel() { Value = ActualValues[stack][chanel], Time = time }); } } GetFilteredChartData(); } /// /// Get data for graph visualize /// /// saved chart chanel Data public List GetChartData(byte StackID, byte Chanel) { if (!GraphFiltered.ContainsKey(StackID)) { return new List(); } List RecalculatedData = new(); byte chanelRecalcTo = GetValueType(StackID, Chanel); foreach (RTD8TMPointModel point in GraphFiltered[StackID][Chanel]) { RTD8TMPointModel recalculated = new() { Time = point.Time, Value = new RTD8TMChanelComponent().RecalculateValues(point.Value, chanelRecalcTo) }; RecalculatedData.Add(recalculated); } return RecalculatedData; } /// /// Clear data from Graph /// public void ClearChart() { GraphData.Clear(); } private void GetFilteredChartData() { foreach ( byte stack in GraphData.Keys) { int pointsCount = GraphData[stack][0].Count; int counter = 0; if (pointsCount < 100) { GraphFiltered = GraphData; } else if (pointsCount > 100 && pointsCount < 500) // one from five { GraphFiltered = new(); GraphFiltered.Add(stack, new()); for (int chanel = 0; chanel < 8; chanel++) { GraphFiltered[stack].Add(new()); foreach (RTD8TMPointModel GraphPoint in GraphData[stack][chanel]) { if (counter > 3) { GraphFiltered[stack][chanel].Add(GraphPoint); counter = 0; } else { counter++; } } } } else if (pointsCount > 500 && pointsCount < 1000) // one from ten { GraphFiltered = new(); GraphFiltered.Add(stack, new()); for (int chanel = 0; chanel < 8; chanel++) { GraphFiltered[stack].Add(new()); foreach (RTD8TMPointModel GraphPoint in GraphData[stack][chanel]) { if (counter > 8) { GraphFiltered[stack][chanel].Add(GraphPoint); counter = 0; } else { counter++; } } } } else if (pointsCount > 1000 && pointsCount < 1500) // one from fifteen { GraphFiltered = new(); GraphFiltered.Add(stack, new()); for (int chanel = 0; chanel < 8; chanel++) { GraphFiltered[stack].Add(new()); foreach (RTD8TMPointModel GraphPoint in GraphData[stack][chanel]) { if (counter > 13) { GraphFiltered[stack][chanel].Add(GraphPoint); counter = 0; } else { counter++; } } } } else if (pointsCount > 1500) // one from twenty { GraphFiltered = new(); GraphFiltered.Add(stack, new()); for (int chanel = 0; chanel < 8; chanel++) { GraphFiltered[stack].Add(new()); foreach (RTD8TMPointModel GraphPoint in GraphData[stack][chanel]) { if (counter > 18) { GraphFiltered[stack][chanel].Add(GraphPoint); counter = 0; } else { counter++; } } } } //případně další } } public int CountFilteredChartData() { foreach (byte stack in GraphFiltered.Keys) { return GraphFiltered[stack][0].Count; } return 0; } public int CountChartData() { foreach (byte stack in GraphData.Keys) { return GraphData[stack][0].Count; } return 0; } /// /// Get all Chart Data /// /// public SortedList>> GetAllChartData() { return GraphData; } /// /// Set Chart Data (used by syncservice) /// /// public void SetChartData(SortedList>> data) { GraphData = data; } //Values Types /// /// Set Value Type identifier /// /// Stack ID /// Chanel ID /// Value Type public void SetValueType(byte StackID, byte ChanelID, byte Type) { if (!ValuesType.ContainsKey(StackID)) { ValuesType.Add(StackID, new byte[8]); } ValuesType[StackID][ChanelID] = Type; } /// /// Get Value Type /// /// Stack ID /// Chanel ID /// Value Type public byte GetValueType(byte StackID, byte ChanelID) { if (ValuesType.ContainsKey(StackID)) { return ValuesType[StackID][ChanelID]; } else { return 0; } } /// /// Get ValueTypes From API /// public async void GetValueTypes() { if (Address == null) { return; } ValuesType = await _RTD8TM.GetValueTypes(Address); } /// /// Post ValueTypes to API /// public void PostValueTypes() { if (Address == null) { return; } _RTD8TM.PostValueTypes(Address, ValuesType); } public void ClearValueTypes() { ValuesType.Clear(); } //calibrations /// /// Read Calibrations from API /// private async void GetCalibrations() { if (Address == null) { return; } Calibrations = await _RTD8TM.GetCalibration(Address); foreach (byte stack in ActualValues.Keys) { if (!Calibrations.ContainsKey(stack)) { Calibrations.Add(stack, new float[8]); } } } /// /// Post calibrations to API /// public void PostCalibrations() { if (Address == null) { return; } _RTD8TM.PostCalibration(Address, Calibrations); } /// /// Get calibration of specific chanel /// /// /// /// public float GetCalibration(byte stack, byte chanel) { if (Calibrations.ContainsKey(stack)) { return Calibrations[stack][chanel]; } else { return 0; } } /// /// Set chanel Calibration Change /// /// /// /// public void SetCalibration(byte stack, byte chanel, float value) { if (!Calibrations.ContainsKey(stack)) { Calibrations.Add(stack, new float[8]); } Calibrations[stack][chanel] = value; } } }