recipes mapping + dates on the overall results

This commit is contained in:
Stoyan Zlatev 2025-03-31 09:09:42 +02:00
parent 6c7960be7a
commit 6915d2c2fc
31 changed files with 1580 additions and 89474 deletions

View File

@ -109,12 +109,16 @@
// | FDRMask.LOG_ALARM_STATE
// | FDRMask.LOG_EXT_ALARM_STATE;
// 0B0126B768500A110B118427BAA2C5C18069035350000219BF3621116029186A00986A0000005A0A3
public static void Main()
{
var dbytes = "34-0B-10-12-6B-70-F2-00-0A-01-0B-01-06-05-01-50-4B-FF-F3-19-00-69-03-35-35-00-00-02-00-03-11-C5-EE-02-01-00-16-00-18-02-71-00-00-82-71-00-00-00-00-00-00-05-0A-4D-6A-16";
var debug = new DEBUG(dbytes.GetBytes(), new P11());
var sbytes = "08-06-12-6B-70-F2-00-00-01-F4-00-00-A5-0A-00-0F-03-00-00-00-00-00-00-09-13-01-88-73-FD-07-0E-10-A8-57-6E-D2-D1-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-04-03-00-3C-00-03-01-2F-76-6D-79-1D-00-00-00-00-00-00-00-00-00-00-00-00-00-18";
var semi = new SEMI(sbytes.GetBytes(), 868, new P11());
var hex = "0B-00-12-6B-76-85-00-0A-11-0B-11-08-04-02-7B-AA-2C-5C-18-00-69-00-35-35-00-00-00-00-02-19-BF-36-02-01-01-16-00-29-18-6A-00-00-98-6A-00-00-00-00-00-00-05-A0-A3";
var bytes = hex.GetBytes();
var debug = new DEBUG(bytes, new P11());
Console.WriteLine((debug.BatterySeconds - 0x02_00_00_00) / 60 / 60 / 24);
}
}
}

View File

@ -258,17 +258,25 @@
EncryptionKey = this.EncryptionKey.GetEncryptionKey(),
};
if (!this.IsValid)
{
features.ChangeMeterReading = new ChangeMeterReading(222_222_222);
return features;
}
if (this.StatusFertigung != 30)
{
return new EregisterFeatures();
}
else if (this.IsEbeling)
{
}
else if (this.IsFuhzoe)
{
features.ChangeMeterReading = new ChangeMeterReading(333_333_333);
features.Debug = new EregisterDebugFeatures
{
OpticalTelegram = new OpticalTelegram
{
Minutes = 0
}
};
return features;
}
features.Debug = new EregisterDebugFeatures();

View File

@ -26,7 +26,7 @@
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationRevision>2</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
@ -56,7 +56,7 @@
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>false</GenerateManifests>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>

View File

@ -214,12 +214,12 @@
}
else
{
throw new Exception(content);
epp.IsValid = false;
}
}
else
{
throw new Exception(content);
epp.IsValid = false;
}
}
}

View File

@ -1,52 +1,194 @@
namespace LaaProduction.Console
{
using LaaPackages.HttpClient;
using LaaPackages.SqlClient;
using LaaProduction.Data.Cordonel;
using LaaProduction.Data.Cordonel.Sentinel;
using Newtonsoft.Json;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
public class CharCode
{
Console.WriteLine(-14 * 24 * 60 * 60);
public int Stelle { get; set; }
//var sentinel = new Sentinel(
// new HttpConnection("http://10.49.40.25/")
// , new HttpConnection("localhost")
// , new CordonelDbContext(
// new SqlConnection("Server=SLASQL01.emea.sensus.net; Database=Auftrag; User ID=sa; Password=sqlserver;")));
//var sentinelDataFile = @"..\..\sentinel-data.json";
//var result = sentinel.CheckVFMStatus(182100041);
public int Laenge { get; set; }
//Console.WriteLine("=========================================================");
//foreach (var kvp in result)
//{
// Console.WriteLine($"{kvp.Key}: {kvp.Value}");
//}
//Console.WriteLine("=========================================================");
//if (result.Succeeded && result.ContainsKey("UsedData"))
//{
// var jsonSerializerSettings = new JsonSerializerSettings
// {
// Formatting = Formatting.Indented,
// TypeNameHandling = TypeNameHandling.Objects | TypeNameHandling.Arrays,
// TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
// };
// var json = JsonConvert.SerializeObject(result["UsedData"], jsonSerializerSettings);
// File.WriteAllText(sentinelDataFile, json);
//}
public string Code { get; set; }
}
//const string URL_PATTERN = "https://nodes.sms-esaap.com/keygenproxy/api/v2/keys/devices?orderNumber={0}&radioaddress={1}";
//const string X_NODE_TOKEN_HEADER = "X-Node-Token";
//const string X_NODE_TOKEN = "d5b8c0b2-81f6-4421-80d0-44eb2093e616";
private static void Main()
{
var charCodes = new List<CharCode>
{
new CharCode { Stelle = 45, Laenge = 2, Code = "N2" },
new CharCode { Stelle = 26, Laenge = 1, Code = "K" },
new CharCode { Stelle = 5, Laenge = 1, Code = "F" },
new CharCode { Stelle = 5, Laenge = 1, Code = "G" },
new CharCode { Stelle = 5, Laenge = 1, Code = "H" },
new CharCode { Stelle = 5, Laenge = 1, Code = "I" },
new CharCode { Stelle = 5, Laenge = 1, Code = "K" },
new CharCode { Stelle = 5, Laenge = 1, Code = "L" },
new CharCode { Stelle = 5, Laenge = 1, Code = "M" },
new CharCode { Stelle = 37, Laenge = 1, Code = "A" },
new CharCode { Stelle = 37, Laenge = 1, Code = "B" },
};
var orderedCharCodes = charCodes
.OrderBy(x => x.Stelle)
.GroupBy(x => x.Stelle)
.ToDictionary(x => x.Key, x => x.ToList());
var key = orderedCharCodes.Min(x => x.Key);
var patterns = new List<char[]>();
GenerateUniqueCombinations(orderedCharCodes, patterns, key);
foreach (var pattern in patterns)
{
Console.WriteLine($"'{new string(pattern)}%'");
}
}
private static void GenerateUniqueCombinations(Dictionary<int, List<CharCode>> charCodes, List<char[]> patterns, int key)
{
var nextKey = charCodes.FirstOrDefault(x => x.Key > key).Key;
if (nextKey > default(int))
{
var parameter = charCodes[nextKey].FirstOrDefault();
if (parameter != null)
{
var length = parameter.Stelle + parameter.Laenge - 1;
var tempalte = new char[length];
for (var ix = 0; ix < length; ix++)
{
tempalte[ix] = '_';
}
if (patterns.Count == 0)
{
patterns.Add(tempalte);
}
else
{
patterns[0] = tempalte;
}
}
GenerateUniqueCombinations(charCodes, patterns, nextKey);
}
var templatePatterns = new List<char[]>();
templatePatterns.AddRange(patterns);
patterns.Clear();
foreach (var parameter in charCodes[key])
{
foreach (var template in templatePatterns)
{
var pattern = new char[template.Length];
Array.Copy(template, 0, pattern, 0, pattern.Length);
var codeLength = parameter.Code.Length;
for (var charIX = 0; charIX < codeLength; charIX++)
{
pattern[parameter.Stelle + charIX - 1] = parameter.Code[charIX];
}
patterns.Add(pattern);
}
}
}
}
}
}
//public static void _____Main()
//{
// Console.WriteLine(-14 * 24 * 60 * 60);
// //var sentinel = new Sentinel(
// // new HttpConnection("http://10.49.40.25/")
// // , new HttpConnection("localhost")
// // , new CordonelDbContext(
// // new SqlConnection("Server=SLASQL01.emea.sensus.net; Database=Auftrag; User ID=sa; Password=sqlserver;")));
// //var sentinelDataFile = @"..\..\sentinel-data.json";
// //var result = sentinel.CheckVFMStatus(182100041);
// //Console.WriteLine("=========================================================");
// //foreach (var kvp in result)
// //{
// // Console.WriteLine($"{kvp.Key}: {kvp.Value}");
// //}
// //Console.WriteLine("=========================================================");
// //if (result.Succeeded && result.ContainsKey("UsedData"))
// //{
// // var jsonSerializerSettings = new JsonSerializerSettings
// // {
// // Formatting = Formatting.Indented,
// // TypeNameHandling = TypeNameHandling.Objects | TypeNameHandling.Arrays,
// // TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple
// // };
// // var json = JsonConvert.SerializeObject(result["UsedData"], jsonSerializerSettings);
// // File.WriteAllText(sentinelDataFile, json);
// //}
//}
//const string URL_PATTERN = "https://nodes.sms-esaap.com/keygenproxy/api/v2/keys/devices?orderNumber={0}&radioaddress={1}";
//const string X_NODE_TOKEN_HEADER = "X-Node-Token";
//const string X_NODE_TOKEN = "d5b8c0b2-81f6-4421-80d0-44eb2093e616";

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,15 @@
<link rel="stylesheet" href="bootstrap/css/bootstrap.overrides.css" />
<link rel="stylesheet" href="bootstrap/font/bootstrap-icons.min.css" />
<script src="bootstrap/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
@* <script src="charts/helpers.js"></script>
<script src="charts/chart.umd.js"></script>
<script src="charts/chart.js"></script> *@
<title>Sensus Laatzen</title>
</head>
<body>
<body class="vh-100 w-100 mw-100 overflow-x-hidden">
<Routes @rendermode="new InteractiveServerRenderMode(false)" />
<script src="_framework/blazor.web.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</body>
</html>

View File

@ -0,0 +1,23 @@
namespace LaaProductionWeb.Blazor.Components.CSD.Data
{
using System;
public class SelectItem<T> where T : SelectItem<T>
{
public event Action<T> ItemSelected;
private bool selected;
public bool Selected
{
get => this.selected;
set
{
this.selected = value;
this.NotifyItemSelected();
}
}
protected void NotifyItemSelected() => this.ItemSelected?.Invoke(this as T);
}
}

View File

@ -0,0 +1,355 @@
namespace LaaProductionWeb.Blazor.Components.CSD.Data
{
using LaaPackages.SqlClient;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
public class VAKOMerkmale
{
private static int uiid;
private readonly SqlConnection connection;
private readonly HashSet<CharCode> charCodes;
private string basisFilter;
private string parameterFilter;
private string charCodeFilter;
private string basis;
private int stelle;
private int laenge;
public VAKOMerkmale(IConfiguration configuration)
{
this.basisFilter = "%%";
this.parameterFilter = "%%";
this.charCodeFilter = "%%";
var connectionString = configuration.GetConnectionString("Auftrag");
this.connection = SqlConnection.CreateSqlConnection(connectionString);
this.charCodes = [];
this.UniqueBasisCodes = [];
this.UniqueParameters = [];
this.UniqueCharCodes = [];
this.SelectedItems = [];
this.InitializeVAKOMErkmale();
}
public event Action SelectionChanged;
public ICollection<BasisCode> UniqueBasisCodes { get; private set; }
public ICollection<Parameter> UniqueParameters { get; private set; }
public ICollection<CharCode> UniqueCharCodes { get; private set; }
public SortedDictionary<string, SortedDictionary<string, SortedSet<CharCode>>> SelectedItems { get; }
public IEnumerable<string> GetUniqueVAKOCodePatterns()
{
var vakoCodePatterns = new HashSet<string>();
var orderedCharCodes = this.UniqueCharCodes
.OrderBy(x => x.Stelle)
.GroupBy(x => x.Stelle)
.ToDictionary(x => x.Key, x => x.ToList());
if (orderedCharCodes.Count > 0)
{
var key = orderedCharCodes.Min(x => x.Key);
var patterns = new List<char[]>();
GenerateUniqueCombinations(orderedCharCodes, patterns, this.basis, key);
foreach (var pattern in patterns)
{
vakoCodePatterns.Add(new string(pattern));
}
}
return vakoCodePatterns;
}
public void SetBasisFilter(object filter)
{
this.basisFilter = $"%{filter}%";
this.UpdateBasisCodes();
this.UpdateParameters();
this.UpdateCharCodes();
}
public void SetParameterFilter(object filter)
{
this.parameterFilter = $"%{filter}%";
this.UpdateParameters();
this.UpdateCharCodes();
}
public void SetCharCodeFilter(object filter)
{
this.charCodeFilter = $"%{filter}%";
this.UpdateCharCodes();
}
public void BasisSelected(BasisCode basisCode)
{
this.basisFilter = $"%{basisCode.Name}%";
this.basis = basisCode.Name;
this.stelle = 0;
this.laenge = 0;
this.charCodes.Clear();
this.SelectedItems.Clear();
this.UpdateParameters();
this.UpdateCharCodes();
}
public void ParameterSelected(Parameter parameter)
{
this.stelle = parameter.Stelle;
this.laenge = parameter.Laenge;
this.UpdateParameters();
this.UpdateCharCodes();
}
public void CharcodeSelected(CharCode charCode)
{
this.charCodes.Add(charCode);
this.charCodes.RemoveWhere(x => !x.Selected);
}
private void InitializeVAKOMErkmale()
{
this.UpdateBasisCodes();
this.UpdateParameters();
}
private void UpdateBasisCodes()
=> this.UniqueBasisCodes = this.connection
.CreateCommand($@"
SELECT DISTINCT
vmm.Basis
FROM VAKO_Merkmale AS vmm
WHERE vmm.Basis IS NOT NULL
AND vmm.Basis LIKE @{nameof(basisFilter)}
ORDER BY vmm.Basis")
.SetParameter(nameof(this.basisFilter), this.basisFilter)
.ExecuteReader(x => new BasisCode
{
UIId = $"uiid_{++uiid}",
Name = x.GetValue<string>(0)
})
.ToList();
private void UpdateParameters()
=> this.UniqueParameters = this.connection
.CreateCommand($@"
SELECT DISTINCT
vmm.Basis
, vmm.Bezeichnung
, vmm.Stelle
, vmm.Laenge
FROM VAKO_Merkmale AS vmm
WHERE vmm.Bezeichnung IS NOT NULL
AND vmm.Basis LIKE @{nameof(this.basisFilter)}
AND vmm.Bezeichnung LIKE @{nameof(this.parameterFilter)}
ORDER BY vmm.Bezeichnung")
.SetParameter(nameof(this.basisFilter), this.basisFilter)
.SetParameter(nameof(this.parameterFilter), this.parameterFilter)
.ExecuteReader(x => new Parameter
{
UIId = $"uiid_{++uiid}",
Basis = x.GetValue<string>(0),
Name = x.GetValue<string>(1),
Stelle = x.GetValue<int>(2),
Laenge = x.GetValue<int>(3)
})
.ToList();
private void UpdateCharCodes()
{
this.UniqueCharCodes = this.connection
.CreateCommand($@"
SELECT DISTINCT
mm.Basis
, mm.Bezeichnung
, mm.Stelle
, mm.Laenge
, mm.Charcode
, mm.Wert
FROM (SELECT DISTINCT
vmm.Basis
, vmm.Bezeichnung
, vmm.Stelle
, vmm.Laenge
, vmm.Charcode
, vmm.Wert
, ROW_NUMBER() OVER (PARTITION BY vmm.Charcode ORDER BY vmm.Wert DESC) AS RowNr
FROM VAKO_Merkmale AS vmm
WHERE vmm.Basis LIKE @{nameof(this.basisFilter)}
AND vmm.Stelle = @{nameof(this.stelle)}
AND vmm.Laenge = @{nameof(this.laenge)})
AS mm
WHERE RowNr = 1
AND mm.Wert LIKE @{nameof(this.charCodeFilter)}
ORDER BY mm.Charcode")
.SetParameter(nameof(this.basisFilter), this.basisFilter)
.SetParameter(nameof(this.stelle), this.stelle)
.SetParameter(nameof(this.laenge), this.laenge)
.SetParameter(nameof(this.charCodeFilter), this.charCodeFilter)
.ExecuteReader(x => new CharCode
{
UIId = $"uiid_{++uiid}",
Basis = x.GetValue<string>(0),
Name = x.GetValue<string>(1),
Stelle = x.GetValue<int>(2),
Laenge = x.GetValue<int>(3),
Code = x.GetValue<string>(4),
Value = x.GetValue<string>(5),
})
.ToList();
foreach (var charCode in charCodes)
{
charCode.Selected = this.charCodes
.FirstOrDefault(x => x.Basis == charCode.Basis
&& x.Stelle == charCode.Stelle
&& x.Laenge == charCode.Laenge
&& x.Code == charCode.Code)
?.Selected ?? false;
}
}
private static void GenerateUniqueCombinations(Dictionary<int, List<CharCode>> charCodes, List<char[]> patterns, string basis, int key)
{
var nextKey = charCodes.FirstOrDefault(x => x.Key > key).Key;
if (nextKey > default(int))
{
var parameter = charCodes[nextKey].FirstOrDefault();
if (parameter != null)
{
var length = parameter.Stelle + parameter.Laenge;
var tempalte = new char[length];
for (var ix = 0; ix < length; ix++)
{
tempalte[ix] = '_';
}
for (var ix = 0; ix < basis.Length; ix++)
{
tempalte[ix] = basis[ix];
}
tempalte[length - 1] = '%';
if (patterns.Count == 0)
{
patterns.Add(tempalte);
}
else
{
patterns[0] = tempalte;
}
}
GenerateUniqueCombinations(charCodes, patterns, basis, nextKey);
}
var templatePatterns = new List<char[]>();
templatePatterns.AddRange(patterns);
patterns.Clear();
foreach (var parameter in charCodes[key])
{
foreach (var template in templatePatterns)
{
var pattern = new char[template.Length];
Array.Copy(template, 0, pattern, 0, pattern.Length);
var codeLength = parameter.Code.Length;
for (var charIX = 0; charIX < codeLength; charIX++)
{
pattern[parameter.Stelle + charIX - 1] = parameter.Code[charIX];
}
patterns.Add(pattern);
}
}
}
}
public class BasisCode
{
public string UIId { get; set; }
public string Name { get; set; }
}
public class Parameter
{
public string UIId { get; set; }
public string Name { get; set; }
public string Basis { get; set; }
public int Stelle { get; set; }
public int Laenge { get; set; }
}
public class CharCode
{
public event Action SelectionChanged;
public string UIId { get; set; }
public string Name { get; set; }
public string Value { get; set; }
public string Code { get; set; }
public string Basis { get; set; }
public int Stelle { get; set; }
public int Laenge { get; set; }
private bool selected;
public bool Selected
{
get => this.selected;
set
{
this.selected = value;
this.SelectionChanged?.Invoke();
}
}
public override bool Equals(object other)
=> other is CharCode charcode
&& charcode.Code == this.Code;
public override int GetHashCode()
=> this.Code?.GetHashCode()
?? default;
public override string ToString()
=> this.Code;
}
}

View File

@ -0,0 +1,11 @@
namespace LaaProductionWeb.Blazor.Components.CSD.Models
{
public class CSDItem
{
public string Basis { get; set; }
public int Stelle { get; set; }
public int Laenge { get; set; }
}
}

View File

@ -22,14 +22,6 @@
<th class="bg-light pe-3">
Typ
</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
<tr>
<th class="p-0">
@ -72,14 +64,6 @@
</div>
</div>
</th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</tbody>
</table>

View File

@ -1,3 +1,68 @@
@page "/csd/programmingparameters"
<Navbar />
<div class="d-flex flex-column h-100 my-0 py-0" style="max-height: calc(100% - 60px) !important">
<nav class="navbar navbar-expand-lg bg-body-secondary py-0 h-auto">
<div class="container-fluid">
<div class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<NavLink ActiveClass="active" Match="NavLinkMatch.All" class="nav-link py-1" href="csd/programmingparameters">Programming Parameters</NavLink>
</li>
</ul>
</div>
</div>
</nav>
<div class="d-flex flex-row h-100 overflow-y-hidden">
<div class="list-group w-auto border-end rounded-0 p-0 h-100 overflow-y-auto font-monospace small w-auto">
<input class="form-control rounded-0 border-start-0 border-top-0 border-end-0 sticky-top small shadow-none" placeholder="Basis" @oninput="this.FilterBasisCodes" />
@foreach (var basisCode in this.VAKOMerkmale.UniqueBasisCodes)
{
var id = basisCode.Name.ToLower();
<div class="list-group-item border-0 p-0">
<input type="radio" class="btn-check" name="basis_codes" id="@id" autocomplete="off" @onchange="args => this.BasisSelected(basisCode, args)">
<label class="btn btn-light border-0 rounded-0 w-100 text-start small text-nowrap" for="@id">@basisCode.Name</label>
</div>
}
</div>
<div class="list-group w-auto border-end rounded-0 p-0 h-100 overflow-y-auto font-monospace small w-auto">
<input class="form-control rounded-0 border-start-0 border-top-0 border-end-0 sticky-top small shadow-none" placeholder="Bezeichnung" @oninput="this.FilterParameters" />
@foreach (var parameter in this.VAKOMerkmale.UniqueParameters)
{
var id = parameter.UIId;
<div class="list-group-item border-0 p-0">
<input type="radio" class="btn-check" name="parameters" id="@id" autocomplete="off" @onchange="args => this.ParameterSelected(parameter, args)">
<label class="btn btn-light border-0 rounded-0 w-100 text-start small text-nowrap" for="@id">
@parameter.Name - <b class="text-secondary smaller">[@(parameter.Stelle)..@(parameter.Laenge)]</b>
</label>
</div>
}
</div>
<div class="list-group w-auto border-end rounded-0 p-0 h-100 overflow-y-auto font-monospace small w-auto">
<input class="form-control rounded-0 border-start-0 border-top-0 border-end-0 sticky-top small shadow-none" placeholder="Wert" @oninput="this.FilterCharcodes" />
@foreach (var charCode in this.VAKOMerkmale.UniqueCharCodes)
{
charCode.SelectionChanged += this.StateHasChanged;
var id = charCode.UIId;
<div class="list-group-item border-0 p-0">
<input type="checkbox" class="btn-check" id="@id" autocomplete="off" @bind="charCode.Selected">
<label class="btn btn-light border-0 rounded-0 w-100 text-start small text-nowrap" for="@id">
<b class="text-danger smaller">@charCode.Code</b>
- @charCode.Value
</label>
</div>
}
</div>
<div class="list-group w-auto border-end rounded-0 p-0 h-100 overflow-y-auto font-monospace small w-100">
@foreach (var pattern in this.VAKOMerkmale.GetUniqueVAKOCodePatterns())
{
<div class="small text-danger text-wrap px-3 pt-3">
<b>@pattern</b>
</div>
}
</div>
</div>
</div>

View File

@ -7,6 +7,42 @@
public partial class ProgrammingParameters : ComponentBase
{
[Inject]
private CSDDBContext CSDDBContext { get; set; }
private VAKOMerkmale VAKOMerkmale { get; set; }
private void FilterBasisCodes(ChangeEventArgs args)
{
this.VAKOMerkmale.SetBasisFilter(args.Value);
this.StateHasChanged();
}
private void FilterParameters(ChangeEventArgs args)
{
this.VAKOMerkmale.SetParameterFilter(args.Value);
this.StateHasChanged();
}
private void FilterCharcodes(ChangeEventArgs args)
{
this.VAKOMerkmale.SetCharCodeFilter(args.Value);
this.StateHasChanged();
}
private void BasisSelected(BasisCode basisCode, ChangeEventArgs args)
{
if (args.Value is string state && state == "on")
{
this.VAKOMerkmale.BasisSelected(basisCode);
this.StateHasChanged();
}
}
private void ParameterSelected(Parameter parameter, ChangeEventArgs args)
{
if (args.Value is string state && state == "on")
{
this.VAKOMerkmale.ParameterSelected(parameter);
this.StateHasChanged();
}
}
}
}

View File

@ -85,6 +85,7 @@
SELECT DISTINCT
oar.Id AS OverallId
, oar.ResultIdent AS PcbId
, oar.TestDoneTime AS DateTime
, CAST(0 AS BIT) AS Selected
, tv.Region + ' ' + CASE WHEN tv.RegionCode = 'E' THEN 'DN' ELSE '' END
+ tv.MeterSize + ' L='
@ -103,7 +104,8 @@
LEFT JOIN ht.WaterMessurementsHistory AS wmh
ON oar.Id = wmh.OverallResultId
WHERE oar.Id IS NOT NULL
AND (hmh.Id IS NOT NULL OR wmh.Id IS NOT NULL) {where}";
AND (hmh.Id IS NOT NULL OR wmh.Id IS NOT NULL) {where}
ORDER BY oar.TestDoneTime DESC";
return this.heliumTesterDbContext
.Database

View File

@ -10,6 +10,8 @@
public int PcbId { get; set; }
public DateTime DateTime { get; set; }
private bool selected;
public bool Selected
{

View File

@ -0,0 +1,6 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester.Models
{
public class PcbItem
{
}
}

View File

@ -0,0 +1,27 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester.Models
{
public class PcbRecipeDTO
{
public int Id { get; set; }
public int PcbId { get; set; }
public string HeliumRecipeId { get; set; }
public string WaterRecipeId { get; set; }
public int Region { get; set; }
public int MeterSize { get; set; }
public int BodyLength { get; set; }
public bool Pressure { get; set; }
public string PlateType { get; set; }
public double DeadVolume { get; set; }
public int MeterType { get; set; }
}
}

View File

@ -0,0 +1,27 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester.Models
{
public class PcbRecipeEntity
{
public int Id { get; set; }
public int PcbId { get; set; }
public int HeliumRecipeId { get; set; }
public int WaterRecipeId { get; set; }
public int Region { get; set; }
public int MeterSize { get; set; }
public int BodyLength { get; set; }
public bool Pressure { get; set; }
public string PlateType { get; set; }
public double DeadVolume { get; set; }
public int MeterType { get; set; }
}
}

View File

@ -0,0 +1,461 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester.Models
{
using LaaPackages.SqlClient;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
public class PcbRecipeModel
{
private readonly SqlConnection sqlConnection;
private PcbRecipeEntity pcbRecipeDTO;
public PcbRecipeModel(IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString("Auftrag");
this.sqlConnection = SqlConnection.CreateSqlConnection(connectionString, this.ErrorLog);
this.pcbRecipeDTO = new PcbRecipeEntity();
this.UpdateRecipes();
}
private void ErrorLog(string obj)
{
}
public event Action StateChanged;
public int? Id => this.pcbRecipeDTO.Id == 0 ? null : this.pcbRecipeDTO.Id;
public int? PcbId
{
get => this.pcbRecipeDTO.PcbId != 0 ? this.pcbRecipeDTO.PcbId : null;
set
{
this.pcbRecipeDTO.PcbId = value is int pcbId ? pcbId : default;
this.PcbIdChanged();
}
}
public int MeterType
{
get => this.pcbRecipeDTO.MeterType;
set => this.pcbRecipeDTO.MeterType = value;
}
public string Plate
{
get => this.pcbRecipeDTO.PlateType;
set
{
this.pcbRecipeDTO.PlateType = value;
this.PlateTypeSelected();
}
}
public int? HeliumRecipeId
{
get => this.pcbRecipeDTO.HeliumRecipeId != 0 ? this.pcbRecipeDTO.HeliumRecipeId : null;
set
{
this.pcbRecipeDTO.HeliumRecipeId = value is int hid ? hid : default;
this.HeliumRecipeSelected();
}
}
public int? WaterRecipeId
{
get => this.pcbRecipeDTO.WaterRecipeId != 0 ? this.pcbRecipeDTO.WaterRecipeId : null;
set
{
this.pcbRecipeDTO.WaterRecipeId = value is int wid ? wid : default;
this.WaterRecipeSelected();
}
}
public int? Region
{
get => this.pcbRecipeDTO.Region != 0 ? this.pcbRecipeDTO.Region : null;
set => this.pcbRecipeDTO.Region = value is int region ? region : default;
}
public int? MeterSize
{
get => this.pcbRecipeDTO.MeterSize != 0 ? this.pcbRecipeDTO.MeterSize : null;
set => this.pcbRecipeDTO.MeterSize = value is int meterSize ? meterSize : default;
}
public int? BodyLength
{
get => this.pcbRecipeDTO.BodyLength != 0 ? this.pcbRecipeDTO.BodyLength : null;
set => this.pcbRecipeDTO.BodyLength = value is int bodyLength ? bodyLength : default;
}
public bool HasPressureSensor
{
get => this.pcbRecipeDTO.Pressure;
set => this.pcbRecipeDTO.Pressure = value;
}
public double? DeadVolume
{
get => this.pcbRecipeDTO.DeadVolume != 0 ? this.pcbRecipeDTO.DeadVolume : null;
set => this.pcbRecipeDTO.DeadVolume = value is double deadVolume ? deadVolume : default;
}
public Dictionary<int, string> HeliumRecipes { get; set; } = [];
public Dictionary<int, string> WaterRecipes { get; set; } = [];
public IEnumerable<PcbRecipeDTO> Recipes { get; set; }
public void TryAddOrUpdate()
{
if (this.Id is null)
{
this.sqlConnection
.CreateCommand($@"
INSERT INTO ht.PcbRecipe
( PcbId
, HeliumRecipeId
, WaterRecipeId
, Region
, Dn
, Length
, Pressure
, Plate
, DeadVolume
, MeterType)
VALUES (@{nameof(this.pcbRecipeDTO.PcbId)}
, @{nameof(this.pcbRecipeDTO.HeliumRecipeId)}
, @{nameof(this.pcbRecipeDTO.WaterRecipeId)}
, @{nameof(this.pcbRecipeDTO.Region)}
, @{nameof(this.pcbRecipeDTO.MeterSize)}
, @{nameof(this.pcbRecipeDTO.BodyLength)}
, @{nameof(this.pcbRecipeDTO.Pressure)}
, @{nameof(this.pcbRecipeDTO.PlateType)}
, @{nameof(this.pcbRecipeDTO.DeadVolume)}
, @{nameof(this.pcbRecipeDTO.MeterType)})")
.SetParameter(nameof(this.pcbRecipeDTO.PcbId), this.pcbRecipeDTO.PcbId)
.SetParameter(nameof(this.pcbRecipeDTO.HeliumRecipeId), this.pcbRecipeDTO.HeliumRecipeId)
.SetParameter(nameof(this.pcbRecipeDTO.WaterRecipeId), this.pcbRecipeDTO.WaterRecipeId)
.SetParameter(nameof(this.pcbRecipeDTO.Region), this.pcbRecipeDTO.Region)
.SetParameter(nameof(this.pcbRecipeDTO.MeterSize), this.pcbRecipeDTO.MeterSize)
.SetParameter(nameof(this.pcbRecipeDTO.BodyLength), this.pcbRecipeDTO.BodyLength)
.SetParameter(nameof(this.pcbRecipeDTO.Pressure), this.pcbRecipeDTO.Pressure)
.SetParameter(nameof(this.pcbRecipeDTO.PlateType), this.pcbRecipeDTO.PlateType)
.SetParameter(nameof(this.pcbRecipeDTO.DeadVolume), this.pcbRecipeDTO.DeadVolume)
.SetParameter(nameof(this.pcbRecipeDTO.MeterType), this.pcbRecipeDTO.MeterType)
.ExecuteNonQuery();
}
else
{
this.sqlConnection
.CreateCommand($@"
UPDATE ht.PcbRecipe
SET PcbId = @{nameof(this.pcbRecipeDTO.PcbId)}
, HeliumRecipeId = @{nameof(this.pcbRecipeDTO.HeliumRecipeId)}
, WaterRecipeId = @{nameof(this.pcbRecipeDTO.WaterRecipeId)}
, Region = @{nameof(this.pcbRecipeDTO.Region)}
, Dn = @{nameof(this.pcbRecipeDTO.MeterSize)}
, Length = @{nameof(this.pcbRecipeDTO.BodyLength)}
, Pressure = @{nameof(this.pcbRecipeDTO.Pressure)}
, Plate = @{nameof(this.pcbRecipeDTO.PlateType)}
, DeadVolume = @{nameof(this.pcbRecipeDTO.DeadVolume)}
, MeterType = @{nameof(this.pcbRecipeDTO.MeterType)}
WHERE Id = @{nameof(this.pcbRecipeDTO.Id)}")
.SetParameter(nameof(this.pcbRecipeDTO.Id), this.pcbRecipeDTO.Id)
.SetParameter(nameof(this.pcbRecipeDTO.PcbId), this.pcbRecipeDTO.PcbId)
.SetParameter(nameof(this.pcbRecipeDTO.HeliumRecipeId), this.pcbRecipeDTO.HeliumRecipeId)
.SetParameter(nameof(this.pcbRecipeDTO.WaterRecipeId), this.pcbRecipeDTO.WaterRecipeId)
.SetParameter(nameof(this.pcbRecipeDTO.Region), this.pcbRecipeDTO.Region)
.SetParameter(nameof(this.pcbRecipeDTO.MeterSize), this.pcbRecipeDTO.MeterSize)
.SetParameter(nameof(this.pcbRecipeDTO.BodyLength), this.pcbRecipeDTO.BodyLength)
.SetParameter(nameof(this.pcbRecipeDTO.Pressure), this.pcbRecipeDTO.Pressure)
.SetParameter(nameof(this.pcbRecipeDTO.PlateType), this.pcbRecipeDTO.PlateType)
.SetParameter(nameof(this.pcbRecipeDTO.DeadVolume), this.pcbRecipeDTO.DeadVolume)
.SetParameter(nameof(this.pcbRecipeDTO.MeterType), this.pcbRecipeDTO.MeterType)
.ExecuteNonQuery();
}
this.CleanDTO();
}
private void CleanDTO()
{
this.pcbRecipeDTO.Id = default;
this.PcbId = default;
this.HeliumRecipeId = default;
this.WaterRecipeId = default;
this.Region = default;
this.MeterSize = default;
this.BodyLength = default;
this.HasPressureSensor = default;
this.Plate = default;
this.DeadVolume = default;
this.MeterType = default;
}
public void TryClearOrDelete()
{
this.sqlConnection
.CreateCommand($@"DELETE FROM ht.PcbRecipe WHERE Id = @{nameof(this.pcbRecipeDTO.Id)}")
.SetParameter(nameof(this.pcbRecipeDTO.Id), this.pcbRecipeDTO.Id)
.ExecuteNonQuery();
this.CleanDTO();
}
private void UpdateRecipes()
{
this.Recipes = this.sqlConnection
.CreateCommand(@"
SELECT TOP 20
pr.Id
, pr.PcbId
, CONCAT(hv.Region, ' NW=', hv.MeterSize, ' BL=', hv.BodyLength, ' DS=', hv.HasPressureSensor)
, CONCAT(wv.Region, ' NW=', wv.MeterSize, ' BL=', wv.BodyLength, ' DS=', wv.HasPressureSensor)
, pr.Region
, pr.Dn
, pr.Length
, pr.Pressure
, pr.Plate
, pr.DeadVolume
, pr.MeterType
FROM ht.PcbRecipe AS pr
JOIN ht.HeliumRecipes AS hr
ON pr.HeliumRecipeId = hr.Id
JOIN ht.TestVariants AS hv
ON hr.VariantId = hv.Id
JOIN ht.WaterRecipes AS wr
ON pr.WaterRecipeId = wr.Id
JOIN ht.TestVariants AS wv
ON hr.VariantId = wv.Id
ORDER BY 1 DESC")
.ExecuteReader(x => new PcbRecipeDTO
{
Id = x.GetValue<int>(0),
PcbId = x.GetValue<int>(1),
HeliumRecipeId = x.GetValue<string>(2),
WaterRecipeId = x.GetValue<string>(3),
Region = x.GetValue<int>(4),
MeterSize = x.GetValue<int>(5),
BodyLength = x.GetValue<int>(6),
Pressure = x.GetValue<bool>(7),
PlateType = x.GetValue<string>(8),
DeadVolume = x.GetValue<double>(9),
MeterType = x.GetValue<int>(10),
});
}
private void PlateTypeSelected()
{
if (!string.IsNullOrWhiteSpace(this.Plate))
{
var tokens = this.Plate
.Replace("DN", string.Empty)
.Split('_', StringSplitOptions.RemoveEmptyEntries);
if (tokens.Length == 2)
{
if (int.TryParse($"{tokens[0]}", out var meterSize))
{
this.MeterSize = meterSize;
}
this.Region = tokens[1] == "NA" ? 1 : tokens[1] == "EMEA" ? 2 : null;
}
}
var testVariant = this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
RegionCode
, MeterSizeCode
, DeadVolume
FROM ht.TestVariants
WHERE Plate = @{nameof(this.Plate)}")
.SetParameter(nameof(this.Plate), this.Plate)
.FirstOrDefault(x => new
{
RegionCode = x.GetValue<string>(0),
MeterSizeCode = x.GetValue<string>(1),
DeadVolume = x.GetValue<double>(2),
});
if (testVariant is not null)
{
this.DeadVolume = testVariant.DeadVolume;
this.HeliumRecipes = this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
hr.Id
, CONCAT(tv.Region, ' NW=', tv.MeterSize, ' BL=', tv.BodyLength, ' DS=', tv.HasPressureSensor)
FROM ht.HeliumRecipes AS hr
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE hr.MatchRegion = @{nameof(testVariant.RegionCode)}
AND hr.MatchMeterSize = @{nameof(testVariant.MeterSizeCode)}")
.SetParameter(nameof(testVariant.RegionCode), testVariant.RegionCode)
.SetParameter(nameof(testVariant.MeterSizeCode), testVariant.MeterSizeCode)
.ExecuteReader(x => new
{
Key = x.GetValue<int>(0),
Value = x.GetValue<string>(1),
})
.ToDictionary(x => x.Key, x => x.Value);
this.WaterRecipes = this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
hr.Id
, CONCAT(tv.Region, ' NW=', tv.MeterSize, ' BL=', tv.BodyLength, ' DS=', tv.HasPressureSensor)
FROM ht.WaterRecipes AS hr
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE hr.MatchRegion = @{nameof(testVariant.RegionCode)}
AND hr.MatchMeterSize = @{nameof(testVariant.MeterSizeCode)}")
.SetParameter(nameof(testVariant.RegionCode), testVariant.RegionCode)
.SetParameter(nameof(testVariant.MeterSizeCode), testVariant.MeterSizeCode)
.ExecuteReader(x => new
{
Key = x.GetValue<int>(0),
Value = x.GetValue<string>(1),
})
.ToDictionary(x => x.Key, x => x.Value);
}
else
{
this.HeliumRecipes = [];
this.WaterRecipes = [];
}
}
private void HeliumRecipeSelected()
{
if (this.HeliumRecipeId != null)
{
this.sqlConnection
.CreateCommand($@"
SELECT tv.BodyLength
, tv.HasPressureSensor
FROM ht.HeliumRecipes AS hr
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE hr.Id = @{nameof(this.HeliumRecipeId)}")
.SetParameter(nameof(this.HeliumRecipeId), this.HeliumRecipeId)
.FirstOrDefault(x =>
{
this.BodyLength = x.GetValue<int>(0);
this.HasPressureSensor = x.GetValue<bool>(1);
});
}
}
private void WaterRecipeSelected()
{
if (this.WaterRecipeId != null)
{
this.sqlConnection
.CreateCommand($@"
SELECT tv.BodyLength
, tv.HasPressureSensor
FROM ht.WaterRecipes AS hr
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE hr.Id = @{nameof(this.HeliumRecipeId)}")
.SetParameter(nameof(this.HeliumRecipeId), this.HeliumRecipeId)
.FirstOrDefault(x =>
{
this.BodyLength = x.GetValue<int>(0);
this.HasPressureSensor = x.GetValue<bool>(1);
});
}
}
private void PcbIdChanged()
{
this.sqlConnection
.CreateCommand($@"
SELECT pr.Id
, pr.PcbId
, pr.HeliumRecipeId
, pr.WaterRecipeId
, pr.Region
, pr.Dn
, pr.Length
, pr.Pressure
, pr.Plate
, pr.DeadVolume
, pr.MeterType
FROM ht.PcbRecipe AS pr
WHERE pr.PcbId = @{nameof(this.PcbId)}")
.SetParameter(nameof(this.PcbId), this.PcbId)
.FirstOrDefault(x =>
{
this.pcbRecipeDTO.Id = x.GetValue<int>(0);
this.pcbRecipeDTO.PcbId = x.GetValue<int>(1);
this.pcbRecipeDTO.HeliumRecipeId = x.GetValue<int>(2);
this.pcbRecipeDTO.WaterRecipeId = x.GetValue<int>(3);
this.pcbRecipeDTO.Region = x.GetValue<int>(4);
this.pcbRecipeDTO.MeterSize = x.GetValue<int>(5);
this.pcbRecipeDTO.BodyLength = x.GetValue<int>(6);
this.pcbRecipeDTO.Pressure = x.GetValue<bool>(7);
this.pcbRecipeDTO.PlateType = x.GetValue<string>(8);
this.pcbRecipeDTO.DeadVolume = x.GetValue<double>(9);
this.pcbRecipeDTO.MeterType = x.GetValue<int>(10);
});
if (this.Id > 0)
{
this.HeliumRecipes = this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
hr.Id
, CONCAT(tv.Region, ' NW=', tv.MeterSize, ' BL=', tv.BodyLength, ' DS=', tv.HasPressureSensor)
FROM ht.HeliumRecipes AS hr
JOIN ht.HeliumRecipes AS _hr
ON hr.MatchRegion = _hr.MatchRegion
AND hr.MatchMeterSize = _hr.MatchMeterSize
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE _hr.Id = @{nameof(this.HeliumRecipeId)}")
.SetParameter(nameof(this.HeliumRecipeId), this.HeliumRecipeId)
.ExecuteReader(x => new
{
Key = x.GetValue<int>(0),
Value = x.GetValue<string>(1),
})
.ToDictionary(x => x.Key, x => x.Value);
this.WaterRecipes = this.sqlConnection
.CreateCommand($@"
SELECT DISTINCT
hr.Id
, CONCAT(tv.Region, ' NW=', tv.MeterSize, ' BL=', tv.BodyLength, ' DS=', tv.HasPressureSensor)
FROM ht.WaterRecipes AS hr
JOIN ht.WaterRecipes AS _hr
ON hr.MatchRegion = _hr.MatchRegion
AND hr.MatchMeterSize = _hr.MatchMeterSize
JOIN ht.TestVariants AS tv
ON hr.VariantId = tv.Id
WHERE _hr.Id = @{nameof(this.WaterRecipeId)}")
.SetParameter(nameof(this.WaterRecipeId), this.WaterRecipeId)
.ExecuteReader(x => new
{
Key = x.GetValue<int>(0),
Value = x.GetValue<string>(1),
})
.ToDictionary(x => x.Key, x => x.Value);
}
}
}
}

View File

@ -0,0 +1,55 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester.Models
{
using LaaPackages.SqlClient;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
public class RecipesAssignmentModel
{
private readonly SqlConnection sqlConnection;
public RecipesAssignmentModel(IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString("Auftrag");
this.sqlConnection = SqlConnection.CreateSqlConnection(connectionString);
}
public IEnumerable<PcbRecipeEntity> LoadLast20PcbRecieps()
{
var latest20Recipes = this.sqlConnection
.CreateCommand(@"
SELECT TOP 20
Id
, PcbId
, HeliumRecipeId
, WaterRecipeId
, Region
, Dn
, Length
, Pressure
, Plate
, DeadVolume
, MeterType
FROM ht.PcbRecipe
ORDER BY Id DESC")
.ExecuteReader(x => new PcbRecipeEntity
{
Id = x.GetValue<int>(0),
PcbId = x.GetValue<int>(1),
HeliumRecipeId = x.GetValue<int>(2),
WaterRecipeId = x.GetValue<int>(3),
Region = x.GetValue<int>(4),
MeterSize = x.GetValue<int>(5),
BodyLength = x.GetValue<int>(6),
Pressure = x.GetValue<bool>(7),
PlateType = x.GetValue<string>(8),
DeadVolume = x.GetValue<double>(9),
MeterType = x.GetValue<int>(10),
});
return latest20Recipes;
}
}
}

View File

@ -6,14 +6,12 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Timers;
public class RecipesCollectionModel
{
private const string addToGroup = "AddToGroupAsync";
private const string recipes = nameof(recipes);
private HubConnection changeHub;
private Timer timer;
private readonly HeliumTesterService heliumTesterService;
private readonly List<HeliumRecipeModel> heliumRecieps;
@ -35,9 +33,6 @@
this.LoadRecipes();
this.timer = new System.Timers.Timer(2000);
this.timer.Elapsed += this.Timer_Elapsed;
this.timer.AutoReset = false;
this.changeHub = new HubConnectionBuilder()
#if DEBUG
.WithUrl("https://localhost:44354/changes")
@ -46,17 +41,11 @@
#endif
.Build();
this.changeHub.On<string>(nameof(NotifyChangedAsync), this.NotifyChangedAsync);
this.changeHub.On<string>(nameof(this.NotifyChangedAsync), this.NotifyChangedAsync);
this.changeHub.StartAsync().Wait();
this.changeHub.SendAsync(addToGroup, recipes);
}
private void Timer_Elapsed(object _, ElapsedEventArgs _1)
{
this.timer.Stop();
this.changeHub.SendAsync(nameof(this.NotifyChangedAsync), recipes);
}
private void NotifyChangedAsync(string group)
{
if (group == recipes)
@ -213,21 +202,29 @@
private void OnHeliumRecipeChanged(HeliumRecipeModel recipe)
{
this.heliumTesterService.UpdateRecipe(HeliumRecipeModel.ToEntity(recipe));
this.OnRecipeChanged();
}
if (!this.timer.Enabled)
private long previousTiks;
const long minTicks = 1000 * 10_000;
private void OnRecipeChanged()
{
var currentTicks = DateTime.UtcNow.Ticks;
var difference = currentTicks - previousTiks;
if (difference > minTicks)
{
this.timer.Start();
this.changeHub.SendAsync(nameof(this.NotifyChangedAsync), recipes);
}
previousTiks = DateTime.UtcNow.Ticks;
}
private void OnWaterRecipeChanged(WaterRecipeModel recipe)
{
this.heliumTesterService.UpdateRecipe(WaterRecipeModel.ToEntity(recipe));
//if (!this.timer.Enabled)
//{
// this.timer.Start();
//}
this.OnRecipeChanged();
}
private void VHeliumRecipePropertyChanged(string property)

View File

@ -4,7 +4,10 @@
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
<li class="nav-item">
<NavLink ActiveClass="active" Match="NavLinkMatch.All" class="nav-link py-1" href="heliumtester/recipes">Rezepten</NavLink>
</li>
</li>
<li class="nav-item">
<NavLink ActiveClass="active" Match="NavLinkMatch.All" class="nav-link py-1" href="heliumtester/pcbrecipes">Rezeptzuordnung</NavLink>
</li>
<li class="nav-item">
<NavLink ActiveClass="active" Match="NavLinkMatch.All" class="nav-link py-1" href="heliumtester/statistics">Statistik</NavLink>
</li>
@ -12,63 +15,67 @@
</div>
</div>
</nav>
<div class="container-fluid bg-body-tertiary py-2 font-monospace">
<div class="row">
<div class="col">
<div class="nav-item px-2 ">
<table class="table table-sm mb-0">
<tbody>
<tr>
<th class="bg-light pe-3">Regionen</th>
<td class="bg-light" colspan="100">
<div class="d-flex align-items-center">
@foreach (var region in this.MatchCollectionModel.Regions)
{
<input type="checkbox" @bind="@region.Selected" class="form-check-input mt-0 me-2" id="rg_@region.GetHashCode()" />
<label class="me-3" for="rg_@region.GetHashCode()">@region.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Nennweiten</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var meterSize in this.MatchCollectionModel.MeterSizes)
{
<input type="checkbox" @bind="@meterSize.Selected" class="form-check-input mt-0 me-2" id="ms_@meterSize.GetHashCode()" />
<label class="me-3" for="ms_@meterSize.GetHashCode()">@meterSize.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Baulängen</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var bodyLength in this.MatchCollectionModel.BodyLengths)
{
<input type="checkbox" @bind="@bodyLength.Selected" class="form-check-input mt-0 me-2" id="bl_@bodyLength.GetHashCode()" />
<label class="me-3" for="bl_@bodyLength.GetHashCode()">@bodyLength.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Drucksensoren</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var pressureSensor in this.MatchCollectionModel.PressureSensors)
{
<input type="checkbox" @bind="@pressureSensor.Selected" class="form-check-input mt-0 me-2" id="ps_@pressureSensor.GetHashCode()" />
<label class="me-3" for="ps_@pressureSensor.GetHashCode()">@(pressureSensor.Value ? "Mit" : "Ohne")</label>
}
</div>
</td>
</tr>
</tbody>
</table>
@if (this.ShowMatchList)
{
<div class="container-fluid bg-body-tertiary py-2 font-monospace">
<div class="row">
<div class="col">
<div class="nav-item px-2 ">
<table class="table table-sm mb-0">
<tbody>
<tr>
<th class="bg-light pe-3">Regionen</th>
<td class="bg-light" colspan="100">
<div class="d-flex align-items-center">
@foreach (var region in this.MatchCollectionModel.Regions)
{
<input type="checkbox" @bind="@region.Selected" class="form-check-input mt-0 me-2" id="rg_@region.GetHashCode()" />
<label class="me-3" for="rg_@region.GetHashCode()">@region.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Nennweiten</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var meterSize in this.MatchCollectionModel.MeterSizes)
{
<input type="checkbox" @bind="@meterSize.Selected" class="form-check-input mt-0 me-2" id="ms_@meterSize.GetHashCode()" />
<label class="me-3" for="ms_@meterSize.GetHashCode()">@meterSize.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Baulängen</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var bodyLength in this.MatchCollectionModel.BodyLengths)
{
<input type="checkbox" @bind="@bodyLength.Selected" class="form-check-input mt-0 me-2" id="bl_@bodyLength.GetHashCode()" />
<label class="me-3" for="bl_@bodyLength.GetHashCode()">@bodyLength.Value</label>
}
</div>
</td>
</tr>
<tr>
<th class="bg-light pe-3">Drucksensoren</th>
<td class="bg-light pe-3" colspan="100">
<div class="d-flex align-items-center">
@foreach (var pressureSensor in this.MatchCollectionModel.PressureSensors)
{
<input type="checkbox" @bind="@pressureSensor.Selected" class="form-check-input mt-0 me-2" id="ps_@pressureSensor.GetHashCode()" />
<label class="me-3" for="ps_@pressureSensor.GetHashCode()">@(pressureSensor.Value ? "Mit" : "Ohne")</label>
}
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}

View File

@ -29,6 +29,9 @@
[Parameter]
public EventCallback MatchSelectionChanged { get; set; }
[Parameter]
public bool ShowMatchList { get; set; } = true;
protected override async Task OnInitializedAsync()
{
var testVariants = this.HeliumTesterService.LoadTestVariants();

View File

@ -1,4 +1,6 @@
<div class="dropdown font-monospace">
@using System.Text.RegularExpressions
<div class="dropdown font-monospace">
<input type="number"
class="form-control dropdown-toggle"
data-bs-toggle="dropdown"
@ -9,13 +11,17 @@
<div class="dropdown-menu w-100 mh-500 overflow-y-auto px-3">
@foreach (var group in this.OverallIdents.GroupBy(x => x.PcbId))
{
<div>@group.Key </div>
<div>@group.Key - <i class="small text-secondary">@group.FirstOrDefault().DateTime.ToString("yyyy-MM-dd HH:mm:ss")</i></div>
@foreach (var item in group.Select(x => x))
{
var id = Regex.Replace($"_{item.OverallId}_{item.Description}", "[^a-zA-Z0-9]", "_");
<div class="form-check ms-3">
<input value="@item.OverallId" @bind="item.Selected" class="form-check-input me-2" type="checkbox" id="_@item.OverallId">
<label class="form-check-label cursor-pointer" for="_@item.OverallId"><i class="small text-secondary">@item.OverallId - @item.Description</i></label>
<input value="@item.OverallId" @bind="item.Selected" class="form-check-input me-2" type="checkbox" id="@id">
<label class="form-check-label cursor-pointer" for="@id">
<i class="small text-secondary">@item.OverallId - @item.Description</i>
</label>
</div>
}
}
@ -24,13 +30,17 @@
<div class="list-group list-group-flush mt-3 font-monospace">
@foreach (var group in this.OverallIdents.Where(x => x.Selected).GroupBy(x => x.PcbId))
{
<div>@group.Key </div>
<div>@group.Key - <i class="small text-secondary">@group.FirstOrDefault().DateTime.ToString("yyyy-MM-dd HH:mm:ss")</i></div>
@foreach (var item in group.Select(x => x))
{
var id = Regex.Replace($"_{item.OverallId}_{item.Description}", "[^a-zA-Z0-9]", "_");
<div class="form-check ms-3">
<input value="@item.OverallId" @bind="item.Selected" class="form-check-input me-2" type="checkbox" id="_@item.OverallId">
<label class="form-check-label cursor-pointer" for="_@item.OverallId"><i class="small text-secondary">@item.OverallId - @item.Description</i></label>
<input value="@item.OverallId" @bind="item.Selected" class="form-check-input me-2" type="checkbox" id="@id">
<label class="form-check-label cursor-pointer" for="@id">
<i class="small text-secondary">@item.OverallId - @item.Description</i>
</label>
</div>
}
}

View File

@ -0,0 +1,139 @@
@page "/heliumtester/pcbrecipes"
<Navbar ShowMatchList="false" />
<div class="container-fluid py-3">
<table class="hover recipes-table">
<thead>
<tr>
<th colspan="100" class="bg-light fs-6">PcbId - Rezeptzuordnung</th>
</tr>
<tr>
<th class="bg-light">Id</th>
<th class="bg-light">PcbId</th>
<th class="bg-light">Zählertyp</th>
<th class="bg-light">Platte</th>
<th class="bg-light">Heliumrezept</th>
<th class="bg-light">Wasserrezept</th>
<th class="bg-light">Region</th>
<th class="bg-light">Nennweite</th>
<th class="bg-light">Baulänge</th>
<th class="bg-light">Hat Drucksensor</th>
<th class="bg-light">Totvolumen</th>
<th class="bg-light"></th>
</tr>
</thead>
<tbody>
<tr>
<th class="bg-light py-0 px-2">@this.PcbRecipeModel.Id</th>
<td class="p-0">
<input class="form-control form-control-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.PcbId" />
</td>
<td class="p-0 bg-light">
<select class="form-select form-select-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.MeterType">
<option value="0">Prüfgehäse</option>
<option value="1">Referenzgehäse</option>
</select>
</td>
<td class="p-0 bg-light">
<select class="form-select form-select-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.Plate">
<option value=""></option>
<option value="DN40_EMEA">DN40_EMEA</option>
<option value="DN50_EMEA">DN50_EMEA</option>
<option value="DN65_EMEA">DN65_EMEA</option>
<option value="DN80_EMEA">DN80_EMEA</option>
<option value="DN100_EMEA">DN100_EMEA</option>
<option value="DN125_EMEA">DN125_EMEA</option>
<option value="DN150_EMEA">DN150_EMEA</option>
<option value="DN200_EMEA">DN200_EMEA</option>
<option value="DN40_NA">DN40_NA</option>
<option value="DN50_NA">DN50_NA</option>
<option value="DN80_NA">DN80_NA</option>
<option value="DN100_NA">DN100_NA</option>
<option value="DN150_NA">DN150_NA</option>
</select>
</td>
<td class="p-0 bg-light">
<select class="form-select form-select-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.HeliumRecipeId">
<option value=""></option>
@foreach (var (key, value) in this.PcbRecipeModel.HeliumRecipes)
{
<option value="@key">@value</option>
}
</select>
</td>
<td class="p-0 bg-light">
<select class="form-select form-select-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.WaterRecipeId">
<option value=""></option>
@foreach (var (key, value) in this.PcbRecipeModel.WaterRecipes)
{
<option value="@key">@value</option>
}
</select>
</td>
<td class="p-0 bg-light">
<select class="form-select form-select-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.Region">
<option value=""></option>
<option value="1">NA 1</option>
<option value="2">EMEA 2</option>
<option value="3">EMEA 3</option>
</select>
</td>
<td class="p-0 bg-light">
<input class="form-control form-control-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.MeterSize" />
</td>
<d class="p-0 bg-light">
<input class="form-control form-control-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.BodyLength" />
</d>
<td class="p-0 bg-light">
<input type="checkbox" class="btn-check" id="ds" autocomplete="off" @bind="this.PcbRecipeModel.HasPressureSensor">
<label class="btn btn-primary w-100 border-0 rounded-0 bg-transparent text-start py-0 ps-2" for="ds">
@if (this.PcbRecipeModel.HasPressureSensor)
{
<i class="bi bi-check text-success"></i>
}
else
{
<i class="bi bi-x text-danger"></i>
}
</label>
</td>
<td class="p-0 bg-light">
<input class="form-control form-control-sm text-start border-0 rounded-0 bg-light" @bind="this.PcbRecipeModel.DeadVolume" />
</td>
<td class="p-0 bg-light text-center">
<i class="bi bi-floppy-fill text-success mx-2 cursor-pointer fw-bold" @onclick="this.PcbRecipeModel.TryAddOrUpdate"></i>
<i class="bi bi-trash3-fill text-danger me-2 cursor-pointer fw-bold" @onclick="this.PcbRecipeModel.TryClearOrDelete"></i>
</td>
</tr>
@foreach (var recipe in this.PcbRecipeModel.Recipes)
{
<tr>
<th class="bg-light py-0 px-2">@recipe.Id</th>
<td class="p-2">@recipe.PcbId</td>
<td class="p-2">@recipe.MeterType</td>
<td class="p-2">@recipe.PlateType</td>
<td class="p-2">@recipe.HeliumRecipeId</td>
<td class="p-2">@recipe.WaterRecipeId</td>
<td class="p-2">@recipe.Region</td>
<td class="p-2">@recipe.MeterSize</td>
<td class="p-2">@recipe.BodyLength</td>
<td class="p-2">
@if (@recipe.Pressure)
{
<i class="bi bi-check text-success"></i>
}
else
{
<i class="bi bi-x text-danger"></i>
}
</td>
<td class="p-2">@recipe.DeadVolume</td>
<td class="p-1">
<i class="bi bi-pencil-square text-warning mx-2 cursor-pointer fw-bold" @onclick="_ => this.PcbRecipeModel.PcbId = recipe.PcbId"></i>
</td>
</tr>
}
</tbody>
</table>
</div>

View File

@ -0,0 +1,18 @@
namespace LaaProductionWeb.Blazor.Components.HeliumTester
{
using LaaProductionWeb.Blazor.Components.HeliumTester.Models;
using Microsoft.AspNetCore.Components;
public partial class PcbRecipes : ComponentBase
{
[Inject]
private PcbRecipeModel PcbRecipeModel { get; set; }
protected override void OnInitialized()
{
this.PcbRecipeModel.StateChanged -= this.StateHasChanged;
this.PcbRecipeModel.StateChanged += this.StateHasChanged;
}
}
}

View File

@ -22,10 +22,8 @@
public Virtualize<WaterRecipeModel> WaterReciepesVirtualizer { get; set; }
protected override void OnInitialized()
{
this.RecipesCollectionModel.RecipesChanged += MatchSelectionChanged;
}
protected override void OnInitialized()
=> this.RecipesCollectionModel.RecipesChanged += MatchSelectionChanged;
private ValueTask<ItemsProviderResult<HeliumRecipeModel>> LoadHeliumReciepsAsync(ItemsProviderRequest request)
{

View File

@ -1,6 +1,6 @@
@inherits LayoutComponentBase
<nav class="navbar navbar-expand-lg bg-dark" data-bs-theme="dark">
<nav class="navbar navbar-expand-lg bg-dark sticky-top" data-bs-theme="dark">
<div class="container-fluid">
<div class="collapse navbar-collapse" id="navbar">
<ul class="navbar-nav me-auto">

View File

@ -39,6 +39,8 @@ namespace LaaProductionWeb.Blazor
services.AddScoped<MatchCollectionModel>();
services.AddScoped<RecipesCollectionModel>();
services.AddScoped<CSDDBContext>();
services.AddScoped<VAKOMerkmale>();
services.AddScoped<PcbRecipeModel>();
services.AddRazorComponents(options => options.DetailedErrors = true)
.AddInteractiveServerComponents(options => options.DetailedErrors = true);

View File

@ -74,9 +74,12 @@ table.recipes-table input.form-check-input {
width: 100% !important;
}
.recipes-table tr > td > input:focus {
.recipes-table tr > td > input:focus,
.recipes-table tr > td > select:focus {
background-color: aliceblue;
border: 1px solid gray !important;
box-shadow: none !important;
outline: none !important;
}
.recipes-table tr.hover:hover * {
@ -96,3 +99,25 @@ table.recipes-table input.form-check-input {
right: .5rem;
top: .5rem;
}
.btn-check:not(:checked) + .btn-light {
--bs-btn-bg: #ffffff !important;
--bs-btn-border-color: #ffffff !important;
--bs-btn-color: val(--bs-secondary) !important;
--bs-btn-active-color: val(--bs-secondary) !important;
}
.btn-check:checked + .btn-light {
--bs-btn-bg: rgba(0, 0, 0, 0.1) !important;
--bs-btn-border-color: rgba(0, 0, 0, 0.1) !important;
--bs-btn-color: val(--bs-dark) !important;
--bs-btn-active-color: val(--bs-dark) !important;
}
.smaller {
font-size: 80% !important;
}
.form-select {
--bs-form-select-bg-img: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="currentColor" class="bi bi-chevron-expand" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M3.646 9.146a.5.5 0 0 1 .708 0L8 12.793l3.646-3.647a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 0-.708m0-2.292a.5.5 0 0 0 .708 0L8 3.207l3.646 3.647a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 0 0 0 .708"/></svg>');
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-expand" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M3.646 9.146a.5.5 0 0 1 .708 0L8 12.793l3.646-3.647a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 0-.708m0-2.292a.5.5 0 0 0 .708 0L8 3.207l3.646 3.647a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 0 0 0 .708"/></svg>