Added Automatic points Saving, Calibration and Calculating RTDCard values change in last 3O minutes in saved points

master
Jan Beníček 2024-01-12 23:22:40 +01:00
parent 9300ce3c37
commit 0250613def
8 changed files with 369 additions and 85 deletions

View File

@ -6,29 +6,62 @@
<div class="row text-center"> <div class="row text-center">
<div class="col"> <div class="col-xs-12 col-md-2 align-self-center">
<button class="btn btn-dark text-white no-border" @onclick="(() => _PointsService.SavePoint())">Save Point (@_PointsService.GetPointsCount())</button> <button class="btn btn-dark text-white no-border" @onclick="(() => _PointsService.SavePoint())">Save Point (@_PointsService.GetPointsCount())</button>
</div> </div>
<div class="col row"> <div class="col-xs-12 col-md row">
<div class="col-md-3 col">
<div class="col-6 col-xl-4 align-self-center">
<input type="number" step="1" class="form-control form-control-sm bg-dark text-white no-border" value="@(_PointsService.GetTimerInterval())" @onchange="((x) =>
{
PointTimerChange(x.Value.ToString());
})">
</div>
<div class="col-6 col-xl-6 text-start align-self-center">
<div class="form-check form-switch">
@if (TimerEnabled)
{
<input class="form-check-input align-self-center" type="checkbox" role="switch" id="SavePointsSwitch" @onclick="(() =>
{
TimerEnabled = false;
_PointsService.StopTimer();
})" checked>
}
else
{
<input class="form-check-input align-self-center" type="checkbox" role="switch" id="SavePointsSwitch" @onclick="(() =>
{
TimerEnabled = true;
_PointsService.StartTimer();
})">
}
<label class="form-check-label" for="SavePointsSwitch">Auto Saving</label>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-5 row">
<div class="col-5 col-md-5 align-self-center">
<button class="btn btn-dark text-white no-border" @onclick="(() => DownloadFile())">Export as CSV</button> <button class="btn btn-dark text-white no-border" @onclick="(() => DownloadFile())">Export as CSV</button>
</div> </div>
<div class="col-md-3 col text-start align-self-center"> <div class="col-7 col-md-7 text-start align-self-center">
<div class="form-check form-switch"> <div class="form-check form-switch">
@if (RecalculateValues) @if (RecalculateValues)
{ {
<input class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault" @onclick="(() => <input class="form-check-input" type="checkbox" role="switch" id="RecalculatePointSwitch" @onclick="(() =>
{ {
RecalculateValues = false; RecalculateValues = false;
})" checked> })" checked>
} }
else else
{ {
<input class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault" @onclick="(() => RecalculateValues = true)"> <input class="form-check-input" type="checkbox" role="switch" id="RecalculatePointSwitch" @onclick="(() => RecalculateValues = true)">
} }
<label class="form-check-label" for="flexSwitchCheckDefault">Recalculate Values?</label> <label class="form-check-label" for="RecalculatePointSwitch">Recalculate Values?</label>
</div> </div>
</div> </div>
</div> </div>
@ -37,16 +70,20 @@
@code { @code {
private bool RecalculateValues = false; private bool RecalculateValues = false;
private bool TimerEnabled = false;
protected override void OnInitialized()
{
TimerEnabled = _PointsService.GetTImerStatus();
_PointsService.EventUpdateTopBar += UpdateView;
}
/// <summary>
/// Start downloading CSV file with points
/// </summary>
private async void DownloadFile() private async void DownloadFile()
{ {
// Název souboru // Název souboru
@ -56,10 +93,25 @@
await _JSRuntime.InvokeVoidAsync("DownloadFile", fileName, await _PointsService.CreatePointsFileLines(RecalculateValues)); await _JSRuntime.InvokeVoidAsync("DownloadFile", fileName, await _PointsService.CreatePointsFileLines(RecalculateValues));
} }
/// <summary>
/// Timer Time Change
/// </summary>
/// <param name="time"></param>
private void PointTimerChange(string? time)
{
if (time == null || time == "") { return; }
time = time.Replace(".", ",");
_PointsService.SetTimerInterval(int.Parse(time));
}
public async Task UpdateView(object? o, bool b)
{
await InvokeAsync(() =>
{
StateHasChanged();
});
}
} }

View File

@ -9,7 +9,8 @@
@if (_RTD8TMService.GetActualData() != null)
{
<table class="table table-striped text-white"> <table class="table table-striped text-white">
<thead> <thead>
<tr> <tr>
@ -38,6 +39,7 @@
} }
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@foreach (long time in TableData.Keys) @foreach (long time in TableData.Keys)
{ {
@ -57,8 +59,32 @@
</tr> </tr>
} }
</tbody> </tbody>
</table>
@if (TableData.Keys.Count > 1)
{
<tfoot>
<tr class="text-warning">
<td>30min Change</td>
@foreach (byte stack in TableData[TableData.Keys.OrderDescending().First()].Keys)
{
for (byte chanel = 0; chanel < 8; chanel++)
{
if (_RTD8TMService.GetChanelName(stack, chanel) != "----------")
{
<td>@Math.Round(new RTD8TMChanelComponent().RecalculateValues(TableData[LastDataTime][stack][chanel], _RTD8TMService.GetValueType(stack, chanel)) - new RTD8TMChanelComponent().RecalculateValues(TableData[AfterHalfHour][stack][chanel], _RTD8TMService.GetValueType(stack, chanel)), 2)</td>
}
}
}
</tr>
</tfoot>
}
</table>
}
else
{
<h1>No data</h1>
}
@code { @code {
@ -66,12 +92,14 @@
private string Ohm = " (Ω)"; private string Ohm = " (Ω)";
private string Celsius = " (°C)"; private string Celsius = " (°C)";
private bool TableBackground = false; private bool TableBackground = false;
private long LastDataTime = 0;
private long AfterHalfHour = 0;
protected override void OnInitialized() protected override void OnInitialized()
{ {
TableData = _PointsService.GetPoints().RTD8TM; TableData = _PointsService.GetPoints().RTD8TM;
_PointsService.EventPointPage += UpdateView;
} }
private string TableBacgroundChanger() private string TableBacgroundChanger()
@ -88,14 +116,21 @@
} }
} }
private void HalfHourTime()
{
LastDataTime = TableData.Keys.OrderDescending().First();
long backhalfhour = new DateTime(LastDataTime).AddMinutes(-30).Ticks;
AfterHalfHour = TableData.Keys.OrderBy(item => Math.Abs(backhalfhour - item)).First();
}
public async Task UpdateView(object? o, bool b)
{
await InvokeAsync(() =>
{
TableBackground = false;
StateHasChanged();
HalfHourTime();
});
}
} }

View File

@ -23,6 +23,12 @@
<input type="text" class="form-control form-control-sm bg-black text-white no-border" value="@(RTD8tmService.GetChanelName(StackID, ChanelID))" @onchange="((x) => ChangeName(x.Value.ToString()))" > <input type="text" class="form-control form-control-sm bg-black text-white no-border" value="@(RTD8tmService.GetChanelName(StackID, ChanelID))" @onchange="((x) => ChangeName(x.Value.ToString()))" >
</div> </div>
} }
else if (Calibration)
{
<div class="col">
<input type="number" step="0.01" class="form-control form-control-sm bg-black text-white no-border" value="@(RTD8tmService.GetCalibration(StackID, ChanelID).ToString().Replace(",", "."))" @onchange="((x) => CalibrationChanged(x.Value.ToString()))">
</div>
}
else else
{ {
<div class="col">@(RTD8tmService.GetChanelName(StackID, ChanelID))</div> <div class="col">@(RTD8tmService.GetChanelName(StackID, ChanelID))</div>
@ -42,6 +48,9 @@
[Parameter] [Parameter]
public bool Edit { get; set; } public bool Edit { get; set; }
[Parameter]
public bool Calibration { get; set; }
[Parameter] [Parameter]
public RTD8TMService RTD8tmService { get; set; } public RTD8TMService RTD8tmService { get; set; }
@ -61,6 +70,11 @@
RTD8tmService.SetChanelNames(StackID, ChanelID, NewName); RTD8tmService.SetChanelNames(StackID, ChanelID, NewName);
} }
private void CalibrationChanged(string NewCalibration)
{
NewCalibration = NewCalibration.Replace(".", ",");
RTD8tmService.SetCalibration(StackID, ChanelID, float.Parse(NewCalibration));
}
public float RecalculateValues(float resistance, byte Type = 0) public float RecalculateValues(float resistance, byte Type = 0)

View File

@ -4,6 +4,10 @@
@using UI_SequentMicrosystems.Services @using UI_SequentMicrosystems.Services
@using UI_SequentMicrosystems.Models @using UI_SequentMicrosystems.Models
@inject PointsService _PointsService
@inject RTD8TMService _RTD8TMService
@inject NavigationManager Navigator
<PageTitle>Saved Points</PageTitle> <PageTitle>Saved Points</PageTitle>
@ -21,7 +25,12 @@
@code { @code {
protected override void OnInitialized()
{
//_RTD8TMService.SetAddress("http://10.250.251.131/");
_RTD8TMService.SetAddress(Navigator.BaseUri);
}

View File

@ -15,6 +15,8 @@
<div class="row text-center"> <div class="row text-center">
<div class="col-6">Device Address: @_RTD8TMService.GetAddress() | DataUpdate: @_UpdateCounter | Chart Points: @_RTD8TMService.CountChartData() / @_RTD8TMService.CountFilteredChartData() </div> <div class="col-6">Device Address: @_RTD8TMService.GetAddress() | DataUpdate: @_UpdateCounter | Chart Points: @_RTD8TMService.CountChartData() / @_RTD8TMService.CountFilteredChartData() </div>
<div class="col text-start"> <div class="col text-start">
@if (!Calibration)
{
<div class="form-check form-switch"> <div class="form-check form-switch">
@if (EditName) @if (EditName)
{ {
@ -31,6 +33,29 @@
} }
<label class="form-check-label" for="flexSwitchCheckDefault">Configure Inputs</label> <label class="form-check-label" for="flexSwitchCheckDefault">Configure Inputs</label>
</div> </div>
}
</div>
<div class="col text-start">
@if (!EditName)
{
<div class="form-check form-switch">
@if (Calibration)
{
<input class="form-check-input" type="checkbox" role="switch" id="flexSwitchCheckDefault" @onclick="(() =>
{
Calibration = false;
Task.Run(() =>_RTD8TMService.PostCalibrations());
})" checked>
}
else
{
<input class="form-check-input" type="checkbox" role="switch" id="SwitchCalibration" @onclick="(() => Calibration = true)">
}
<label class="form-check-label" for="SwitchCalibration">Calibrate Inputs</label>
</div>
}
</div> </div>
@if (EditName) @if (EditName)
{ {
@ -59,7 +84,7 @@
<div class="text-center">Stack ID: @StackID</div> <div class="text-center">Stack ID: @StackID</div>
@for (byte chanel = 0; chanel < 8; chanel++) @for (byte chanel = 0; chanel < 8; chanel++)
{ {
<RTD8TMChanelComponent StackID=@StackID ChanelID=@chanel Edit=@EditName RTD8tmService=@_RTD8TMService /> <RTD8TMChanelComponent StackID=@StackID ChanelID=@chanel Edit=@EditName Calibration=@Calibration RTD8tmService=@_RTD8TMService />
} }
</div> </div>
} }
@ -72,6 +97,7 @@
@code { @code {
public int _UpdateCounter = 0; public int _UpdateCounter = 0;
private bool EditName = false; private bool EditName = false;
private bool Calibration = false;
[CascadingParameter] public IModalService Modal { get; set; } = default!; [CascadingParameter] public IModalService Modal { get; set; } = default!;

View File

@ -6,8 +6,14 @@
<PageTitle>Welcome</PageTitle> <PageTitle>Welcome</PageTitle>
<h1>TesDevice App V1.0</h1> <div class="text-center row">
<div class="h6 col"><strong>TesDevice App V1.1</strong></div>
<div class="col">Added Automatic points Saving, Calibration and Calculating RTDCard values change in last 3O minutes in saved points</div>
</div>
<div class="text-center row">
<div class="h6 col">TesDevice App V1.O</div>
<div class="col">Firt Fully function Build --> Reading RTD cards, RTD Graph, Points Saving and exporting as csv</div>
</div>

View File

@ -1,4 +1,5 @@
using UI_SequentMicrosystems.Components; using System.Timers;
using UI_SequentMicrosystems.Components;
using UI_SequentMicrosystems.Constants; using UI_SequentMicrosystems.Constants;
using UI_SequentMicrosystems.Models; using UI_SequentMicrosystems.Models;
@ -11,18 +12,24 @@ namespace UI_SequentMicrosystems.Services
private PointsModel _PointsModel = new(); private PointsModel _PointsModel = new();
private int PointsCount = 0; private int PointsCount = 0;
private System.Timers.Timer _Timer = new System.Timers.Timer(300000);
public delegate Task AsyncEventHandler<TEventArgs>(object? sender, TEventArgs? e);
public event AsyncEventHandler<bool>? EventUpdateTopBar;
public event AsyncEventHandler<bool>? EventPointPage;
public PointsService(RTD8TMService RTD8TM) public PointsService(RTD8TMService RTD8TM)
{ {
_RTD8TMService = RTD8TM; _RTD8TMService = RTD8TM;
_Timer.Elapsed += SavePoint;
_Timer.AutoReset = true;
} }
/// <summary> /// <summary>
/// Save actual data point /// Save actual data point
/// </summary> /// </summary>
public void SavePoint() public async void SavePoint()
{ {
long time = DateTime.Now.Ticks; long time = DateTime.Now.Ticks;
_PointsModel.RTD8TM.Add(time, new()); _PointsModel.RTD8TM.Add(time, new());
@ -42,8 +49,18 @@ namespace UI_SequentMicrosystems.Services
_PointsModel.RTD8TM[time][stack].Add(RTD8TMActual[stack][chanel]); _PointsModel.RTD8TM[time][stack].Add(RTD8TMActual[stack][chanel]);
} }
} }
//other card types points saving //other card types points saving
if (EventUpdateTopBar != null)
{
await EventUpdateTopBar.Invoke(this, true);
}
if (EventPointPage != null)
{
await EventPointPage.Invoke(this, true);
}
} }
/// <summary> /// <summary>
@ -64,6 +81,7 @@ namespace UI_SequentMicrosystems.Services
return PointsCount; return PointsCount;
} }
//Create File Lines
/// <summary> /// <summary>
/// Create Points Lines for CSV File /// Create Points Lines for CSV File
@ -82,7 +100,6 @@ namespace UI_SequentMicrosystems.Services
return string.Join(Environment.NewLine, Lines); return string.Join(Environment.NewLine, Lines);
} }
/// <summary> /// <summary>
/// Create Title Line of CSV File /// Create Title Line of CSV File
/// </summary> /// </summary>
@ -179,8 +196,55 @@ namespace UI_SequentMicrosystems.Services
//Timer
private void SavePoint(object? o, ElapsedEventArgs? e)
{
SavePoint();
}
/// <summary>
/// Read Timer Interval
/// </summary>
/// <returns>Interval in seconds</returns>
public int GetTimerInterval()
{
return (int)(_Timer.Interval / 1000);
}
/// <summary>
/// Set Timer Interval
/// </summary>
/// <param name="interval">interval in seconds</param>
public void SetTimerInterval(int interval)
{
_Timer.Interval = interval * 1000;
}
/// <summary>
/// Start Timer
/// </summary>
public void StartTimer()
{
_Timer.Start();
}
/// <summary>
/// Stop Timer
/// </summary>
public void StopTimer()
{
_Timer.Stop();
}
/// <summary>
/// Get Timer status
/// </summary>
/// <returns></returns>
public bool GetTImerStatus()
{
return _Timer.Enabled;
}
} }

View File

@ -11,6 +11,7 @@ namespace UI_SequentMicrosystems.Services
private SortedList<byte, string[]> ChanelNames = new SortedList<byte, string[]>(); private SortedList<byte, string[]> ChanelNames = new SortedList<byte, string[]>();
private SortedList<byte, float[]> ActualValues = new SortedList<byte, float[]>(); private SortedList<byte, float[]> ActualValues = new SortedList<byte, float[]>();
private SortedList<byte, byte[]> ValuesType = new SortedList<byte, byte[]>(); private SortedList<byte, byte[]> ValuesType = new SortedList<byte, byte[]>();
private SortedList<byte, float[]> Calibrations = new SortedList<byte, float[]>();
public SortedList<byte, List<List<RTD8TMPointModel>>> GraphData = new(); public SortedList<byte, List<List<RTD8TMPointModel>>> GraphData = new();
public SortedList<byte, List<List<RTD8TMPointModel>>> GraphFiltered = new(); public SortedList<byte, List<List<RTD8TMPointModel>>> GraphFiltered = new();
private byte GraphDataCounterCount = 10; private byte GraphDataCounterCount = 10;
@ -44,6 +45,7 @@ namespace UI_SequentMicrosystems.Services
Address = address; Address = address;
GetChanelsNames(); GetChanelsNames();
GetValueTypes(); GetValueTypes();
GetCalibrations();
} }
/// <summary> /// <summary>
@ -73,6 +75,18 @@ namespace UI_SequentMicrosystems.Services
ActualValues = await _RTD8TM.Get(Address); 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) if (GraphDataCounter >= GraphDataCounterCount)
{ {
GraphDataCounter = 0; GraphDataCounter = 0;
@ -482,6 +496,70 @@ namespace UI_SequentMicrosystems.Services
ValuesType.Clear(); ValuesType.Clear();
} }
//calibrations
/// <summary>
/// Read Calibrations from API
/// </summary>
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]);
}
}
}
/// <summary>
/// Post calibrations to API
/// </summary>
public void PostCalibrations()
{
if (Address == null) { return; }
_RTD8TM.PostCalibration(Address, Calibrations);
}
/// <summary>
/// Get calibration of specific chanel
/// </summary>
/// <param name="stack"></param>
/// <param name="chanel"></param>
/// <returns></returns>
public float GetCalibration(byte stack, byte chanel)
{
if (Calibrations.ContainsKey(stack))
{
return Calibrations[stack][chanel];
}
else
{
return 0;
}
}
/// <summary>
/// Set chanel Calibration Change
/// </summary>
/// <param name="stack"></param>
/// <param name="chanel"></param>
/// <param name="value"></param>
public void SetCalibration(byte stack, byte chanel, float value)
{
if (!Calibrations.ContainsKey(stack))
{
Calibrations.Add(stack, new float[8]);
}
Calibrations[stack][chanel] = value;
}
} }
} }