From f539289f45ec456bf9c6c0d8b93ee805c175fee3 Mon Sep 17 00:00:00 2001 From: Sami Alzein Date: Wed, 6 Aug 2025 21:21:34 +0200 Subject: [PATCH] Refactor code structure for improved readability and maintainability --- .github/copilot-instructions.md | 124 + .gitignore | 78 + Configration.csv | 5 + DaireApplication.sln | 25 + DaireApplication/App.axaml | 20 + DaireApplication/App.axaml.cs | 32 + DaireApplication/Assets/AdminGraph.png | Bin 0 -> 12846 bytes DaireApplication/Assets/AdminMachine.png | Bin 0 -> 57619 bytes DaireApplication/Assets/Board.png | Bin 0 -> 44667 bytes DaireApplication/Assets/Fonts/HLL.ttf | Bin 0 -> 50240 bytes DaireApplication/Assets/Fonts/Helvetica.ttf | Bin 0 -> 317968 bytes DaireApplication/Assets/Home.png | Bin 0 -> 416 bytes DaireApplication/Assets/LeftArrow.png | Bin 0 -> 1049 bytes DaireApplication/Assets/LineDots.png | Bin 0 -> 249 bytes DaireApplication/Assets/Logo.png | Bin 0 -> 1303 bytes DaireApplication/Assets/Machine.png | Bin 0 -> 21910 bytes DaireApplication/Assets/Manual.png | Bin 0 -> 372 bytes .../Assets/ManualControlMachine.png | Bin 0 -> 38182 bytes DaireApplication/Assets/Plus.png | Bin 0 -> 2470 bytes DaireApplication/Assets/RedUpArrow.png | Bin 0 -> 1187 bytes DaireApplication/Assets/RightArrow.png | Bin 0 -> 1048 bytes DaireApplication/Assets/Settings.png | Bin 0 -> 1313 bytes DaireApplication/Assets/TempArrow.png | Bin 0 -> 1092 bytes DaireApplication/Assets/TemperingGraphics.png | Bin 0 -> 17561 bytes DaireApplication/Assets/TemperingMachine.png | Bin 0 -> 68251 bytes DaireApplication/Assets/UpArrow.png | Bin 0 -> 1204 bytes DaireApplication/Assets/avalonia-logo.ico | Bin 0 -> 176111 bytes DaireApplication/Assets/bluePlug.png | Bin 0 -> 10056 bytes DaireApplication/Assets/errorIcon.png | Bin 0 -> 6291 bytes DaireApplication/Assets/greenPlug.png | Bin 0 -> 10085 bytes DaireApplication/Assets/homeTrack.png | Bin 0 -> 2740 bytes .../Assets/icons8-green-circle-48.png | Bin 0 -> 2545 bytes .../Assets/icons8-red-circle-48.png | Bin 0 -> 2222 bytes DaireApplication/Assets/orangePlug.png | Bin 0 -> 10062 bytes DaireApplication/Assets/purplePlug.png | Bin 0 -> 10108 bytes DaireApplication/Assets/redPlug.png | Bin 0 -> 10048 bytes DaireApplication/Assets/warningIcon.png | Bin 0 -> 1235 bytes DaireApplication/Assets/wifi.png | Bin 0 -> 6183 bytes DaireApplication/Assets/wifioff.png | Bin 0 -> 7111 bytes DaireApplication/Assets/yellowPlug.png | Bin 0 -> 10109 bytes ...tomatic_Fountain_Control_Implementation.md | 294 + DaireApplication/DaireApplication.csproj | 75 + .../DataBase/ConfigrationTable.cs | 202 + DaireApplication/DataBase/DataPathManager.cs | 311 + .../DataBase/ErrorSettingsTable.cs | 81 + DaireApplication/DataBase/MachineTable.cs | 124 + DaireApplication/DataBase/Mapping.cs | 196 + DaireApplication/DataBase/RecipeTable.cs | 239 + DaireApplication/DataBase/ScreeenTable.cs | 112 + DaireApplication/DataBase/UserTable.cs | 83 + DaireApplication/Loops/CheckInterNetLoop.cs | 111 + DaireApplication/Loops/InteractiveUILoop.cs | 100 + DaireApplication/Loops/ScreenLoop.cs | 172 + DaireApplication/Loops/TouchLoop.cs | 54 + DaireApplication/Loops/serialThreadLoop.cs | 504 + ...l_Based_Fountain_Control_Implementation.md | 247 + DaireApplication/Program.cs | 33 + .../PublishProfiles/FolderProfile.pubxml | 17 + .../Recipe_System_Enhancement_Summary.md | 225 + .../Temperature_Error_Fix_Summary.md | 217 + DaireApplication/ViewLocator.cs | 32 + DaireApplication/ViewModels/Error.cs | 93 + .../ViewModels/HoldingRegister.cs | 20 + .../ViewModels/MainWindowViewModel.cs | 7 + DaireApplication/ViewModels/ModBusMaster.cs | 306 + DaireApplication/ViewModels/ViewModelBase.cs | 8 + DaireApplication/ViewModels/X11CursorHider.cs | 69 + DaireApplication/Views/MainWindow.axaml | 487 + DaireApplication/Views/MainWindow.axaml.cs | 4917 ++++ .../Views/UserController/Admin.axaml | 1517 ++ .../Views/UserController/Admin.axaml.cs | 394 + .../UserController/AdvanceSettings.axaml | 1391 + .../UserController/AdvanceSettings.axaml.cs | 1077 + .../Views/UserController/Diagnostics.axaml | 2393 ++ .../Views/UserController/Diagnostics.axaml.cs | 1037 + .../Views/UserController/Home.axaml | 140 + .../Views/UserController/Home.axaml.cs | 755 + .../Views/UserController/ManualControl.axaml | 535 + .../UserController/ManualControl.axaml.cs | 266 + .../Views/UserController/Recipe.axaml | 341 + .../Views/UserController/Recipe.axaml.cs | 719 + .../Views/UserController/RecipeEdit.axaml | 232 + .../Views/UserController/RecipeEdit.axaml.cs | 253 + .../Views/UserController/Settings.axaml | 513 + .../Views/UserController/Settings.axaml.cs | 388 + .../Views/UserController/Software.axaml | 783 + .../Views/UserController/Software.axaml.cs | 698 + DaireApplication/app.manifest | 18 + ErrorSettings.csv | 2 + Machine.csv | 2 + Mapping.csv | 19 + README.md | 93 + Recipe.csv | 2 + Screen.csv | 2 + Users.csv | 5 + review.txt | 22739 ++++++++++++++++ 96 files changed, 45934 insertions(+) create mode 100644 .github/copilot-instructions.md create mode 100644 .gitignore create mode 100644 Configration.csv create mode 100644 DaireApplication.sln create mode 100644 DaireApplication/App.axaml create mode 100644 DaireApplication/App.axaml.cs create mode 100644 DaireApplication/Assets/AdminGraph.png create mode 100644 DaireApplication/Assets/AdminMachine.png create mode 100644 DaireApplication/Assets/Board.png create mode 100644 DaireApplication/Assets/Fonts/HLL.ttf create mode 100644 DaireApplication/Assets/Fonts/Helvetica.ttf create mode 100644 DaireApplication/Assets/Home.png create mode 100644 DaireApplication/Assets/LeftArrow.png create mode 100644 DaireApplication/Assets/LineDots.png create mode 100644 DaireApplication/Assets/Logo.png create mode 100644 DaireApplication/Assets/Machine.png create mode 100644 DaireApplication/Assets/Manual.png create mode 100644 DaireApplication/Assets/ManualControlMachine.png create mode 100644 DaireApplication/Assets/Plus.png create mode 100644 DaireApplication/Assets/RedUpArrow.png create mode 100644 DaireApplication/Assets/RightArrow.png create mode 100644 DaireApplication/Assets/Settings.png create mode 100644 DaireApplication/Assets/TempArrow.png create mode 100644 DaireApplication/Assets/TemperingGraphics.png create mode 100644 DaireApplication/Assets/TemperingMachine.png create mode 100644 DaireApplication/Assets/UpArrow.png create mode 100644 DaireApplication/Assets/avalonia-logo.ico create mode 100644 DaireApplication/Assets/bluePlug.png create mode 100644 DaireApplication/Assets/errorIcon.png create mode 100644 DaireApplication/Assets/greenPlug.png create mode 100644 DaireApplication/Assets/homeTrack.png create mode 100644 DaireApplication/Assets/icons8-green-circle-48.png create mode 100644 DaireApplication/Assets/icons8-red-circle-48.png create mode 100644 DaireApplication/Assets/orangePlug.png create mode 100644 DaireApplication/Assets/purplePlug.png create mode 100644 DaireApplication/Assets/redPlug.png create mode 100644 DaireApplication/Assets/warningIcon.png create mode 100644 DaireApplication/Assets/wifi.png create mode 100644 DaireApplication/Assets/wifioff.png create mode 100644 DaireApplication/Assets/yellowPlug.png create mode 100644 DaireApplication/Automatic_Fountain_Control_Implementation.md create mode 100644 DaireApplication/DaireApplication.csproj create mode 100644 DaireApplication/DataBase/ConfigrationTable.cs create mode 100644 DaireApplication/DataBase/DataPathManager.cs create mode 100644 DaireApplication/DataBase/ErrorSettingsTable.cs create mode 100644 DaireApplication/DataBase/MachineTable.cs create mode 100644 DaireApplication/DataBase/Mapping.cs create mode 100644 DaireApplication/DataBase/RecipeTable.cs create mode 100644 DaireApplication/DataBase/ScreeenTable.cs create mode 100644 DaireApplication/DataBase/UserTable.cs create mode 100644 DaireApplication/Loops/CheckInterNetLoop.cs create mode 100644 DaireApplication/Loops/InteractiveUILoop.cs create mode 100644 DaireApplication/Loops/ScreenLoop.cs create mode 100644 DaireApplication/Loops/TouchLoop.cs create mode 100644 DaireApplication/Loops/serialThreadLoop.cs create mode 100644 DaireApplication/Pedal_Based_Fountain_Control_Implementation.md create mode 100644 DaireApplication/Program.cs create mode 100644 DaireApplication/Properties/PublishProfiles/FolderProfile.pubxml create mode 100644 DaireApplication/Recipe_System_Enhancement_Summary.md create mode 100644 DaireApplication/Temperature_Error_Fix_Summary.md create mode 100644 DaireApplication/ViewLocator.cs create mode 100644 DaireApplication/ViewModels/Error.cs create mode 100644 DaireApplication/ViewModels/HoldingRegister.cs create mode 100644 DaireApplication/ViewModels/MainWindowViewModel.cs create mode 100644 DaireApplication/ViewModels/ModBusMaster.cs create mode 100644 DaireApplication/ViewModels/ViewModelBase.cs create mode 100644 DaireApplication/ViewModels/X11CursorHider.cs create mode 100644 DaireApplication/Views/MainWindow.axaml create mode 100644 DaireApplication/Views/MainWindow.axaml.cs create mode 100644 DaireApplication/Views/UserController/Admin.axaml create mode 100644 DaireApplication/Views/UserController/Admin.axaml.cs create mode 100644 DaireApplication/Views/UserController/AdvanceSettings.axaml create mode 100644 DaireApplication/Views/UserController/AdvanceSettings.axaml.cs create mode 100644 DaireApplication/Views/UserController/Diagnostics.axaml create mode 100644 DaireApplication/Views/UserController/Diagnostics.axaml.cs create mode 100644 DaireApplication/Views/UserController/Home.axaml create mode 100644 DaireApplication/Views/UserController/Home.axaml.cs create mode 100644 DaireApplication/Views/UserController/ManualControl.axaml create mode 100644 DaireApplication/Views/UserController/ManualControl.axaml.cs create mode 100644 DaireApplication/Views/UserController/Recipe.axaml create mode 100644 DaireApplication/Views/UserController/Recipe.axaml.cs create mode 100644 DaireApplication/Views/UserController/RecipeEdit.axaml create mode 100644 DaireApplication/Views/UserController/RecipeEdit.axaml.cs create mode 100644 DaireApplication/Views/UserController/Settings.axaml create mode 100644 DaireApplication/Views/UserController/Settings.axaml.cs create mode 100644 DaireApplication/Views/UserController/Software.axaml create mode 100644 DaireApplication/Views/UserController/Software.axaml.cs create mode 100644 DaireApplication/app.manifest create mode 100644 ErrorSettings.csv create mode 100644 Machine.csv create mode 100644 Mapping.csv create mode 100644 README.md create mode 100644 Recipe.csv create mode 100644 Screen.csv create mode 100644 Users.csv create mode 100644 review.txt diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..f4d9f79 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,124 @@ +# Tempering Machine Avalonia - AI Agent Instructions + +## Project Overview +Industrial chocolate tempering machine control application built with Avalonia UI (.NET 8). Controls hardware via Modbus RTU over serial communication for chocolate heating, cooling, and pouring processes. + +## Core Architecture + +### Thread-Based Loop System +The application runs 5 concurrent background threads from `MainWindow` constructor: +- **MonitorPortsLoop**: Hardware communication & recipe execution (highest priority) +- **ScreenLoop**: Error handling & UI state management +- **InteractiveUILoop**: Visual feedback (flashing buttons/indicators) +- **TouchLoop**: Touch input handling for screen dimming +- **CheckInternetLoop**: Network connectivity monitoring + +### Hardware Communication Stack +``` +Recipe Logic → MainWindow → ModBusMaster → Serial Port → Hardware +``` +- **ModBusMaster**: Implements Modbus RTU protocol with CRC validation +- **serialThreadLoop**: Async queue-based serial communication with retry logic +- **HoldingRegister**: State object for motor control, temperature setpoints, and outputs + +### Data Persistence (CSV-based) +All configuration stored in root CSV files, managed by `DataBase/` classes: +- `Recipe.csv`: Temperature goals, motor settings, pedal timing +- `Machine.csv`: Hardware limits, delays, pre-heating settings +- `Mapping.csv`: Hardware address mapping (motors, sensors, I/O) +- `Screen.csv`: Display settings, communication parameters +- `Configration.csv`: PID control parameters per heating element + +## Recipe System Architecture + +### Three-Phase Process +1. **Heating Phase**: Reach target temperature (both mixer tank + chocolate fountain) +2. **Cooling Phase**: Cool to precise temperature or show delay if already at target +3. **Pouring Phase**: Maintain temperature within tight range + +### Critical Temperature Logic +- **Heating**: Error only if temperature < (goal - errorLimit) +- **Cooling**: Error only if temperature > (goal + errorLimit) +- **Pouring**: Error if temperature outside (goal ± errorLimit) + +### State Management +Recipe phases use integer states: `-1` (off), `1` (active), `10` (paused) +Timers control phase transitions with automatic goal checking. + +## Hardware Mapping System + +### Bit-Based Motor Control +Motors controlled via bit manipulation on `holdingRegister.motor`: +```csharp +// Turn on motor +foreach (var bit in motor.BitNumbers) + holdingRegister.motor |= (ushort)(1 << bit); +``` + +### Temperature Control +Four temperature setpoints (`setTemp1-4`) mapped to heating elements: +- Tank Bottom/Wall, Pump, Fountain temperatures +- Values in deciselsius (multiply by 10) +- `-10000` = disabled/off + +### I/O Mapping +- Input registers: Temperature sensors, pedal, safety switches +- Output registers: Motors, heaters, alarms +- Mapping defined in `Mapping.csv` with address + bit number pairs + +## Key Development Patterns + +### Async UI Updates +Always use `Dispatcher.UIThread.Post()` for UI updates from background threads: +```csharp +Dispatcher.UIThread.Post(() => { + footerMsg.Text = "Status message"; +}); +``` + +### Serial Communication +Use queue-based system via `serialThreadLoop.EnqueueWrite/Read()` - never write directly to port. + +### Error Handling +Errors use enum-based system (`Error.GridCondition`) with automatic display/removal via `ScreenLoop`. + +### Temperature Validation +Recipe editing enforces logical constraints: +- Heating: 40-60°C +- Cooling: 20-40°C +- Pouring: between cooling and heating goals + +## Build & Debug + +### Development Setup +- Standard .NET 8 Avalonia project +- Build: `dotnet build` or Visual Studio +- Run: `dotnet run` from `DaireApplication/` directory + +### Hardware Testing +Serial communication requires actual hardware or simulator. Debug logs in `serialThreadLoop` show Modbus traffic. + +### Common Issues +- Serial port permissions on Linux +- Temperature sensor calibration +- Recipe phase transitions depend on precise timing +- CSV file corruption breaks app initialization + +## File Organization Priorities + +When modifying: +1. **Recipe logic**: `MainWindow.axaml.cs` (MonitorPortsLoop method) +2. **UI views**: `Views/UserController/` directory +3. **Hardware mapping**: `DataBase/Mapping.cs` + root `Mapping.csv` +4. **Serial communication**: `Loops/serialThreadLoop.cs` +5. **Error handling**: `ViewModels/Error.cs` + `Loops/ScreenLoop.cs` + +## Critical Implementation Notes + +- Recipe temperature goals are validated on save, not on start +- Motor state changes require serial write to take effect +- Phase transitions happen automatically based on temperature + time +- CSV files auto-migrate missing columns via `DataPathManager.MigrateCsvFiles()` +- Thread safety critical - all hardware state changes go through main monitor loop + +Focus on the interplay between recipe logic, hardware communication, and real-time UI updates when making changes. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0115f5d --- /dev/null +++ b/.gitignore @@ -0,0 +1,78 @@ +# Ignore Visual Studio-specific files +.vs/ +*.suo +*.user +*.userosscache +*.sln.docstates + +# Ignore build output +bin/ +obj/ + +# Ignore Rider-specific files +.idea/ +*.iml + +# Ignore Avalonia-specific files +Generated/ +.avalonia/ + +# Ignore NuGet packages +*.nupkg +*.snupkg +packages/ + +# Ignore logs and debug files +*.log +logs/ + +# Ignore environment files +.env +.env.local +.env.*.local + +# Ignore temporary files +*.tmp +*.bak +*.swp + +# Ignore Rider and Resharper +**/.idea/ +**/.vs/ +**/.resharper/ +**/_ReSharper*/ +**/ReSharper*/ +**/ResharperHost/ + +# Ignore DotNet tools +.nuke/ +.nuke.temp/ +.dotnet-tools/ + +# Ignore build artifacts +*.exe +*.dll +*.pdb +*.ilk +*.obj +*.so +*.idb +*.lib +*.dylib +*.a +*.exp +*.o +*.iobj +*.ipdb + +# Ignore coverage reports +coverage/ +*.coverage +*.coveragexml + +# Ignore dependency files +node_modules/ +package-lock.json + +# Ignore Mono and JetBrains Rider-related files +mono_crash.* diff --git a/Configration.csv b/Configration.csv new file mode 100644 index 0000000..2ec2168 --- /dev/null +++ b/Configration.csv @@ -0,0 +1,5 @@ +Id,Max,Min,H_out,C_out,kp,ki,kd,kl,Name +1,0,0,4,-1,0,0,0,0,Tank Heater Bottom +2,0,0,5,-1,0,0,0,0,Tank Heater Wall +3,0,0,3,2,0,0,0,0,Pump Heater +4,0,0,4|5|3,2,0,0,0,0, diff --git a/DaireApplication.sln b/DaireApplication.sln new file mode 100644 index 0000000..4897487 --- /dev/null +++ b/DaireApplication.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35013.160 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DaireApplication", "DaireApplication\DaireApplication.csproj", "{DA99F148-6A84-4C76-9DA1-73A9FF7ADCBB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {DA99F148-6A84-4C76-9DA1-73A9FF7ADCBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA99F148-6A84-4C76-9DA1-73A9FF7ADCBB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA99F148-6A84-4C76-9DA1-73A9FF7ADCBB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA99F148-6A84-4C76-9DA1-73A9FF7ADCBB}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {CA811FD3-EF83-4D48-9173-EA545A7C1D44} + EndGlobalSection +EndGlobal diff --git a/DaireApplication/App.axaml b/DaireApplication/App.axaml new file mode 100644 index 0000000..6f4b603 --- /dev/null +++ b/DaireApplication/App.axaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/DaireApplication/App.axaml.cs b/DaireApplication/App.axaml.cs new file mode 100644 index 0000000..2948c32 --- /dev/null +++ b/DaireApplication/App.axaml.cs @@ -0,0 +1,32 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using DaireApplication.ViewModels; +using DaireApplication.Views; + +namespace DaireApplication +{ + public partial class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + public override void OnFrameworkInitializationCompleted() + { + // Migrate CSV files by adding missing columns with default values + DataBase.DataPathManager.MigrateCsvFiles(); + + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } + + } +} \ No newline at end of file diff --git a/DaireApplication/Assets/AdminGraph.png b/DaireApplication/Assets/AdminGraph.png new file mode 100644 index 0000000000000000000000000000000000000000..2ca30c79cdff3b61900eee6c16906f17f95a0356 GIT binary patch literal 12846 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

VMJZpK<<%0L%1d z9Yk+{{NLOEO%kIp<_@sB-UD=qq&eIs7?pfX#+8_~tx~A5A1rdX5Em&1>itfg-|2>8`ctlPk?lQjo{$_AUF7i zr7uG4eP7_`3#P;8CftYApu2@}d9H<|4T$9!FIG=>sN3K@U^QTe5^>SS()>GCu)su` z(H7hPU;)sVKP)f`gZvEvJ%q~ttM82N;mvC@JQ9HM&-`a}`Q8_mtodX%EY%wzkeh@6 znR5(;^>X27x#lY*`P>sMAVD4B5HoZ&E#uR`0{IJlf9VfP0GhVb=WA-3#H5uf12HNU zIE+~^hw(+rp<`x@l)TWIbuSU1?~I8>!IQec2$t1An;Z0@RD-1pyW~C+%|;bbW`@mk z-u<%`D2_!zgRB^McrkfZpuHm&ptU9`No*`TOkBl)dUYc!49@WZ%0T3GC%1YMp%xIR zy*1sWgg~Np$8CsO!I6xK5LwluV)N41cnyfbd$$;zbCoy4?7uW&ZZ8Az4fTv3eVKTD z>@z^GM&3jV|1|^bw77kXWklAt0I?5d%rijP8vRf&3r- z1E@9qpFX)%gg5#DiVgtQV&7*kY;hGpKmax{Q!Gn@nFNq?E-(`4ZUj&b;(7_t`Wnzr zaeJT|C*-Gqe7NDRr!k+!65%ix->?N=yK=nfrI5&;{Nw)k809~XL_&aH{ z{6hr8B-Y?VpkPrJfD<5=;|~P@9jSn!_WubiAb`7n(eVyfTmvYGrUJP6BSH{BN6ZEY lAXXP37GUN731Tn(MrLaQoUlFt|Hc6VDafcumrK40_#fJl%H;q6 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/AdminMachine.png b/DaireApplication/Assets/AdminMachine.png new file mode 100644 index 0000000000000000000000000000000000000000..6a3847bef6c85720ccc431434123dd086a8399a9 GIT binary patch literal 57619 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 Hrq})t6$NHi literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Board.png b/DaireApplication/Assets/Board.png new file mode 100644 index 0000000000000000000000000000000000000000..f9b18b95ec962e8690d30c76d38d043687be23d0 GIT binary patch literal 44667 zcmeFZWn7d&`zXACh=ic1AV^6_NH>cJh;*lPNh2V!bQ&NjDH1CwUD7E?haio#G%P9I zyt9PQbI$Moo)72qnGdksJ9EudbLHIlE69o8#3IImKp;0IC7vrmAlS1I$hEc`sNjjE zd6qHwMdTo=?x1XA;^1UpXABWGvN1HKkhC%|HC8ehbHxi(H!6nNo`&z`<%v{3N z&RE%1PUWSm0fn>GD{FhGvjF8eTqyXAe9S^gaX!VtQh@RT zDRo%|3K1JSV+tN-Hl~-XtgI9~e9T4$h6XPU4H+reS=rfGSUFkPIGI>kp&WcrPELx; zK?%0AGctiHJr}#&4E!ZPY3AVY8p^`rh&ID#K*}GUf z7&tRo+f!XZcy4U}($4&~gSm}01rnlxp$*JIfD)j3L4(z6S=oPpt?e&41$f5dZ19?e zjhU6j$_h!?`D}X!CFB2~@juSCS8;i5%%Ws$Zv(S?2?Sz7b+s5U@Bh3Jaw5P6DsN{F zq+;;uxy?(Mm9e#hU(Z}eZ>yHHc`1W@t%3K=LL;3W?)yD<~TOG9oZLoQBsCPQ8mPA0aO zyha?XyheP6hA$~u0E#R~#rZEqx_Sh(6Z!Gqxd4CsJ6Xoo;5gZVb3)>)ah91 zvNgr$_!`_H;x@Y_voREs-0Xk%#jg>ru2!4F@afooTvZ}}DAUVVN}nS*xqIqb&r)kh)fdg#^XTmJuV z`u`7S+Ft!?Idxx|a& z-_&b#B@prw=;J%mlXb*^c)!tDL?UbUcqKsUO$U8Z{RlLF5JN)ycTm??Jy8oV!w{#q z{hPaSHVJY|7erg|Pb}-TT)iekg1WEMMh?5~I+>&p$fj`=Qgae>N7PhIxHz3+W${8| zzp+Ez@}47s1gX!RZz%$~R|86Z2qe{}@jY%BfCHfrPgxLq zG?Sb0)53D?`3Nb+?Y3qIZWbjY0EP1kS@^vu#ZSsv_d)UeGOeF(%t zKj|EgsL5l5n$qL@DcZj{H%W;xAoQ&~JCylo5FyHN9r=QGrpUg%# z%j?$;tOnc;yTUMqD}Xl|IxvQ=%~9uROshEygFrqsU&?JbSMGWFpG*VAIw6$bU&D)% zN&L|vLf1ZFBY8B^?jUNs*zv{U?rPES<2D>(!*cs&22>~yO(!5pa}6tSpwR1JWY#m>iK823jKCE?O3e6pwQ zum6&|09t(2Dd}dI86A+@7PEH;v^#vjX3FddenP>IMgz0fsZ~FY_>zbUql zNGFtHjd29dNS7@lfG>l{(bdXO z{+1Z!Tjg7Ink--^MLH|y>?w`j!jTIru zzRtQtioL9-Mmv`(m+=?}CUbvhF}`2JcSB8IcU0<4}J?mkIXW?J~y}%xE%paVpi4l^Q~Vy7$!~Mzil0gH?G(Ao%sHQEcN&9 zsj_f@h4;0a#mVem!>P$seT8xSBg<%wLxPzR<4hgPti=yY4^xTg+}_DQ7rMTj<6}Z? z6*xs2e14P?8T<)dBoW-S!u8M-78*JGy)y>S1spoD5J~u0ethFi(#&tda#(N2ZVYMM z!F-0Zt}b}0b!oWj1Ein^iJ5umt%?bhY!wSShuXE%&{y|NCr8$Jjq&Vm-{Qc(KOs#3 zP6s$#0j0^|t@(no%jUL_M_*Oa6!rYP4Xu}kNn0qyO%0qMOc-dWAZ>$E=!=7iyJ{+F zB{##q1m_8H-WmhCUV8Ev-q8>lX}jdk60lsraBA{p+!lxLr^NjUf3K!5g8S0Hkh>JC zP6bF!7KCsyVhuighH_g1v0Y2$LfUNX6kmuDcRO#KB5X?M*UPyJp5+9GKOhpwVISy& zPz8L#e7rM8w_woI^1;p7agMFNN8|p4XyG3uScSKzwWpjW>Mg_sOUl}Q{ntN-vnH8I zuE@W9=hoN_<~0@6A$1{0Vrl|6Ef%sHF_h$;r0RG;)C60kc%RE(HRIgPN`<5n2`=iv zU#HOKlb!U;Q)_9uoM)zjXLN-k8^QxqHn7Lnl|?>%9Ti~6Ygl|mZfKTN#9FP~w;=90 zXN6p9X2v~8Sn4b4I16i46i_vtcRE~|3nNR%)S9_J#l|w9?j*PvsVx@LRlm_SGWqfJ z6rB6Y2Vfxub`8UF1{>O~V0Ko`C`w6OAELS)eSlC(Q8m(T-x^lA1BuM~QV4}ju#ErC zZn)tjiQEvvO0*+EXFv)`Brx~A{+y^TXf}(r`lb!?t1J+-g!WA@C%@UK%6XGo6* z5+H>B)*y-m+&;FLm8*b1<7(gIoUMej6PX2+R55cRrn*ONet+1W zoBB-E1kNG-mv^gJc8>Da@Jm2UXpJd^u?Pv#D7E)x!C{WU!FvvhN3@*grih0&C|?}F z5gr0ewIxE%A&#{`^$zDnk>W3C8{~Dq-=m@LjHG}%V?@s@)&d;Q)@U67umCxks(srz z+4hBsMNZDko7fPEh<=78UZ$b~j=W0{NqqESk-@f?PR6 zJU5geb_UNjw+f!vdaT)iYFO!PuSI2M^`SnbAYVo&WX>8}$vLVK646GL!# ziEhrN(2!i$eSa^d))He~z##)u+Yh1OktM=LYA{Az2I&;lQd~-SfN4jm>|M}x4E5Z~ z)>`6mrDVc|g#Ot4F(N*5HuilX>k~P#F;|kLy=;y{!FwasPk1k4IgDI8RVOw|yQgaW z*4H1s_K4N6&wM*ak6hmYxJhzJ5N(?8@R(Sf#-I;#2e zg+GPoDI=wqHeWZzhTyx;Du1E9xt@!!xA>v@&3ug?PsEbkpVUL%RKB0bji!T54o0$& z83KKUw`u(0nu;+5lWR%3eMIVzP*T4x?aB|KU3jaOwcOG3v73!*C@LGTX^vXcpU4x? z_frbBW0MY7?`_D$)D?LI#=Z1QI|y~Xvqt-LT}DPcjVefMh9INekC6Pj-pT!GF1OfE z<7*ZO2xR5Jwq^!zwL!0!dH`O1H}n=f zZSVbrKqz?y1jY{TX`j^KhIhyLU1l#56b7lq zU{g2OxsC}9zBzlNQ1(8oX;SLIDItxX$2FUPBstfwiUs0*`*@~h<=S5B+g$5+I^q%~ z6^S@)OcZG+t+Y^iwYq11dt_fSQTU5PFrO^1x6VAlHOJ);{2K#fBRx2MV~fqY+b+@o z3!nO={DyxYaq^<->Fxr*7h)rz_F#aC%HM)iUaHjrCmZet?lj0WabNXg+tIGB#Y&$+8*3pkLQBC>1% zWp@omiXOy|?&L#y?b+V5B%T)mFgRsAu zJ}YFHz5?p%^+1|>ke6b-!pvJBE_@4GT8_{qxxc4dz1KQ=Ydypwwyx+jgd~55oyf#< znqyh%lwa2pb)OpxnA^-8su@%jIbDp__XDG2aoC$hR^v}P{iHoe+av1jg7?TKWL$rJ zGWV0aTf7k(3na1Qp7?J5oJ4uHiZCDRMmF_1JW_}^ikI0(H_3>cEhqsmMRo<9fA$EQ z&F{Iw=b<}H&g%xK`MX(m>)rm8nUhSA4ij7s~rMc9vE*Rwe%aOp$!+-_cPIeK%{PC$Diq2R#c z`z)0=Abp?^38j04?;I*n9f<3;i8le?eSmalsyk ziO%N9+AC;%Il9^7zI#zgEN)pn9rx)Vkhzm?T}@rneYhJdVU(k4bms%d3PxfhkIo6V z&vn@~S!4VThABNFK<6Ed&X-H#yzEm+c|Zw)w4HY6eaDSV6SnAdv|-ya%4Bpv5|1~S zq?r73qG)cL*NFez@_engH9TJnvY*&Yv0o0LNLbvrlD@q1!bXIN(r8p$!PgP*#Tka+ zmbhoUOQAIZRLpHcKp9$`nB86@BJNJ&kdd&@N_z9DTn?uG7%C1`U{t_?Xmdpu0A{8R zDdDT!Q~|!`!!H}H`3Y@(=B$mdJ*}lrx0R~vn~!eFCggm0Q2ZtHRa$$zp9Tsk)Hc)) z2qti;)#05jcDK^>V+J-B8{)0Ja4RQC(nOqd*5;!8^)$mPjJR#+WgIT5+tQ48&0|B{ zz1&bw^)?_?Nq4T*I*Dq+*T=N|TAs)qFA{e0bA2;}vXc^(H8a(HofRWUiz;&q!B&Sr zM9vzYwr!U&H84{eO#o`I?XA;l3=Mtzt@$JCndZ=)jW*(!+pcL@adj{=>yK}FraY$` z&iTz{?IWY17}JQiOg*q>2r~Y0Pc!nbW{tCj1Hl{5bmF*-@6S(3Z9U1^_~_ogMST|9 z#UQ?hO&WH+0N^Dz{qb#gHIj2tT%;OzSgk!Cp#T25c`wQwzM7YatH59?XpV7X|ISe! z`G|bJ2hX(Xs;2l2FV$613+4wFZhs7>%~)_Wd*!UjTe4O zoxFcfn#!3>#)vD0WM=X*f{q5#OG>If>sf3k`i?&U zc-%_MFJD-XG=HD#0?$w$cDDRD*RI(k>}IPBTgye%l>3&V#$#1q2K&w_7Vt8YwyRI9!3CRY6On2BMk#lW{~zbWFfsiB5QO`>W(M+C?B7H(IhgZB5P(+O}t6H zAl;ck;Pb8DfP#vcrs73$r<<`vOpjaP*I;xHN`S4yoVi~$Zmy;}l|p{gbkA48vX-%T z*7lO=Ls>RJP|N{)e`wErbs@-n)&*q#JbF!vc*wPkP;mG9QNCk!H!*6!I8^C{iit+C zX9R9&7m7O4O^i%KN!t;Sv$D|Q!<3`)Z0T%04;NK`M(3~YRtnA9k^K!(D^xbj?V#j? z1X_Yul*8XIf_Ru~@Y!H7HiXq0CA{B4lqO{^QX>sSsdWW{l~q||`8Q?6cb;s{CqL0x z+$dO9Ce0Gr$sFuU`V1E6+!NAj%E^$~p%FTS#`me1`o!Qmt>Q2uLqQP7KLWA%<@oSi z9V1b_8vQG2kpvA%`G zH-{>5V-PtZhxh)w%THjF@Zno5hkt7czo5AOB^P`Et)mOcds5?UU$r_3n6e16Ql-)7 z8kdMrP%$h+RFe7|3M_bM&nqbq2puR^3YkEo-_f%S^&W)$+q@a13<_c4n^0uvb3XX+ z2T@w(6Y5!wjkFKP-hxwHO<7zNkqXEd^&CX@s6J%Qk`6L!R$#W&} zZ)4l(-HMGGK*8GTt0L#TAl*n@9fRVf>KqIi8zP4{>Q7D-p}|W^w)FI<^+BaY;(+YP zFW}#t=NUO@LcKJOc2DvyNzo^a0+AR{yES? zjUOv_R?p`_grI4|I)7(o7UCq~CGxyp&Z@%|DiTz`=l zJv36&F!ho#otm9BI;~y6%b#%G(8NG1!Bp2XH6ThP%INMAa-opC5|k{T>Y(|TehmdZ zjEp`Zz9`YTIECTZf_#E>bPC+sMZ7Q8tkp;@NqkilZf(MqS+udge^65tS4s3?Wo3c9 zrN;Zu4ooeV<`uEpn7?E4r&L^psQ(pzqP9ml_U0P!&eX1@rA*vMu|)}9Pri7jl1j8B zy1-R?lz4BhYYv^KhalUF`(*nd9Ga@XZOCvR)6zmZPXbX8^_H)W%D?Meh7wYk2JjP5 zJCoiN6551b7qWQyXR*DHn36GS>=8t$a8t^uEg6Y0Yu=NPA0v0l6_x$^TbDx<&BP6Z zVNR8w4S(~ejusr~@A^A-Uu2lGlA?)`Bg2IASKIBK`-#1Pk6UQ(oos*Fk{V+&R=HH`_BKs?B+ zXm!JL$iNj%c$0+P%mgt9mMSq2c)+TYCg8hE$o%iy9(7MV6yt?r<6IO(Xn^scf+K7E z;*Nf{!G*%s>$j*#;P0nyA~EN>Gl;p;6Y=YT=llu39?!wDmSFB^)3!_IDdDZNY_ya2 zSc{y;_;2`wC^vDFb8UlO<1aDNxjDy$AQwx-6v!dS1P-3Ge3sto#t%)rK?Fb1dtu?H zG|X$1<3niraqP0F$b+07B%$uNK@FqOd)eers_WZ|+rwD8?K>e{Y};CXUd_AW8~($b zJHHFDx(4f{%82<~?hS?Y`;gFt_YA{SmG~Rk7IBknM1o#B5Zpg6T@|nnTtgcU8rsGj zGYa#L(MwImHCmYNT;+^_4(m`G-#3h~IgQ=Ll{9^a$Jttv+l6`|oLFTIKh{PE3jX0H zz4%~J5`&M8g|-s0=ZIV?{|A-9HnDc|&z+W4UJJ`XA!~22=Cm@z{7I)5&!o?=5c=;@ zuGBjhOl?b{O`!ekJsjKLqY;{eTF)%Ca!b~afxi@|&HCMg*(-^B$az=L1`Z(@b$w#w}Q1ny@5_RLIBSew zHMC77l`z6pXO|SgHVIbG{=<;&KF*dvU1`KC&+X%>0Yg_aj?-|>TzJ#HuCo`&B}Pi= z;Z>LR4l6?A++P5TRuK^qad7qtK4kk|$ezncWA@5NY0usrtl&)JIG9ZBdM4=t=gPb{ zgwpE(l2-xxPg&LkNZA6j=0x1ggN7+9dPf?nM#psbIa3W0SK9vu+1o(<%|=bbj~mPF_oo!?^3ruu?)Pu zzq>l>zP`P&QQ$k8vmh5Yna0oMFrJx|EdqX6E+P~}hTy~?B)$6KYkgB>Z`fml5TEtg$8G23_Oj!A*-PYqMcrBJ({n`XEZs&85Gh2}C?xb{8`9zHRJ?GZ>7KPk7c#ovG}o0oMV} zL#jWff640v_mU%!X0Fb)0GlVyXh*9#@)9Xt!XYSpHJX?g5 zFc1<(`VeKPe$0C^aH;)5oD9p?2C3;d&f2}6AR~2mwoCfbVjkVdHkEp$-}>l%b;!?KkezbdnbSc*ufNlQ6!~X=TlB7b{msp< zm_I&N{7tx$IAFzH;rn#8G&{v_`A|VkD^0absoCLfLEl?>@qsSU+apZxm(0#!u^|?_ zb8Riro?V3LEa5ft;*$x>jVn-xGf@OGkLau3KT4SBt`M_{O(|%Q_GY5n6$Gw$(~gp4VYqX0Elx-!_qT-FzLT_PDuz z{ZmE^qIU)@N?R|q9)-$?3$W17Yxk$p+Z`~A2<4WR5G2I6%88ZTO1QO+_Gb6xp67({6yKJ5mRyTe?jBZYC2 zV+((+Tzgz5+=iix>_AL5(Z*{RrvgPLj^fz0%XD)By5#m6=WCVpaJE z(SaI*Xwx5SZhW*_>+8w;m2l?rGmh9$;#EzFZ*bywxgWc)^j8kKrgP&kda|5WYH^_3 zOL?D2isj2ZdrDZGoSn;e9J3f&@DZ4##UcwVRR^LxwV!Z1zl!`=Y$_+U?Ot32ul;+Fw^Ic67uiXdv=VuRiov-$Rxo za=#{VJUl#}$N4LH+Yyk_?p^>w2y_XSlC$ShUXNkZ<11jiMTw(R(aM$8jT&&mp zJT0D+a#)IHTyW8jC)>lu<0|3n3xhYL-}EVF#|7|_TAgT$P&Y}ugJa$c zA2>~mDC`wccH{kMzcr(O4^g)Jh(%>=ncQ;>O%-zeSBvz&hRYVwcsI;$~=? zw|oXJ*PJgrfQ^*qDXB}D{$Qu;AiDnZzWO!OuzrouAry<571~^3gF(lZg|lJ%+9$7c zsl#e!DQy@elru6#BK*ION-UF;tWbrm=>LAE#%AepbA-P@{5J#P+b=~$%Yu&yUn@(E zrVS^dB#_EfBz+$|7P~9SP8t)!x{Uj`kc=R);;qeO{%POVz2b$e_HS{_qNbOD^a?O-y=-pu{QL+ihCH)_Qc?Z1y(#q;Y>z+E~zctTZYK zufZK|90?8l0o(5`XI^KsIiW8LKn=kA+Rm_C*R*!{m^~AAGSjUs7y23hKn~Gpww7l? z-1o#d8%-FNUjMvBFH_NF`orN`Ra)aUy;~V$ye@DZ6nOkwewuf%U0N73QyUuOmiR*F zIIi0$niX}n2}%sZ=@co?5I%#?UD~!t(fg5On2vXC5<68!C2)9dOG0Kvl`tmtGFF50 zT=4W0=7r;JCK9R-8B_Q>sB(&EU#Fzu*45`O6A}x@)iFzHK*qm3`USVS^;T0_!~fkg ztMHNN@YNgEjpKi_DBl{7)vCK zJ-X)HP};d@F?85JtmVAu3XbD!Bwg!!0i29R;98V^*G=H$t8ih@ITzv9B?m2;Z9R6y zejXB0fP%y6w6S`$=f!(}*Roh1alE;n|CGOGSLe{`^ItY~kX;KoLQ`L-LZ`96KtjJ$ zqA!tTi0e-JCd-zBQd*

w%bqT-7iAL@M!%Z&Pt&o|0;jhc>0oIx8p@#hW|b92b~W zMM*})_8-j2+hycOSQ?W8v=dbvTLRY=P#E!vVsd>A%WN&5aghE<{Ql(NcPXD=D`$&nl&vO@YtPMQ@ZCL#*s`pi&$tUik#wt&P!iQA)2qf=~8LljGUQ z-|h_s64_J!VB;lBDneM^|3_S}r1)`W#QS50<>HGpA97={IrxZcy`VIgm@>1We4gqx ztb2_mFNH2-i4LBPem~?S{mqezE-gzq)QCs>#SE?`n)3_%XJPoUfy&S9R;5YE$gDly z8ZDx_;V5aR+iDT7c`g=_4sydx>ePdhp#tJ6HeSPaT_I<5wA{DdLf4_=$>*) zs@zCnW{y1wX%8B*t+X^WNR=E`4L1=I9FYE3UR;4RRWm&~@Me7NhP+o~1MJ+39K>-! zobTnOR!`<9(|zLt2X(cT{QeNHoia>yj{*N6KBhrZEb>?oVmW++&E|=UpY_SRhK7dD zZzg7r^-a7Yk~5w*wSQ` zFzOnyXRSjU3LGCNrgc4&Gk}9|IiFytqBsiF3L(8c1+h(t1RPjHCKQxvk#hO&wBG+3To*LVe$!zsSl}ScURszWu$hMQ=)pJ3uZ-;(fw!2HsH#K?l^Zp~8{V=Gl2nBVdBU^IG ze>4awSS-Ifs9~>OQ?yVrMc%e$P0sBJ_TgqfYI&~ooAj4;^iV0M%grucm%=}KH18So zPHY(LKC{$=ifg9!Mh(vcn@r5_EL>)Hg^+j}FVYjrh~Mg4#59?-_CEFPSiT$I9}`Ce zWqmiZBu<>f4es=0-1f%x9cA_a;eH8W!kKAZaPRZ3I)sa|rR?3QwEA6C93Db+l8m@M zMRNbh0ZcdL+w;GZSa|0@P%7^U*4%#WG1;u;zO{y3?gOHqiI%>P1ZQRe z7H)zomSmvmZIIG4^1R5ajD5J~rvok=)45b7-ox^!k9DyxTHQ)&6@jnh!wtv7^2^i^qHZwhd) zQKd92HvAdxpwda?(pSyU?l4iJg^&O3;*O&nkqs_i8!knhj&tFjbr5D{q#8^R6qHmepRMvzOV5u z;~wgMwX!8OEkkKzNI54_$Qe``JgXd;F-CgE4hv;_nYQF5vOb7r#El&CiP#*B=K21y zS1hFYPTY)9=BarchZRQ}*>BL7*Eu6yhT-TDQvDv+N&U&_z1O*N)KzW>%J$lTPN1L}Y$(^|e)d#Qid=kkNx^^{N8jA@ecR-0HIi z;XSkhwRqj5wb=pFvu#>qV5UIlhk9+XT{$=rPOo$vDR!3c?0HI8GTukgc|Vusxjn1! zd)L3$7Lrf*xTfz;=|81hto?olLbB0jNtjva(}D1&CrSQJW>#83O-^)T`Aau!99}-9 zXl7zf9yo-~fen!N-~B%n$c`>ZQ)|s8{vvY;J=uBsDpa{`_RdC+G%MHrR2r(i`uS)M z(%Zrb&VB+jMn}c=eu%#MFWpA`oDu~xes6j#p@xY(qAArqRy+5CwG!h>8VU~8XJG*{ z2pN*M=n7=C27GAPyXw~6++)$5a}?oC9$b^J$R4K@xf}*H6i7IJl34xLX$ZC8ZwcAo z7k`R!^Amv^TIVnH0)zN+z|dNcBQ-xncYj)lf2XKC-2^L+yVacqjBmLqala~O?_JZK|dAD>R(D&o>b{&pZ3%twxI^%v5wNw+w+{;9jWJ*r4 z{V(H=y2rU%h%4tQi`ME9PlczontZJz_y>~SkDIrXR#ulby^n!myFKfy^tIMaae|4l zJKP-Cnam0=Desy`fxG&y6`dU#&-|G*Ib-)ZKG_+cbo5v}YN%Z~?6#OsQ*DdSHGo4z zow$|xF^wFadK`^{Te`@*_OB?xX?&*c$A!`Wz2gGsriL}s zH}9hScUc2e<8ycqqm!8}=rYpMrTv4cA-O~_7(*O+QAdG5-YHpd(%uCX3mgZ!lis8{ z8I*r5IDDSIfA3S|AT&tDZQ%kcpyR1#)dWK@KDzvFRur@X@#HLfvo1gip@8~>l$!iE zqJP~_#-F~ zl#tz;izgJ~9I}v5IH;DfOpLAVIwjORsf3+S?h!0T^ed{J*RsNQKoO|J>uh>kG<3*( zQ^_)+RxbfNMFQzMjNXBZVLPDn+p5&*f{dNP(0`tUFADC3sC2NYL%7=aaOl(Z&e2*j zQysY$qy-^B5;0IDArq1r{beX8=e*i=Yb=_UJn$)4*B$V(0Kz`Fz?vgzy`IRr>iEaCI>kqw@J6WyQC@Pol5iROAucDD|APZLo73~ttFADw&W~Lul9$o_a^Za3umUo-6 z;+K$-{tk_1Q8`_YPojawcLtY2`(yY81a?#)B}A0zg{^(pWCpHz{YcU}XNP_t5L*6e z`X)6*#gZw%Z;v%c4kQkz9Ddbu4_ows>~gT2$p+H~oMp2`3Vrjsi>jS2mDW)MJI2HI zaC&1yp$LMx6b4cyJUx$3`!4DinJpQ)V6Bs5pZ;|V4l`X-db!iI0i9*n^Iahy)*1BsD+ehu|ajbWC4ef3kGq_WU8RNAPKxQi5=O0kkBm=7ahQI(TP23%FK^wg(Iwy zQ0Ur5Bn9$ri42vat5;HIMpSDU$g*Uj6_|t>((@vFh{#EeWiihC)7wo`Q%Rp5R@r82 zcq^dB`wYmefdKTo0nm4EH7TZVpaqYd{5*{nDRzojQtbiCOb)LfRT$O=L6;iZzul>*lx z(#Da$FICI8uk^ZqBU&?)&^wNT07-;QA+oTK)~z>)Y$PMGNW}LDzt$sneA|iQPX;Tv zuVmHi;7gaStfXWbuBd+5*B#}q1SX-%h!DJ{ajvqx57)eHu~ojhOp!>!ADL);yv_yl z=0ti3=IB^aqf3k>d=kOdbz~xq4v%Oa!5+E1hgm;yuF=$9=oNdR=J&bF^Ykyc!{bPy z49c(<=zz-}55UzFO(ME94tmZ^j<&qQF7|w?Op!OUF!hjkGWkz3TSGoy*1M?a#iik6Ph;*Ff2KQj2+H0Bj#La4m+M+%1b$zV9Aa3Sb0BUuTqIsJUYIes# zPhwCKUfhBBDI0v=A4hIlxdhuD@a?mlJn8cyh`vZmkk7$w^LC3Qxb-I&IAsL%PK!P| zvb}IqaO)JFA9uWyn=rU)cv!6x>PCKuDls`4?MI9vW#zuk;6rG12Xz{t zC!$hZ{;9m+OfPG4@jmDIds)bNf9wKpbn&dSoWchhK^WqKc`Zoz7Sfb#MaR#g4mOUw7Vtw&7KqXwcpE&@gfc za|f2$2eSRi?;e(8sB=r7io&|g>)F%~+~ed6c{?dz_fb1i#a@8~Bt}GTT{=DpL|aOo zRtI$NbkuQ8RvmkPl3jXA2#)EeC72+x1uFu2w*+GbAHTTgg`c<40Y8M&3UfeNEVF2T z5!5Q0wnNP>MGHA^sv%pqf|(pnc6RJ%li;$EWjxurw*f0dGtCY5iX;$>cO!;|8S|9I zbj5opz;onCro}JJ?-#Sdy9Mc>Y6ybJ zoF-d4L7e5@(W?b?y8rI27(K7M+M2@B1yl#GSzGX*SjaLr!Ttp?kk7Na8tL_^a%=xO zhmd~8nF6^IE?D7X>68ms40f%nXY5TxmM^<<7vTE>WXBX(rx$0+ zO0>}p1tdLJdmHoaJD!kNw&fSfjiz>KcBkJ5Oouz)HQCzyhlY31iu`Pj=k^JCv6^yU zHS-HuxIlROn#84(g$NC54sk8fb^6fsPPX^IfO1DbtKRT7sPzq#_i3EO=TP$V zk-mk^{8%11tLD6DQ7UDZTv~ImfySsZyXk3Clc0~s)^|mv1uuB@;j2@5=2gDV?4xK9 z?!dpM_Oex~z>3xm&2RC(!ttRXEM+@yz3ZLQL{xWiRu8Tnusi&mpwX-ah7NXC7KFsInaNtxSYtgU=XTef9X8$U%0vjYodm{bo#(*iv z)ua!Y)1j3(aZ{fU5}r%{{6{H-%}N$wWRSKcbuYI(1Qdxb#@(eqqaSDuO6aqJKHIyx z9txg0?NJP?scNK?q@)^6CzM^uuzzI}l;}XS6Q3`?DCQ~-1W*b~)ua~wjMC|qfD&Pv zB%B-ON@4Beme9suJ3<%x8k>D%I1;#UK&m_2EIP?y< zB6m4{7t@B_spyuIl!W^i$YqlFUZKCeeTp|D?uaFgOuFuA|B95U3+?Q7A$6g+T$%BM zJ->)6wrIb>2e+AlC6hx@x(MS1#BUnA5tr00_vxhpHsWqvD3uV|3RjX)KNAy__Y2NX>4|Wt;5GT9k0$Y zCI5b@crLsOgEs%^=*|yEN%*@CgbaIb&K9^Amv<>$D)UFaHy0{Bz167+bIIF+hxrK%556jBwY0OX?cH)gkwc#sW0E`gPmYJ?FOC8=xbBhla+o^5 zF@B%M=O{LXt56mKc{Y5fktjK~%dz9!ogBQ&iM%y9oY3#$etbMJEGvI;TM^h-p6Kfi zsGkOgDSs(+F(b`ZywBIPE56sM`vxyX(p`ja7YIO5nCf|CyDIVfmLAO%{71X%Ze6qW z<>=h51Q+8jN2}aL@P#x||D-@N_d+AxO39RI@yby^UbZpjfVRigvV+(;yCmQWzJTiv z2Mhmf4P@3Zc4t5@w%_*p<=q$vWT}-t$Nt=aL|%mc00sq1jOw7q{C`e2q_vB&>alKi zev#xw;0Gpob9S=VtPMOzMmDHd)(pHNtyw4VpJN>QJ`>y=yBOZQAZfZB6!_;#cq-`T z^lP*=>MP3Uqmtk+3Mnu;Pg zit7_K$?n5C8c*yE?uwrbk=qe1CNiSgoT%Tt%V2f z<_2zIV`U{;1T@@U)bdVslt*m4!gS7-XIKQEw=E+pxse6DdPgsEes^SKzDb7JdZOfJ zCt@Kmu2)O^n7ZMSZR2A-ESR}9_e*#aDvr7A?tCP<0A9ocmt6L4d|G~gPerz;lD9Sy zR+9II!OVqg2kk8(y*l`NhpEm6R~F%3LGw(v#Rzofdj}UR$vZV`3St@PGzk|7i}MCm z70^|c@7{G_IaHfOMR(OuTIg6EUVtGbD5aaMmHn8`Oef?;_ZJ)jv3GC6W-K zN!0jOdrA1MLj(pS^cVh#bN2SjTI@PW$8tbHTPmP-u<2K&ZmMo77D6;&2OCgMu<}IB z)LzMyJ!XX~iB*x(hM1~NWKa$Tj-#xb{9U7l&z8Yafl9BD?i6_wx11$9MI{f$u%IE#GKdb zc4{E&@22`+Yz6BR6WxR-QNJ=g%IxFsHG;2uF+M@to?4}4L4zcE!wS9B(f%AyAHNwK zsKkbn=ib657<0H+X$2ZV-(9l9E7j<(3zYmlN z82}fsjpTYxD1A<%CU$P%8&q6WTyZQcUJ^c%B&}^Gg`mxF=sDNAEoVNG3u!AW`3iH*;Bvn&0Ug^?lMTyJcZvAE%j{r zJ-u7)x+A62eXckDx_xR`h~sID>m)E+UOV1rlZesieVrY0N06p;2%Zw#7D>w@wq-zV z=SHOzi)V!Q>tiZG412I6bIq|Qm1vkCt8*9>@y7np90POMuxL>w?;Wa-p>O7u_{W3Nb67mX1`o&~P4djgI`s-9I7w8id6p`X{J>zHhNZ^o*J3`*^=4T^~ZT zs@a+*yiZcX7P3c>G>GnPxDTgPI6kKn`!!CW3mnLeLv?H<2xHIEhFsQ+woDe-fC1A?RilFkJz$ze1(2%op#_`<#fF8!?49NKB>jF>=&1bo{`=wTfH!NQSD zcyZ#v3Fux}vwtm2PDZ9%<7({Z7M7g2s5>6`9sR?!-WDvc%XR&!O|518XE`ceb>z`Y z%Ud39X&JQ#ZZz?a@j)2Ds;AHG7DR{eV6z>O*r)CKj#hEybW%|3n`hJu*YPuL2k({-?0p?L#O+_7R}<|`QxLQ zW?Ac-=HBy~1;rcG#QT#|Os}=8{K(B{hUA zt~qpozCcI<>#3|H^uQK+Ds^M|l^g=FJ!MJZD~dNe!Rjxj@!U4-$4F}+sRvL!HhTwb zb3h6+u6UviiUd`&aRIkBT8GSeltHJiRU5`G+Pj7dNmqoh_u$p+AU$ln!s&Xov(1fM zY)JekuM<3@LMZP9Qrch=?k(ONWKb?dq&DgDR~JW<5FC{(d?t+NdObo;hlA#K|I8-) zBK@uR2gbK3uMgkS)g-~>oATwN?u+YyN{?<(L6;d+`&b1;0gL5SHC3xMir$GK4v@VL zmE+WRB46Pqv_N@CM5^1MM~`5i-aLgsx|8F*e5Rrwo9XP*OnVPDv5|B(e;3!mFv!un zd&2{}4h8%lho69TjQuZMZ0>r?!S}l#Y7zn&gU|>2&LEMjACjz=nVOz@M>w$F_wFX* zb-z|tq5qI4>}~WQX!o+5O9I;dTyXHnb~;Ay1+tY$nnM> zQN*qEL|zh~@92w2sRzcTH_0QToIv~RZJF6pw0n1feUFLP6I$+7GluKMC(=6$pBqXD zG$Wv-f{;fZ=$8QU>cQ!=lc}kx_jtX7Rml@vt?$Yz{y8~l?Y_^Cz<#8X0zc#+T-~9s zGxmfj__qdoEG}|43C08-{_52?gXndN;|HR`D1KCaR1V-+v})XQsA{qWZ@my8SkB6V z)Rru=67Smc)&r}P4O2wAHWBD->&^iHPkisLxK452n&>1#%ljA;_;v@^Tsb!M0SPmm`2KED%@@K0 zD#Et?qRR-~?cDF^HS6t#?g%;D2f;eQi_0-AkuP3ML|G91SBK`q+1Rta6|=>ZjcZVq(iz< z5a}-I4(aZ=vpF2}cklB)&->o@|KWbP^99cA*)wa_tXVZ{)*j7;g$ZSFPT|c$SP}xE z++2vaU2Yot^>E)FHr^(pbfN`gYiBD6u9u~Ldm#P1dB9g!8En>Lsn5KIi^I7_b!vtf zhGVm#s41+}4oNhB=FCj?Y{O0$@4(9TvPp1R>AH!lalOQ~q`*nXS>S3gL`tmk8QR5i ztG6F&Hb52w>AL*}OH|bimK-XSzE4&A3|>9fT@r|<;w?uM*sts(CrE<(SHv3lA6h{g zRacPibw~-zQ>RiT(&sjuuLMK^s3X*6WMJ{rS_q`(9V@ZvU6s8$f-G-;Q>XJw_3w~( z`{r3envt6zFH23(Owbe_o-*;Nhd`inKD@`1Ld24o=saSEy-hUqaNX@seLHe*oSRSW1A_r6h9 z4xa{ZQ%Z7PdEyKm4uJPyHLBDp0z&QR;&x9n~zQS?aAcLfl|VfU>ZVSf`z zdTJ8vRCM|HOi?zTc#2ICmj?MM$>VDUl|5@;Wrhdlb{@(nO=>-&4roZ_syK$}JwH>$ zwG0byHdkgitL1_Hb6D;M0#{>+kUw%gwV{}C^oIj$1u~6gK{HM*vR7FPGZqS89H=re z?~s7cCs&6eit45{6#=r*E@03RssYwtV$^Yx--<;<5m$UNwp#go67Oh`jM-_U{VFRz z#94xnuh2p%aou3%!RN{OjP1=VmFJf*{r!IUBGktQOiXebym5Q= zW#gy;n3=*Co)vrn-koLjg%sQ)_$)iedOvsd<(tY*GH&eN%gFEwMZ6*#Vd*wmY~?zz ze;XFw7<%kEv+R>qi!Y9qVv$kQ<)9FsW?~o;mo*(I+jqJ_@djgPPvzRG>6SgN?oj#= z+xYlO5npdotFNI(Ly7IdHVRw1wz&xqr6jbyyH$5Ed6?A(M&fN1d;S#3G%874H*j?$ z-`1{}{~+~_A7Unx#dRDhHMKI?q^n!@)e=ZTbfFYpuqvIDPae#38!Fx@-V=z%4ohKg znt3!`pE`jo-(o_aa)8DuSMGRaDWQ43aj9_EZHFAjJ~IrsD6a%(lMPKOUB3JUB=483 zbxp-j7(zU5Bi9K!eS}*=b|7J7`puK4OBH_3RIOz;?qKu3m?@A1+UFHYjS+C zG-AipUhc%#|u zcUMmuo!|62w$X)f0i!iCG`r%?{_l11crM90q)MdO^Bq=SHn>O~Pc158;i$a$Nu&xMnrC%5?G34X@uQr5k^&t+e@ibI|DBJ3v zgZulqyf2dffd)dU)G(VsNDah!le#pAUZ>Dm4Ejd31xFA?PAR1zT$9 z@?SQWtFmc6w!>2~g!8@he?j*Djj8>+Oa2?p6Gu$8ZOqEn*IO(T(lArfrXSOeSQ^?d zh?QFD00vpy@lN7iDo2oMB0LMzbgz#eZ`o?e|L<<2t1lv2Eb})LkNFjJu`(xp{= z%224TL5%*`11`RaWMGn2%F%B>CjGlC6C>}DTt6*Ik*ZAsK>=M#ep`K?;?8Q=dSa$q zf9mYaY)HF4I8jvcEY=R|GRHbf)&QaKlZ1K;pUK8A+1NXpugD2S0A;3pT;o{XLufW1 zGzqEj?yU-1C8`<(N6Lg`G-8QGgw|*S1J6CBFKi?Il|)58bmZJ_X86`hkQ^5A;#&Fb z9Kn@^*5H}oC5}jm>35E@5??IY%B}{T)i?qy;u1HG@8r`EV-MA&hY}7%5@;uZ5k<}A zM*-%X#~l0REm|QN?MvminNu>yk@~q%Z{`PuHhpiK1^%}P+s^YV@l|}w5ZMp zDK~zlc%U(!V{sWj0rIvSmOFIz+QBA7cT?KBLlH`zX-eYLfAxcmd+ixgRq2j7H2&RO ze-|)J{zk3^2Za~z#tN{U0cL`LIUr5YSUVfCRmpvLa>Z)%!0&S$j(AkyYybOwA2O6E)NCpEh!(~AXbfHsKJ$=CX zpCIrb8OW_V6*;&c@&s_Pe`*GVA}Z~@9O`S;`Pr4_GO&^>W#aR%sI%`sgV>F~Ok|CuTVf=s}Cv$SO6Zvf*NU4#^<-Xqt= zr#Z%sfvXlh-eobrFmGzdsH6RE=n6_F5b?xChs^aF!{8sqp$V$6O<)hxQKOH){r@>q zI!$Ayc$}{ULMfvCUq@|E(}}=TdE1c@6AJ|iJy@azYX4CK=z<)Od|>m(CGuga%oybZ z@F^r+0bfea3;X*b;a;;!8RvfplMjd1hw`C64gESw(OI%Hbn;&S}^wJ;?#TU>)l8+gb(ix)8Zr1;>O>O~}2m334@8_tDQ9o9kM8!7N zYqLE$miKHeETj5=$=0XrQaK{bAE6?;jCoCnlohCUC%AR~()PpIn!gbu5cVas_ZaryP|bIBD-cTQQBX*2U{7lx4m)(Gb;2dKO@z`SztKl$_6{7?ZW=GhqV?kih4*yeGnWi5<<)*+bs_@sNg zckn=i&SBzzK zUmgA*I^|`zzv3-g-kjS3w%E*pxPBT2)Ug3^A>DQTSG<^)hu?*#umgKra=N~3)y7`! z@q0G!iL2|F;WLVCUPMf4B3@w>E~@L8M~4g&SlA-0whmF{xz}fwSPt41u1a6LeG}CGO;&P`38|C$a2auXx_}C;a7^}#n5w@DL3B& z_bz!70i51nE7+29K6Ta9x)_H!i578`&9AKBvFmi zt^?cWX_2)dkKz2<=wkVF2`VR`vbyhaCjl}yQN-~HsX(PZrM8}kd2w31u)K_AJ#|J9F zfr2JxQl@+2(iJGISTV{mUyp|z^uAg`;V3ZTly1I911Il1~ZC8 z%w9pgmb1E-xa{%gGy!G^)y}-LA6qPsV%O64=f=fzUN;fb}f*veO&g}aa0Yq6$HJYr+gL;lREG^_m zz@i?OBeMT;6b1M{dI&i=3<8!3*;2B&zGiL46{fM6M9Li=#Da&Y z6j(2H0ev#V8Zjo+_g-@owP!^2$qL z(Y9gW$)BG4R~8AbcA855W1t8L03GqRNhHy~A}2`0A35<)lpj={SZ=)3`Z^-#ukl(f z17t$j-9r+l#^8P|5wBzo6RZrr8r1s#yQt8p`EQZ)|Ip|3Z*#^XFwWhizkx}3;CD(X zR+J6wVH4W1dhKpDr@mBr15}giW0l%Coi&5*9)>|hN#g#rjI_r#B?a{Q-B)371^3%F z4r=v;EAr?>30Ahgi)Am147Z-NtAg__dKE&%-B>7?A$R_=Br20Tj9&mJ`9f@|bV#D> zoxCofm059zb(3HS7AkuixNU@G3Sk)Zw%ZR%g z(;9%oS(t5G0kkz2Hf(YQ0G!Ljuc>9ds)Vr>UW!GTM*9=d9oJaydt~7FkQSVSIOIJP z>8R1JZG)ilocmq3jysA1PVOf_i4zQN}`^GFy!7aEtAzDa@sQBjlTZ=Ikh zraiM;k)P7pgJD?3<@zi0M**$O8S}z2{$^y3@d=0~?Yd?E7xKxafvj!a8AK*f*be#-JjVip%NZbUWId>4wi8^>H^EuOuRVIdy?|L19>_V~2c5{gIlFoHQF|@fP}RV~=c(>Y6E1Nbk%ysjCbdh*uI6 zEF_SSf9&gm=D5e;MKeI;LO&5H;>RYrkG~?F->RugPBiF1FRj(-y@|a&?+x#YPA=-zzDX^o2Uu>DQEzW=RaMnGcm*=xbxYr; zJOuxWMP}n@iS8G{XM6JgYSBMef-h7!f}=1Ax2}ojw_t?Dt3rD5Hs2b{i6%j|wWjNR zdW(i%y%T!`_qPiGaV0dapV|S|b<-i0@S}$Cat)X~nOW8t)VE4BAUtbA0rPZ0$AA@gZgj+ zc8yPkaguf~!#14sfs0yay02&@;inMYr0{s?VAkR*oo51%jS~P@c^D|5S@r(@A+}rs zI5n<5mc@U-?lSYcRmW6cN%JQHP@DHgr00ObbiMpRLx#@f&zfg{Z!LL8I;~E&udl4G zW=|>rNACLoizk_X05iP(Zy~*nm)5IB3HN*Q$__dQ1^0Ai?RPqYS-8`Ux3RFGjKYFv5boPI zx88yY!fbx7ouFj12ilqiUjw?78a&cawLv z%UA^WN7etMfk`FrhV)mF*?NQC{`9XYFY_B2rMI_q)z7;MACSU37ZlX58C=y3`YKzn z*Vo@NTP`$y`CwgU*I=ggWpoguCN`V(Hzy0;?fJYrI!;cO!z({{BRQa|?Dd6XLD76d zRi*h{R)2j3oweb$JpYwHGG;{bT_O&x7Fr!4t z|3rBD-QV$RnaRh(M94Q=XhtN}yD+T9GOlePvYKr6BfRz>J7~{IU_7si>7~r{&#Zje zxAG*#kp>2Sn(sN07XUoL^NclsnIp9FdjGTv>;3I zOI3^sxSE-g>_#HE(9WO10hR_`G%1o|8jp|$g#bQ{c_4H7+p)N8fAH54&3SPK(?m#e zJNnsy%|iEB5uk6iCzyJ_E1aF7wU%E65_&K_Q{G$Bj3@|gjP1<>-$U&CUEnnG*X&{F zSFCGzHeI~D`vX7y*gGcXMmRIZf)rUjhLt9+H)KIOshvdW_XcJxA>(qO&~!KS$xZ@I z=qxOw;Ua{<@GFc3h#%$XXXzNH9T{i2raYf-OSp zIzx|q^rJI}zz9vULbCN;Sd=e;qiwcNkfa0_lW;+C-C@8*x%_ceSpwU$%DyR6@KCWk zd?@6+eUX^o#9SwtBJ_wJv|hPp=HHWDeRgM(*e)9D(Nn?I>A0f+uKK`>w$*o?KiPGN zq<;z1#=0OiNCbViE7_dhtFg{YbI_26d)0V&_T>2zDMAvKwyAVl!F%~9g-!$2CZR?y zAZs?>%?55m86RHhq84xai$!nJxr-RZ;f92w?(>|CczInsA6B%WXG#XSA0xjc_FX%R z3V@%!zR88?_D(+}I+Rky@Zv04e0==m^*@eUt7j%n>3K*Oc02OUK(S(goL?p(+Cq0M z{SFa$m7tpB6k<|@`@Y?%C%0Y6z%Rec)*vf0kVYtr_V7RT0y*F#d@!oWa_;Kt>Q)S! z@rjB?orGu}fv%F3wZ5_!ovS&-k1CKw{_q1X!ynfs7}eaA$nfc53jkw&j+Q+XZexk_aparY`rn`W7yhRYnU zNto?tdT`b5!7!b2dA7SDJGpx@!u|3uaEW#}FLTij{Jo}6Fevc}O9u?3E zu&M9lr|t)pw>)O(+-wI;pf}n9h^&W=vqhmbjWQV^aQYe`x)6nwcBP%nvnf9gkM*Kd zUC2n{q#CQLA6vPQ!Q&CZJsCO&Aw~n4imsNxi`-09@h5%Ax@Fyl30CgaZ z%>l#VbD><#H&O#tz5r7`Fs&Wr8RhzEB>Hcb!(ep2aKwmYC6$wuU zBpy=}8iwK0Kf2;9NLu;rAqe7d0jG!`PqP;OdJUj~P~S3590F&Q>VbG4G5`~>d70S4 z=INnv?r;S^rL;}OpM)q0(NvT;s&mBAeGY3bCO!!Nr|vvx#qk;ATe@@uq}QJN1TG{L z_QQaJf_DKB(=D`t1%5KXKX1>usiFr1&`bmKL@y`&g*dx71w0wJXv_hcIVy)@B>Pe0 zFk=4Qk!ZUD5ZbJkT8Mij41G@g-z1IFCvJtRC`xn>iqzog9nnVncW7<}Nx<~mBj$nT zY0YvACH97iO$Uqq@m!ug0GcSIN&oAm)lud{g&W|n=8$sb=VVTTo}T{!RL_O(it=SL z2ZF@=Yfm%+V^~3ykrwO`1q8Rdqw!P$8P%_iByRwV4=z42(s^ooi39cv14$fbVj}*Y zemN(^wS;Qco*!pBzAyPfgCedmgn>8UAy|KOiA_!0QDctndV%~q+6(wo#.fPRiz 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

e8W`yj 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

-XhL))Sv<*yi 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

2@_{8LR|oXk?AoN z7;?qKspk^S;TCfU`Xr#u5|IMY0OtWH0Ok}Tm$*4Q)}<`3yy^7GJEjy^l2!`Q1GBrf zMrZGyH=zERwB42W%8O^dNQrdLVB1FS+I-7U`TF}gjz1#2g+2Q#Vihyp{y=PKib23x zbWx$A)+lU86fi>+m>?=p5sK2Qc9b1)o)?W5kiTLo9+N1Y_>?OGvC#${`BF40%op+} zML=fV9D~DnfK;vrrM7_fY__Xw*~%&XBLjajrLA3-zNUHOvk%`jMU1@d=6$;l?pyPK zuvh0~n=kxvu&U(8k01Xh@g%$Oi13-}Z3XpQ%5i7mCnUkC;|iYAY;8{=tEbnJUR7~L z3nfxLu5Q35??*3kGefNrPFMp2Mⅅ9hzNe3fiE`HRpF`&IGejrECftmzsN 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Home.png b/DaireApplication/Assets/Home.png new file mode 100644 index 0000000000000000000000000000000000000000..6fb4637037513e02b17e5fb34afba67357534b99 GIT binary patch literal 416 zcmV;R0bl-!P)zUH=H}U^YF>cW#%x!K^d!2x@((21 z+GJ$V@DH2*K66Y}5}&{oZ~?s6(lg?a=%_+QPDoTCBNHWxmJv^hB4s2{q9_@Olqf<* z&LlCbjGS3w78yw-kyS<#OJtFeOcEVQWO7R+kr_&S0Sof6u=k9bHUCvl?8wh9rk-&X zMWu+eQ)F&{WAB8$hsbKADs*M#A+qmnA8lJld9VkX7yGUtkz4x#_y(Ss$USfgGzEz? zwoRsO-h_&5fon&$5hB5aikQU)7yX3@74b!T1UEXgh(L!HI<$VF|B)g3j!^LD_W(SO zWF0U?S)aJ(A%%!fri%EaQ4wGXyai-4^7J-=*IdT*h@vP8Mezd=LFuU{z)y$(0000< KMNUMnLSTXlgR8Ru literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/LeftArrow.png b/DaireApplication/Assets/LeftArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..7df4a9b25a9f01fafa8943c6c001ece5987ec430 GIT binary patch literal 1049 zcmV+!1m^pRP)1;TtakY(>j<(HW3lvL*Nxd_yX{pi`HJ4WD^l7C!)P>2wwpDBGo@FeLJm7-P33)+6TZJ zhW>ti2%Z^r(b|%_Mz&P6OTe3kz7|PD`@<0H1VC=tGNKI{`dK8II)69BI)RW&wp6qW z*hE{xMRUmU&X$UH9vCvTztjnRV=kIQjgc)C?S0@aL)(>3cy>(nH&bR#a8#A83^Ty6 zq1_75JEmH(B;|yO?6k!w7MTIg7~1@+1gF=*|K13g4p?2Q@2|7F|0!E6G7XFrmYEYG zKLStXth+2Qux%QRMW%4koZ38+v)(drY(n*$2V{#yCV|ny({h4C^T~Ek;6$W43z;7X zvB)`KtXau9VNrrTHL9!t$0t<3+$iV-h(*o<<4w%X35*&e+lnNj-N+V78De0fshK(L z#D-{JY<*DZffvWAMk!K_fOG$MB2LS3Z-??Oh3jWU2DUyZ0Ys`3z+^KsbAsb`m1kWF z*JF_vvW1(|Xr%fsFx9NgoUoAUvH^6FjBw9y6g=?G7O9Q{(@n_D35<2PlcUAslY^thdcpJEAXuEqAzMc|!+?1IU995^$%}VzVyqL}*kW8t54x!D- zwOo~saKj|0;Opfe@LeqOm?72)h}>(Vsc=Ksggb-_*Y?!45T6n5BST+@fN!To4j5vc z0Lb;uwk_!X#WI%rKKx>tHpR5XC>`Mjfy;*Q9+D|_zol=dbusT}(_}~-B)J*9UV4D9 zVv$F!{X4CPX&TLvx#rYwpLD9y@J`(ms%uZcYrtoQ@Wa6DjL5!5^Kf=Qg=`B?g*$~! zxF=U!xVE6-X*5gbqZ_7gA&^X|{w;(+DfGZgI>NmQd~OIo0?fuDdyCA;***LVbWJc& T;dq)&00000NkvXXu0mjfp2p%H literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/LineDots.png b/DaireApplication/Assets/LineDots.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5679a522c67a0de9b89182fe99f2fc3478fbdb GIT binary patch literal 249 zcmeAS@N?(olHy`uVBq!ia0vp^Oh6RC!N$PAcsZjr9VozA;1OBOz`%DHgc*((zh zS-xA&Sl_4*M?mdKI;Vst01lsH_W%F@ literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Logo.png b/DaireApplication/Assets/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..a0918b9e13e4c0b7d40e810105593c085c1f6a5c GIT binary patch literal 1303 zcmV+y1?c*TP)001Zm1^@s74lBV900009a7bBm000id z000id0mpBsWB>pF8FWQhbW?9;ba!ELWdL_~cP?peYja~^aAhuUa%Y?FJQ@H11f)qs zK~#90?Oa`MBOwfCqP`|g^0s@b-emVEy~*yW`dC%H0Q;~aBCdbI1}5q!MM@`(G2a+t zY^GbzIeFr6J)dq8>+c*&JFNYo{^R}QbAt`9=ToLSg6*&8Q$An~CC%XXBKZB|b30Hs za2l2GaOl_bDW{y}&z~Q^vZh_mIi<_<@z%KhuK8f?Q4Z0eD0%%N@OnPwn&kRAyt)3p z;EO~b9w0I^-3kK}MP0t){A{GC%u>E-Pey$7Ssq#)K9(!@=e@*CADMtOaWlKmu& zpa`L!sn(r9St;Fn0!p^%87z-kBTHf$;>Mt4Ben2eCF}mmWFci+9E+ECvwYI!`Ixa! zi*l5bJ$<0=wna&+OV`RrXK}F!jhm5Xq83ng(SdX`&~UXrkyC*4k)=;~O%;H&t^$-C zi#&CNq*bVx23))`_d+RK|4u&QR-eZWq{WxA@eyZpUIU<*EPp>yonfnp$4XKwP{(zY zd^X&I@LZQEl(4OU3g0kj2=pGq-5imkDQr?k!a`mR&fQvrDG7HLs1a%<5nI6EZ25>2ATdLoI`L`~dvi|$PXO3+L_ul*MV zPBu4dthzT5IC?R$kWpXb{I3_x1Zv3B?3^st*E(=4yGju*wW(3-Zi)jjt54=&mNPXLm`-ni0lmXApHi)P2i&t*AmuAg_i{3$!A78<&#*IMn$V@69@e zm$%m~()zr|a9f47RfXQ%qy%V%Ezs=g-S@)Quw%rOwm`f1cqbFoaiBJ)sv%|B;kEjD z^aGOg*Xka!mE-)(%E^S3WZfa@rehB&@o8#Ffz_eW9ky|`K#iYVmEhI@+iZbaP)f{9 zK1hBSUWZVfX=#OJ3pRs9FUyCzhb$tiK-!CIuXC72pe3Q&LWEbjT|$@-ln}j`Pz7jj zgd|kG(UVZM2L9H*rdi+&L|A=uHinxbE0s2TGU6D>K-!~50jG>rxhPmGfEL}&HIbIn z2o{;G$pq_8!fTggI^d=q)Cz&L)GsxarJV@;y}2sKDfdXA61=Nt&G+&=+zgPyUWmYe z6$opCj55NAwRY9#5FSR4s^vw(qs%oMt3C(R1Gdf<%>Y-Oi4-v7i#{^pl}56rux7y3 z03obr`o8fWo_WmGjW9GBO&t;~*F0ynRu@W!r3kmm!_&a)6m=BuL#iPZ2^J&lC2__0 zXLXD)++pRo)|n{XGxJ51N5x3arx(;IFX$CNa$&%pFe+s6h#4*Ao9PCKAtG>o1Vglx ziCQM`4BnSCKnz}izgJK`6CN7^t;}fNryJm&c9a}ijA9Q5ioA7!m~Ma&BfQfdy`bh? z57l;M3^PE>`+w2K@d&k6j;H81@H{cK7HlDDZysv|xZ_VfXX09AaG+#`8K6}Bw!Xnq zWJc<=S8#l-z!`VH+Y)S9VzuqKmlwai=RG{io|25ZjRqRt!_Na2^u#2iHYVD>N4)#p z)2GJ} literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Machine.png b/DaireApplication/Assets/Machine.png new file mode 100644 index 0000000000000000000000000000000000000000..524d1d0fec2537a44fad7c619a594bf3ba91c59d GIT binary patch literal 21910 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Manual.png b/DaireApplication/Assets/Manual.png new file mode 100644 index 0000000000000000000000000000000000000000..94e4986041b8454f73fa4c01cf779e8de857c499 GIT binary patch literal 372 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/Plus.png b/DaireApplication/Assets/Plus.png new file mode 100644 index 0000000000000000000000000000000000000000..368d3657927760362957745a4a8ab519389de73f GIT binary patch literal 2470 zcmeAS@N?(olHy`uVBq!ia0y~yVEh8Y9Be?5)7S2I0V&P`kH}&M25w;xW@MN(M*=7o z;pyTSQZeW4b;CSqM*-J^ma_R5+^@&ZIH~X;;@p+j=AjPH4?QTBFX00kKvmHH$?Ex; z!|y+vGcnlzuzFr&|HrOgnc)MoBYOkGC>{-i;hhFH#nsyvos+(^q4B%r^WP7@*B!97 z%>NKAU6Jd)Aw}*3WAVKMY&i$m-rYHnQvYU?kYlfKcwduLbU z&Ax=r1@HN9RWeI&XpA;DxGkt7_~oyob$$Y~S;1?zH0vhSrhWDq&v}8C=iME(oIb(M z5_{pg`wLJEH}J|h)(ib#_*>(r#?1yG|NjMMmb?5nkKX|$2Nqk03x6lnp2-D9t^+v| zanI-IKj+oEdEmGGkAnU3ANN$!**C9FUTO2@;}Ve3p00i_>zopr0N%E5PXGV_ literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/RedUpArrow.png b/DaireApplication/Assets/RedUpArrow.png new file mode 100644 index 0000000000000000000000000000000000000000..3f5055eead0182bb9892a85dd5cc4846daf924de GIT binary patch literal 1187 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
b%GS(w4AJVD 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

>9fYGg?ktZ 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�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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/avalonia-logo.ico b/DaireApplication/Assets/avalonia-logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..da8d49ff9b94e52778f5324a1b87dd443a698b57 GIT binary patch literal 176111 zcmeDk2S5|a7VMr~?`&u9?L6D5r)O_~sMvcwdp~TLayYQR=&jt)Ayzj1|ar_qzjj>}3?t6{b(C9x>L&LzJ@V=g=#=Jw20UVfL=lL2M z{~gmTy4MTV(6|w$snH9bK-Q3=ARS!FJP09mMIup;tn{o!d3kv!@^W%);OYRUBb<*& zUfu&ZAL5yllVg^Vkuh1CsZc0vmX(z?KQA};38YPiymH{ogEL>rnVXlJ_Y}Vu#0Z*Z zXJ>DO??NCgJkKTk#1sX_t1C|tlgWFD>4bgc>I_5jV7WPYGW!B~zVr%7^rTZC!#6?c{Pd1_ zIeFIbAU9KzPF`JjK#u*jl^h+ik(i9#LoR9kM=p*!K(3EAAonMnB2VL3`nrudy<`&NuX{dHBmskjyxgulTMQtE3Ohgoyr@s&2vplOB)Vp ze6g71$V6hl<|45ib%@-XX-qtiKP3U?F2rNcJ@R0RF?IT1cn$exVcoK!f1QW^)&ly{ z3AmSFJ)>R+k*BM#kUJAklKT@+kp}>?{lwGck?uL-bKHT5m?`)zmK~l0c(=2&s|j@& z40U)+@FF@h54?V(MG?laiB_b6A`x{u%op_95uY zW1-*KL%t#^|D0TsDM}~l+*GQ*ST{KEPYl%i81@@|ef=8vJsu$;A$77+Q~Lrw4nRI0 zkd6gsDx7I>3SrDdK|i|(V{0j!&2A<8Z9xti8u*N)q%=z9^M8XrJqz;M2Ito zsTq@?%nl@y)Rm@J$CU}0xWj1xrz(d5Byxx8h6%MGM1z`VI>EECaN>OQtsQ_HOm0cSY;4uk#> zo|l~y0eFvtdp3OIm6MrmoGM5ilg>+Tr>sqgfkBP<`1ty1DQRu8g=s@zE?JSAlluzF zpgK9!tx^Z%g3O-fKBfwplZ21Pz=E=#)4O4lkeR48$b^**d-mC0@{*Wv!9}3Zo ziHWHPYh@S2HI&U)Rxr-H(LQ0s{fZ-bcFdMI9JkdK4TP>??!5IIGk1zkwgp1W|T+_51`MJ_tvk-iShpsgTd>mb@2Efo5{(cTgmBR z{}7YmJITfI2Z`&y_o#Up=Vs~o;l#5NS;82hVfpYvGaUMxAXzXlJ1g6!L_&BVWb=vn z!XxC+pfyU%HvMxqF&nX$T!ZykTCVh3M)|dQ3A}dcsp)e8c4{Gzt%H~=B&W1?t5o*I zkq5|)F^5$uAMhVi2!BI~Kr$dVJJ(jWT>K4bh{cNIDwl0B>R)0t_NYqbOWR+KFG?15 z%ScOG1!W^$SnRkkSHA?lEoK}cyqM24jP!#vu9!SsV?k`j9WPP7&oM`7vZ5=LAC2uV zWTgzs$;vua^a6e$y(eIC$+f@F6zk__{@g*>Vezs_i~Ytr*lB<6_tO67vFl#3ba(^f zkB#Mv`QpEFv$CzE3DN|q#Ac5kef1?@Ouk+=4?S`1yyT@$Gr}xip#5tH0^%66L>Gezin; zXnz5gpPC{V2Xr3NXw>oHkw;PaNVf(&dQZ(QIKJPTm7GVU-$}30j-N`D|H;fn`nu=} z{XY`R7jyU{VcxkeeUUDbkau@p5r;E2gcFrWZq7F%(z(Tc^+jnirB|P04kgNuxa(6Q zJo{S$m#jldZ~}3hcdI46`{ib5Un-f95SJtOsd-Jd>^tL65W5LR zC18~;7k|5LvnBbkUdtc(Ik^r<*J1hau9hTO(mG9)HWkKXiHR*2*7Rqat`)(pYS}NA zS&~cvvKS?fv<#7CNd}+ap|E^S!eaddbWh)$?Ci58Qp1B>T>FndA*z=BX7@dk1w4|X zBR4nqep-rfFpo}ejOF72>1v9_;uc7g0&V(1(RcWap?n&G>|mIOkp}~psiRi zHUVd?aeP91i~~A#KCBn|Fn?c$b<-Z!?gzk2T?JWyA0Xs0TftV%!Ss)N}l7JjS#1jpNwR;TWh{xfL5WqSHeYXqDr!BFM zQM|JXFk@Thf`}j!P9dC3INjkiC_JGe*lra*F(3DWvnEqRqb`)u1j_0NWsU(c1wnZz zh*&jN!1*o8DWKX_d1&Hz#r})3SmcvF2B5|c&LgQnU!)|a^aMJ4WGYuM3*ejr@Xt zFpBf@bK!S3Ji~WNPfQ0V9+_~az?|crCKRucBnt+J6B1e=3<~O}^bs*2HDcUi>Lt;W ze!;dD@`RJ2&Ie(fzk~dX1l&-ksyxzREj}hlP9A`GS6W%Q7dY3@VO>X>66t!Vw*j0id=OdKwG7!3B;>J@yXrfs#)R|YM}{dZB_*9XF&qzcc71!0v+NB&q@++RafN_ zIRlU2!e=G_RieT&58xwBx)Z%_a!hh-n1}yNOHDHX*m)%~`w9=B9$XmXdNS25_LHhR zon9B|F_8a^&d$iTfM+G-0AHc%RFP2sd_If2q*$e8Zg6aK7@St(Wd5k!tXyQWziNL` z&`!BHzsgj(=qIGD3G-ufkZTXkOiwq1`&DqZ*kQfne@!;WM3OBYLa!#&Q=WgdV|LUZ*e z_x4(l3DZ%q80wmfel$b9%O3CB&2dz_D_cMjE*mHmGBIif!Avg6( z%EMHye;(AI!(S}h{!q6XLRgzoZUS_ulcKuHJ_9)y=r8Y*g9BHWyY48@H3zweY<=Z_ zm)8DJ4~Zm2v`Du8us+qrH38`8&F~)Accn*GdM3HK>1-wHzMowB>tN;T&zBU{A9*9B zi>Ub~C-oz;hDp_}wIUQ14{RzyMNij*CBm(hDs9&jV?|kvG8tVQp=$!vk zTm6%1w1y}zM%h_uZJ*3wkwZh)mao5$+)K&Y%tvCMDUkJ{zWmx~eYMmd>Z^$~rGzJ( z1Z`ice8YN&d6{*;F!2EKyz+vi&{>px2=!7T7M}#$dlB1t#+0rf>yC0W`7tYdU)uPE zdZqy{OU*yN7QVFw*mp#d#Q=-azQc)5EVJ(SHkgxikh3d0aBX{U>_FAsYRr+!)IUSQ z6;bp9&1^OUW+aL1D0{Vbj zf1{(Ln{e6OVZevnm*y|M0=Goz9`nF90%?LPOO8`|6Zv)3WaKWwk1ch*mu5*_QSSI? z{)JN8Kg`yv*f(-FIbyDuqJLNs5kI560_gg;vT15$Es9Agwf-MZl}ZBS0bRcm>yP{i$c(1s=j0Vr z9?;zVi`5S154zENu35f2>ySh*S( zzs;0n?&h*sD5BON8bmWJEUX3CqK$vTOrU3wCZKev>#q}< zwI^k_iux@2LqGC%-+l66Qh{xyY+sT8t;nW9rV7}v_+o*0dP-bMTdY4GEML}7{CM_n zKm(z?LFs|=gBw!~DSfwWyCW?ot-I~`@4rSJ2OsF3 zg4zQPKo7!==l+_?6V3+sO0^G*^Nu7}$LLe^yL`J>rtSz!m`$lP4^}@9+K_lKCUv?IjMtB3|xN4sO)(LSOqX)yHfPpM#+g7R3XUoo8>@{pA5 zgrB+qa3CzL{`fBRz7M%Q-jM3=m2G#NZ;-|ei)YLfdm-Y|a-XC3TYR_tJVx zuaLe_*UsrG;fof-cgh!WY37Ajq{m`k(2RrP>6WI?~# zo66?*L;WdySE{}k-q%2VIv>)5z1nuTFJZf=O4)hYxlm6b5y$Z;S*I%BC`gl=nVES` z#N`e}It|{Js^gczLrs)tfu3n#mLy|8v_XYnP*9)pJjwwc;S$I>N3wy(D!0B4#sbRG z1&PT6!FFsrz@R#VTb^1fNDF191C4N6%n^@3Jp>Kp%8;zoej{yr*((9P9pZtqyB0|n z$@2&bimvn{;A7)5Q`5I1O`HmHsfyNJ3I|jO?AB8napE{#VP2Y)ot}9C+DEA!bwvSy zJhMOs;t2X}Jzi2$pV*)RJvG#$-0d!{yYvcms)1_;^2%rr4RhH%u#>ZcG6fZ_Z_#)8 z`58ddIHPVF`pciZL|%KeeJjfzM_M;kuTUOkFM_yWMYB2pt?>uYfit0>o(2BKAKt4x z#sTh3)E}dLCg@}r;TT056Vyppw!f4G55j?S0m6YaEa>9u#p2ipSkQdhky zk`MAgXcL8NJL>;%?1@>dpK;#C6Xo0SwD{&oU!e^J!mX}4Lq2c-4*5m7v4*+28H+XSA1MF(@3#Vg;)9VrT6Yo4Gmc3 zrB^221E(RqQg8z2M8Vy$usz^Pwa*yjXW`I?s{w!mH^d#X!z+B)1h3G5lz|p80NacL zf3mUg2_y&bJHg){$B!1M+7>{4E6#gp`-t-(i^1xMHU}IgX9U>4O$HiZrija50yd`q zr1C@tU`Kuh^vVz5yq6(Pznzhqb~!yY%`81F{XDFHre&U~nWpfqsYH}&n#vcQPvr~D zAWw@lN!m4uP<%X-0N|~Axn=%+>SyKB>HMatcH&O#_icsgnqbIZj+Oj{$oyG~1 zh4a8J>}XDA)-zb|B4BMsJEPJWVw^VBcR-POEbwc-%1`2Jr$ndpi1v+c0@b@2`d}cB#nZw%mj+*H?+|wE>j@z5 z;Ke5O5hd|;V9cHexW5=5SDD5EfAC9SKR2i}7?r()a&dn9DLx|pS6%{pcp5)-BeZEy zW$N>#zXiL4IDS&HjxrdPJx9I=`#YP-?u;~gra0XM`bjls8|L@WUXuxrM9de%o84(539=gDy^nN!7{ zfUJq6#3T`>ZzQ3=3n3hO0!ia5pGqVwA*Fvp9aL#&VLX&FD+NC4M)L5=-D@IUgL0*m z_>{3gzuA?UX(f1jAho4620L1t)u!abZP#LU zKVF9+W(??p$~rl|s=2@c{3qq$Eq04BEl^efbj@J!T!n1R*??E;?H7ptkad)e z7REtP20PjjV_XE|;RQAzXTg5OdWkWKat|izhCf{>K2Z!{nHxZ(ChA?2qvN}y&kev{ zZr=cmzwki+I{9z#XPd_I!j3-FXpf9~b$h+DW#S(DhN}2a7pIp7e=U@agB{NVnCpw# zj+D~Hi(W;(4<<)PZz2E6*e_QGcJq<@6vik}G!|5bU!oX(#63mhM6-X(5KH#KeYyJm zJBasjXz&`f!jAsjHlVv#1h4!vRpHM_R{}riW>T2UHpnXiT}vxMstP}x&f0%ffgf>?a$B@Hg;)Y;vy-m^*i;gX`%zV}V+;dZ@Sj%%ul%#hz>jnu z%7a0sJppvusCQ85U=;9$s^JG%DH{uJT+$!e8ClkaC&+9@05{ErE$&3GN z$ioeniREN{Ds}~qcPZWxcC?AVJKO(*_G6m&ys=%Kvl#pX%wiemWtFp#j znSPiAKJp|Ot3>`lyMj2c2=Zj(6{^omVW;fpsu+Hn9jy-fnTXi@ML_QqcSe)1XyLu< z<)`I>{UyXd!gyP%91)IwW68} z<{79=)4sc0s?E2;B9j7Q$gPQnR2-9gRSZAMgh9_a6m;h$d=(T`PQ>A>4EvKk*U`C3 zQ8r~hi*WEGx5pY1b;F-7krd;9P**|mdD%JW!>sUtaZ&6!J2HV>TX|X`A1CEyOh@k_ zVs<4=5unKDU~_5*@lqA7ck<6v?f;+~IVHpLXvENBT8lWmDImk87Xwn}CMhzGJUVfU zSnn|-9#&2S{V34i#A=O6F&Qh!C zj1{a1UioLSFN?XFD9sl7|5aJ|(bfd?le3}!mk>g67>UL3E`=Sh7grW67q3s-mylhY zAGwE$7p$}r<#?eePMAFGcpqu+t5U8Izwnkk{21#4=C~5}!QvEwQuuFdHKEFTe)LW; zxs6nIf$^5rakyi=G8N=syl{oXw?q|E1tL>f_)#B*dP^Ap3hi2D{e5KdAM6a`U|1Kf z%{fl_{$QV%!j5tqL7c+uO4O&U2N;`775HW1d6$|cKbgB%7XG;KxV9qDYXJUB1Z%`~ zPXe-8^W{g1`T@>`u2-K@WrV*f@OzSn9pyH`4=WuGi?X#<1$K<%2jjO?xTPcZx zVYa3FLrUAmX%U73Df<9eGC)@i(e6JVXak0EQ$WV=Tv`s;4%o)Xzqpz_BBrDED1}|h z$01Ks(IZQoL7wWB?$0WP-}g-EzD?3Pz!+!YTK^e(4UO=3;A_TY4a&~Sx-Lyu+BG{p zi<}?5w@lbkc40f~3`t8Vv8}(e^Kq zk=Rqj6a1r6CXndyu4~2SI%%Jm;vHd^@~}_-zFe+0fI1TN9g*U;tm~tx=U~$T)kL)r zAI}bX9a;F%?y+zUz%{T04Wy_|qTGUu@m};xl!YJdcoM)@u8;>(ZPJGRd4IJT_{|l}b&BvVg&kuoBOh1b zLwAFqk2mgpkinNwelFrzE{Syp9}$DcN@GjUVkQ&ud=qDBGxcCam;h4ij0{P0^7 zZPqyPoc`czcd{sb89x#O7)oVUieR^eSj#BOLwOd)L&bd=l)MRVPkf*toS;j2jRA}m1LF!<~g-4vkp&@ZzD{4fS$z?UK( z^q!#mS`MF-6jEYF3J!51pV&+@Dw5a9j`ynQ^SFOXoJ;w5Yw-Cp1%37)v~|b%P9A=| zN4+=7g1}#L6vQ}JeNu%s!M#%MOg~M@>!fpCRltrueyZ|$QdFVM7uv7jyoa)0MX*!w zgB}2FKG5Dp#G!QG=I3n_F&D8?m(JGkh9#1zViSLz)sHEV^U-MDloy<%gh`zkI zSBNtBsWt#z0L}y4c=j-`6)e^7TD~B>M;ny)M<1(wo`1dO2JG2Wb{qitIsr}Z#ba@% zAdd%n4#d6G`$1tdfa?Hd--&k2s0RjJpr3r6s@$hQ91GWNHkDrEo-MpgVqU-=PAc+t zvULMmjt{Z3R-^!Ji@IH9<6gcYD7$7iT0`{v0l%{4Fn3m%k;gaz-bbDi?7OP2={Uxb z2EACi z!kzMINBD3LEX1$dRvY4}|A+)!a3)OHlMCa8SMmVo;4E9DXPKeQHfYOLR==0;1DL+R zmm#VpFM;zX_$QozI;o@=u4LUS{W;jHy+Au}Mku4BC(P%NVX0$Y0qoQx{0?osQ=kn& z&OIs<{4$^)s7I(*X($zEfd2SkuQ-(x%jtq+9#WM$-z$S%`W)LJ24cD3{F%&39tFN7 z$Ds{Wri~QWvPz!99ub*OMag^}PF!49^l?DFwiJ%aTyZ``83FbK4vqz(WIxDJs*Sxr z;3E^(>Z?MK;h}xHI$@W#8}%(P`7y>mgm!oUeUejII2C*^0ejRp0QYtwhdUAMHTpya zMzzGfLDV(R6#=K>52Tf`Y~-60!V+3wJ0Puqx>S&n9|1hQ0ooDULN&#N9MFJk5%{fr zg7{9CL@A<$;8QpTWp^9~qZO`g>h#xE5oCqQpxOoP0OJqZqABv3Xh$iCO9uac!3^+| zS`R*mmtfD0XJ}gp{UaK9Qrt@*nL6|GS?~<^f((ZD&JZ)rN+Oo*Nd=!ev_r=Emd#{# z#x_RTO?81=L1Snle~Due=V7F~(Y63>$&+Ie2B04-z%yQy%+mrLgsy-sn1LtiBhV*{ zo5-Dr<0vJTHJBU2>cxY0#F$QKlZ-Sh_BCv41?5(|M_5m63&a(!n>663VuOO3CHd2T zNsftWoe~$<7Uxeqv5k;UXXAK=HbY-4q+2nDE#y<dM++sV6e(A&4oBHVm`4)zXi75>h@ zZLmjh`@okzo&8>Tb_;X<)FaR}uxI$Yz@CAwAA5#+1azml`E`qY8`LG-Bd~LrS6HVo zuYgVr|Im(jhQ6=r(;v!!)5X7IfSXq*tY?t($1c83@4E(i_;jYd^X-5z1ipOVGRX05 zGlUUkxk!%}%1FKmKBAHx5M?zKZ;HGGz+Ug&lXs0gUwAf093y^XKSp+m@r~%k@C)xB z8x%D-A&mKFTqt97EG>FMOkk82!;d~K+Anez<5T#&n81hy@N7X`aMb)*8e=XqBzksS zXpCMQjXonbj4>@CELJxuGGS^$B$GOmqT_Ycen!OW#78i7;zOf#q5~qQM*BuirGE&S z7Vb@(5#<}97ZVVn#|WfPkEb!U5r){1sF8^@=0HYZcu&xMxASrKY2oYO`xCau7m$@z z5`7i=oEqb91_rfodwU`jYFgiOkD+{!<9PIGhM)rh&o}9HfQymna)t2b7p#mGwfUH4DqU6z>mR2B1m;7#|Sh1Xie} ztI}DHBlvLo zf-EW)(3$>ifR-Z9@A%YaQiB>&6VF4@wAUj!&Y;&Phq&tOeP$DU3;1*l#oja9yo+ zm{r-60QOXfnfI6z&03ro#vBn75Y`FXtx(qX&GZ4pJJN8tmeD+E&1vsw9pVC``o+=W zMp1KmEN5++NOA+lcNmQ7|66=3>q{^nFkm0zt?^+oW03~(ef_!#wkPT|R33a^J|VTX z<9vm9$2APsbl87qAgpbZQka~@Vjlk##Noree^Zsg{^NN;3&6U^bf--vK zjlMiu%PtXWtciQlpk4sSdl<}HNXxLoDFMApwix;Kk)y#1<>aW;y!F* z2GRdSelZ4kr0T>M;CzIA(#grGZonhArcob)+sDu%2Otdtc>f#dZfoer6}Hd&+!Fu4 zzd+|2o){IkAUY`ex7fEq&5)jg5&6~E0qloJm(W0Vf&3fYpVkLxx^cj(EeBfmKIqof z<6!*%i~1tSVV_VdTtiWAg*M<{c@Ch)yxR@8ddSBy1H(JVgvJa99(E4I-9HKAJ+7$Y zKYpmC1)xm@z!$G%gfM;&!Z`re+Ok(=^``(}sMyLB5AQ~6jWj)r9ycX9p1lS5w|DS9 zPb~od$fQIIzgf$Lz5W^bCHh&dcMkS z>q<1p|JeiBH-^TFjGr9_GBcE$mX0m8z6Dz$QUm9Elut(oM0dx2$YZ6fE*$gUt6Z*n z^)Rrb=EShp(Y- zWB5gk3U>Bxr5t5ydsCpB16fY!8{al4$6-as&w}~>Cd~Jl-+yaYKL|m$Kb5s{W1Deq;9}-uTE-3 zc=60ASsrDR;2qd5o)$BV!(c4|xvlG00{cg?g)IO&WN*5E_;j=-Uwo3q+PI4T370MsKKIA`YfGr^A zi=85ULZ|vad*4xQBfc;r$i4>37DIhQ+r)oj3{8qjSPtVp=ts*}pB4c7r$-T9LE6DD zKd6=dL)i}6-=Wh0LktVLj}q%_`c^=Xm+ubMz?z=vTzAyWdKyxXa3{6hW}iz zQh8!~MnL2wFO~kF zb);bbhVtVc<6cW+U!N)5zsh{lLGtRj9Z7)rfEXWG_Neyw7o^%Vf*FASh)Uxh*L;-g zqFo6yIBG;PGifu}o0LC@m23l6@HZ3U|LNj1`^3=LN{@e>_tB>cb$RT_SY61s zQhO+tci4-P1?2v}S7BeS)dhPLeMQ{kK7JP<9z4c`x0-ykdgDJe-5%|LDl`8Bt~Ak( zkdo_zJvQJ1_fz{KYd+HOxG&Y=ksGTW?#&=p@-^7gN)@_J)imm+|G=)UviR3TJ94z! ziVtS=XEUjJKeD{zw<7659SqecfZ9qg?rp11NR3| z1+S{6sV?}(SZ^rji-)n#iDK!Y51xV{tF}i^PuhHQxJUfsUNEZSR+V(s1pkz*Ckobm z)aeUYyd7Y|Rb{cVoi9E9CUKAZ8h?-YM>#Lj{OEVjrYBAZn{79>4RpDT{GPu5W^sSz zJH!d_^)2N9H~rKD%(N+UfH;p?uGe1;lE(+_pFcp+3e^9UEulLDvo8v zU!siX^0H&!1@5nb?Em(6H2zWEhrYUu;PCz!lL2Hhe8pI-_*1_p@4h(hujn2oPXF1E z4>w&%#H#?p^o}5LA0i3kEsfBgejxA7oyg-YSBS;fLzGNcm2r=_zdqUk_Qv~u=6{^~ zk>|&`U(6Gpt~izze~B_alj#S(i2mLT_VIQ<_k?i5RVQC?e|!4tK;pRLMhQ9}X+7zj zFU38|{;bCtelP34Ci-iKLaf^)h)D|jFTGNX#fm@unJO|5RKqh{+Wf8aFykka|H` zTU7M9!*S~>v(@}?%cY{#Qu(_~Q95y0ccp0DBkpluY}@Z+{1>eK5Pv=?Dqb7o>Z;r@ zDkOyc*U9m*+euZ}XurGkOobY#CkgB~PaZ8X1H2dD9(jM<6I@l5P zbR+oWZ6M|G$5Z5!MRW31cNJC74gc z<^KN^?GO7bVBGLDaoY8AHH2K^jMOv|@ji(7K7C7Q?*0V!FPBRJF)3g!xG?SCGW~EB z;U4|*XwN>D$n$GFc(uu@+K>M?Ig?K^l9Z zG~AyB{0Ba$ULj^27hO~<{yp{8YiKNi+f^Cs>^T}U4`)fRx17X@)peh;O7UrA6)-GFV1DuM9AS2u4JcInHySBoyzkg^8QD);ve%<=ON|_9z=YkY5O|7Q_BC#(Eqa`rc-cv%C}g1 zvRwE-I$;aR$;>V)!tLxMf@8k4aWBO^#@k7ut2aJkQAH~F!~fhXwc?-Qq~4HPuutyI zX#a=_{;&MoDx?1j`2WZ*xX&v1<@lASDL}SZE*=2o!qNlujKos!sLHrU`}~L({?gB@ z#no+_dilS2kI(WEbpR-W{lXdkk)uo5{{#2us)zfovLh**|99mr7wN#ggI1I|4>+3K zDVBBcQ}1%&9^>t}o%~EY6wB-@+@QViLoE}vj(-82qgF^nDS{(0;KPlvdXz8wL z`iUyD^D8gh2_6w@#l8Kc(**mJIuBk#%0IDTQG-j{{|WVf7{fg&JYgKf(5)~7f;!n~ z-*Dn=`Gh<%x=oPIM;)N-dXKQ>X6KMQYcG@=_ZV*neKX>`BGlPL70&DZp@(Y4|Feac zD_j>vAA${UdNPx}3gfoXA$FsZ@vnh){}LM#HB!js8!5_5UC+`55@NT}yu!Fg ze>}&3Zm6p|70yQ-$0H9WpHVCR-yM8V;rb~05bU87F>=zAwe=A@f7s=*R+20Y)0mO2qVYz9&()@7mFS|hUAU5dN zIFbWm39i+u%5+psCx}$(zBRi(;G(`12PnbYDcYRCQ4nHSW)O&;#Mm_&~s8~P@+4bphZ#y>o#;`<^G zm;kYzVIP;`h8jv+L$w#M2Nf|LwYOY!zM?rFb3hoaDn&x5BK6j-j9HPS1I_{z}W8CPm;po$EFD-U|6r-1MPNHRdMm3Sw|wv|^EvKVCAdfYz*14uX#uI1><@B8|76ZG#a1OGK~ zujaUr=s$P~?CtQqTAk^lLC!DLezqQJ9rs1Jm+{AYvg9I3^oc5^WmJ2Wot8y{uf9>c zd{=hde&1z~ zweUHytfk;{-;eI?-56u}mWFrfJB$Hv6kdxFQETD`e4hBds*D0Z{}U_&$v6`B)JE6`e>_fH{leyKk?KT8Qb#s zmcOrxbsu{Q?8$eM6%qRv4dOYJ!S_p1FTGMR->Ln4!(zsyrijj#uji?jI@&F`+;O(P zH{3fdvQWFO4_hDTb~YF0{%DZpVk|eD)1}B&<%;QXZ%>AQ#P8f#hyjblmPgI~uy>a#c$cPuyeNMVnsTi<kyt zWnOkU?ZV3gAk>{a|Hn#Ue7$d-$D?>YuoZ|=vt74*`=;_!&nJX4$D_O#7R&*2t9rlhZ0G|owp)ES>pjl-(GH)aXsW7f zeySkV6vqBI9Q%N?`cP1%#=f*aU_Nx1147^Uwn5uaej;}-OaYly1qkMgdO{C_2j8?@ z563;qcH`aE>&v02-C@iOu+9RE)K6O}2xwJzi+l`>EkrJejuVh5u=Im#Fn^+k0*V+SzF!#So!x}54R&&P59{@;frOPrzZrcjt4?Ct)94SF8* z-3^B^ieptCf9kkLIReHA34I^hF(D#$0{9e~LWQb~7L)}xgC`+x4IV)PPk@hLEu<~cJ_u~eXRF&rR2Juo zesjP+&S|A(wbbKzA9+eL`RcdfP}C0i4CehDNwV++(tH@#4aa6hWqqpl1t=D1L3-U_ z@8DKwBgkg3R>L|FudI$$@jMseh)04R-(mj6YN5k@yWgI0LlUb3)Kc?IPfdG-`?4|u z!+WBR567mec&to1Twf?Z0q`e?2RmVq3;tKt{D7i{KzR|vF_64ie)Ws%@sX$VGI&h* zYWCGo1gD~BD2GE{A8mAyCd1gBkWMZ9o(g?K6Zs45bGR=!>IWqv2?k{RLaScM7C}6q z4VA-evnuTiXah>KdQZ~WYITh&2~a6da6h)>c=ndWFy@Fj|M0e+o}Trqdfu1s6Hq;h z9|!|makMc&eG}{#QSO)lrGQzXSGYEyeHYqnx^A|vv~MQ*ajkG*O& z;Czc~KGNa71-kt&HSf!J0Sy3@;t3->KmE!KV*Z)JWUU6<`>HW&sj61}HuBAfm<;#O z9uxQH2=no2@rBp?61XpXfa^d_H}ET`y`y!AqcKKt6S4%2Ih$GZUc zV?;ZgLR-#ig?njd1AxG0(4scoo8FiSv?=^^?oU{12_qxGaXF6&xoGf)%tQk1?3Y*ORFCq>BS?+2Pdy@4*iJ#>GrF)B|a z8Lk+oBQ7Ft6x}ztYmj45Ga8LnryB8iWuaTydrbhe2J)*kPg-;IDMh*v?MHyG!S$d@ z?8!ejZuR~JvV0Njvwa@@D^P|S4DnZyc0zwmsCl(t>y;s0{yFwzU*7_{FzQ28dxRBb zS>U630(iu@>W!r;sa+n#*!Jau9)}gin2h!m!Op?0aIVC46ZvWRHvHD_DH#Fk4FSd| zplc%if_tOwLQ+h^a^Q9BK-m6&K^Nras4&W1gVLALR*94gB#TluRJHQJqV}g$cGZ^Br0&j;j zGRjT9r}2t^1R?{dJy)X^oBI$3))g8({$xCh5jr` zm!v!JSSf2@&C^1j9{YVX^nV=l-x_bH5TO-&s41ljP>+qWZQOq#O(8l>&&?P`$%|`#IRH5inQcTivR(QM?%05sh5&`oZ z(7-?8T>l;LbrnUo((jNy#JLdr0m=?hW`J=E(atnJJVuMdU@ZY#!^1EqxWZa0RB;%7 ziDdc6!+<^JL+q^y;C{+sK4C48=0%>a5bxhJeWw(^s=lD+gSmD!X<*Av z(MB+C(B}Z-n8nhf|H7D7AS+oe<_nELKlTD-Nzq?=je!0q$j;0T$Vg4ML75#pI&mR~ z&YB!gV+_T)D;(_d&^`xcw9@Vgabbs`Bf*3d2 zxL+l#vFlQ~qH_?Z<|WL(!4OX%3HpROd=w$8JTdy#g0I5|h^J}CWpn>USsf>eH8UY1 zVFKcu+FJp19Z1U}Era|G&Sfz9{21%SP+GAYYHffy0q0N$(1TLEBghbIoD4UT;oUdW8 z%%|z85^G@!{}eYqc?&l#X+?4jdp`O-qTMCxv#|f+ehR4DK%ArP3(7cujP;7)w>)3r zn6jh#f<o(B6%4}cg*!?0hl!xP5izE)^E$z~)@!#(bB z{9<20IVAW|%)oU8_esEbxfuVPvabd?Wjxq7qrD}{X%OELZV^9Y|HCyMZSate|1rOp z2ZL%&ORW*o{y@oB{NsssLa`y(s@AGAD@q5|q@m@B2yqBphRUT9Bd-pQ#4dmX- z-a`Jxsss1Ms-xh(SoPq2vFa(fXUdi5UdFwF+;7i zgR4=uy!XYMN26|e@0oJ&RrS5QTzTKxeO0$lIq}y-E`1ZZ{!`X{N4fMJ<@%@m{TR9T zW90h3{Jp;1_>sRaHaSAqkh=#{yJ8(g{vPJ%VhDlzVhticy}@)_3}E^Dj&jrG7_jb! zS`{5|Uko69xqG;ko$b+5P!<4cIbjy%2D1wsG8LxoWh#iPgY1Mk2JdAmq>uM96{2oG z7f2N^(?W%-Sy6#h_A&)@Ecm{t0R4h{DMW?Y6=hhMT~U)3W>-{0>F0$_Q1p4>2Sv%D z6l{{h!l(_6A?yl9)=%k@N zaon7JSGg|x_q7Y#&B|juxcD%6>#o1+)<1u1qE3x&3mg2l@bqsBFY>&nHeaW^e|htf zKHp7TRkEX>*5L>^pzveE1V>uh)=%(!z^tHeJ#h+r0a!kz;Gr zYCHCK+Ow#GNlmtEwrbkxQ{M${N#n-2+)TM{_b?~)-p+tgtxg&#Jr=G!H~H75v*%9F z8I^W*%8CX~S9AZ`dvV*1bVl@x#W!-_w7GL?be{3$(5@{FLgU|Uv$a|`a`)Esv`?Qj zGz~mND{E+U{q>;FZjH&Qw`(1(={>z&5BKiwbvpgIKjBP_>p5QNzS9Gjq~#9hw@n%~GWGBn z7c??xYW5@cow_}`f86zINN}5han1T)7}`}gwbrv2J+AzEky+!&(T!HM_2>s z*@g$ht;}ZXSOgh18{g}WVW086W}a`}v__2@o}J9Qof*`qx8_d|tp1?sYPa8@bFblq z2fYFZHGJ0GaH3}5d7U=e_pBSPskPPc=@QeX^^9yym)GxlYkk7O{YLeg{X226j#k^m z#K6GY8#}hE-SEDZl_pfXU4!vQjcVU?Z92B=Ua{-74gz72+2+V~&JRZU%z6_WV%VwO zkpaKm?Q(o&oAIre7;LO*`0EmPjlkn8j%zqtwfV)Y`8ccEt^YP_KHZUJ*wmw;>CabR z=(et7W^Fd}sNNg%IxEc<&FXuj#!sDej?bKQc%#jllUl9b=>77h7gnyvh#;LQI`_1C zw{LDUzVkX}LkL_FQT)lsPIo>Dau!*zYi4pxKcAMofXV)$>?S*Yk zd)8hVI>9@UAKLS()#WQK8jR&x@FXvPTfKh0LBqy-&TF2TZSC&s=wo4?*xPFV`khBN zt?g#GMsM7-4@TNA1{~A8&|+)zpBh}fVmA1~%#E{dOwf4x$z=4w&s4$I*TEDJLp;b zJGs$~2+PDdACt5jU6xBwQ1Y7(~SpNM?EHiS>{JLR6 z>#den#~iO(Z`tu-^OnbkJ{ykgFl~CId%fcMkf2Uc4adS`BUXgWmyQuE*I$HTAX+vfoFt*%q z!O~~CW=jjs#GoO=pReQ?uDM*_)8cKt-A39=roY@2zV^AL(<8^tJG-{9zcDL$=z%*M zkIj44d{Us*2>CCKso7F$j|%k9ID zENVQ=V$>bM;vH#BMM^iTc29b2?wZ?m$#^3&1v&*$4Y4<9@?%1CS4 z@ma0LkLfpgoL>q0^wSpL%aNz;DE z8i=hI_n5fJc+1``x3hGww;i^1^};{8cH4XAp_BcFmv4I1Fj;Z2t8TaYYkGHHf2zUt z9rWgx{_LHU_9o%dOq~|S3{%?)U4J^V{p@_<_1@FwUl+aAS(deNa-Tn2)PAa$?sC4* zEo*HXuJ)t2X$QysW8ZpJo#qqHy%q61_P1!@9@qKh68_J_Vt6}hHw@E_2pM|Kddp95 ze`z_Rxrw8P@y~zki<}m5)M!pznr-j?x6h0)W*A)@_qItcleXiDSa;=9;b!*z-uK>Y zXul%z^sOU(rc4@hwf80QyS|y%1CFj@8eexFb@JGXf8N!2JfP=@(RDny%PbeSnR>3* zh9_s7+6V8^eXBKVs&&7&T7$>Y4LuGHZhvoBxXCjk|5q6UKaTCYRNOb#|DKV>l)jV5 zvjGk7IGWA2>gboba)I9A{s)3*Gjxy5d8hT~z6i6xgoGB&p&7OMX{7F)>~*$b*!rC- zx(6+!JDu#?sH-`%%d|f~4miCgs7=Q1t&8J&yd5&M2Gf{v_?MH7bGP4^FaB@nPDi1` z%`QE=_D=0{$~L#@;AK{Nb6n^5H)+-PU8nqyvmxt={WR9?xE0@|$&sbQ?!>1WT54IJ z?>|gCl6h;|<$izH3%${2UFI?GzUH>4A}!4l-4ART@lGQ_xV>H1;nx;uux?uUEVX1ZpxaRLs1ONQ~Pi^wdyGf7SvC}4-udw6pul@U(Q`y_C&i|fxGot=K@`GDDs+kFB9wLa8;bj$Y54x6Sef3o@a@Vp*PoSXCCzN)t`;fP6- zCGItD`mp@y?Dl)@?;L9V%hpSq>h)><=AWfrPQkvn7WSWb;@W_Nks~gQS@$~K&n)Og z{PTK?QoJ+X-0A7n!%blRHg9G3zuHdrnD~-8E$97RX6>09>}LrdgxOALIBqM$Y2nh7 z3y-zBrO|F@#<)iT%L006I_%sXsnhy+%G&0=k2>@lY~1+cfRVx1_`l9-lX1-~Q1`a6 z$-=gaHn}Ykb{KVFxc+kXloN*nM%qmnG_%ja;AO2_-U@QOG-mk0#RDRT_4$3sHs+D$ z8jYqoZDCA4QP(4MCdBEu5EGa)X?c+;83qQ zb$iq13|yX{AF?n1$>Zk6bN?ml^-lHZ``_^Px-%|$rrurQ+}GXxT$FRx8|~j*^=dKS z&DH-cRLr0Hs!>;qXDw{C7TE@_?P(l0?s~p^?N;rz*Y?iVna9<2zT9HsvM1vB+g)44r1yzkKS$)1J8Q_m zQSGO{wd`Y(Jji zuJo8SLjTF(ZA*7H+4`C{baRZWOW@EjL-Rfw4*f~j6>Ho!uMXO9|F+A=X|IjWaC*Et zW4OS4yM2B-gZp|=^p=kCN4(nn+p3erdgZ@JF7?pYJv ze*-e!1nM;HU^*B&b8FpJE_Zh&&{`cm6y7TOP)79mbLO3E^kuaiyJ?!!x!?K)nm3Jh zrt9psSwf$-uAdiw&*q)x=7Yj^KjLR<^+|EH{FFHVgYm-sO~+r}VAN=9pMU=O*=J^r z^&iqUuh!BQu3q$fl2Zpa{UytH(I@ro(*JSuS_TO_{ya6s{i<2l$WZ%dE!y@xf)Q+MaEdmo3m zt%|GhpudI}KjWZ<#Sr5;eayA?I@+A)Ogs^LY8icK&fw^KzmCj~)HnX8Wh>Ung+mOR z_KjT>W?}1*tF!%Qv*tQOG;A7One~*N?Emz3VEu+onhcAK>K^=I{@WHFuDjC>S1#Vu zCAP<`J&T`STj=QJ=sWk?{m7VWT0I!kwKiQ0G1<`g-{1GGbGqumo z*9i`uVlsKnm_OtG{xxCgZzCKY&%Gad&d+jKux7)@{&!bsUEibYrDM5e?TN?x9%)_K zbYTAO|Dqg?@3-BuUN`0MNYA-0DX;!pw|RB$X`42`nKgdVwDHG@qklWle}9^>@cF96 zj{7aQzHD}6o{XiDnPe;qn;5Pp0%kX&>6nxk?DZnISc6`?Ug5Y8xI|_ zc8!(whqK1I`Ah$Kl{;Rqag#}jE4b_b>GQ~WmWU}F7t?0@8^68JLIAJZPMQ>anI!8lP|3?nmc{yz;GA4ybJ$y_P@Ny$}HX1^G^PTjhnOYxISuf zU>QeiLBDAx9Ym*QkA44-=VF~&i?lRYd-ClqbS6Kv&{^A}{+*AG>|`esrxb@#TRQeM zduQ|f?~SKINAyXUN=6JEA-Xx=q;Z|@WP59~9y*D$Rtn~9G8%jOoyPP%`5k62Si9(@ z_Atw4{RIPcokj$kyABMdr9atdZ}@8qho**2uYY*8cc9KSk!kMUdZuP(?VHy!v)}Z0 z_{iFu>92kZ+53mS?#*A0Yx;!x9qsur*Jrw^?wu(6#MUlr-z0An_(w&CTI8?)%e1Gh zf77?ke?8{Ib8j$ZNZ_KuHoIDDx9m-u_k=boEb8cq=VR=jub6s!%e6~uGpJ^tvFpFV z56*MUET?s|?=W~}+Vj0O0e7E1_+JEe$ub4fp)5boU z-ibRT^P+V8tT(&>;==lx)0{WFq0Q&%FJ341+`N|+Z`d?&{m8#p`5)V0H1&l?7q{l^ zteSNjsI_3I*{<=Ok4nrp2HU#YHal$F3>L`_FL}*a*8P9EH`m9IvuKOY>RTUoouS=3 zvvc>sZLF|f-RIrroiSQi>)in3sr5S#KHO2amrfT}*CV}eAGtm+^jwG~!$o@=ECaD3 z1KaI3XXlF-zD}RV*rfGw`+^TT3wgF1ByCNeS-Je4W3+GX_0&6mC3e++Y!GC9_Ga_W z_7m&5)H5HyFK+(=(-n1&t=!qVzGiT2(@^e>*zMuHTWoP@JZq`Z#Sg!38DePQw7XkO ztJ*WK>$V)9SZh$1`Vq?q(jKPNFb>XuHHcULHd7_COvK1=NHXx-FPbAVzkj=O%?`2ufJpZgES92UKcc16YTO?WN zu#R6Pi)(2oHRDu*tQ$nww*L?tj2a@+eu^RG`5}docs6x zJTLa;IlD7EbM5S0Gy9cXUtyXerU$mrq5}I|fxOr6yc3H7#R^$?Ca%>zjZn6RE79)R z9rNwNTUIGqA$@2@g#H)TN0TK^N+r7_40s_o(ZvS?dt;Sx2?1>;Rp?yu08UP@a}o`I z!_O7UP1u@GmucqfuC=e7c5CaV-b#8u4(}4w`X_h(xkeX3wwkz-$BSG;NXnv%d10&e z=U$=8X?SCWVky_EnGdCe(;&e3eD~jS%+W<|=GO%5(U9mQtBzGr*4|Efrvf)6>0CLg zWUIrr>=sYQ=4G4xq>ZiImuXUPY}IUzspa|L`GHIEFGN7Ec^RJ|t8Xs!?Pebhjr_hy zGFzPsp5mBj?8kMDt@DfCD@C;hyvPy>7niXA?0nLAB$UXe9=%lYiyxavyQdLBB9+xp z7F2xH_D}tnst9L&(@zJogb3TOg;7|TfEU#x|toHuf8a{6E)6!%)%Kd~UGf#F9XzDV!@ zI9}6v-7OLT>6vEt*U#Igiy+?Soc<49iZAeC-qK zo^WS0H2*!F%_mDGQ!_6}e$~DP-lK2^$kA~!rXQo-zHF~9q$FpmPK}HLCn-p+k`g{l z*CEBSsv_!XeG7u;;$`npPkci9Win#!SV6#A5cOGj(y6s8@#55a!ji4PNLKA9v{yqFT%fC2h%|%wC*018&)Am1k z{HtMaP=WS$GQnpb2U74p-155bC{L2!h;OYy2_qQGaVW1(2Mnln!rUPrv+>183+FM& z*z7YM-^Sd~!-|oAQ&u3q|BS?OoA8N4{3~dwCWf`EY4fzcDLue#kkn}3luJ-VyOri6 z5`^Qq(+h<2z2+hNM9urStfF=4ydS4^H6jTFu5J*P1rkCLZ#rXxo+~1+SA_?FAXZbWi zW6g6T;pLUE%}9&VXdf={1v}s#jfET$ThZ|T$neTk$(Y`%#Q8eB_&?xUHdsNSYH+C~ z3PT^Pk9QkJGF;Gokyp!CBc;<#8mutUm}L0Qg#$j#JnT1z;c8FWa#|HvWTQL;tRJa2 zheTUDFQ^zR8fS+-3H%O3-qAY)xe<*OJrg7fDyQPo*zR`&+-l`0nkMX<`834fw~;Cm z)fxJKEmTrMo!rHsGI~gmR#B>BX%(bHio)`sslE~F@kZx~Q;u__o8JFwUE67Dy~C2P z&m(L#(DK*>5w-?AVob$l9C_?%L)(b|lk0lEhEPYOSTLa zhN8MaZJU({y}AQWxr&^e03V-xiX*Q;}5U>^)$G2}I_HD^-cC7m5>wa+DWBvY7){{t8cc9ch zGAkS_6fCJi5Bt1s84xF=L~7kkKRHrAyrigiD@!BZX>!-RVZFBYd46NkUug(YdHJ6J zS-E4kJ(DZiit948DT*1^u}cQF>pLvS^9uxlR4gRJA|KmObc$YO25CydGyj{QfHFLz zjVx%xr1&klRWiHD44y(9zpGQw!22s=OBsgu@1l_Jj=uLbwwD!^c*++hypTbL9fzul z`afvx7-dkBS{5I57rE=IT=d+{pHd?0A4G)W>M{4Gu(z?U0Kd9ru@qRdhrLgaXh|Qc z;inWpLN|UMz%oC~G87h6YOa85OC_p%O8vJyIYRrHWH$K*?p$|n2@}?e@7&DEML7?< za8%umS@Z)M4*-k0&y_o_j84rCs%&niWqa)(?oX8oXioiFT1_=RE>2#=MxRqq@Qg0O zRk!1#YnBbPb99e_?$G0?L|a7c@!aO)@RP@16*KbY=gh-4LuKB-`!-e@igK9(paJ%J zgMW@N^_u9+wKYc+*6|3^t=9T>R`UdV?#W1bHS=r>-|kWpMTxPj=m`ISX7h(@rO>$6 zlc@)JFDBhexe0PC+a=T>rOndNyQ#X7HDX}Yr=h@MuNwf0spYF}SxR&>aMhrcTGO-k z^ckJU%dus>f|dhFy?M9sRK$C-H`L;xqIHmxNc$=92z{Ce>mec>v!vzTZ1+vo;yQ2N z?SLLdLlPeC+dK<&_;D6PJiPiO6giX_)X=5DtXg_&*mUwh<2t6bWw%KzW7S_t19~Mb zr`g_4v_;br)2m}Xyt`E_E1V+H{j>ZJgb@!VuJu&ve!epq&p$lyGhkHsVm;8%^q~W> zDI0uH6`&y)1YGo&5ok-cci`V!&22TUvAMGEl*9j_!L?paYeGFB0(v9cy{^InDE4-Y znj8CU^4-i>gK;pb*WR2?{h9( z`GK!>0yq1KkAPn_@~%1B(7O4>zLwW>M|rl*1ag#_&W^x=v0n&DMWwm$Is^E9fawF5 zc$^@82P8I!%`szW8jfhwY{6lLc?SW_$>|4?`vu-h&>3w)H~(_x4-9RU^R7U$h|8T7 zD~=hWLF^3O+V;F`&2=~ANWJw&U;F=?uv5{TDOy|XPIJtiu-ZAFy zGn1JAMJ%waqH4LNChZZ-VbTQp&D5%oD3farRL>)U{?IRCqe?MNZq?e*n#kb2^87ru zg!f;wQky{nyD7VTlNi3B1jOj{uLx(LWcsANbrhUvLOd zB{R+o=%n{@XpYLY>;bX?zS=I~GPfTMRN1l*0nWK>T^i2*O5#>+1>&b4q&8F=@3KRS z0u$u(eCoqaN|`5Q7IrCfC;qfC`DZ^^-p(OkehdI<4M!=R_UeJ#-K!sq^OD)lhT65> zLcnGPr}Sq1!ApDK4*(QrWC;vZ1{0ut6ZgkGL3I-gRn#1ULzWDUcBjcry6pSQrIBC+ z-A_vouz+9TNnhVxncW%5k>?%Dsvq>p%~vTgS~4w2y@i{-t$*nzQUCv1fd0M`L;wLk zA-SDDnHahbEFLNzXPTXop%Q&d#-Hg9j{7lNuNPWhrLF{t-2u}>X#yp`gMFV zI}DwE;E%0}$%EzF%dRnPKW4xNHA2wH`D&ml;ecD%Fv=o^{%_0#_Y2k575D+!u&cmN z+A=p(a&YQ9iMHpKodyjXyro5KSchq;^W1W*c=~IS>*#CIButTaXs};p0IkHXAgn1? zWWCkRIT?or2a~84xiv#7uWPbA@c=jOQ?l5;@c1}vQk%jc@{%FHw8a2{1FZ3c9bkGCe`HfFG1){hEA|@YkKZreSDhbz4U8ap`FGT)P2Yzy93U z2e~ugFTYx3?r(PzD$ZegS9z&lAHsSI_I=)3&w65*XCcmqpsE9Cl^KiYUh=f|hM__kQtm7#Rkjse8aSeX*PaKipFk{l$`X=IH#8^*b=)rZ=L~bNv zP8+~(+@8X=A-zRFp10JVtsS74P#tzTxM|r>VbRUc%Bo<(#iI?pfW{ z@Oo9}JkMOfr<~o6lgl)24QE0Ze>l`^yy+E(R6S_z#&j~fPS9dx0>2}Wtk!2#0(^da zqoYnp@qqhqar&9vYX672_^3$XetsGbp*7eziPEVD9BzU6%Y#=$AU6-^BEm#?wu793 z7`%1B8uay`Zyt1kWmRPjIfk@5|DXLDyuFyVTCuk*^`!*7LTDi(j^njo{byI}Q43}; zET7ka2-4Nan-xt-=FfJ)o23kA@MSc(@i1RAS9-lJJ8L)5Ih6X>0ii|56x?X!;GK@l zb(c`kUcaJ?f88{+2@MwKHv(q`J$;X!4QptrN5vn{4ML-aHOLspU38&5T~{v1Jte}l zH7PCiC*4H<4JWH374SR;%o*~oUrQxry{z9Lkh@A=NOTAH@zj2PIp8!|onm)a*=>a| za$Ip~aHp7&1GtPOfq8i`3m65D>^LHX868#l9uFB`Wy^r)z&yddo@7%))v6fLw=7Nv z(2{NaP3e+GIZ_j+ronvhlm2}0JRa>$aqmVn)NCTp$WMm5ra*6kjGgVk{U=*Zx{^$B zhIz8EPY76x8)!V+d6~9QToOq;vw|8UnzWkB4A4MlT9GAzQV+1a6g0^ zvzD)(bMb6)5cG^~_S^CnHKRf`H(lOFuz2^$%~WZgvuC%<@+KOP~EW5_OJ9t>8{s8gN>TX!X|f(nvd^YA%B>5gu0fO`H|Wdvr);OAE60%f%I-_~ z4}4#D#K?#Q?)5mBy^tp&8aWlU)pS!ro!D!ES9Y@oKGIlRaJkJ8kN<>%lQpXveto+H zd)(p-wVn}ep05*Lk@CJ-B($ysG_uq#6zGE4>yEb8I(qEh8Fr@?m+bRBJL%Hip`Ra5 z4DHgf83E}#JVv^$LqXOT{PJNt8d=-KVF=v*eW4)YIad`l92zVd9(kB#Cw)txw|((9 zLI1039sYmgM@_R?O3*oR;fWtFvwQn1Pt08@3es=u*uwXCj*?ojwTn-;kD*bz#-#-p zt9V2qYeSs!HoPGX!=n(m8{UaqpwM<$oEWTFSBvb{KVIIYD|y9mrS*YU*p^p6Y4f3` zsUc4c@p|811m>G4I{%Q^t6~yh{kP@cK^h8Iba}x>hz)O+(;`FTC=Kb#UyxxL`=gHw zl2Oo5wN{|KSntSTW?2WAD9Tw0EL%+oKje5ig$4b0SX22wE4jq`tedWrMEr>wt12_* z7NzB-b~8SoE$&fTdDc_!EdIbaK=GDU!CRsh4p9zpT7} zsH2OqYKQd|<~%UHZ;cdkT~DDI4xHq+XG-+B@e1FUIf{8aOdP+DV$clweqPgt()dcnFy)54A%n+ z<}H|_?Dg|DxxmLxhge5d<}>d%E(_Rp!AT9ln?%IjsLK%t!0(tJe~ z4LT~XGe@Hh_BP13eA~-t#Z*;2d`URqUsibWeio;l`;+ek!AOWf5t5}WV#JtiCN8L~ zgRD9c=nMDshW;6D`&+#?H1GW@BGFIpmlx8l0t&Q{{u%E3>z;-k%_MftKHL^g2Lj7n zV0AR~!dUR@Calfkb8sFEc-W`gDJ6%qL*iivF|U5#td{#?SBd~lwa!Z1RHFHbK{LvH z)lHcHGBN5r=?hM|lzsBX;{vI>W%Cp$%(OD(8}Q`ex8K_f7pE*q(66Bh%btDeTD!>pVed?R5F3^$~`RZ%!6ubeokffb!oKf*>RaBxV$NNLMVU@6O4A$m8b1nY6 z&(8@i?{!b{+{XhA@nwNN-!;^9%e>0zK!M14QJ_x36Vy(U=2jMK1iCXCF#0_0EfDk< z+)~R|r8%EcH3INyW?cOR@jmz>rQvldLj~SB56{*NH|=b1fvr{M)3{-tCI@T6N>z=r zyi^}Q=cSfQ0Q-;s=M_`sk5IC8b%t>|wHzBtcxrbA^~4bPC;yYtKTmm5%D)(L??8tB zCS?DOo|iVXABz`SyR|z$qkQ27#Ui0-?}48CR{>WT>B|?voDiJzx=YpoTS{V>lD%1)KK)SvVKwQQXwblm!EpR#r~3 z!Z-}maF(JEs#Ef2?dgNB^>g@XcI`z;iZPy+Y%>`2ybTH_^E(+W`@NYrbHHN|mc8Sv zuoVH%((BF4)aHJ>cQ$;`#^dSH9)n$qmO*4c!e;_It6JHPnM~07jl-Xy@qjob1UI$u z3;>;^L|?2f=KR$v1YI>FY8olAJ5J<%)yTwbb~U*T1Dt`nFWVUb_4pF~&JmGxI;z`J zZxaljbTDj7HPE@ye~&oKhhy`uZ^y&Hft9mS;8Tl(N&2=`-FdG9Kp|hupdjdvnr4!v zGZ(M#_yZbL>WUEo<@)aWe$!}uI&RA!*l~PW@5&20$oc~W@&L;HM|NLr^%&xd9KZ>0 zsw8WN+440l44SYneAM#JrGew&h;guO&<5=_D+PlF<$@B)FeY$rmyM_*AJFvham*9Bo;!`SHG=AjbkugKXcLnm}(B$)`M_ z8ns`aqc8VS4S(|AGaLrkE~Bi>=FgG2DVc{ zw%8X6hHT~RYPos~y5Hy(tSa~xW1K_PSZ?X+y+1)lR-uYEIm(LB-;lq93r&-=wtxGB z@}z9qy#ak{Xct4P!A(k6=Noh3f35rbY+^)5v!)s^jKLbZm&V{TMYD#&*%$b zu%17k_Tt}0X8Bfkr`BD0`{bdI&{2e85lV>TrOTb(Q*=4YSqNwhEYQZh`>!%UdDBIx*QS<+)yt@9yr7yZ*9fhLG0i z%rAQ?dQBUZZR>PWwM^tzipNpR=1?ZVi29DOHU#n8qA)YmuJ1k1l*4JiD?SJy3a;qF zJG|4u-AqYR>Eld2%(4Y!Sz&69{^e-D&vI{BzbCNkdMxr5A=(fiimMKXSC5&_m0my= zH*wuz;PNJaN@Z*|*E#CS*Hs3v(dKa6{*XPBt{|^G!5_;d>%=KF*pP_adAZp*R2U-&u;VE*ULLOqhmX6M zWm$YpQ)t55wDM?P(4~hdZ9z>K&f&;36f(j#?my`Zw`)tEpQ^qh`)*xh`-)`FujVz| z>u)>V+WVSJ+I11yHud&`wX+l5babO71ubc)>FOYLm7EgFn(^>I{G!$ z6-mCg0 z=f}@w;QLnuoa{1U)D!}0=*7GSyv zheBP3;G0unLtnunWE%jw*q_K9Tb!R#m7(OfD*v4B3U$e}i~RfLQ2@*pDA)5VAFJ0x z_SaD||A#i`HTS!fJ+x4GqZgK^yyL$uxWPwcS%D0<;Zw02Pf%8$>bn*Z=+eqo3N4!Y zwoC;8B&Cb3Pk8X-wbf={(vle{Wy57pC{0^xkll#CBW&L^=s5!gYWusN1Vf~H@9sk$ zAQ7nXyG)?AUvBi+yapp+Hl9~NHvrUbevi|AGFP$(KcwKPn7(nY%fvvJ^FXeG@lA6H zi+r+mu84W9#G(5!+c5p^s01Asp6I`+Hh;q(XDrCyl+VENp zo$B5qGOf)&5cVXoRfeC}T6ukmy~27V(paiI7+$YEcsI2>UZ(D-Gl<43rf_>1Ht9cH zAPTw4m$R5>;=vBu3bCqBFmFb4CNH6yON&_%=kePd_l~^{UtDbQ>9^gNi*D$5s=zpg3T#%vwN7OuWq9h69tq zo}8q~k33jj(xlT2d->5RbyFhpI@5q@=6cEhpi_D~<6o^RUjU9om3mu>2|E{W&wVf9 zQP1&58$z+0Sa&4Kr_?Q@Qo{!6`{0OC;FlFgO>7r%~Roh_b6nvkvcRmn%?p8Jm z6;Gxf@PZ?I@6DF*M64x9-;Qzthr~c_=yYU?ChI=TAPQuZoHyO>dT?*eKvk{;?2H3weQm_yxg|5H;dncj(OpQ>~{mZW3e?lMPkq&U6A?Fiwe<>T?x6BvAvT|Wx^_)23 zLPge;h3L6^k-90|%;gfHnI4&KMKQJW{9G-}_SH8{AEa-Bz>}`lS4aM@1FAGemKo#w zr0DoqMv~wgq_0BA0lwG%8%qJN0sqUPwbng2*Ob={lIXgB&b!;_$F;mQhDiJbA~i{w z&D?vS3|=+fIvn?J^fVe4J*aK4iS~zse_KRvEOuQ ze~(Bx>7D)xSwetjG~-Vu+bV8luCoc!QZl(ulgV+eRul+elLOv|kRQG8NPK9auCg_V ziOtjfGyzaE8jd^qgs2pY-N@biXp0fu8h9NhtJf?Qnm_oz4oOXX);BbiMJBfF|0_V_FF zVVk&v-_a64@oIaT8S*LMhE4EuIxUT?{_2J5c|HAt*1>s(8j|h7v;ndpk{_=5Hc=Mm zl=WWBh|vJmzr8JeL?hJJp_f?mhsXX8#^}D4&wmi_*ZFz+Q(w7->V&vLSOO1&`D{<8 z*EY1F2`7q#g8Jy{7WJ z3l!FGqh7S_zkBM9Vfl!JLr)dUan{F(6)o0j25iQ6J_z$N>@%nr-r`ub^Ilvm%JO{3 z;yHR9as671)suuS2qv@lhkbhQ_uOk)4WX1}5WMD50xSHTYD{|nABA=t{LtT638X$d zkBxd&i1@BKwB|U$8Z)+-q7Sa-ItG28E&k@Zi2@CY-SCUfYfG{>OJc8v3N;o*Rw2!S z9nj&^4KUDqZ)#WtmjbLHU>7bQ5kBFZlvJ7dze!PviP+y?H733-uC!66?p~0!AN;FW z4xwaaV-KJGc-3+S?SPuCEzxaI1m8Xkp3jV4_)*VunEiZg)J1TEEr5Q|qG)KSw&2by zh@@}ShzzolCAaeJ)B{UAp#2uBGx^qLcyW_3GQS(z=M=P0)5Q{0vTdR0-nV#1AQ9*R zBh~U?~2Gp{kVb^(Tw_fu+ivIszhDEh)fip*wgQr2H>jL zh>Hz@5+5z5_PpQw2K)Kg)|((S%fn4^cl=5Jen#dvY7}^Tw%P{tYQF=%wG(4RRlvpm zLh-_c4B7Nj9FHN8=mBCyrlu~0&m|g~BNSU(!jc}fJ{cyyeeOxoDf-Uwa^Kl`5RxnA zl6l>}oHRjXo8wYI^iPUx#AXDx;^7%}6Snz#VSV)-SRUwrhQ>B(`?PwZU)j9HIzl{(~P004c;M?Xn_kwzif5BDKwT1t8}sNQ;LBLE|G z@wFAE!h+lUt|k4>>c|G@NgBf?0KXI{0xsIcoH!8l?^@-YFE&_4PbWK^_s=wb?C)~s z1zu|iK7|_m;^h@8|XC zS;%4S&-r?ih$&PYy!Q+E9wPqmbwaN2FY^Np6>pXTh#fXy6cU-)fEuGHbM?|T5V;7a z#L_VPBBz2rEgtaPXhPItwBeiiB^h`7F-h;brq}!UzV;8L`0n%FzB<9I$UUOr^ByAr z@Ex9gOUA8soP2F>Kt|6vXTXE``2fJKN;msVcQA>+BNG39Jk`*=wRS-gm~&CqQTo4W z^#A~4D=Yn{Z4)WHwC^If<}&LxrP|kdF=lez$02 z^Zpa`z6a!jOK`V#xqUh3aJePO9M$}*4OZTWDy5{4(?^>PRoB`D0?&E3Iw1(I;aag^f@I7rK_xr`qZ2I(DMtOD%UPx*h74FwDQ{i1+l!;RoX zzehX^qan(A(QGjL`z4(k01XXpbJVykF61Hc`i6}iqO3SAk4pwSr`mgnBJ#w)d4IPu z)e|LQ9L#Nsp-s=^c^E}XO1$jrahYUJ@XS6pOb1^o$FW_@`tz;whY88coMixM_nCm@ z|INXL4FN_=b0w0=0~eph4_Q8rOE~`WR4A65B$Hn(iWvdwC{Sn7)%L;4RoqeSI}%2glWi^!%#%14TRly^0j`32G-ng!S}fq)i9LRP|;@6Xu@OBityyQz<7 z{qo0eDQc!_8)*wKHZ5vO@D$I-mVp>r+g%NcluoUv zzK2gUUU3rS7SZZWK{?wU?oAT{FIGNX=Td1dDzNNiFfP@cYU_r>9;Xv_rMqwqpA(c6%Pd>8I|spT1>bnxINc8?<)5O zKUQ>#vV5EY6B>MxDt5W;V>IEdnWUc0PFE#iR&a!=iv|F2=l**a04EaMpoQ2mb0U2Vh_QFE%|lAxZD%@ zT#wS0T*bxAR#0>9Y2&zC=|@>ExBH?Ztx9RMB_%IOCzcXfv`u-1o*sg!9vit%44vwi zn~pyJyp_DB&fZUFh~!fEq-JsbAl`hDzDeKN?$svVBVW%aLGD>ZqO-2!V;lP z;iFadb_2(nwjK+#T_GrkQen;Eqr6wf=h5C57(rfNVo?IfHY~`J?k3ul@hfC_k6Cvl z`=t9<8J<~tj>Oos8Qr5vz-3l#UkhoDP(t86Q6N$N3tYZv32rKdaztNG6DDZ(Ql~`7tcZ9KOpry6UPb z0haC}UI+K4p=-qAcC${JZay1NLeRhS4z`i}fR|X_ zhlWv4nq_9O-7IPgMbhEfkETRmKUwxSYsYhQK#-^x>MS2;_Dj~1OxCF)W_IcF@Wi3+ z8&9t5iD9}W{$=11r!a^`IJ7L_?P?di9Q-isNMUGFzbDSm*WULppO4$?@-qt8(wTw!35Dw;_B(*a>Z1u*4#O5`0{_;F=B(lOv7@usFO5HCAJ0D$5_ zurB<|>%x>Z^hC0bwGWyms1JX0{W)u;&Ua_2q&1LTwE3>*OgNK3Tno(()o{%)9ir4= z0uh$O-qRaDtpV}#Txti*td;N)i}1PAR^BU{Zf-Amh`|Sa(<%s#$Q~(+nY7MPuBr?} z_A41E@bR{SZa4cAD5mt?}333Dztpp6a|98 zDOWNDim-Ll2h?KfKX{|d_4X=pb%JJs&USU_9b*W zZFzB2QU1f9Vrb~+1dlo`X?B0~sKvEb;0^6f_mSa1ThFIZ*ZqYnor|mScTxC(XwT{0 zzoTS>iGlZD7^wD0>e?^?7TQRgr%4YcFaW@{8j7)rF#B*y(&b8s@EE;PJsAevr|yx6 zlA@Ada8wsXx^uap(Oz_-Py(&+BX5rTpXXab!`DZ?uIKlv=fx}iu<_|0#9*q?QRiDB zTBqA?@DM^v75G4B1srWM=j(7x0RX|j;D8Xr6_2<&aSsb~YRHfL+0Uj2RpIkgRN$yu zZ=;a<_n!s!=jWpUNdEDg3D2*)aDmT+Gu=)IXLXJgmtR(^(67bNMoDvqKAIN2?*Br0 z{rme-o~ZTItSHOV7vzo$3p>YSIDgx_C0(GH%rnRD38 zoLV62H}$u<8Xm;}fDH;(5m4O6i;UIL=-)P3Y3koBVY;1vUi3!E1i3F^w#QBI?h7zg zjolg}=Ev9TV^uo__4mdO({Cwzt<}uyl%Rb$y6Rc4ibSHOO3X{%8WM^ETGJjI~Lj6D1sG(K>&YEPP5jK{qa|0>~AMcu;~rumSivUpTL9nx-jrjHX|mmuFkHrYO6! zBwkw{;rPeFup;GfZSQPaNM{f!E;nz=RZoIU27PQ>9;TTV^&~XiZZ!qk>-{K1I(;4^ zGT_fAar+V^i~FlMs<=sn@*OR#lRf_wznw%V-c8Ez1Xu(259_o|wIU5>RIPi_W3Vw0 zO0W@RQf(50)H=WRI_d!gaPjbNhOm^J@O5ibuELy`5lvu{%qP9mvFp@N(^6DpK70?Q zE1IQN8@BY%gfq<7(&tMDy@~VVjTqB2@X!pAjEQ&%Q49?XT8C1U%EDGN4hoF z$2%>kE@(4S=sp)G>uNvrau0V1Jif`56#jq*e4(HS<5Q-E+(N#JL#WOX(i8t!`n|Ju z{>XnLxxSd;o}RBK(EFLcZ}`fDI&KgyTf##=m)05(a5szwepzWHOw_+6PwIm%NoHOK z=tq@MJSmfGU}b0{yyz%l)NkNZb)$Mh^9vt!>O8gc1aGg047w{RS1gRSIK@Gsu00F6 z+QbAptiet`@9+$H8@aOIH1Z_?vSculREuFN{Fh45 zPdy;As3xTcudm0-0h%57B`6HG(2D^MB;x8Nz6XZd4Ou&!9=34iYIpD2*g*GLf2n|0 zRYOI6e&`}aw{#NA-(ePmrM(C3nMnk&4uYg!1yF$1o~k)(52QOJSXT_ZCpe~)a;}F; z7%Diu?tq?`GpSNq%~N2D62^S6(UGb(Pxx0&7+#$4MHst6D9eme3r`XxUaQa`9&vKv zZl`r-)3xeMpw7JwHV==$#g~bdCZ=9|sn?eHv}LXAj1AB_ekb?&ZMv){{27yoBL!x$ zxMc8DqJypgPutY$!PsgrG4$s2ZgoFFfYc4@3Uk)-*wpK9L?moGiA(wI_>}v%;HyNh zo({CmmRQ*ms4<GlUgOb6rh-nL_QJ&?g)n{kwM-%D8eyd?Du;r=- zC;l$p;0Upu=xtD5+_>K0myz*Q@WJ4M3 z0&VM(V``1oC#iA$mW~2Q?NG@^y0AyUZZsjBOGW z*EA6XamL1I2X=#;wBxXJ=%f787OXn|Iw{AO@kzhrR54CL!voL`M z6j)&Skqv@~$Q?Lg70SZHVYHYAOW9dm(%U_+tS0D(4VUiYxpLLca@^O1pRmROPB5P;o@Re*l+{4QGFTY*60 zoyUS;mZf2#R9R*8RpwaLSl+n3p43Ung!IAMO~rg7T-vVs8YLY{HkX6BYste-96fh3 z=b4o)kTcO`YJgjj$KfOo|3EVCTifo*aM??~Qun}<;B!ZbgNfOgM3P0jc~a7}8fDr) ziERa+lUT_O>Vt}`+kYyl?%ITq7R%F1HK3p3Ct!@%lPm5@yVpPcha$=KT8&wl#w zBtFFLL!&@9g>Z1F?Z=YCsufykO*@fQNlaQ($^5-8u_U`X`B7wm--P2{>>5zR&Jket zFEq{P8858BWube)a4(>$ckb%9oV5k_f_z((Cas|-dmVE>H?G6Q1{vLK_znseAxc(m zE;W;wMGKpwOX+E1M4Iwaxh4U^S@O^?BZSd37FtN9Z4Pd($KX@x0~z|^Bon+IH_uq` zy#gH8oMkd8u$Wo*EL;xNq&e_(fSpF<@AFR*`D$0&iNmw6|Cxk|34|+I7SO|a+`P`s z{;(1T+hqdNK>Igq&M!)(>ZXt8j9x;|6vqa(IwWeSl7C+&UYWb67Xn^4UuDnQ?&OWw zqYYvOI<~g{vKg#Sf#3tpM7o~$HeS0LVVrEs=dI8IY_U2jnYHB|Mo%hY+9*{xY?#Ym zUZ~Q1Sid6zdu~VGD?RPpT>kkl`8*%}#vYC6hAatXNl4x?^7VK9M!PmF$X>&MUSajkAKnBOagJ<8aEwD(gy~n6Z|H2Tiw6 z$i{WMre7jLR}N)6fi>)aZNeX{inIB+uC7ME$H&zZY%3%aUJc!+o(8kPPIXdXCzv?C(;KdG9Tk14q zHoMa<>D`nZ$aQe*`N|21D8u$`gaagtoh>>wuIsP0-Ws`KG)S}zwV&Q&8VijoB4gAg zV2T)obZ{oByj7RN+}tbvN&9zw&eZRVR6@Fcr{@wYLJkv)ay57_XxaX#b58B~Ri@J< z9XriAttah1YnSyK@9FkK_T{<{vWl`&R{=BZO4R7xvFsK%hnMnD#+65N!9_WAZ9eOOZrtI!Ys`S~L? zs&de9ZQ;V?Z~*(VNbvz_%L3$`dvwOl$nV{M!IaqP{ljN{eQao}*}o#U&B!KuDN|#^ ziqpZjIgrO3a86=V@XZRK9ro+DV0 z0PtUauW#4GKK=YcfsYzwjQeG^|C=Z)0&A4EDC;hOLOZJ8)WX>uNG#~7%*PAI zYq?h)3TEs9Gx#om99QV0DEKd7Uo7D1qXFn)LFmSmE??3#l94e8r1Sx)DGlqa=5~D3 z?&-R%GKKW>GRcjKY7=yFcFCXuQ-!LBuHi=*+doijda!-h7_83;-GuOy&{Hv3QN!~m z#YGOM19Vgu;tHxGm8wk(b#XE@WrCW?2xNYi3=39i7Elm zBRgDHe*sN3L3MOPJ#76<@-#C903*p&5xM6HF6i4<1GMi%llV;XEpk5rBx1@2rRNwm zU+xJ1Z2KHPSNqDccSNwf#ZZ=LVY`F*OkYPV{u?t5D1>h76qdbHqVWo6l8 z-07!&peKW?*r%?POK)n7G{P^&32DhEWL?t9l1)1MjkXg4Hwo^P~qsAm5!$gpQ zOD>z`5a;9a7w(%7zu;}=0vl=Mgr_~OnSgN03Z$Vy%wm83!HN2z7Giovul$*nwj|6o zg2ttj)@m6aNJheEWxPtAP_>MKS=4#|6z81DvLACC^D1_ICo}~RAgPN&n8P7&%P_O2 zSRU-NPc*1o-fl|cakGjv&fuw9VcmKPIF}1R=Su3WliM~*0b}H-u(PfdlZy-ZocnD_ zkoqp7m;y%V)Hw#2E10K6iG{vZ=(%^LFEtUnUa1hCH+Drxeu1`c zSIry2J!!ol{6O=R$&(M;mlAARw zRdRBuS?#PR=i9vo7^D5hh20`OG=QF;nO%lyVU|NH_3EeK^tYxSvgbQ5A9I1>JS*VR zXXzuV8Zkoq8Z&Db-)s7^dspFQXAf#=$=bO6vZ_2^6f3b%sTAA|N#_6mvJCwc%#GW) z6xNfI1{XX4Y4M+8RU!rf|9692AoyP(;C~wA-n-4e{+~l};0C!HD+#6}-o%ev@oU^i zS?!CJm7X4HMB{*kWvJL3De{73zGR!QJWQAI*gQdXHWcT-3hQH((x4kZ$8-oY<@oqX#r-zvoqbz6h#W@TOlb35@{k7!9i=)%eT#x zZP}|+=TGtH-4X1rC&UjGeU9Kz3U{GGKrBVX6Gycu_X|j#b~mHO{pu*&Q+~+VSHJaX zBf|cMFyj3n0dUh45-TDSPcMW3kiPA0ojUumeY=MFl#u76G@cz;Sy>JTus?YwUqY!S z1Z~Jedf^#(KfR7Dt!5#i1GYuwH{P6GQCu%ypC*X}yS#4W47odsNkH2nk}>&{WdI$1 zBK)3hNo(Ns4*)=eX-WQbGHGx4#_jIdc-VjEBA^d@C&Ga}=S={ahJa$^jRM+_!u_iA z#QED3f5cYMj}G1S<|f80%*Xt^PfHEo+mci}`9IIO#Q+x+St!6Uip!0G*7hn-PcKD3 z7J%!V3kqOgFB&w1A$Jr4{*8lT$dj?X{k-*84KMfUi$pi7LQ6E@yzlZRB)p6qz^hU6_QGr$0^@d(aQptenyySNh-%_RYVD&$3|u9t~~8hhwV zWcVjUxGQGQ*Z|@94p|xi#Yns3lJ#*3W#>zz&s}Ri+e>9-gxkrp@e<0C{nN;q8#=qkJc7-=FaS{D${LKzMLd8{xAVN$ zg}iHvw$!wnp`&&5ty+6!4c0=3&UrzKrMz%dHth%P3DLNzmfV4XD@p&Yg3q<6A6U9g z0yK_ceBgD`+n>OEgIE!;RQUf%C4ZH*6ydk-sOI|?`RS6|?c#>KGnf76VdKnA1>9~1 z#icg&tK0MhbGPm`ThztRA45b~uEg3(e`d@WXbNLh!)$HB(wN2M2ZF?c27=Zx$i85Z zVxTt#NoApxijxg2Hd{nOT=C->=R928xFO@*73G7es(YLbv$N~~8F5QIK&6-wCIlcB z=bJ_-ZXERCm)8)lVc2)9+ zie%bqvEDSUjqEW4SK5$+-1Bv=EdJ-2@0v_Y2MFtF-&>xOFcISSH~yPQo16URPp;W3 z-7giNt2^Iyd>sgzsYD4X&kbCs2aU807AI;7lWn^GFwC1Ie>bZoB_^bqu*f7O)}B@T z;tHp#vfoIBg#|rWkVmB^M+#FnX$0rbg^??c6bFYMXGB6F#vU4q$3jBpA;#zP1)bCl zst_P51c1)je!lR8ulIumT$A(xk${_l%wvQk7~-K^M4el3u+dSW%!6*2C|sm3Z-C`F11 z?A>64X*Nf^M1hvrD?Cal_dO<1~Oc@h$&Kpc7M1eN>R)-laXPN%M{>{lLk``NeLSXA+QYK7)QcM+QI6JLtz6a z@}C6A6cj3By429wP;3{5+N_Mkf2b%EexKY+w5>Q=61O|y5=@QI~mvn*dA)Qds6v^clW&gb9HUQGQeK;Y zH}9+BqP>qJ!*^8KM#lRZN-y!dC^e6nj*uIHt^6O-c;5g;oOoy>DH&ySfSedT25wj? z99$Rh^Y5+5tm=Kgu3mueL=szKVT^R^1IvXD74+kIt z!eQ*r@CM;P3z7K2$ppFGOG(~AC`#ptg_2d*l&iJHCB}YI0Dq}6|@cmSfY;?qN&5Ld} zM`*Gm8ZD_OZ%#qo+?w9;XMXD*$UbUaZh8IB&n ziq1nuX2OmE9rup}u<<5GkkG!BsFf#$2~Rx>755d&%fdK{Bnq`F9Kt-;^2qkfp}=b^ zR9GmEkP+qp2}E8flrTKTw@?E9JcC%AfB_u9%o{Z+41DOZaVP}oE8y680}6288?p_} zZwNz!0OqpZgC*{A(H(q?l#XrqrhFSJvomW-r*2!{Xasm!mb$WX8 z{v___;2_F(dg+<$JC*o3XWinXbj`_ZFD`0TN{|e8py>!5g`t2x4mO)<=6Grn1sU^- zN@|Eg%y8gfxG*N2(m;g><`22>(D@m1T69IJ5;&<`5eea7IC_fkxU@9HH5O6Z`)Q5u zBm*dP3lIS!G?TG4LIX(XTV6!n)MScf)U4RV=EA!aFlpk%RJLnG4bID!r)KSytKMO| zfkA$udLnSZW0vrkfX!hvw45kKFQl1aG=7nLQZdxLRX}e(>L#RzO*D}=FDly15<35a zZLD8cJdZ*}p9=H1oeGN?&iyC*WnkFp>aUK?)D~T$(c_`$p2Zoj;X^lNM!gPd`PE?WQR>{#sl$BEVCdY-pUjvH_ z9ZM6748Ew1aU=sAJLv$&^D?XO7cGmOqKE`tiNXZ|;O-(l*2#_P>^w56$hL6$Wz85Foy>=GT1sau%9IHrCA(c>4 zk?qx;Td0F)ju3crVk>t;+w8SS17Y$TDQBcCH0mXwAP4@SBUx5L3^K=}!{mp4M@t=F znZKagtSNjXTAA`HH)PD|ZK#Y{Iu*>OwF1vOO$HuTDt zYg?Lk-PWQDM%|I{;uLHm)`spZHu4&7XLb3rv&HfiC;_C1zCO{s4qLy~pE zDhupy&d$vH3}co#H@ci-(##{7Ok4hllwiYQU!^t*3{pea<}d;Dvc^NhluO|zoEXkb zOyZeO;#vQ!FFJ5C18s+~OnU9rHEo0OB1UfL!K7P0GBH2W8?$ZsALD^Z6 z$O)6U8~lfH$7tKn@ttE&Uq9BYU#(rSytObGTMdw9l(8|-4-2wAPy5ncliHK?h@hWzpX5k<(H zdO336+daW@*_;RwrxoF6Mt)!;m=XTm@{Rr29+xHO<=MHci}Q?Z3HHpgo_qk z2G%czD^vOQ^{geeOi{7Uo;~@mB!Ao#)Gs3Lq#u?-coT>{h$&}=X{Ab{`~0fC@U5Uq zSKBJ{Q+SLj%G1~(jJ{B+;-4-zp{*(eZrP!Vc65F5y6k@-&VZXsA=e3Nscj`yk1>ay z1*A9RK5RG#?VjIYf@tToOfu*e*a!=Q*tKVER%)95 z{HUpj{2uugi`(b`GgovlI*d(iU*q=*VbYWd;a#NjqgVQ({3Rust#)&@O8sHT+{enH zmy&H`uR4Y)ihzoM$bq)LI1`pgMLLPIO-5U~^d2dPP6%aeLqcci)1CKLNp#FZWx`=E z=M;k1jROL3#0c!E^rM-5zAv(Fp!yG@iT*A;0{NRW9ZOS(N`|y?g3J@dIJRVZnv2*O z%Lx>CHj437>bXC6lQ|vJCx_V$t?n@3*!pFiqP2RvAHQDup>MM?u-m5mHR{;#(l`~C zm^O^nPPD{`upCY)xU96Ca*-nU@rRAsM1}2PZe^}*ecBW663z4b&`pI9`p)h`OKX}3 zbo`(U1j$Rz&IjXG;LXkIXU60sgM}^YB3_cBsTq4+Bey1uLqX)68uxB~Ky@gaN^I?J z9xpZ1e&Ji{*hNSfwQg2Q2mWq`eSW&?)<&oEb!J;xGesZ$Gjj^Hqh()5lv1O!Hgp&k zM{U_^8OjeEW_x~1Gh1HphC_s%3SSmh3s#c)P4Mc_!&*I1zm=K>j)J%V?0BdMU9F{8 z7U>{OKF{AWe1=7AlGbmuXPJL5v{4pu&4cpl(`p0$;+7N8jEB;g?;>FxR#0Cd^Agjx zWyY+^`KE@}i4)u3N?~jT;oq&iw}-6NcbAwgRHF5dzcHt9jIWX09q;i;{e|69d7xjc z48ki{m`c}_75@IV_C>$`Y0&4)khm|3lL@sz7Cr%03Y==bon-y`oH)AF>3dStPEgOX zxnhqYtT{zWVzSyuh*oQ56|reFwRSYdl97<%wRM)jaWqP*--!&nby#klJ~8VyaC~A% zFUrgIiZxnmsGdYE>t5dwcy6lx5DqmwTw{(AHnY9H+ukEsV@4gW2ioqpRhlDDt(u{F zuWd$l!21E5Gs-5L|yQjCWY9+?KUon4WvO^*Jz0+|+ zkul;ILhYy-8e>9o^9q_d3Da~INi}Y|(I~dS-j=u03a4zNB*rD#ukvE)9*bUA_O7o{ zBb)by+x_Fi%n_C2dC!{K!|oOt?iR*arwZT0%j}u$@NOnH-*Z$$nru;iy__ZBB=eAV zbhz7P3xOT`jT9W~I-QOpK|i9rm+ zzaLaEt7{#Eb4m8)wa>fPoxA$Xm>rUbmVEUrk#_LyLe{SDe`$W)Tn3q~J#TF9jW_#z z?aUSrtDoMjc>DqFoZ8&0UT?N(kmKQNK1*A=RvGq$tNyvzsC|>;%A?cXL^pMbvb%r@ z75}6GwwovP7TR%MACo{{GIB<|h|QCMl#jg%Hg|F672+arpYSsJkW< z#|qK!QT2G{I>h5t3{7P>354CM!X;0n1ozunB-cez!AfXSK8)bJ>}rws>nHFr>4cF+ zdr`|=7kP9!+8D9oFWY%6xA{bCEiF}%2+P-hI`>1JsIG5=Oe^Dj&;ZM+kNw=QUhC;Z zlUi*ZioyV|Tb9+ioXN@j(PpC}oG7TS$xtCd!q^KWQB zpGdqOR;$i0QH-?kq&6$T6Dxa38v(ST{NakwJsaJKPFOjDP)^8e%dPBGd`%|~&FrG_ z+q_{NU(xQdS26pzRLX2D<2p$H$7yz!Qlwc)jv9A z{?JiXY#SAR=F+sa*>?GXq@{n={q+|Uasf%~|E$IcmcM=dTwOGgJbGaW?*3vsjP+H+ zlqz`3zBe49vPNMPbF^&7p!EqcQ|}Yk=#=Rdkg)$jNmiTneQRq=;Jv>;a3tp2zXIES z_QeZ!snl0LWx?_z@Pu*MRCBhlzJEdm0`^*3Ta(hE6S6hIR+m4^YQOEp%Ha*(svA{n zoo{?BT;S&2<2fw2Hcw_VP^A`yrlU<%3pToJ>8nB->eL_Mxm1?2!1i>LuEXiNSwej* z0{OUFU-8x^iC%qBa9prA{62;Jxpr)Bt4av%zlZCenekS6d)Ks^g*s=wV@gfd14dK# zhKcKgF)Dn7LbTY9|55gS7K0}z2dBMjjjSuSk9ysxg0(uHaZ+tb1KWx=f^P_>b0mj& zaf<$N)Tn+_>x$4oLsvEh0L`n#*^T*QXfrBM@Gff0E-+h+m@3z{xC?%+>9Kx|4LEDm z$jNO}qdKu@GHkB%!i>CgFtPRq*I{bj3-yMMaRbqK^t zdcfZpQ*U$%_+F8z$Rk?p;H-GH>x97>6kYqeo`*^=O{BsyFtTs(_@K?{ z`bnYo`^p8aq}&BzhZ>HZVLbh%0;8`it!bk2>Ec|_^M-yRN5NgbJfL#2;rlX{wpsA^*2!4aDore#7G^D1A!*CT6U@%{ zkzR+VD;#ryhGR(C_z-cV->fUy-XDumnbnfSPiu?vMjJo9kiO^>!$SCJ@;|Ba^Hvx~ zIeWLv5j8bE+~MbLR`nw`Mp>fz?_U%EV%IOa&fdW|G>GBoI#Q}+>Y?%2;1uY*%9C-1 zw4k`t{0GsctzYUJE^YhAt&VG{IBe2m80^8ntinD>gP#rQK z8YvN*mS`Ao6L68axpldW5lpBX7r)`Fy0pEVfWw2Ut|1c;!0_4=zpsetwa&es@wxLD zl_?lw%V*IkcyG&f@0{A;{N2`z7qM}?tf|Tj);X%u%B`WoD!aTyrM8>@{L_u@ zDnX2xk)i)n9g%Nn7NckHq@|tsw_}I@r(0XMZ&Nh^7olhH1uDWA^nR2*#2ZsltQjT0aDiRBp`-#Bj2{yLZm#2Urzi@U)i&-sn zT1v?AV<|c^7*ePqOLb<2Xyaubt*;s|E%(9Iy@hls%nXQpdb6CbHx3SqzOJsmPfjVe zSL{!=<@KNOlxH@Z&__;G#)0C8D!CP>XpZXmy77IN_UmtMcJm)^6>c@hfim&KnV|z# zi(cku3m049dP&V=e4-$1x)|4OmwV30>!1YSlGyD6~g1l;aN%} z(GtaPp&uimzckmnPD8h}C8a|Vlb>X~9ebW>f(r8~yEjjB9S*`zEzB|V#@ZHZ8(Y7( zP5*RlI8b77T~S)XdKq=Iy?(0e^8wEC_{Q^12cT-VbE5iO85~^)H{HPIM!`DI5ezl) zM^?&F+VVz(Ja}nMl%M?CAb530R9#$LV}jORdtPA2zt)gq1H?2X)PF|Zz*M0wj#St& z4?=pIX`Xy;H`KO{hVzY0Ff*~{w-+(buzZ*jsUF zCuBPf-G5)a-yYTVc>~cO{!?~*HZmPiV&G)4t=X-|>N*)vLTpe-4iEQxT%BBym{@2q zYi#}SieB&m+>U}Ea`*i{Zp-t#c#FdUDqvfd28vHa3E+0W?zrgdUGvj?3AtLlFl0>T z305?}J$Q@|tI4q;O$}R&mK9MpuKth9v5EK8 zOAhMM8^2sCPm_jH1qnklRr*VuIhawfob@M*-~pz?WgXxC1W`Xwu;mu^x-cItHlT-` z1lmt>?Bq{=diTi|TCFR4i7=Yvkx!;hjrLnm?Ht=Mr~ z1sh#{y=3E>GYWacQH_uXhTi67`1T#ROmlojQHzL`#HLA;vXHTm)2K-Wm9X`sJJN^X zrq=zzetLawm;Z#z>h@q^fafEd<-DG;SI^(dY=2ytacBHf@efA1ZT)bO`@rTGqAs(N zW#lRCux`Hdl!=-1%l$ENOP`O;3~T~;hmJ1Dt>$g$vwH)KE}7HM-djN*i%YN<9sCvP zTsMl~wVbS})3U7fvh+@m#Y5(YiAG*mTsh#0g$2A0Sc)GlB8PaDv@hbE zx^uepk3U9`HJ7nZ-bc=P+qzq1;%Zt;^f&gJt7qYS6g8dB=b=(c$3GFHuXcUrO_CH&pFN@d>s<~D}Mg>w8zaBNxKGm@3$42*K#4?`ns)o#?C#B zW71Z^g;rT15SLMN?==nIWJ3pQe#Buxb?E*_73@%1T)m6ReVwEA(GaL%Zp`=F_m^)Y zdy8=OzPt z`cEuILAM9IQ9cte!1BC0?g~NG=(2{B!JVak0k#Ubo+y!yYqgcmof`XQL&!Pyq+0$$|mIAT=Zrnng!26-pX2kcClR zWS%-=CbBaGtFr|hkL+8E$9(r@VMQoQFhH)^fj_ z&EvZW);j!p=QeiII+KszXF!YbfUH}8EZ6jggo2Mt)qwL4{g*%%423e_emsCzQn2^U zpT=u%gzbdZKLlJYqJ|_qd@>0(i;s=rv(uw$iWiPu;@V2Ko-trg;_4o+Cso<&9@*&g z65(1)44oXH{ImV~f4BgRY-6C3?)8rlvE#4a%+g?hRM7S=BfumEXCvVP93uY){)OYB z16DAAfJKN{ZwN_QApbF;PH=uZqMnQ_5Y-xk!;K;#A?4S5Af#QV*U9os>Ot3U+*Gg}LjAxY@Ei4QT z4Sj|dGLL+q)!%ExpMm@@x2r@`Rfp+b&OSsUuqW`M<=OYdq%%8tlA4$Lp(SRqb^M_7 z*RT4He724Hv{T-_KVaA7u(CV|E9~aix&ZOeoie-%fnn#FgluhGhq~=$rOm2J)DMnA z&JPm}j+zV-LQ4n*jsxl7pp&0o67KGu?HWu7-q^s7N?n_x|Tf7hXlo zL&;oiQHE(+y?EBjtl7Gw`{I%s@{eB62Lf@xNFEwEdY;! zy1FPI8=4v#iz{u(K29Q&6NdHmudp%wxB;TTPO+;lts6ASgouEG(r-8B%!((^>Svq! zUT=J?sF0$D#jm0%nw5y!`-QA+c8iRQkJwO*PBtIBE4OgSj%@L0D|&hgu->a(DRSO-r1SF4Ca)gMEGC%}xV`ovRJ zr_?kLps$ocrI`jm#H4B-M&m7N1!?em{VEl|&2FO+-pJb!rou z4@m*8AM9|ZS@#5T2ZFl0li|RIO^GhC?UE_uRQ$G>Fkl0TT|C8vm%B2d(9%s%B|9jqxs@wwb$gq zBYA{CD1|f;u~=eC=WfEd%EXyV318?*pj> zr_q54_gS?B!18 z&TR%Zj$*_Z&R=&&VAo+TTmG>63z-DkEcoD64lIxzJ(hvJFhHWH$23U(x!!J*om$fm z{F1Ylm8)Yjf&L3pJITVao9X?`Su@Clqe(0^#U&RxeQsX%pHYbdZ3A{Kv!E$77VUds zFyY0GO)dNMK7#5@^G*v2o+7d*fEogx0S!(l(xCTW3mpb`--=UkPhTORhRY3?aqrME zgA0dG);t6GGCQp7X!-tCbnPnHeUp20oyyfaAuX4+!z4pw6J~}83qJgIc3uz*q z3mwaj!t<&ti7d;LJ^F8VZ%<~hHGccfz{Y|tkw8M$HZEYxsyt5h@SOq*vo{AW7E{Q8 zB$C8p;7=}fjQ!!dP?HkeGnjpJ-OEk$slG!yH;e0RrC?=Pm-#J)J0CG6qiO_9&f}f_ z8P%XBD{GyvucJl$u1qH5dLtXZpKDa%Lw03iU4Qb91%*K-Mgo8alDr-xKzy54fL>}g zw|7GI=k~f#LVzF+0*@WX?d8^V9fueTba{fTcln(MKgM>&f84C9hH$Qt@~nLwrGkb0 zY<%|ii!8{{cl|>Wyh`Q`028$YQBCJtj=##Q-o2Vaz(a-lLG=JQXv0_n%)UXwIy9*F zT;Rihq_ns@D=WddfeQL=Kl|6T-}HjZJAQivX510l0xC}8+1lvk;*y4bPiYZZREDgU z6fV^7`KG$o>+9WbCx9)%V7zdmEMN7G&8gq@&`mIUFHR>V6-Nu@q+-CEnXeS7V|h*o za672p-W}Y6pX$G((2ooCgDYjZ=1(yLZ0dt$JJ{2HiFV&h8D5X%@mPi!Yn=?|JHyFu zcQ1HveUc_Z%p*3Ri1N1F#|pX2x?$@!}E}=iXL8C zUkk1*0>o7|CScQ(%JrU?=Ch_8=2y;`-joA`yC!Dvq)s!nE^#GZ>v|M;6NU@?8wyS4j}1|ts9`D=3_so~O}g!!=mFS-rLz7^*)Di4 z*PB|c8Xe7}mdkC|YVE4?$VtL$?GyNY`aXK3c{7?foCWq+A5pRI8YhC1a%N`_nSzEG zLQqim%Xoe+t2q}Bzmd?JwgHR2Hhf4~!C-P6k&=9mCl$2c)8a@2C?mqRdTnI-6h(XC zyViqk5v*2u9Nk9igCkwGxp=-fssK2I1O|l86F+^zv!rEI+kkR~htLQDZWVw4KUhEb z$XrBw6oZydGG1(7NhRa$|9LP<*G3xXV%H9FVS;t7IXOh@OmU_WTWzw^D=W?8e=P_! zaMk#P6xyy_asl;72&n-8D6IPALa@;yfS#{%1}(@Zr+!Zgrx0#-1h%(qn?2>&{+w;# z`mE^uq2j`Y)z-O~T4l+s$*vOjbUkuZ_-1}|u5S<9{4wU{QJr95V8@KM3pQM z6ZDb?n+>)g35%NGjzb2x4V|9|COXC-MSz1tSk6QS{uWm| z)ZMe#ZosoDPT~1D?>k*dn)+gBJ`*Sp&d*|T%_ptO7i<K3(Y4j*V*M&T{@ zAxEjo4(9N6yO_N+hn2SfuK-9DY)1`;T!Iz95d6^c(c*OD~j@O(n* z2hjV(U}O@MEE;i74P<<^a6Zwwlq>#Muf)CP3QmJWWvl*WY48euGN}FKcmV_O%StZY zc?iI8cJjj|h&qTYfCNYo+$nY)&=gr-OQnul)i<>GN2kLBy{ackJm$kc1=u5hBSOd73dq@1dYrjd(FVN~}vb+=$+b0Bm*y-z6bo=8u@=6eJKRS0g|x(|-f z<5}4Xgistw9@6l#2l_XRBVoL>&}Ka#?8{Jsxxw8jDC-jc`b$A3z_-rx*CpHga_pP= zYq+;{Te+@v$6wk%Qf1de^lnhzz6=a#Xe7?c=UKBde zgupVzX1H52M9aY;m6;@RN9g|5WzHMY2LT+&soIa4x<0%rsF%zd=A9Q$`|xzzbRHt> zA*~<&X>>ZgmM$>i6lZJP_kd#u5mu;_Ce@og+)jG+9;pl(M7Rh6sTll#;&57t$cSvU zgoe+nV0^XitGZ>3pKC0zhnII{*R_0kx6!l^=2yj7m$O7UI1e2*)0F3BtC5HSC)#J& zYT2%>-exn9|9R*<3E5HRdB5u1J9UGSI2;f?Pb9oI1V=MMa2}Wzy7n1Yzz^I6Zw1(0 zWm$h%o+5|AB3Zh?ufdUGY&! zJu#d?ARM|M8MzoR96~!cJ0pseLjy};QXT)o^4KvD8q zAb?3tk&;k7<}JXq4}_+-k^^qhNZQT=h6S(J8lLEIF=YFA`; zexW+iWmVO`Zf7IX;&D@^)8(Z}@&Nf4j7yc5>>s^bMLUmw)g`}FCjUvkjeTk}-I1AN zqr^{*Oo?3F+gaVVi&T5-4hyxE_~yQ~F!vSZ*Q5dH74y*!{55o6Fg^8zpL(&xENGFF z`Ih}Y=mS##S69XTITdh*_wVg14>@dSBhZ76`(6$4II`|Oe5A}i{6EbYCY#xH7dls6KM79JC215$YTlB1@`7ty=v4{igdfl39H9@{p1-$cbV-j z0pS|OIAdxm$c7+WX(O+RXOaIW)90wqzVJzh_H)FO2F5>A9d&0>_O0e2-+S5p0S!FZ z?d>6?GU@tMmKV6WOoSrd1>R5YMW~H~eCBCwI)f80?4cu1W`QlpHR*b|5zk?)$NaHk zNzl!NdNZgp2TJ4%&XTFA*9=%K2`_gvw~D)&By*!sMThReGlE6!Ii{> zSZ|dnkA`ohrqS2s@2jr3cs)nX{=K}(CbU=iyZa1=SFRX9`6UzLHq$EG)H-69FKb;$- zzzhoYBH-}iwUIRkUwkce;QGhP*`OA4_p{06bR-G%7rC0jV|%3Ev`)A8ETeh*0lR7E z@X2-O^~r@)pkVN`GZvM;f}br&nV7J*G=f~i+YGM4a;9H~2ux=ErMvdB#H;3QJkb5!jD)Cov^g-`;tAVWZ9wU?jB2XgeYiCWt- zx$-M(mA~0M{4+C?=Iy*42ySFr9`~{UPhcXiH%{~GJ;8Q}YA;VjJ>Q+La!p(A2p_+T z>HAOTAh|wnzHxyN>1rP1(9w$ZRY!OuSkyT6Heaz}+Y_!{-0K%O9ISbG*YE0E^sk8I zj_P0DquMio%7WlS0QT~8#ArR5jVz3b+2+5T$}(8iSm}N+F|8|T>#<5OWqUY05Fc%v z3u;`qB*3a50hhYlk(oYEklkLGHvKXLmv!%BiL6#>xb8++be=P;?LXPd6{73KQEA+T z2GLygKYAZPwdsr1i_Y~6<7F3R@f)uO9$c9Va~__>9v77CgHB7n&aP-o0*9m|4}hMG z<`>gHcyip6m1dK=LxkF?RWogNk$6bzu-T*SE7kNK<0FBlP3rxqpU=*2H}X~ezllOFM&tohSgn9+jv4C${>|Nw+hCS~d~Ao6|^OP%2FM(NMR~MF=Oz z6lq4%+6$(V$_c_>g#SuxVGVtb?Uw$$Po4O#sAss-@gpnq^VOVlo_UE9Khh?yo$PFN z*0jjHg3u~oVlcOUPy)>R4}K#9sG6T1KEHVV+NdE+^l)ZoZ*$VT)RDBlY+Xl68Wp%FGrbHbb~EpdvBhyx}nNfzb&PCR%o5COmNymB{X&r{XO@^{@PwsPlWT zqg<{1TPx1}FV7vce{2ZK#t++=-4~tH@Tjf-fS2*Wi6%%-(X6}SSeS~q0<570&=b~k zHz-3eMDSzD7n#$yCZ*_!7~}2(Pwz8=bDQZi2HWsV@@-oN@}toRJkbS&LQC#gc?H3{ zt?EYiQW$v(Xz();sOL1h4Uq?R;mz-udhWOQ_7A5;d_P@Lya*tBW*$EGkaZZFTEJUt ze_B}x3kk7{j*)JaG#8qOkdu^UKMFUgVD~NsB?g8MLw0{ZjW%!k3BF@9^<05meIW$j zU%#hbEJP3~-8zN~8@wGrw!AK=Z~v#j0XSwJW#HNHjr!JJNGea2ec;LGc?dOu7hD`V zBm|5K4uGXhGxojm0}vBDe4%PzcL_Q-$g~KXH~0ux6t(`5cHmxoo;rRXIU{OnS*rZi zTz!(>J34eWV3(Zn6>bZ(x3u&0xn|eL`PqEc`#1(`sS849TPxow1jEqQtDt_+3216F zV@T3L_h@5^`-rjeKHwKUq`{y1c(#2cnpp~Q=>qC#j)i(&M8t4)UE8r0;sm!EbK^z}t868nFG5ah%>Frzl=xRHoEm=V>Tt~bVO=JCl_ZK1q;6rkpqFZA?YW6>g1;L##LSI#;VOs)}Wz{J;v6@ zGNadvAb$|{6>sFJiLv_R9lfuP8Zps-gSwejrb0^rb~6fRh=>sk^cIb3IFtOSFXN*4 z7i$)qsGOooXpX7i!d%goMYPvsr;n=)sU8kN0viGnU^}q0{YtwqS2?EpA_PC!$~;-V z>;#odgKx|evGH=o(}rj#nE|>{Crcp5S_j<}-y8_O5}^n<6IfR21!lizdx*0+m;l?m zT8TZ01j1V|b2=!uY^1Yb`sIYt(xOLZN{{Bo3-@(o>}jO=i49)&3+P}oaS77~=0%n1 zjI6-tD8biQHYAi37l-iPWtJ(8TCYLk2l0eE8Zw3l2C%l7L|!(;o#;1Ky}6j(vh;Eo zSrr7l34F45y@#M0fSzE_R^E>uUN)iJhGOJ*((DL(x+G&3QrIpZ*kD)T3m0h7e#ptI z$C%ld8dGRWScYri1A^#RVsIwyU(^^;3H19wY|WPb~U_LHChwWo6# zEGv0zb9mo4D?F;3tbWvsd*b!qYha=JoZ@=zpb`&!4o8#z*wEbIbN{lPmQ>qIgXCpQ z{K)Tt1SZa4s=d$#UWlNjKPZ2ho1&6tm1dMxK2ma_lvYW0h+<7IF@4E;4^PEgzJxI_ z3)_NdbD3zYPy_c&V0j@y=o1lW@}H2by`0t>9WASx?7C%WjXr*u_ev(6UY#qbTveGY5@Xb~~m$cxjkgoJhiYC|az zM(G5r`0zMP6(+3pPGAvCQ!9jhgZB}Cu_y=vn0a+v(@Gtg_jmF{$Td|cDQY3}H_PgB zXWLz;*gm$D)$d0E56tX0)UClePz$Id8nhn0kpY+*WNq+8it+u;StL=e(OEgSgl_R$ zOnL??opQJcMd1&{M6AN$Y$C;v_>)Mwzotdx_}N_Ri=q%0?+itm4_H|(f0<5 zbcR(n!J^@^=S9ixm};MAQY1ng-g5Hd`cHm*J0Ra(F^8&tmfMu5jZO{};%~+;lUk9;sBC5e%8a)7erv^Nj^`&WCBtrmN24i#&j>HQ-be6xdN^o(Tol zaCuxqSxsgOZc15}*H~mzaYFBmU3GHI_zw4;*qyu|{D!(a*X_*&HpTh+LPsb3H9hMd zRng6UCK!{9@KQR<#!wL(NCq%r;%I(G|KtasilEucM(R#A(z|A^9Q8r6`_Su|K zWOiy_3iwjzu8$P?EY*Rdj;d9#2{7#MUlQC-&)%kIu=5>lb5|VrQbIY}mP}8!=lAd7 z{V+zUrCC#CBrGL(zD3YytEZi4URA>`7<1l;XCwd zZRA2KtEsiUE>(MkAWtNL9iSD8;Ci3)al0OT&O37D3v z1l@QQBaFIdvJJT;1x`y)+U1uRRM1%F^F$Q(9Y$yM#bBUwYBwD1a{V^I^aZtV4fXqi z2;!}H%u_CZ_!Vm+b+bnocXgpE(g;lzMVpP?=uiw`TI2_m)}CyjXznVN`NtJ#GGH-S zek(T_z)InKIq!`^H8NNd(nf-ANPyrfUIa-bmA2$tIQ&Li^+GG3{wiY4)1a0~Ij{R+ z?fDD)n}FUD8Q;qT|MU2j7k+=p(A3J+4?pwPI2Gj%`z=y}HU0o+!D&ds=d{5}zuGpz z%5Shm#pP6CvEZ9F6_Y8HrAMRdtiBc$FCw&g6sRy);<0S(}Bt|;VLtdDE!`E_!bMGHmjENpJ01YSN#{Nuo7JX&$YUvIP&K; zeb84FL0+isB%Xc87_K)$u+1m(I5Kxnz!-n8foxrU1`z?8q&L^#QqwZ@sHodAWgMx~ z0`3N}QBX)_mS^d4xV_8S`k9Soab8TrXZ?KVRlQVS`Khd-ijc_CN}>S$C74j_>?fAY z(dk3EkCx@a0yxsPN|(`Gz6fp&FMZxUF=`YoWdP*q9Kd0|<9b6>!`m5qS83XYJ1eDE z!+YgkQhQJ2e$@=|aeQK=fA4wU?wvfV^{7YFlc`X&>-t&w%I(XxC1nB? z9nSNR0Hz0-lN~*WcCwP ztC8S_c4=|3HjiqNje7IQQJ(_%E)+$L8i}Mx)l5Z!whB+@7jLosqa%9dM}8kn-#7d% zp3GxTb!@N8WUzS`No5JMK$oPEs6UK9qRM;DyE(_u6=#Lzz|Dt8b17uM{3%~3vs4DgZB=rM zyYDW>2{^Q?%)b)YgQ#HtKc>Dis;Vw(_nbq6beEJM-QC^Y-Q6h-2c=VyZb3jABm_z6 zPU&ut2I)9=`+oPkd{SrZ+;jXv=oyI51qdzohlBo`7nt{&Nzy{l@tEc zzLI6JD+R6isVVWa8?y)jCVryo^F4Cn`Iqm-`F>uNZ~4ARYX0M&-KL;7T{DL9=&Ba; zd^c9JdpNP}9YlwoAEFyjRQLsjZy-IhoSTMOlv8g|bm(ScJq_$Qr>5~CMzbKSjmcof z3pO1_eXYs9ME2+&_BoA=8oej2T*b2LmurzTD+{sx&`gh@b>x?a^v*CiHS!(-lTzR` z@FlA>^J%g0UOhD3^~tA`E`3{D@;>P^O4)_D@V`$+~=PNWyq(!q_2uY^;Q;!7Mg>i8aLJ^ps^42fr{oi)F!!6)8_JQtjn| zk3*2(f6f#@853r@z_I@Ua>;;`erOM4XYcvtdu8*Va&rB7o|zTJ?mUX>GhdyCzkN;C z`EE7vojKLwcB3Du&S}0njRehE2F^WT$xLm9hWx0h{M%?hRzyUiu``^}q;9%$!HDe9 znvPTJnv!zJ+8C$h{A%DuCg$3QVQZH(U%;PLDr1Ooh5uTmS@8A}lWq(N&~2qu6x=xI z1$+sIr?yH?MKSSgd5qGEHVaF$qo5|a$GwREyyFpk!&h)YW@+f(%Fks2EUGMe^ zDRG`lc#>x+nLNSJKOW}8P)E;!VJD~2)al*i&C;He;A7eB%C@l8OCuOvcb+8 zYLaiJZcl6>H6zB${SvNZ!ZTu=kl|Pz+3S(4sxl=o1Mxi}aj()O`!@SZJa}n6vFbN2 z=5YUus!i)pm1=t_qXv&}AKu4!582NW<99cjv=`@t8dvO`mA?PpWP;sG1nqCD<*o7g zMj5aFv*om$0>;0%03YTve|uLbF#>OinyRt*`|fYYs7+&K+N@?eow1jKtbyU!`@b7g zFNTVc(n7HN^K0O}d!sxr*m} zoj2&h55@cAi(uXg{U*4 zds⪻d~AI?xBz^Z$N&azD%i`bv67=(oXHrTmj{nwVMNAhEzCHOseHxL&sUcX=NAare!0~<0z-2WVQ3ehVF)HLE-`4mXn(Av@p6l+tNjk~xtji-(e zPN6*QB6Y-CwMKF5<9<(q_Y)>e7$NJp8A#d~syTIOO2JP;AMFnk@GYhvVoJ-w(6*)~ z5BImC&YPxQyU*k`Y|1hoN?DiaGv-r_^ zU7i!Y{85Y7R zv-910u%)t|tWg@TfQK3+q{eaw7gL}k!00&5YMvl(5F_KEih_^2y8<@$2J*if0MS<6|_rW*im{p>@-kL(z}@NyzzN; zDiX8!Iz9MJ7a*~OJ{t_P`^g@^i?E)5kJr$xV(=ksawzsJ6qqZdrpG6mvXcQfjZ1^m z>`b7$WME43w?6qiH~B~Pbd=-~eUyaZCH6Exkd!W@m+p$Ty^#g%B}TgxH)w0VGx38O zrsYlPB^N0GD;jWK|0ZYDerGUNyU{Rx)r}7%E3B@>X=i8QR-njnPkl^XgbkIQ0~bL* z&j+0518@Eo>hhuW8~bIlH_}JWh9-~aLkemRrt!M1#2}82;zdI}>PE#_wWo*qI@nMq zwOGAqYX0K+e?sF<;~qK(m_tw$qAIu1aI7@(A(Jn@XbkJtn*^}Ch)@jN0lQdUWJ82J0mS+nJhjCxLGBgxG1Ghc8S zjjEmCnT_CTaiv8>KD3>d$Qzq`e<4EP{jKpa?nq<6cEtop%*yC!x3|($?O7G!}g)k3LfgsQ@a=38U+W0u{{S;Ksr3`hXH>@}|mbxiS zw`pc0qao)`G5$MB6I&f>vwGLrLe3{qa8K?~I|gC_;jm6v?pdL(LN<#{p9b^38?A~! z6~C@5bu^lngtN2hVFwx7mQS0DJLyTK8j3M5^8hmFq*wLN;h_cK_QvyGtE}SmYH*+y zQc}QAf2m|OsA&DE2Yige6#>XL+3)37`uU<*Gtz0>_@W%dwlx~C8fj@4xHJ6s)BL=h z7CiQ8>j`!q=6lAvN|-8Yx`;6?$vU4Ik!Obvhu(ar^LVgM`@b0s9cnGJei~vypd6oB z>z?7bS(D-}>TtLKIl+}iWh!e%m-m8rx>7rNP0ZCM`WQiLGXK*PO3>5%skCPHGfGc3 zbdhxn@O=&fb#8bLJUu^;0<&0bWWH36|BGrlM~o5NQ%7xP9fuo-y|c9IDRZ-gKkeS` ztlqRQr>n4bd6Gg3au*bq5r1g(={CQ|wzLa>kyRavuNfRS>N@hGtpE4My&WF z9kFQp6$J-i%es_dJ1SixKlqfg0ZJ+@x%K6kgUtV3^CG7%-o583!4!^D5p}J!thTu% zM*w~W4{)sr{%azA(TK3L&;RJSDmbGuOQuRmS}L7Jl+>vlgjiafJ`S{9)LehFYd4gZ zs|kv(wX=L9kI`&s%hF%Eu6kj4Ct}gifoFgh`3FR*=+P$1?-dQ|%!Y+s^5*=Fa||LH zza2mP+0{H`U5gRQTDylE83AoztVsB#o^DBBb7p@(`1Xy5p&}k#+Uu)ypNHt_k1s84 z0QgbWR<0qh?~c1h=a_R-`M_-JYs@YIxEltH{fMRK#bSO~tXJ#V#n9-l4dr)&Z*#a5 zWfZ;ar4i_+`(+h}j`)iQ>QkS;DzyUe>2}Yr!F=SMg*0 zr@F}iMske>UJfqW+ItP?E+?9K$+_CZVYe7>{Ci4Nt8BDOOC33^3{9-Xm+`f&B)`-cyv2XBX zu$f{z{_15I~xOXCInL;V~64JV2aA{x23*;UpuADLwN z7(S7q$;6uM=tIbB>r@@^Z8c9>W(*?2vi5e;KY;l~u4`6|N<4i(RcRR_I76(e>@iXg z%#*HWKpWDZ_%QdZJ7){9&K(Cbe_)2~8r1J|W(z6;KL$`1|y zf6s4*ZL4ihvUUcYTLQc~RkRPALu~w(Ix$K^g7TLXtyQq~DyKZ6a}&5rbwvU&3R6E_ za97C1QHyh?c{zvWyJDsK@FF}Wtt!_hovTj9#a{B|&Zn!bxQxcLp>Zw%iKvG5sTjlT zrReO7pn+3U%Dbqz-R=ZtJT4Dwd?ZxozVEsM#pMTEfC=EzfYPBj>-LlqEpUhjXFq<6 zWd;7GSxt=4RLF0>HHgyJ=eb$3ThN%hc-xD;@^~>YzI>$8CG+F(pPYyQ`yTpqrp9d~ zyNtWr<0PX{*??kjDDFW(UyE&|&N%wjlIhj4czrTBd$DZXTKrVJ{nCuiQbtDbcbJ7! z3PuX=7y6i@Aa@m9pC*ynL-_oc4{p@iJOYEjHeCPP#>Ma4z>6)oD6@Oom+xhy=v(~b7iixbvsZ5B>Xi|aa%7CS`V9R) z)lUhH$WmT5U+O=D(^Ke3pqV?J3D3W0#l{#l6`d@qnQBXj~Q1c-jJL zOAHcBeTwoUuRp=z6)1+|NVH9cHH2H>d1rMwJ0|xxy;b50dg-|}#(KD=>jL=6VW4!g zlJG%|+^s3TDI&UgA-7Y47{!2|JFF=TB_2g4{nb~u;MB(~ZQOz~DNq#etww&?cZL2` z&&s}9j#%b6RD31vgIKeKU9IZolji;Hq|HgM0ggbzZ58Oh#1ZO+;rnt}Bwy}OU);dr zA=;*@Z%K>ueOjVKi!@WdLcI*0R#e!yFpS*Dp)9mQg#(0v0VmX?33HE0e!e&)l%IFj|YvrG-nGw*drl2Z^+=5$z+v1w!sfE~G0m(MMh|gZ&hJj><(xr7(Jw zxLv;w^b9-_>#-XYqCsa417|8-5d)n;|FcBY%Z&j*Y&!vRqScG8!KMAe$><*YLA+ig z?4T@1bN1Rqg&5I(39IX$mH5#y%#MIPV8~6XLB>vxm&VT8KhLXV)Oz)MmCf?Dh%L8% zA{&a96nf7KWc3Y%K-uCHw&?`NOdw&+8<&=$-`!xo8K7`)2 zxCz5itd!JrmN&AAZyIKFf?#8~SpQ&dY)Taes%`r)KXY5BCXD;;=W7u_E&xO3`%cUo zKJc~Rv@@{_3UC*t@R?Q@ z%+YPku=b`qf_AQny7~5V(&n8Kjorxw-A3wo$p3xo^#=+yN~Q0%Blb#LlHLjQ7^x*) z*hrOCn~;>@gj`niwv>P@PWVY*#;0{1tX*j(*~mV9SprlABElX$9x1(6E>Z57Kv500 z+s9$@%ZSG#z#^a1bZFCL!Im0q&!pkx@-1(kPJ-XV{1<}FlpJQj-kXhPbz^9(dh33DH_)Fb1y^F*5q5xPrJob4wR?Jx@9w)^ zwW)=gX7A@)SVdU6VF1LK%JbXhCLYXUfPgCoQzR#)#TEptT-xbo6^06%LUXRlby;ykz>VhMaAdd!% zdS5j*vG7`7aCU|F-D$Bwkp%-f2pVt$Lx0wZJp3##$A~cB1B(}bh2*go1ta_*1lxym z-`9S+qT6_1MZg2zH2jw< z3S_~q3xuB>q<}p2^-A+LDqi5Wt&#(iazPEHj6j)UfwV!zpfgg`{Jm z!SlmD%n6n<@INoI9Qi|YI;s9UY{(vs$q<23TEaT`uJhM%@D_Vspt~6K>XFY4!n)uH z##J{p>MhBBa9^zWSr=gRwlJ~p@Yqhu;8!`5qP|aGCJs4(umi6i{=45O$H6=FrU94y z(^+cNPCnCbdf@W?5XJs7g$Sg{b}N_sHfZy753v6j0l~G`s-P9LvrKJnTxt13`)8#! zp~-?2NGZ%u>jn|(wGj(C{+>}HAHCH_sFQ9{*Z;I9o;|8zj*mpXyR|!dd}90IzTZqZ zdd6fJ;W?WROz6zQg)2U)ALxQv9n@p9;HS0zJ&+o=?_hl?=A|mv?^?}8)wDOb}VgLcVW_*T1LPEMZUpCk0T7e9EXmPn8gEjUj2acD^B=Ttv1?;I^WNh z{aKOk55sN1m0VU0(qx%AbwACkyzPsWOoEGjakP$B4h^Ad&o6xJp59Mw?bomOx?ll5K|UIQaov0p_+#63rQKdIts8_@`?=|4 zK~?XjgtLlzb+ODjXC$g$-qZk?{gdKZ?5EX{(&~fqw~{C?*qox{dLDCPN+JN)UE^eI z%C<;FT+R&R$IF$|IZbCUS9P<$ijv5M8S^l5z>gG<6Cpm!)oYP&D#h1JS0S3eF8je+ zH2BW`Jz2I)4qV?jLp=Xv{2;L zdc_M+ag-RP$lOkgT2DLTYNHAKhfu-fODl3Z-X0qJ5uWO0G(`!#l9rA1PLP(MvW80d z8&MDB$2>u;nZTR(Y}dhrsz>kY+p?@iOqxSaZ^i@cBwWTrPIMUwv`vk=T0^dU?lO}) z$o1Bm-pTm9*lBezC;fPSNVr>sJxck_3h`Dhz%WP1_sL$r9AAy4P3cA_tA6GZVRlY! zl3i9;>JMPd)NVYb)^m=ivqB=^l5To~Xl_2xHM%9H6)(vcre9n&_olY6H}*>oZ@{&t zy#d3@!oEtEbGnfsF4i8;+5;Njh8gV4cPooxTg z`dvR;i+Phr4vrl!J`#lvEElRYC{bGGE2fGbV@hYvp`_Ug$f;mozc!?m~F3IM@RlTi! zu@|dEGKGjco`6I18zWuRj(s@OK7f=WkR&!(wN6r`a&76VQq+9mJlh#=#M(354 z)PX!gY~$xY4~!IsJAGkkZy@gW$5{A^9J{F4^>i|lhFrv!`q)htqCYJeyesiepO*(d z*E{;Zro?)mpK=0X%K7QdO!j@M$3Q@#bT;c)(3&$woWBVAZxS8yyz7E)T4oGRKg$7HGVDRM z1Fih{kxo}Og$Qwxy-Dx+@bD&vA{Ux2b zhH_U{Md101Sg23{ulJ~ji&~L}?738D5ZoFt;r9I=J?4pl@b};M)?J8}+vY4zywc9m zLmA>sa;o-Qz>4J80U&gnx>ulF5}2IuFMqvFcEV_shUr%>@l(vsTS09hpO(x#g#Q+Y zWtN53ObP_xPO9V9`aA}#yp)O^5Gp$0%){<>@21v+SsJdTSe3>;o2{bp4Y-YZIS^IM zL33=d;aDEDUyEm8^0W4P+h2W|BZYwejKI3Z#WSG=1u`FUz&W$JH73V5dJtBxyR~#g z_o>_>J}^25xF&Fd_i5*BZExT)dvy25U#o#ASDBAjJOpXUpJ;FwUAx(DD1IpB*m*Ne>#<8a=HmI|(Evlq|xxr6}G+_3~ z$=Wrwp)}Wy^=CtuU;2Ffjyl_?)Rc_q{<@v?sy$y+iQ?4v-dT4={<09&$9%5?FQt3P zbqy-Fn}xG?e%)0_3=MdO^=R*r*yW&bq)aO^^chmpq4p#rKNc60boH18@3jH>it&Q& zwsMzI=&9_=4O?~gwy;_~P#OxmeL8fB9y$4ua_PAXP~BfRHU8ybl!J>t%+}(T(lHPr z{O_rT9D7%D2=+vA7NBn-M=N2TZkfrRdB48s^Tz5su*c)tb+_fe%p)f|zAx>3+;_~fTV7s_r@K(Nh3i$3jJ$6U zcVK7Q*;jnvn$RS#6o5$4gjMG2a` z?2uFiedNQ*Jy8;It1A$J3-ZR~0#$4r2kkwh5hr9?F-3!t2$9(3cUGTcAnnDoo2c&` z(3(IvzgG-cju30KkOM;3tnJ_l&!RvpY_XTenk$qnCC}>m-2d$b0QvwEEdtt>oQYX5 zxia}F{z@%CrI~0@dFV+=s(t30Lz|@+z@t7%d3xFCt<(O0-HuDyF&IW6ykD?wa&Qo; z^qn+t;62aCQwfjXV`u0InW6AV>a3pcrc0+sQ4MbG z;8%sn{m$(uFo^^a5-HJmZFC8qAt~*K@+IrU?ivmJu{aH|*AuU%*REhsm%i26!zi* zLUeae>*$myRB&N>KqZ>DnkEGKRgd5t86 zx+KW{O5`94unfma(D8B`Z@bMXiRi-8lr!wsAm`6 z>Ajv<>9m`B{!eOsKZtut#4eV9ge}-5{-7~hZzIraUreVocvUh`!GAgW55&U#2REe0TET=wH%!J*exZ_!abCvQhh+W_=jE!EuOlRvM#7J_^u(Ss((C4PPzkJ`v zQU@nDHON-Q!j+Cb+N}Wuh|TiTC$m=kKAjeU>JtZ~wac(0^@Er!mLitL=XM$Z$(Qs+ z0YqQP3lLNpShl{IV%Mt2rn}%!u7(NOyStP6R1a%a5nc6qGY->pba#)&;xUlg=YyKX zO@nqo8>+rF^{=;q@UOHjDBH-@G|t6sg?)fW;S&Ez`{xVmr#TXn#U4FI5bWWg_Q=%SvzyCTGu z>v){ zy}Lk9K)clyo0-DPXnUgs;={4*-qWk;5qoa;-S{E;%;s?vSRKW=zo#GYZ&AB7*q05h&ArdxktNXSx@&3>3Ui~DKlQbQx)Q;b!XJ>UUEFG%Zlv3kfP3*9Zd#tRdTtE% z%Gq}C)kpsETmf|D7FGT0yHCAXoTI-mW-k01r=Oy!sISkN8#B&5Z=8TuoYBPhEmxKp z^wY`~9XhTfWet&{n>;S)rB&tl{PANnjv2@vrRBI>=dQ2w&Y|s!&^6-QL;g}Wl&h2- zckQXZCU0ARLeZi}rM>xBr-R?2$bEcsa;D>Tm!!E2f}ARcd|fSl^czF{OwPVO3&-Ee z(8xW|D~wZWb8^S(emWiISOe)lTA<7n&SAoBQ%ij!x2MvYek9R{nFC`J7|{PC{+y!M ze(mX9bCj{oKcTpFeYU>jjN;Pw3!INsi*>zumC2u#@}}bQz)!vlJ;9-r zN-xtw2r9`y=fXqFyE$r;jDp62BA}@l!v|8?`d*>Cnf`K_zww998M2`QLfKA$wQ-11 zs~y!p{9&zp28&59(qoA30&XZa!8!9+EIFFdh$2IiMM9CWcn>KipEaX-j~%$T?_)Bv zbt)r_h1~IsTmhgKJY%3`QZ+Tts>`wPPN^`&?V#@qoP0{|V8vmMnlxg}z zVXkoIA>eF^Ib?m4KeB&D=G4fn)kHv*R9aT0;F%YB+Oq!!=I5T1+q`3Ep!piVH5yZE zEvamo^1XNG$c>kndc%aG8U5_;-bkXsQ>AO{>>|c2&&$9!7&CzNR!TCVKvw~1KK+Lq z5}V?k4Lq(mTmp@51>Nmlox5JYV8)H^pD;ucDEJkYE2!TSyja;^hLa~jROwwHGzINL z6HeGv`O!%t_QK?bSbM456-jY0kW~@XJnu!t*YOw&fP)nAHXiU0N=4F&lGGTPmgx$S z4}jaMD)XAf0t>0Db>xS3E*0q9lR@((Vdoa8yw}N$jG6}B@0D|CsHi!@uDL+tmX_8y za+owwlNZjB$Y!aKT2G)|^5uNrm$k7rqChpT6X)nO}Zo zvujmPJR=5gjIc})78lDysBAr|^VHY`=&X3EdIVQQn&WD_D8;2-LE+A|xOhOU`O_)Z zu`(z^1CpbXvAsk(j?zX|@@X~;&%eRP0S5@e&+V%VuobF!bhWlE|J^kV=VnKq>VRuH z=fE+1{r0kpBl`C1=bB%4lkgo^nFD&^D9CXHMy>{YBX)oNKpOEbZYEJ@!4E9}5$ccV zo5T%Bl14EWLlyh8eUEVk$J8qp7Lc zX80zG$6`Lqy8|M`j%UkdAVysGpiN0L5X~RZ+Ryq?HE=6>wbG5GugCu(unnw_JZg-E zqY(4Pi#c;d`Y`-+Wxt0~^DDIqaYL_fzZ* zI1tTY^-zOqY%4R9rB__@3{_EEW=re&Os9G3p8>ZLZ1?;U?fv%sTh%&!SAISEib*)iP$x?U37PVBo=|$aof2iWEKR^YLp`v z{Wa~s-~ZmM@2%()g0dQOP#fo{!OF|y8FW;b{6`VWL1!VFiIZMD<~1{vW%+r*hlc+Y z7fdLP6}cNPpX1d%S~(q_N)YP_-i*xLc|-^=C$R-J!4c&~D`YAtdMC(ezDqpvB2v%~ zUk<36bql_ccn#H~pqBH~$VJq#FbtRh>@?MF6B z^Fsouoy*L&Kt79`K6>F|WVdj7_eJ{}h#B7I>tLd^gC&722Hbap?q54ZfFCjyjeue# zkQa7@mjs>*8G=bzReNS}7kLJ5HHY*eP$y?5S-{`CqC zQwzF7lb?yeUtf6XAe{{D%lvt8VhyPd*)B0yzVaJ?%Zl_Ly#<6#G;*c_i;G-*ie7mc zy#hGn(X>hiDIXJ-xb&_ z&^C!MF0gVRbG9)Na&PrbcdrwN5N-Qy$n}`Zj}-Tb2OPoqhG+Ve(lF;B6}Nw0u}F?C zo8?Qf#U5FBM)ZQf+cHbrK5lFxL5`4cP)<1ld*>0Kp1k(y}mf7$LjXDJ1XRqja`73=gi63Pe;r(=&{9X*Ju^q_#&&Z zzG?Gfv@bFnPaEg*~jb$bCyljwX#!S$SBK$U zS`FV(7A_6lK*H&=^A8YIk&b|S$#X<=3w96XH_FPD3R+pT!fABE76T6U%$>@fpm(EB zKkCsGQ9OvS>gcE~JylcojHQ+g5S8PVx1_{wJKdkoFOQ$pF1m3aFaDjg_2QE!Bv!<~ z?cs!w_0v);ow&oV2d78d_NIX=&pUhwVgGM?{Mn&56p7GZ)p z<`!$d|A)Fdc;+~+s393eKd_Nv7#IP6&r{+Q+4-t|AH(#2+G}14A{LqIgO=x3^k8#7Qr^p*hK_7gP_@K zK0K^dQhEM%#F^0Rn#;}5i6{CRV06e5kas!IMP_k{{3JK0&i)!>o#L^VF~gi21G0~O z8|m;US+kD(3B=CLD~+rB8F^lgnHwAX+o`ePIwk7q^i8)S<&CsK8V9zAEOEWMlF@Tgjw|JQ8|LVm=j(PNVSewS zeQez7(4*ASpYsMu2IF*;g9dnkOLR!HGw?t80^n+~N@Sm>htZ%C$jRK;!<^&g4D;a* zKMUFj{GCd6gcQnRZD#SRYH; zdS(>mW3<<3ChmBNW?nTBqYkRK{jqwz9r(9^PlbvmwYnnnE5srl^sXSZ17_d7tCpYh zY2y2#MuuJRct4*Kmh0UwO<2S}w>Z2>ZCJ!HB*Ed7-WcVmAK~{R)=T|}USeP9)Nro= zT?Y5!_Q2zH@z9}Ds>INbAzv?oSPY_ONugZ!73zjMT?pi7oP1!7sr67h4CsO#&!~`b&5UM3WjK4s{ZMV}Iuf zd7GF6ls#lDCT5WKeN1nEPLEd1v4iO*C!1(LsO8zn>azofJpFa(iGcPBwDgAz%nUDx z5B{h<2tT9!EuK#d;vRc=$RG&uWuKluA(&vs$N*r}6+ZdlE_j)%m zG6jE^-BhY^cQ)NE?*tf~HTCwN)mG&-2p@3_NDB;S;VZk(|2`2SIOc#4#I7!X=XAcJ zlyjv+oirp{^KDziAwb_JOMK1mF|?21A@XX8kxo2{Md(!}$dmyp zHgeq=s#m^nT4IYY`y4{o6+~sp&J``*D?KS*n8B#4F#)M*=NAAeNT!sO3O>s?Sk+|$ z^Cq_NukM3*c{AFzO!Mf(wUt7yg-1S4S%s)PMz9MWz+hv9NP3vhUe95XGySu3Zg=FK zX*ow}fe%Q~Ki+{tFT+8vx(+`EIAwqUpO*0cE3KQ=NF?*M6bKEPL2QtwF}D%)Gjg5E z&fva<_AS(YX3Z*O$@Jmwu4ROZEfn{o4a@!P6|+ zZ3jltPn1Y+^#r{4cFU%`5QRK{CnK8A+T@O<)qWe@ztW*&^m@0+cKhe|o@O@mPeT&O zk3=f1VFf_#uPp#30$fii)CiP?IRq!5jRi=}>SU)PR(N$Dytx^ zE1&`iK@76SZGUN1qcD;nuGQ56_nFY4PX?Tt!g>DcxsGRFH~RjWnl=yks8{k@ApX{Z z>F&~UwpbP|MS=a^m~AaJ7z?2o(>315Gy91M>p9oc(A^KVn+q>r9^wc%z^Oy!HR5{? z$g>O-Du&3%b~~e_Nc_|QxoEdKUfINox`iNO%(qkH$p`HLK{c!ey&9K*3kq@v26R?^ zw_!Pfc2kZe7e2TB~cE2uZIG$rrPIqts-*I4w^z7PRianbX4MH9>q7 za4NT-=f%45D7}L#z;CWupAOu8KHlyuRh7-bHs1O)iW`ztk5Pp5c7@a;CLCJO)edq# zPtc%?I5e5aX$@3LiO*UtexJi&)E!32AIutFQG;MlB|pvA zAI2s$x^}l^jO~+%WC#VQui_ws`!r0U;bXb4?r=aA_}^c{|1u;3q3q*QhE1>B8qbDg z+RjQcq*GUcFJpwMFE>~gfjO@}t3G_8jaFlx&it?x+>rG(@~Dy!%TG~I=TM8RVD@)U z-9f=MuZ9WO_6NZj=RqW-a333XC7?t(%N-Sd?*hRfEE-vAiJkP$qM>da$~5bs(*xs3 z6}=ok-+RlON*ln>!GVb$a(wa4-@K7U#Vlc+B|G^P(Zo4+4dCBG&&WA&xP=`jGeHVg;1p%NY+`P z-wB0@(UI+FCKjY7@OH%RdhKn<#j(b6nj$iPvzK4iE&IEm$XjDFwqkASFtEyL49&2{9v_R%he2(igHkf-o~E}lr4e*s!W47rxf~8fKDlkF9<64MKQN|RCG*r zv96-=lpen#6PWlUH!kqw>szbGjws*Yr-W~pxkQA@UQPf5wqKJu8;B{)1(j-z^yq%O zBZCLQ5aHt-J0i|roUC3MWwUh7iw`bNJ%dvxRwaZ}8KTRwb)ECbb^`G~`8*1Llpz?` z_Z&|}0tM`tOTbHeRhI6JckFlr)sqUx)p!H{M>#iXx&7}3?YEm0CmGKu{-463?P_D! z`6y1>eVbSjUs~8&h8HS7eL#v=11sN&E=qfjbAh0Ye?iXuwh-t(sG&c0x{QumZbx80 z9*q6#lgW|@$ZGB76RF38{}HeRuIFq8Yu>eTBqhb>7YbK4G5u~T^RsstAm?|c3mkKS z+Nozo{kAsFD7K!6IepJW`E)rjKecCnGwnK{i80!c(5Kro zea>5C{m^%WuJ?b>CLW%RI`5IK`7Q4HanQk!zJJs8imi{~+iR`DC!U=(C>bZ+Z(ZK9HGU1S67N6<>`5{~4@^I)zPh_qoNt_ z+)96LPJ+%Qrjlk~KrR*5$BDsCQB_mN#hd$HE%aH^%|1wtK zWPdpnre*JQC#fY84uzX|RgkfH4O+NZZmjCm1Zk+g+~7^a2fG;GI`>c0NW|UE@OXp8CeimVYf^=RIDdu@BGvB#sYL7rj@TkLd8h zcvKzTY?ouO7Lu>wNclK6-XySZFpYkvf<-e3DY2i6Sq&FAQ)J{!1P6n8$cz7O*6-`k;=*fz4C_QHLQEe^qwYuh?! zLa~fJp@hVg-``8g%4~^J* z;^SEmUhr~Wl$RF;mQOfL0=oQIzEb*v4)7qBeX`ZJ9Q-a$@U zf99?Zemr)K86}bWm{9jP6*i3BM+IfU$lL!ECPD3S7w~X72eH7o6{?U06^t#!XM5BW zksB+JvZ)B2IHYrScy-rTPs436ll^R#j*E5N)F!ka1F6A%W(TEwGB%EaTdNINB z^sXkd^7Kzv3DbCQ3DZP3Et?SLSe1&7+tKs7|EtcYy`CsOtXUUizw<}6O&hn?S4w}I zFr2~8utQgVEsSF_$bu#1AWc^yCPbO8oC~plQ3M3(Qu$ViNaXOx-tC>~QvEo?zVUE! zy)Hv4!XB@ZdqO#cuSV1Q9p&f% z-V#2mo#ou>Aca20m0p}oko&Jv_>e+mG52a8V+h^%XzN?Ks4KkSonb?#G<+9_`LoLR zP7A*(ykT#j-XyFNnvdE#m%RR)bKX(GhX^>OY$$)Sbv&&ZpU|hj%mQ`_$W~v+wX3RW zU3V2m>MpYVk9X-tTICp3Hhizz-1*2+yj;)Z|P6H@a8nQJXw>5Fl);en7vkLqQt zoDo6LVM%f9tZc)*6*To?0}y2OphT**^;?GWmOXve<|0uQpr!gxQUoBOnFCPp;h{F{BJLS6`JEQ z`;La6g>(h|GY=M8C!f%*=zi zdj00**~+M(SYRu&9~nF+Abei6u4=;Or2k>Uu5Q0BY-j*K3e-fTd;pezgCj?lYLpms zeR1|~?kuN!>825Hhepv)!LGq0uU41RA{@6rxp91UJ-JIM#w#55u*G(9J@G_X>67uW zT*V>T)ztcqa&Wd!h0!2Y*jsMhFH;I+#2o$>859Kh&_2>6MMd_>Hnb;`o0o|RY09!w)S%H8@SAX>pNRg zhnZ@J1s?Fm`hK{oPgX@B5D*Ov3y^2(p#M)Gb0eXkqDZ`tGGS;@^?_a5y0R%~vk~#( z^-9D<$FAA=-zJk?^v@F`_P?>tD_A;ZEWWy)YLD%0gw?nrVOu;DrQ?E($dY5;6el}4 zIylk_i~R`JVFFFsI@6h>$s*}#;y9%LO&%vX5>(dvO0I=e~R2d%hp* z&w8G=s!>&=dRBMyK(EiO`C~wJcn8Z-KHTAwLJ_;$Il~)$f#gJ45k)@C8%bc;==Aw#oR(A{EGG`)jlz&%j{6e=v$FY#XOwMbshUWa!5~)}~qo3kKD9%Yn zZQX~W!fRzAs<~YgQKc6PwA|-WlI)vJjyP~&CQ7E0r@29f__!@E^D1iiTu+`@5k0xOsIEMSc)E_!MXH5Ix#LYOtc*2#|d1Fi0;uRMG6KC%HJ!A9Jp6sPyBhuLW z)`j18?}t!GAiEyg4A%?SZlQ{@lBMVR4hHXzKFa@=Q8_frx1Zj7rKp?SFK{#!8L@w&9+Kby%V6_JmvVBT2jCMV-p z?pAs^=JtAmGxTs1tU5tH9^3rlctb2iAIE%l`fN8bp|NVnSqgyxTzXtjTKOg>1uR;Z z=X|W|)rNvsbkddO(C+6Wocw9&ruqI^WajHQ_u1zlLooUrogU}4lW1~hQ!QV$!7+F~ zW;s0)>94OnEflbMaOBsy1G;*PJAPi8?!-YPcGPwdnkZ&6UB8u_a%YCMt+U-V33A7#;2oM*Ac<9&0!n+%o_O+H8fgF$rYlgmFL}ug9~TPC8&J+g2pS|2pTVKbD9~|=rnyG3^vtwRo zkO6XR;!aD+ox%7&-7GyH(g}E0cLF=&Gf)64 z7baPL*=H9L0o%r=S)MJjMj&Ov!%OJE{%uyxD!ee;Onkh!2&Y(gi;yoj3%a^=B)sr# zmLa(?9??ZBNTdjUeuECG1`rn@sU-JO*ioTPf2Bh-x)#OO3!pp2W$I4Nd+l3mCt$ij zfy9;0?-)~9g6PaE$j50-E3fZj2{lf52fbVS3JSO~;&2Bwy0@olD``nw8K*$P>d`#HSEp&m&GidlMzrb;G`s1s^Qo!^zCK|Y~bniU~ z^sO7{NJ?3D&A4n<1UP$?cVy}bXg5JGI-?84ENjr?H#jGu%R%J%Hy?M;JI9|)4xSn$ zPk%QQ-afBABmS{^#LJEp2W-tQToCdJSKO>_$mQ}EdhRt7Em80(hivSdX610Joipyr zIuaYJt$Nzh9f8^)(BzRJ(4N<2!Qe31la_Y$g`(>&{YGTaqBqJ9l{~19kAnpQz$1je zC6er)_fD)QGe$;0ftMsJE)wFoFql_h4(z|%GDn5Dz=b?{9IW;NKSY$S3hTMaWx%%t zUhcxzpWimOg#rTy6W?G!fn)4^(8BogNmiGsscwM4Hk)hF3jZe*$8pH$QPSamjS!JUc?FIR1T0?`twqU+F14&@U#jaCd&eGHkM4 z;eRh~G6Z_l8Z}~tH%^dMiX_m_3ZUjACY3|i z_>4-H?IX1Hhy^vFu00--Zk@0Q@?1SH1miCz_Xj@yjAv~Z4(yAM76(iR*$p9rd}=d% z__-(cj1r^oy1mC5oQCl*7OlQyyVE0Yc3!9l{_x&E)iA_f)IX)Ut3=a zeBjXjann)}wh~X=oBnbuJ%pAUrdlD(D9iBo$G%rLpmP{!e^KXzQw|s%EH*g>WgCQ9?tv%b(HW z-3pwVRL}w)_Fw|q;qc>Q>77%qqm<6_ohRD*;L90$wqX5k*sB0+R|kPAdqa7;q7TY3 z*~qC>NcN2rW4h+m$P<$HU(hYj_cEXx_z zdg1uM?^h9CkAwWBFFIpt;2c*+YysMMsJ-G%D{mrz%1FHm*<1M!nKAi~BtHwGrQb5D zin8CpS0?}k=lV@_R<&3S1PEOlzX!*_@UQ-x5q`4y!z3MtI**6G0YM*k(bh^p5@p)J zod*##Fbg$=tUdsNMM=nS-5AQXNH6~$=b|5~?+`+L6veTFAXn?T&ISH+P1hZGySVWK zOWuzcpTW8FqvlSvxgT+QbeJ1idF^m7S2t)P{nBXopaYyg8hM}sGvKK&apLd%Xg7=m zvec~=-`nyO8dbT?_S4V$?sgEznq0M`e(-rJIUfY&Q0e$AE)vih8u;-0=IlyoHB6N` zvz^&Pq4WE4NTAQ0=h@|x@2|kGQ`rf;(5xPtJ75&;Ud*vYpx@3% zEMyG`AYYuIH8>wjSMV7jH)_A%5rzi3lW$J?c31B;1pXGT{hF@Fs zL+cGDS~F-sXFcx1*K6P52b9r#%32y)zL5mU@TZfB!!GL3@+8gj;qUZX0%sBj^t@Y- zYPIK^SIN!JuW|`PfGGYD$`1yE=W(VM(;G}b%8`8u$tcp7t&rPZrnMirYa|tRIh!#2JAG~P)D@W!GkYTcBEuD20*ICar8H4+tVw&aUb@XP@VZQ2b1*x}dlkmy@W){iR1 zZeHTWGRX$Q*T|woP1q7apAU$oXV|@cnGUM3WEHg58adO%!9O#~4+Kos)TU*@^l01F z>!54b`6tTmx~F3sqV0Pchd@YChs~-e{D3smc>2K~i6u`u@BJ($ zPfGYON`>CzRpKH|Lj8uyZ*j$>Qs_+_(W(47gs#h9h^%9s^Xb#w`a+nMd?9*nx2=P> z&i0!dXaz>*@LVu|k@kAD9A7_OyXN$}qx9TtlfG8c_asJiVLN&HTX?&Cx)zuBI3*5W zFa174ATDovz7XaJ!Kf;iQ34G}rR-Lu;P|chT#>9#zprqFNNvuCMVBN)$-EuxpL3`g zp1a$`D3V3ctMRoBPxyKG32&J@ct0?GGdHNvqfVoQlv?DVVWm(#h9x~>Pa4^QDp z&J$Oblrz}^?I`lg&%_~Kmk~;)4}#-AX!*Nx$jIXED|!Dj3GY*I63>i7Q~KoaP>dwokXOSG$sHu9mQ_|R|`ctBUcY63pmb_Tw)cJ=VASjnN>ZUenm zTfAF4=fM}Q_PZzG`J7kX`p0v;zxXR3ZmD4{POo0O{zTXYptRC~6u)})F8tae-d_wP z6!XD4wE&P(3U!^A>q1;%Bz~NMZKbtnor;;w%_jC5YevKH~IFP;i= zIUHYjbo5B5Fu1^4Vzg%?{wKO|X%32_ZPac1+@U>p%bKQ0>~j6d42G_O4fT%Y1) zzk6~X!2DZ)@=83y5P|6slI3Y{On11f4{T~~QQN;1&161lSGp~x2T;7hm5TN!u1uHR zh`NMqsysnZTE9B&AbEMLb0m5AT{W8;PH}4={KJFNd})h1>(}oM|mEGuXt{T zr<`|+OY;kD7bfg0A+W8Fd~JYnK|g?>6g(E*sRN`cdEUl5%QHcyYP?26Mk`>i$D+O56)83j^>_d1SbLS_Sl+8Zg07qxMM$7_(fog zIm@G{D^(Q3nFLL7XqRs?dIS3z&hc(2FeL8`g6NKa)GdCmtkgPsE?$sh`&9PZ`|g;g z@%Hz>vDDV%w>Tg%S3N1*C*Pb3_VCfXI1^nddRe@8AKN^2KUiVY)WTs0Vh-09l;~nw zzu|B(_6;0pBW#%zDk{LLl%t=NNp>9Q&*A5I?PoC)27=M!;27i)8Z@9+J?IyM0~TXO zrJQ;gD9L$fylqBWJbEpa>6SD zksFl|@In(Q^U+C_BSlbd6Vz8<~^$$AOMV*gYGD%R~FF-${-b^=!^9_EfjGl`sesnBX zA{Sqz92**JHjSmB4_}S#lUA9x9rAj@$U0!9Xc2Ib#RHDWf}kvXsTB3)Zt8K@&j^} zRcVtwl4GiPI0fQz2e>xV1MPFmnFIX7=k0%?P$4+x{%I*#ri0c!Zyp5F?IdsQ9H)}E z;`S-2T$*(g)D$7Cj8gG)6|u4Fz3I81aPb9$&v#5wXm6IvBxSs;^}}PfbGvf!JT1O!=M46rNn6FBv#wZL+R;@y zqXmiFq&f7mX4^Mt-Ve~0rb=t-7MfUo*ozGAwK{XMU($IocwCfs>aS!L`1bLi@d>Cv z3o^6`KrpgnHF9p05r4wB#m*238>YwA6MtikDBnK`QF!!4x20*d^CJ1{U_}jf1h*6X z=e9AqMDR`zU?4417Y@Kc-#a-eY*gsLW*V?4_;&syG&&_Y&F)VXf-EKcCvs59mLOO4 zx>;L>9?x>p{;&2)x^O}DxqmZ(CttOi^4}IQwAPg-=1tK}Gl>(_BdFK`@)Gs4iq)Q$ z`YwD1SJHC|t3%{QJA4e1uh7KPqsI{k@JNv(jq+TJ-!OzU&L*lzEoe(JyX1>7B!7}) zTO&1s__i@i=rjOR`u}T+2sZ8R>j|Rt=*z&s-v*Bz$R&KrcK*UiKN5#SLPnu=I6KQf zesh)!p196T=Tr;`{zqyDjG)vaaAW}<0X(O8S)M)}2B<

r@R8DskCg$QY%d=x6zD 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

!LxQh!NmF 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/errorIcon.png b/DaireApplication/Assets/errorIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..32217b3d3db689f57ca1acf6a020f526d4388fea GIT binary patch literal 6291 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 XeV}+(uCfLA%K*|))m5ocvWxg1p4zXB literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/greenPlug.png b/DaireApplication/Assets/greenPlug.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef1337b29be5825722a921ba4a743309ff34213 GIT binary patch literal 10085 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 W4khVlO}#=*ZMWWGb<2W&>c0U+)f<}t literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/homeTrack.png b/DaireApplication/Assets/homeTrack.png new file mode 100644 index 0000000000000000000000000000000000000000..6e89eb8a19f06e6ce072dce17f0a39cdac936582 GIT binary patch literal 2740 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 Hu0mjf)4&3P literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/icons8-red-circle-48.png b/DaireApplication/Assets/icons8-red-circle-48.png new file mode 100644 index 0000000000000000000000000000000000000000..c4080c740d77f0d3fc66432430aa8d23efa055d6 GIT binary patch literal 2222 zcmV;f2vPTmP)24aT_k zAUpe)#~x3X;&T`;ii*B`;Bx)5&upIUv)S<2?Zz{Y2d_#>FzWSUw7fhhuUEvl#vJDM zS}ZdUb8>!y$@Inlr1(eK**|t0jVl9ACteg6W30R!Q|HfP?$Ra9*Vba8z8;GW4MIF; zjBCtcF82&Lo#-){0)sAB>wm5AiGl)UkJ;S+z;4HLj|bxw6_~qt5sP(oSZZv*T zzW*MpSFd9I+BG4bGsZRMFqeDAD=LHsy?QK`zR{eV$WL1QqwMUYF1>z!$mPOFNeO1E zs<2Q~g8&O}X%WS~y?$NjU27}e{qRFjt*x7J<}jCg7HVpQ2fgUoZ8Z9aU9QAWR(!W! z9~gGKF;-TFx$0^x)zx98sYzVjH`lJ=9Sgs4L+E{L>lVpz<}g>>k)|f$K`(mJTQF?4 z{cU2xZdZ1tr_Vph&Bd743x9Prmh0-U+SG*gmKMCddKGV_2HsO_;KmJXNRsDVV-9n< zXT7CGc+iWU^d_S#Bg6l~YW;fO8tBT%=pW3?6t{Y=stQZBwODCv#CmhH&>J?eP49L% zm&HBn(tdi;lip;I)uY$<>`U?YZMN2alL;@2iZEMQiN#Bo5U8ueT4N*Dcn6xA@V2=b zZ+R!=hISCww&XT72@iVFlip;IMdkyG<;RcyoWG~lt~_=~;mQ@fxpF0V9;(pTAFPW#SAubR(Uaa}kVR&vRvY-J?}=W6;a~SH7QFU&;5%~$ z3)R(FxqKO`wY6B~U8t|ex^!HvuNTKP&ZXEEg~a9Db$QPBiI3&w%Ys1`nPm5yOn={V z1NTx>eZx69m?|xWzp@fbasxFrSPRiAV^Vzcd?$tEtc7~i)Cg}f$Rd;MuC%n7Jr&<$ zwK}_XI=sls!wesv%1SI(RUvTU0#>T4v3l{MI0o316cfikBPln)W2hG&(W)xJB9m;^ zaNlaRhuuK8R{QHilL;e*g_tcX!(wG60_V;lz$VV0$BLwYEUtwkY2Qky553Qw6D%^x zW(~bs?ayI1a4#igXvpEfIG=wuaOMn_&Ys0GA0>+CjP0hgXM@@$XIakU9hQ8_B9m;^ z(3z4l7BPMCcY29fyBfQ z+&o!S1mEe?n3tf7B_&v(7&~uJs$Ywqpa=o-PVeOb9&KJc%M2YSY(pT8hA0oZy-K? zX%OCxZug;j5>z!&f26Z~Tmqg3wSzg0MHA3BtH zQ>6;@YBU&3OT)ADbiCB-@k+19NJfUxs8sxjT(nLXRA?+ceKY@+UN1c8MNfLSsZ@b> zmFnoe79ZL~`=LW~UEh9-f#hTiYqfaJcY}{sdOBXSIGrvispw5fapo|Wd!Flb!h>G) zY>$rik)imMgO5{NR8-I1*jV%*J&H%k$#}{;A~&Pe;+0m57djnYNfPH;typ6YbGheH za_ z;~I0A%RL>3597D!=;ijPsQvl033ouD_@XT$;va31ku$eqVsI}m4!vqM?#IXDVSGFu zXf#4RXN+siVQyPwK5;LB=|0ssI207*qoM6N<$g1$RYdH?_b literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/orangePlug.png b/DaireApplication/Assets/orangePlug.png new file mode 100644 index 0000000000000000000000000000000000000000..0c0242e8635cae85d975e4a011a4af1ff6c3aa5e GIT binary patch literal 10062 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 UhJ8~M#YfEEcDv0rD@xpd0O6O<1poj5 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/purplePlug.png b/DaireApplication/Assets/purplePlug.png new file mode 100644 index 0000000000000000000000000000000000000000..3026fae47fdb798120921fb22c3e4f88e14a7b4f GIT binary patch literal 10108 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 OfsHm>tgl)!j{iTlyY1ir literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/redPlug.png b/DaireApplication/Assets/redPlug.png new file mode 100644 index 0000000000000000000000000000000000000000..15dab0283296f441dca3f3d13713922235a14f24 GIT binary patch literal 10048 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/warningIcon.png b/DaireApplication/Assets/warningIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..154ff5114c5da3f56b9158f3c1b0fe08247b16b8 GIT binary patch literal 1235 zcmV;^1T6cBP)Px(jY&j7RA@u(m|ck6R20YmCp(*D>qn^{TP;$h&fTu{L8*$MK2#C(Nzn(TAifCg zi&as(xvNF1RVP!asC_9u2;xgo5YYz(9~7h&N{dhw=_IwbBJN@<3)d+(xN|izs@g3_JK%2W}o^jk5vv0{;mE1wjAD3%JM(}qSsHQdUuh%sq!Z+bF zeU7f8n=0q>gvlMmcVqydwRZrRHH5vY`NMbQEC6%i`J5r_uum>Lxq^7Ee2^GlwKETM zHHqE-HvjWUYjx0|^WnQ8@Ixh0{W2Gd`Q<&o7Ax={3}N3DweHvC5fJVuqVRJA@oLrq zBHEr5WDNF0L)cH{k;>daq5*0|)^NG9w_AXI&DsT`JxRc-aJhi^t~?FK`n17Cp_%cg zIcBd@4Lsg|U=VgDt_z_39vbF)W856yd!k=pzGK}C&`)8XM!mFQWc-a&gTM?7(ve+Y z+7$LRX#(Q+v%knKS_$9wdfz$4_&IZ|`d*qObn7z^ zNNffA)DZS#Q71_to+Cde;Ni5j)ekZ=i0@cm1N1<@Ad*0uV`EeEJ5$*AW>F;*2=lh# zz`de*6q#=g-fC>D9*hT&1|)E;CzRGg@SEGc}zHH0nFsFDhVPs=qyuy}nAvyluEEpQ<75kduIL6t)Q+E?YI({W#rz>yy_@PvxQ@qj&7 zmP<^VN}}>b2AIW9u0#ioa%F3#eI!~NMEs0iuI^U}COSn3bVL`GJ5|Pe&gAn1-j^nk zJr(gBIYq$QG)8&_$G^U`HmEnITJH%{M%lhr1th*4Gx)42s#kZj(G|q2$qhs}84l2g zOB?8hY*$h5gnSwrKWd8VeX0=6{+_e*M#7LAj%9){%Xa&J_`EAf$CLu5^_17wEPw6-)r-(rEwn>CTdf9Hr+6Hl)9maZG(mWb0n-;wmw?TYIHt)&$vZ0v& x0w3tYZk@>zk0{FpYz5>(Q))$#6-5fl!2d8e(n6vo7(oC4002ovPDHLkV1l3vMMD4p literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/wifi.png b/DaireApplication/Assets/wifi.png new file mode 100644 index 0000000000000000000000000000000000000000..3f2237c66315593fade59f8564139cf6d9fd0eae GIT binary patch literal 6183 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 literal 0 HcmV?d00001 diff --git a/DaireApplication/Assets/yellowPlug.png b/DaireApplication/Assets/yellowPlug.png new file mode 100644 index 0000000000000000000000000000000000000000..98fc614ddf9aa016872568b305838e994b03cb10 GIT binary patch literal 10109 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 E4FnGZjsO4v literal 0 HcmV?d00001 diff --git a/DaireApplication/Automatic_Fountain_Control_Implementation.md b/DaireApplication/Automatic_Fountain_Control_Implementation.md new file mode 100644 index 0000000..50d1ffd --- /dev/null +++ b/DaireApplication/Automatic_Fountain_Control_Implementation.md @@ -0,0 +1,294 @@ +# Automatic Fountain Control Implementation + +## Overview + +This implementation adds automatic fountain control functionality that triggers after the pouring phase completes when the pedal is in Auto mode. The fountain state is determined by the second control box (RecipeTable.Fountain property). + +## ✅ Expected Behavior + +- **After pouring phase completion** and **pedal mode set to Auto**: + - If the second control box is **checked/enabled** → Fountain should **open** + - If the second control box is **unchecked/disabled** → Fountain should **remain closed** +- **No blinking/flashing** of the Chocolate button after automatic control is established + +## 🔧 Implementation Details + +### 1. New Properties Added + +```csharp +public bool isAutomaticFountainControlActive { get; set; } = false; +``` + +This flag prevents interference between automatic fountain control and normal temperature-based fountain control. + +### 2. New Methods Added + +#### `HandleAutomaticFountainControlAfterPouring(Settings settings)` +- **Purpose**: Main orchestrator for automatic fountain control +- **Trigger**: Called when pouring phase completes +- **Logic**: + - Checks if pedal is in Auto mode (`!settings._recipeTable.Pedal.Value`) + - Reads second control box state (`settings._recipeTable.Fountain.Value`) + - Calls appropriate fountain control method + +#### `TurnOnFountainAutomatically()` +- **Purpose**: Automatically turns ON the fountain motor +- **Actions**: + - Sets fountain motor state variables + - **Sends hardware command** to turn ON fountain motor + - Updates UI to show fountain is ON + - Logs the action for debugging + +#### `TurnOffFountainAutomatically()` +- **Purpose**: Automatically turns OFF the fountain motor +- **Actions**: + - Sets fountain motor state variables + - **Sends hardware command** to turn OFF fountain motor + - Updates UI to show fountain is OFF + - Logs the action for debugging + +#### `ResetAutomaticFountainControl()` +- **Purpose**: Resets the automatic control flag +- **Usage**: Called when manual control is needed or recipe is reset + +### 3. Integration Points + +#### Pouring Phase Completion +Modified `PouringTimer` method to call automatic fountain control: + +```csharp +// Handle automatic fountain control after pouring phase completion +await HandleAutomaticFountainControlAfterPouring(result); +``` + +#### Fountain Control Logic Protection +Modified main fountain control logic to respect automatic control: + +```csharp +//Fountain Motor - Normal temperature-based control +if (checkFountainTMT_PMT && !isAutomaticFountainControlActive) +{ + // Normal temperature-based fountain control +} + +//Fountain Motor - Manual control (when not in automatic mode) +if (!checkFountainTMT_PMT && !isAutomaticFountainControlActive) +{ + // Manual fountain control +} +``` + +#### Automatic Fountain Control Processing +Added dedicated section for automatic fountain control in main monitoring loop: + +```csharp +//Fountain Motor - Automatic control (when automatic control is active) +if (isAutomaticFountainControlActive) +{ + // Handle automatic fountain control state changes + if (startFountainMotorFlashing == 0 && sendComFountainMotor == 1 && errors.Count == 0 && !isPaused) + { + // Turn ON fountain motor + // Send hardware command + // Update UI + } + else if (startFountainMotorFlashing == 1 && sendComFountainMotor == 0) + { + // Turn OFF fountain motor + // Send hardware command + // Update UI + } +} +``` + +#### Manual Override +Modified `FountainClick` method to reset automatic control when user manually controls fountain: + +```csharp +// Reset automatic fountain control flag when user manually controls fountain +if (isAutomaticFountainControlActive) +{ + ResetAutomaticFountainControl(); +} +``` + +#### Recipe Lifecycle Management +- **Recipe Start**: Resets automatic control flag +- **Recipe Stop**: Resets automatic control flag + +## 🔄 Control Flow + +1. **Recipe Execution**: Normal recipe phases (heating → cooling → pouring) +2. **Pouring Phase Completion**: + - Recipe timer completes + - Pedal control is set based on recipe settings + - **NEW**: Automatic fountain control is triggered +3. **Automatic Fountain Control**: + - Checks pedal mode (must be Auto) + - Checks second control box state + - Sets fountain state accordingly + - **Sends hardware commands** to control fountain motor + - Sets flag to prevent interference +4. **Hardware Control**: Main monitoring loop processes automatic control commands +5. **Manual Override**: User can manually control fountain, which resets automatic control + +## 🛡️ Safety Features + +1. **Flag Protection**: Automatic control flag prevents conflicts with normal fountain control +2. **Manual Override**: Users can always take manual control +3. **Recipe Reset**: Automatic control is reset when starting/stopping recipes +4. **Error Handling**: Comprehensive try-catch blocks with logging +5. **UI Updates**: Visual feedback shows fountain state changes +6. **Hardware Commands**: Direct hardware control ensures fountain state changes are executed + +## 🚫 Blinking Prevention + +### Issue Fixed +The "Chocolate" button was blinking/toggling after pouring phase completion due to conflicting fountain control mechanisms. + +### Solution Implemented + +#### 1. **Flashing Flag Protection** +Modified automatic fountain control to set `startFountainMotorFlashing = -1` instead of `1`: + +```csharp +// In TurnOffFountainAutomatically() +startFountainMotorFlashing = -1; // Prevent flashing in automatic mode +``` + +#### 2. **InteractiveUILoop Protection** +Added automatic control check to prevent flashing in UI loop: + +```csharp +// In InteractiveUILoop.cs +if (_mainWindow.startFountainMotorFlashing == 1 && !_mainWindow.isAutomaticFountainControlActive) +{ + // Only flash when not in automatic control mode +} +``` + +#### 3. **Temperature-Based Control Protection** +Added automatic control checks to prevent normal fountain control from interfering: + +```csharp +// Prevent normal fountain control from setting flashing when automatic control is active +if (!isAutomaticFountainControlActive) +{ + startFountainMotorFlashing = 1; +} +``` + +#### 4. **Flashing Processing Protection** +Added automatic control check to flashing processing logic: + +```csharp +if (startFountainMotorFlashing == 1 && !isAutomaticFountainControlActive) +{ + // Only process flashing when not in automatic control mode +} +``` + +### Result +- **No more blinking** of the Chocolate button after automatic control is established +- **Steady state** maintained based on second control box value +- **Clean visual feedback** without distracting flashing animations + +## 📝 Debugging + +The implementation includes debug logging for: +- Automatic fountain control activation +- Fountain state changes (ON/OFF) +- Hardware command execution +- Flag resets +- Error conditions + +## 🧪 Testing Scenarios + +### Scenario 1: Second Box Checked, Auto Mode +1. Start recipe with second control box enabled +2. Complete pouring phase +3. **Expected**: Fountain turns ON automatically and chocolate flows (no blinking) + +### Scenario 2: Second Box Unchecked, Auto Mode +1. Start recipe with second control box disabled +2. Complete pouring phase +3. **Expected**: Fountain remains OFF and chocolate flow stops (no blinking) + +### Scenario 3: Manual Mode +1. Start recipe in manual pedal mode +2. Complete pouring phase +3. **Expected**: No automatic fountain control (manual control only) + +### Scenario 4: Manual Override +1. Complete recipe with automatic fountain control active +2. Manually click fountain button +3. **Expected**: Automatic control is reset, manual control takes over + +### Scenario 5: No Blinking Verification +1. Complete recipe with automatic fountain control +2. **Expected**: Chocolate button remains steady (ON or OFF) without blinking + +## 🔧 Configuration + +The second control box is configured through the `RecipeTable.Fountain` property: +- `true` = Fountain should be ON after pouring +- `false` = Fountain should be OFF after pouring + +## 🔧 Key Fixes Applied + +### Issue: Fountain State Not Changing +**Problem**: Automatic control was setting state variables but not sending hardware commands. + +**Solution**: +1. **Direct Hardware Control**: Modified `TurnOnFountainAutomatically()` and `TurnOffFountainAutomatically()` to send actual hardware commands +2. **Dedicated Processing**: Added automatic fountain control section in main monitoring loop +3. **State Synchronization**: Ensured UI updates and hardware commands are synchronized + +### Issue: Chocolate Button Blinking +**Problem**: The Chocolate button was blinking/toggling after pouring phase completion. + +**Solution**: +1. **Flashing Flag Control**: Set `startFountainMotorFlashing = -1` in automatic control to prevent flashing +2. **UI Loop Protection**: Added automatic control check to InteractiveUILoop +3. **Temperature Control Protection**: Prevented normal fountain control from interfering +4. **Flashing Processing Protection**: Added automatic control check to flashing processing logic + +### Hardware Command Implementation +```csharp +// Turn ON fountain motor +var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); +if (fount != null && fount.BitNumbers.Count > 0) +{ + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Automatic Fountain On"); +} + +// Turn OFF fountain motor +var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); +if (fount != null && fount.BitNumbers.Count > 0) +{ + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Automatic Fountain Off"); +} +``` + +## 📋 Requirements Met + +✅ **Automatic triggering** after pouring phase completion +✅ **Pedal mode detection** (Auto mode only) +✅ **Second control box integration** (RecipeTable.Fountain) +✅ **Dynamic fountain control** (open/close based on box state) +✅ **Hardware command execution** (actual fountain motor control) +✅ **No interference** with existing fountain control logic +✅ **Manual override capability** +✅ **Proper error handling and logging** +✅ **UI feedback** for fountain state changes +✅ **Chocolate flow control** (stops/starts based on fountain state) +✅ **No blinking/flashing** of Chocolate button after automatic control +✅ **Steady state maintenance** based on second control box value \ No newline at end of file diff --git a/DaireApplication/DaireApplication.csproj b/DaireApplication/DaireApplication.csproj new file mode 100644 index 0000000..ffed958 --- /dev/null +++ b/DaireApplication/DaireApplication.csproj @@ -0,0 +1,75 @@ + + + WinExe + net8.0 + enable + true + app.manifest + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + None + All + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/DataBase/ConfigrationTable.cs b/DaireApplication/DataBase/ConfigrationTable.cs new file mode 100644 index 0000000..c2fe0ac --- /dev/null +++ b/DaireApplication/DataBase/ConfigrationTable.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; + +namespace DaireApplication.DataBase; + +public class ConfigrationTable +{ + public int Id { get; set; } + public int Max { get; set; } = 0; + public int Min { get; set; } = 0; + public List H_out { get; set; } = new(); + public List FC_out { get; set; } = new(); + public List SC_out { get; set; } = new(); + public int kp { get; set; } = 0; + public int ki { get; set; } = 0; + public int kd { get; set; } = 0; + public int kl { get; set; } = 0; + public string name { get; set; } = ""; + public float i_neut { get; set; } = 0; + public float i_mot1 { get; set; } = 0; + public float i_mot2 { get; set; } = 0; + public float FC_Threshold { get; set; } = 3; + public float HeatConRange { get; set; } = 50; + + public List ReadConfigrations() + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + List configrations = new List(); + + if (File.Exists(filePath)) + { + using StreamReader reader = new(filePath); + string header = reader.ReadLine(); + while (!reader.EndOfStream) + { + string[] columns = reader.ReadLine().Split(','); + configrations.Add(new ConfigrationTable + { + Id = int.Parse(columns[0]), + Max = int.Parse(columns[1]), + Min = int.Parse(columns[2]), + H_out = columns[3].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + FC_out = columns[4].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + SC_out = columns[5].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + kp = int.Parse(columns[6]), + ki = int.Parse(columns[7]), + kd = int.Parse(columns[8]), + kl = int.Parse(columns[9]), + name=columns[10], + i_neut= float.Parse(columns[11]), + i_mot1= float.Parse(columns[12]), + i_mot2= float.Parse(columns[13]), + FC_Threshold = float.Parse(columns[14]), + HeatConRange = float.Parse(columns[15]), + }); + } + return configrations; + } + return null; + } + + public int GetMaxId() + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + if (File.Exists(filePath)) + { + return File.ReadAllLines(filePath) + .Select(line => line.Split(',')) + .Where(columns => columns.Length > 0) + .Select(columns => int.TryParse(columns[0], out int id) ? id : 0) + .Max(); + } + return -1; + } + + public ConfigrationTable ReadConfigrationById(string id) + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + if (File.Exists(filePath)) + { + foreach (var line in File.ReadLines(filePath)) + { + string[] columns = line.Split(','); + if (columns[0] == id) + { + return new ConfigrationTable + { + Id = int.Parse(columns[0]), + Max = int.Parse(columns[1]), + Min = int.Parse(columns[2]), + H_out = columns[3].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + FC_out = columns[4].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + SC_out = columns[5].Split('|', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList(), + kp = int.Parse(columns[6]), + ki = int.Parse(columns[7]), + kd = int.Parse(columns[8]), + kl = int.Parse(columns[9]), + name=columns[10], + i_neut = float.Parse(columns[11]), + i_mot1 = float.Parse(columns[12]), + i_mot2 = float.Parse(columns[13]), + FC_Threshold = float.Parse(columns[14]), + HeatConRange = float.Parse(columns[15]), + }; + } + } + } + return null; + } + + public bool AddConfigration(ConfigrationTable data) + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + if (File.Exists(filePath)) + { + string newEntry = string.Join(",", [ + GetMaxId() + 1, + data.Max, + data.Min, + string.Join("|", data.H_out), + string.Join("|", data.FC_out), + string.Join("|", data.SC_out), + data.kp, + data.ki, + data.kd, + data.kl, + data.name, + data.i_neut, + data.i_mot1, + data.i_mot2, + data.FC_Threshold, + data.HeatConRange + ]); + File.AppendAllText(filePath, newEntry + Environment.NewLine); + return true; + } + return false; + } + + public bool DeleteConfigration(string id) + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + if (File.Exists(filePath)) + { + var filteredLines = File.ReadLines(filePath).Where(line => !line.StartsWith(id + ",")).ToArray(); + File.WriteAllLines(filePath, filteredLines); + return true; + } + return false; + } + + public bool UpdateConfigration(ConfigrationTable updatedConfig) + { + string filePath = DataPathManager.GetDataFilePath("Configration.csv"); + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + bool configFound = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 10) + continue; + + if (int.Parse(columns[0]) == updatedConfig.Id) + { + columns[1] = updatedConfig.Max.ToString(); + columns[2] = updatedConfig.Min.ToString(); + columns[3] = string.Join("|", updatedConfig.H_out); + columns[4] = string.Join("|", updatedConfig.FC_out); + columns[5] = string.Join("|", updatedConfig.SC_out); + columns[6] = updatedConfig.kp.ToString(); + columns[7] = updatedConfig.ki.ToString(); + columns[8] = updatedConfig.kd.ToString(); + columns[9] = updatedConfig.kl.ToString(); + columns[10] = updatedConfig.name; + columns[11] = updatedConfig.i_neut.ToString(CultureInfo.InvariantCulture); + columns[12] = updatedConfig.i_mot1.ToString(CultureInfo.InvariantCulture); + columns[13] = updatedConfig.i_mot2.ToString(CultureInfo.InvariantCulture); + columns[14] = updatedConfig.FC_Threshold.ToString(CultureInfo.InvariantCulture); + columns[15] = updatedConfig.HeatConRange.ToString(CultureInfo.InvariantCulture); + + lines[i] = string.Join(",", columns); + configFound = true; + break; + } + } + + if (configFound) + { + File.WriteAllLines(filePath, lines); + return true; + } + } + return false; + } +} diff --git a/DaireApplication/DataBase/DataPathManager.cs b/DaireApplication/DataBase/DataPathManager.cs new file mode 100644 index 0000000..08d2aa5 --- /dev/null +++ b/DaireApplication/DataBase/DataPathManager.cs @@ -0,0 +1,311 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; +using System.Collections.Generic; + +namespace DaireApplication.DataBase +{ + public static class DataPathManager + { + private static readonly string AppName = "DaireApplication"; + private static string _dataDirectory; + + // Expected CSV headers for each file + private static readonly string UsersCsvHeader = "ID,UserName,Password,CanEdit,IsAdmin,IsActive"; + private static readonly string RecipeCsvHeader = "ID,Name,TankTemp,FountainTemp,Mixer,Fountain,MoldHeater,Vibration,VibHeater,Pedal,PedalOnTime,PedalOffTime,HeatingGoal,CoolingGoal,PouringGoal"; + private static readonly string MachineCsvHeader = "ID,TankMaxHeat,PumbMaxHeat,PumbDelay,MixerDelay,HeatingDelay,CoolingDelay,PouringDelay,PumbMinHeat,AbsMaxTemp,AbsMinTemp,PreHeatingTemp,SetTemp1,SetTemp2,SetTemp3,SetTemp4"; + private static readonly string MappingCsvHeader = "Id,Name,Address,IsRead,BitNumbers"; + private static readonly string ConfigrationCsvHeader = "Id,Max,Min,H_out,FC_out,SC_out,kp,ki,kd,kl,Name,I_Nuet,I_Mot1,I_Mot2,FC_Threshold,HeatConRange"; + private static readonly string ErrorSettingsCsvHeader = "Id,gridFreq,phaseNumber,extPower,phaseVoltage"; + private static readonly string ScreenCsvHeader = "Id,Brightness,DimSec,OffSec,Port,BoundRate,Parity,StopBits,SendingTime,WarningLimit,ErrorLimit"; + + static DataPathManager() + { + try + { + // Determine the data directory based on the OS + if (OperatingSystem.IsWindows()) + { + // Windows: Use LocalApplicationData + string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + _dataDirectory = Path.Combine(appDataPath, AppName); + } + else + { + // Linux/macOS: Use ~/.local/share/DaireApplication + string home = Environment.GetEnvironmentVariable("HOME") ?? "/tmp"; + _dataDirectory = Path.Combine(home, ".local", "share", AppName); + } + + // Ensure the directory exists + Directory.CreateDirectory(_dataDirectory); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to CreateDirectory: {ex.Message}"); + Console.WriteLine($"_dataDirectory: {_dataDirectory}"); + } + } + + /// + /// Returns the full path for a data file, ensuring the directory exists. + /// + public static string GetDataFilePath(string fileName) + { + try + { + // Ensure the directory exists before returning the file path + Directory.CreateDirectory(_dataDirectory); + return Path.Combine(_dataDirectory, fileName); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to GetDataFilePath: {ex.Message}"); + return string.Empty; + } + } + + /// + /// Migrates legacy data files from the application's base directory to the new data directory. + /// + public static void MigrateLegacyData() + { + try + { + string[] csvFiles = { "Users.csv", "Recipe.csv", "Machine.csv", "Mapping.csv", + "Configration.csv", "ErrorSettings.csv", "Screen.csv" }; + + foreach (string file in csvFiles) + { + string legacyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, file); + string newPath = GetDataFilePath(file); + + // If the file exists in the old location but not in the new location, move it + if (File.Exists(legacyPath) && !File.Exists(newPath)) + { + // Ensure the target directory exists + Directory.CreateDirectory(Path.GetDirectoryName(newPath) ?? _dataDirectory); + File.Move(legacyPath, newPath); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Failed to MigrateLegacyData: {ex.Message}"); + } + } + + /// + /// Migrates CSV files by adding missing columns with default values instead of deleting them. + /// + public static void MigrateCsvFiles() + { + MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues); + MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues); + MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues); + MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues); + MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues); + MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues); + MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues); + } + + /// + /// Migrates a CSV file by adding missing columns with default values. + /// + private static void MigrateCsvFile(string fileName, string expectedHeader, Func getDefaultValue) + { + try + { + string filePath = GetDataFilePath(fileName); + if (!File.Exists(filePath)) + return; + + string[] lines = File.ReadAllLines(filePath); + if (lines.Length == 0) + return; + + string actualHeader = lines[0]; + if (string.Equals(actualHeader.Trim(), expectedHeader.Trim(), StringComparison.OrdinalIgnoreCase)) + return; // No migration needed + + string[] expectedColumns = expectedHeader.Split(','); + string[] actualColumns = actualHeader.Split(','); + + // Find missing columns + var missingColumns = new List<(int index, string columnName)>(); + for (int i = 0; i < expectedColumns.Length; i++) + { + if (i >= actualColumns.Length || !string.Equals(actualColumns[i].Trim(), expectedColumns[i].Trim(), StringComparison.OrdinalIgnoreCase)) + { + missingColumns.Add((i, expectedColumns[i])); + } + } + + if (missingColumns.Count == 0) + return; + + // Migrate the file + var migratedLines = new List(); + + // Add new header + migratedLines.Add(expectedHeader); + + // Migrate data rows + for (int i = 1; i < lines.Length; i++) + { + string[] dataColumns = lines[i].Split(','); + var newDataColumns = new List(dataColumns); + + // Add missing columns with default values + foreach (var missing in missingColumns) + { + if (missing.index >= newDataColumns.Count) + { + newDataColumns.Add(getDefaultValue(missing.columnName)); + } + else + { + newDataColumns.Insert(missing.index, getDefaultValue(missing.columnName)); + } + } + + migratedLines.Add(string.Join(",", newDataColumns)); + } + + // Write the migrated file + File.WriteAllLines(filePath, migratedLines); + Console.WriteLine($"Migrated {fileName} - added {missingColumns.Count} missing columns"); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to migrate {fileName}: {ex.Message}"); + } + } + + // Default value providers for each file type + private static string GetUsersDefaultValues(string columnName) + { + return columnName switch + { + "IsActive" => "0", + _ => "" + }; + } + + private static string GetRecipeDefaultValues(string columnName) + { + return columnName switch + { + "TankTemp" => "0", + "FountainTemp" => "0", + "Mixer" => "0", + "Fountain" => "0", + "MoldHeater" => "0", + "Vibration" => "0", + "VibHeater" => "0", + "Pedal" => "0", + "PedalOnTime" => "0", + "PedalOffTime" => "0", + "HeatingGoal" => "46", + "CoolingGoal" => "27", + "PouringGoal" => "30", + _ => "" + }; + } + + private static string GetMachineDefaultValues(string columnName) + { + return columnName switch + { + "TankMaxHeat" => "50", + "PumbMaxHeat" => "50", + "PumbDelay" => "60", + "MixerDelay" => "60", + "HeatingDelay" => "60", + "CoolingDelay" => "60", + "PouringDelay" => "60", + "PumbMinHeat" => "-10", + "AbsMaxTemp" => "65", + "AbsMinTemp" => "-14", + "PreHeatingTemp" => "5", + "SetTemp1" => "0", + "SetTemp2" => "-10", + "SetTemp3" => "5", + "SetTemp4" => "0", + _ => "" + }; + } + + private static string GetMappingDefaultValues(string columnName) + { + return columnName switch + { + "BitNumbers" => "", + _ => "" + }; + } + + private static string GetConfigrationDefaultValues(string columnName) + { + return columnName switch + { + "Max" => "0", + "Min" => "0", + "H_out" => "", + "FC_out" => "", + "SC_out" => "", + "kp" => "0", + "ki" => "0", + "kd" => "0", + "kl" => "0", + "Name" => "", + "I_Nuet" => "0", + "I_Mot1" => "0", + "I_Mot2" => "0", + "FC_Threshold" => "3", + "HeatConRange" => "50", + _ => "" + }; + } + + private static string GetErrorSettingsDefaultValues(string columnName) + { + return columnName switch + { + "gridFreq" => "50", + "phaseNumber" => "3", + "extPower" => "1", + "phaseVoltage" => "220", + _ => "" + }; + } + + private static string GetScreenDefaultValues(string columnName) + { + return columnName switch + { + "Brightness" => "100", + "DimSec" => "3300", + "OffSec" => "3600", + "Port" => "", + "BoundRate" => "19200", + "Parity" => "1", + "StopBits" => "0", + "SendingTime" => "50", + "WarningLimit" => "0.5", + "ErrorLimit" => "2", + _ => "" + }; + } + + // Legacy delete methods (kept for backward compatibility but now call migration) + public static void DeleteUsersCsv() => MigrateCsvFile("Users.csv", UsersCsvHeader, GetUsersDefaultValues); + public static void DeleteRecipeCsv() => MigrateCsvFile("Recipe.csv", RecipeCsvHeader, GetRecipeDefaultValues); + public static void DeleteMachineCsv() => MigrateCsvFile("Machine.csv", MachineCsvHeader, GetMachineDefaultValues); + public static void DeleteMappingCsv() => MigrateCsvFile("Mapping.csv", MappingCsvHeader, GetMappingDefaultValues); + public static void DeleteConfigrationCsv() => MigrateCsvFile("Configration.csv", ConfigrationCsvHeader, GetConfigrationDefaultValues); + public static void DeleteErrorSettingsCsv() => MigrateCsvFile("ErrorSettings.csv", ErrorSettingsCsvHeader, GetErrorSettingsDefaultValues); + public static void DeleteScreenCsv() => MigrateCsvFile("Screen.csv", ScreenCsvHeader, GetScreenDefaultValues); + } +} \ No newline at end of file diff --git a/DaireApplication/DataBase/ErrorSettingsTable.cs b/DaireApplication/DataBase/ErrorSettingsTable.cs new file mode 100644 index 0000000..e443e47 --- /dev/null +++ b/DaireApplication/DataBase/ErrorSettingsTable.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.DataBase +{ + public class ErrorSettingsTable + { + public int Id { get; set; } + public int gridFreq { get; set; } + public int phaseNumber { get; set; } + public int phaseVoltage { get; set; } + public bool extPower { get; set; } + + public List? ReadErrorSettings() + { + string filePath = DataPathManager.GetDataFilePath("ErrorSettings.csv"); + + if (!File.Exists(filePath)) + return null; + + string[] lines = File.ReadAllLines(filePath); + List errors = new(); + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + errors.Add(new ErrorSettingsTable + { + Id = int.Parse(columns[0]), + gridFreq = int.Parse(columns[1]), + phaseNumber = int.Parse(columns[2]), + extPower = columns[3] == "1", + phaseVoltage = int.Parse(columns[4]), + }); + } + + return errors; + } + + public bool UpdateError(ErrorSettingsTable updatedError) + { + string filePath = DataPathManager.GetDataFilePath("ErrorSettings.csv"); + + if (!File.Exists(filePath)) + return false; + + string[] lines = File.ReadAllLines(filePath); + bool updated = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (int.Parse(columns[0]) == updatedError.Id) + { + columns[1] = updatedError.gridFreq.ToString(); + columns[2] = updatedError.phaseNumber.ToString(); + columns[3] = updatedError.extPower ? "1" : "0"; + columns[4] = updatedError.phaseVoltage .ToString(); + lines[i] = string.Join(",", columns); + updated = true; + break; + } + } + + if (updated) + { + File.WriteAllLines(filePath, lines); + return true; + } + + return false; + } + } +} diff --git a/DaireApplication/DataBase/MachineTable.cs b/DaireApplication/DataBase/MachineTable.cs new file mode 100644 index 0000000..9362701 --- /dev/null +++ b/DaireApplication/DataBase/MachineTable.cs @@ -0,0 +1,124 @@ +using AvaloniaApplication1.DataBase; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Security.Cryptography.X509Certificates; +using System.Text; +using System.Threading.Tasks; + +namespace DaireApplication.DataBase +{ + public class MachineTable + { + public int Id { get; set; } + public float TankMaxHeat { get; set; } = 50; + public float PumbMaxHeat { get; set; } = 50; + public int PumbDelay { get; set; } = 60; + public int MixerDelay { get; set; } = 60; + public int HeatingDelay { get; set; } = 60; + public int CoolingDelay { get; set; } = 60; + public int PouringDelay { get; set; } = 60; + public float PumbMinHeat { get; set; } = -10; + public float AbsMaxHeat { get; set; } = 65; + public float AbsMinHeat { get; set; } = -14; + public float PreHeatingTemp { get; set; } = 5; + public float setTemp1 { get; set; } =0; + public float setTemp2 { get; set; } =-10; + public float setTemp3 { get; set; } =+5; + public float setTemp4 { get; set; } =+0; + + public MachineTable ReadMachine() + { + string filePath = DataPathManager.GetDataFilePath("Machine.csv"); + MachineTable machine = new MachineTable(); + + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + + foreach (string line in lines) + { + string[] columns = line.Split(','); + + if (columns[0] == "1") + { + machine.Id = int.Parse(columns[0]); + machine.TankMaxHeat = float.Parse(columns[1]); + machine.PumbMaxHeat = float.Parse(columns[2]); + machine.PumbDelay = int.Parse(columns[3]); + machine.MixerDelay = int.Parse(columns[4]); + machine.HeatingDelay = int.Parse(columns[5]); + machine.CoolingDelay = int.Parse(columns[6]); + machine.PouringDelay = int.Parse(columns[7]); + machine.PumbMinHeat = int.Parse(columns[8]); + machine.AbsMaxHeat = int.Parse(columns[9]); + machine.AbsMinHeat = int.Parse(columns[10]); + machine.PreHeatingTemp = float.Parse(columns[11]); + machine.setTemp1 = float.Parse(columns[12]); + machine.setTemp2 = float.Parse(columns[13]); + machine.setTemp3 = float.Parse(columns[14]); + machine.setTemp4 = float.Parse(columns[15]); + return machine; + } + } + return null; + } + else + { + return null; + } + } + + public bool UpdateMachine(MachineTable updatedMachine) + { + string filePath = DataPathManager.GetDataFilePath("Machine.csv"); + + if (!File.Exists(filePath)) + return false; + + string[] lines = File.ReadAllLines(filePath); + bool machineFound = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 8) + continue; + + if (int.Parse(columns[0]) == updatedMachine.Id) + { + columns[1] = updatedMachine.TankMaxHeat.ToString(CultureInfo.InvariantCulture); + columns[2] = updatedMachine.PumbMaxHeat.ToString(CultureInfo.InvariantCulture); + columns[3] = updatedMachine.PumbDelay.ToString(); + columns[4] = updatedMachine.MixerDelay.ToString(); + columns[5] = updatedMachine.HeatingDelay.ToString(); + columns[6] = updatedMachine.CoolingDelay.ToString(); + columns[7] = updatedMachine.PouringDelay.ToString(); + columns[8] = updatedMachine.PumbMinHeat.ToString(CultureInfo.InvariantCulture); + columns[9] = updatedMachine.AbsMaxHeat.ToString(CultureInfo.InvariantCulture); + columns[10] = updatedMachine.AbsMinHeat.ToString(CultureInfo.InvariantCulture); + columns[11] = updatedMachine.PreHeatingTemp.ToString(CultureInfo.InvariantCulture); + columns[12] = updatedMachine.setTemp1.ToString(CultureInfo.InvariantCulture); + columns[13] = updatedMachine.setTemp2.ToString(CultureInfo.InvariantCulture); + columns[14] = updatedMachine.setTemp3.ToString(CultureInfo.InvariantCulture); + columns[15] = updatedMachine.setTemp4.ToString(CultureInfo.InvariantCulture); + + lines[i] = string.Join(",", columns); + machineFound = true; + break; + } + } + + if (machineFound) + { + File.WriteAllLines(filePath, lines); + return true; + } + + return false; + } + } +} diff --git a/DaireApplication/DataBase/Mapping.cs b/DaireApplication/DataBase/Mapping.cs new file mode 100644 index 0000000..c997c78 --- /dev/null +++ b/DaireApplication/DataBase/Mapping.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace DaireApplication.DataBase; + +public class Mapping +{ + public int Id { get; set; } + public string Name { get; set; } = ""; + public string Address { get; set; } = ""; + public bool IsRead { get; set; } = false; + public List BitNumbers { get; set; } = new(); + + + public ushort getSetTempAddress(int tempAddress) + { + string tAddress = "4000"; + tempAddress -= 30004; + tAddress += tempAddress; + return ushort.Parse(tAddress); + } + public List ReadMappings() + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + List mappings = new(); + + if (File.Exists(filePath)) + { + using StreamReader reader = new(filePath); + string header = reader.ReadLine(); + while (!reader.EndOfStream) + { + string[] columns = reader.ReadLine().Split(','); + mappings.Add(new Mapping + { + Id = int.Parse(columns[0]), + Name = columns[1], + Address = columns[2], + IsRead = columns[3] == "1"|| columns[3] == "True", + BitNumbers =columns[4]!=""? columns[4].Split('|').Select(int.Parse).ToList():new List() + }); + } + return mappings; + } + return null; + } + + public int GetMaxId() + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (File.Exists(filePath)) + { + return File.ReadAllLines(filePath) + .Select(line => line.Split(',')) + .Where(columns => columns.Length > 0) + .Select(columns => int.TryParse(columns[0], out int id) ? id : 0) + .Max(); + } + return -1; + } + + public Mapping ReadMappingById(string id) + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (File.Exists(filePath)) + { + foreach (var line in File.ReadLines(filePath)) + { + string[] columns = line.Split(','); + if (columns[0] == id) + { + return new Mapping + { + Id = int.Parse(columns[0]), + Name = columns[1], + Address = columns[2], + IsRead = columns[3] == "1", + BitNumbers = columns[4].Split('|').Select(int.Parse).ToList() + }; + } + } + } + return null; + } + + public bool AddMapping(Mapping data) + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (File.Exists(filePath)) + { + string newEntry = string.Join(",", [ + GetMaxId() + 1, + data.Name, + data.Address, + data.IsRead ? "1" : "0", + string.Join("|", data.BitNumbers) + ]); + File.AppendAllText(filePath, newEntry + Environment.NewLine); + return true; + } + return false; + } + + public bool DeleteMapping(string id) + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (File.Exists(filePath)) + { + var filteredLines = File.ReadLines(filePath).Where(line => !line.StartsWith(id + ",")).ToArray(); + File.WriteAllLines(filePath, filteredLines); + return true; + } + return false; + } + + public bool UpdateMapping(Mapping updatedMapping) + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + bool mappingFound = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 5) + continue; + + if (int.Parse(columns[0]) == updatedMapping.Id) + { + columns[1] = updatedMapping.Name; + columns[2] = updatedMapping.Address; + columns[3] = updatedMapping.IsRead ? "1" : "0"; + columns[4] = string.Join("|", updatedMapping.BitNumbers); + lines[i] = string.Join(",", columns); + mappingFound = true; + break; + } + } + + if (mappingFound) + { + File.WriteAllLines(filePath, lines); + return true; + } + } + return false; + } + + public bool DeleteBitNumber(int id, int bitNumber) + { + string filePath = DataPathManager.GetDataFilePath("Mapping.csv"); + if (!File.Exists(filePath)) + return false; + + List records = ReadMappings(); + Mapping? record = records.Find(x => x.Id == id); + + if (record != null && record.BitNumbers.Remove(bitNumber)) // Remove bit number if found + { + string header; + using (StreamReader sr = new StreamReader(filePath)) + { + header = sr.ReadLine() ?? string.Empty; + } + + using (StreamWriter writer = new StreamWriter(filePath)) + { + writer.WriteLine(header); + string bitNumbersStr = ""; + foreach (var rec in records) + { + if (rec.Id==id) + { + bitNumbersStr = record.BitNumbers.Count > 0 ? string.Join("|", record.BitNumbers) : ""; + writer.WriteLine($"{rec.Id},{rec.Name},{rec.Address},{rec.IsRead},{bitNumbersStr}"); + + } + else + { + bitNumbersStr = rec.BitNumbers.Count > 0 ? string.Join("|", rec.BitNumbers) : ""; + writer.WriteLine($"{rec.Id},{rec.Name},{rec.Address},{rec.IsRead},{bitNumbersStr}"); + } + + } + } + return true; + } + return false; + } + +} diff --git a/DaireApplication/DataBase/RecipeTable.cs b/DaireApplication/DataBase/RecipeTable.cs new file mode 100644 index 0000000..58819c0 --- /dev/null +++ b/DaireApplication/DataBase/RecipeTable.cs @@ -0,0 +1,239 @@ +using DaireApplication.DataBase; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; + +namespace AvaloniaApplication1.DataBase +{ + public class RecipeTable + { + public int Id { get; set; } + public string Name { get; set; } + public float TankTemp { get; set; } = 0; + public float FountainTemp { get; set; } = 0; + public bool? Mixer { get; set; } = false; + public bool? Fountain { get; set; }=false; + public bool? MoldHeater { get; set; }=false; + public bool? Vibration { get; set; } = false; + public bool? VibHeater { get; set; } = false; + public bool? Pedal { get; set; } = false; + public int PedalOnTime { get; set; } = 0; + public int PedalOffTime { get; set; } = 0; + public float HeatingGoal { get; set; } = 46; + public float CoolingGoal { get; set; } = 27; + public float PouringGoal { get; set; } = 30; + + public RecipeTable() + { + Mixer = null; + Fountain = null; + MoldHeater = null; + Vibration = null; + VibHeater = null; + Pedal = null; + } + + + public List ReadRecipes() + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + List recipes = new List(); + + if (File.Exists(filePath)) + { + using (StreamReader reader = new StreamReader(filePath)) + { + // Skip header + string header = reader.ReadLine(); + while (!reader.EndOfStream) + { + string line = reader.ReadLine(); + string[] columns = line.Split(','); + recipes.Add(new RecipeTable + { + Id = int.Parse(columns[0]), + Name = columns[1], + TankTemp = float.Parse(columns[2]), + FountainTemp = float.Parse(columns[3]), + Mixer = columns[4] == "1", + Fountain = columns[5] == "1", + MoldHeater = columns[6]=="1", + Vibration = columns[7] == "1", + VibHeater = columns[8]== "1", + Pedal = columns[9]=="1", + PedalOnTime = int.Parse(columns[10]), + PedalOffTime = int.Parse(columns[11]), + HeatingGoal = float.Parse(columns[12]), + CoolingGoal = float.Parse(columns[13]), + PouringGoal = float.Parse(columns[14]), + }); + } + } + return recipes; + } + else + { + return null; + } + } + public bool DoesNameExist(string searchName) + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + + if (!File.Exists(filePath)) + return false; + + string[] lines = File.ReadAllLines(filePath); + + return lines + .Select(line => line.Split(',')) + .Where(columns => columns.Length > 1) + .Any(columns => string.Equals(columns[1].Trim(), searchName, StringComparison.OrdinalIgnoreCase)); + } + + public int GetMaxId() + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + int maxId = lines + .Select(line => line.Split(',')) + .Where(columns => columns.Length > 0) + .Select(columns => int.TryParse(columns[0], out int id) ? id : 0) + .Max(); + return maxId; + } + else + { + return -1; + } + } + public RecipeTable ReadRecipesById(string id) + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + RecipeTable recipe = new RecipeTable(); + + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + + foreach (string line in lines) + { + string[] columns = line.Split(','); + + if (columns[0] == id) + { + recipe.Id = int.Parse(columns[0]); + recipe.Name = columns[1]; + recipe.TankTemp = float.Parse(columns[2]); + recipe.FountainTemp = float.Parse(columns[3]); + recipe.Mixer = columns[4] == "1"; + recipe.Fountain = columns[5] == "1"; + recipe.MoldHeater = columns[6] == "1"; + recipe.Vibration = columns[7] == "1"; + recipe.VibHeater = columns[8] == "1"; + recipe.Pedal = columns[9] == "1"; + recipe.PedalOnTime = int.Parse(columns[10]); + recipe.PedalOffTime = int.Parse(columns[11]); + recipe.HeatingGoal = float.Parse(columns[12]); + recipe.CoolingGoal = float.Parse(columns[13]); + recipe.PouringGoal = float.Parse(columns[14]); + return recipe; + } + } + return null; + } + else + { + return null; + } + } + public bool AddRecipe(RecipeTable data) + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + + if (File.Exists(filePath)) + { + string newEntry = string.Join(",", [GetMaxId() +1, data.Name,data.TankTemp, data.FountainTemp, data.Mixer.Value?"1":"0", data.Fountain.Value ? "1" : "0", data.MoldHeater.Value ? "1" : "0", data.Vibration.Value ? "1" : "0", data.VibHeater.Value ? "1" : "0", data.Pedal.Value ? "1":"0",data.PedalOnTime,data.PedalOffTime, data.HeatingGoal,data.CoolingGoal,data.PouringGoal]); + + File.AppendAllText(filePath, newEntry + Environment.NewLine); + return true; + } + else + { + return false; + } + } + public bool DeleteRecipe(string id) + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + var filteredLines = lines.Where(line => !line.StartsWith(id + ",")).ToArray(); + + File.WriteAllLines(filePath, filteredLines); + return true; + } + else + { + return false; + } + } + + public bool UpdateRecipe(RecipeTable updatedRecipe) + { + string filePath = DataPathManager.GetDataFilePath("Recipe.csv"); + + if (!File.Exists(filePath)) + return false; + + string[] lines = File.ReadAllLines(filePath); + bool recipeFound = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 15) + continue; + + if (int.TryParse(columns[0], out int id) && id == updatedRecipe.Id) + { + columns[1] = updatedRecipe.Name ?? ""; + columns[2] = updatedRecipe.TankTemp.ToString(CultureInfo.InvariantCulture); + columns[3] = updatedRecipe.FountainTemp.ToString(CultureInfo.InvariantCulture); + columns[4] = (updatedRecipe.Mixer ?? false) ? "1" : "0"; + columns[5] = (updatedRecipe.Fountain ?? false) ? "1" : "0"; + columns[6] = (updatedRecipe.MoldHeater ?? false) ? "1" : "0"; + columns[7] = (updatedRecipe.Vibration ?? false) ? "1" : "0"; + columns[8] = (updatedRecipe.VibHeater ?? false) ? "1" : "0"; + columns[9] = (updatedRecipe.Pedal ?? false) ? "1" : "0"; + columns[10] = updatedRecipe.PedalOnTime.ToString(); + columns[11] = updatedRecipe.PedalOffTime.ToString(); + columns[12] = updatedRecipe.HeatingGoal.ToString(CultureInfo.InvariantCulture); + columns[13] = updatedRecipe.CoolingGoal.ToString(CultureInfo.InvariantCulture); + columns[14] = updatedRecipe.PouringGoal.ToString(CultureInfo.InvariantCulture); + + lines[i] = string.Join(",", columns); + recipeFound = true; + break; + } + } + + if (recipeFound) + { + File.WriteAllLines(filePath, lines); + return true; + } + + return false; + } + + } +} diff --git a/DaireApplication/DataBase/ScreeenTable.cs b/DaireApplication/DataBase/ScreeenTable.cs new file mode 100644 index 0000000..60f5d1a --- /dev/null +++ b/DaireApplication/DataBase/ScreeenTable.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DaireApplication.DataBase +{ + public class ScreeenTable + { + public int Id { get; set; } + public int brightness { get; set; } + public float dimSec { get; set; } + public float offSec { get; set; } + public string port { get; set; } + public int boundRate { get; set; } + public int stopBits { get; set; } + public int parity { get; set; } + public int sendingTime { get; set; } + public double warningLimit { get; set; } + public double errorLimit { get; set; } + + public List? ReadScreens() + { + try + { + string filePath = DataPathManager.GetDataFilePath("Screen.csv"); + + if (!File.Exists(filePath)) + return null; + + string[] lines = File.ReadAllLines(filePath); + List screens = new(); + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 8) + continue; + + screens.Add(new ScreeenTable + { + Id = int.Parse(columns[0]), + brightness = int.Parse(columns[1]), + dimSec = float.Parse(columns[2]), + offSec = float.Parse(columns[3]), + port = columns[4], + boundRate = int.Parse(columns[5]), + stopBits = int.Parse(columns[6]), + parity = int.Parse(columns[7]), + sendingTime = int.Parse(columns[8]), + warningLimit = double.Parse(columns[9]), + errorLimit = double.Parse(columns[10]), + }); + } + + return screens; + } + catch (Exception) + { + return null; + } + } + + public bool UpdateScreen(ScreeenTable updatedScreen) + { + string filePath = DataPathManager.GetDataFilePath("Screen.csv"); + + if (!File.Exists(filePath)) + return false; + + string[] lines = File.ReadAllLines(filePath); + bool updated = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + + if (columns.Length < 8) + continue; + + if (int.Parse(columns[0]) == updatedScreen.Id) + { + columns[1] = updatedScreen.brightness.ToString(); + columns[2] = updatedScreen.dimSec.ToString(); + columns[3] = updatedScreen.offSec.ToString(); + columns[4] = updatedScreen.port; + columns[5] = updatedScreen.boundRate.ToString(); + columns[6] = updatedScreen.stopBits.ToString(); + columns[7] = updatedScreen.parity.ToString(); + columns[8] = updatedScreen.sendingTime.ToString(); + columns[9] = updatedScreen.warningLimit.ToString(); + columns[10] = updatedScreen.errorLimit.ToString(); + + lines[i] = string.Join(",", columns); + updated = true; + break; + } + } + + if (updated) + { + File.WriteAllLines(filePath, lines); + return true; + } + + return false; + } + } +} diff --git a/DaireApplication/DataBase/UserTable.cs b/DaireApplication/DataBase/UserTable.cs new file mode 100644 index 0000000..6a7c848 --- /dev/null +++ b/DaireApplication/DataBase/UserTable.cs @@ -0,0 +1,83 @@ +using DaireApplication.DataBase; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace AvaloniaApplication1.DataBase +{ + public class UserTable + { + public int Id { get; set; } + public string UserName { get; set; } + public string Password { get; set; } + public bool CanEdit { get; set; } + public bool IsAdmin { get; set; } + public bool IsActive { get; set; } + + public List ReadUsers() + { + string filePath = DataPathManager.GetDataFilePath("Users.csv"); + List users = new List(); + + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + + for (int i = 1; i < lines.Length; i++) // Skip header + { + string[] columns = lines[i].Split(','); + users.Add(new UserTable + { + Id = int.Parse(columns[0]), + UserName = columns[1], + Password = columns[2], + CanEdit = columns[3] =="1" ?true:false, + IsAdmin=columns[4] =="1" ?true: false, + IsActive=columns[5] =="1" ?true: false, + }); + } + return users; + } + else + { + return null; + } + } + + public bool UpdateUser(UserTable updatedUser) + { + string filePath = DataPathManager.GetDataFilePath("Users.csv"); + if (File.Exists(filePath)) + { + string[] lines = File.ReadAllLines(filePath); + bool userFound = false; + + for (int i = 1; i < lines.Length; i++) + { + string[] columns = lines[i].Split(','); + if (int.Parse(columns[0]) == updatedUser.Id) + { + columns[1] = updatedUser.UserName; + columns[2] = updatedUser.Password; + columns[3] = updatedUser.CanEdit ? "1" : "0"; + columns[4] = updatedUser.IsAdmin ? "1" : "0"; + columns[5] = updatedUser.IsActive ? "1" : "0"; + lines[i] = string.Join(",", columns); + userFound = true; + break; + } + } + + if (userFound) + { + File.WriteAllLines(filePath, lines); + return true; + } + } + return false; + } + } +} diff --git a/DaireApplication/Loops/CheckInterNetLoop.cs b/DaireApplication/Loops/CheckInterNetLoop.cs new file mode 100644 index 0000000..ee7b404 --- /dev/null +++ b/DaireApplication/Loops/CheckInterNetLoop.cs @@ -0,0 +1,111 @@ +using Avalonia.Media.Imaging; +using Avalonia.Threading; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.Loops +{ + public class CheckInterNetLoop + { + public static async void CheckInterNet(MainWindow _mainWindow) + { + string textToDelete = ""; + + while (true) + { + if (!Error.IsInternetAvailable()) + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.ContentArea.Content is Home || _mainWindow.ContentArea.Content is Admin) + { + if (!_mainWindow.nowifiLogo.IsVisible) + { + _mainWindow.wifiLogo.IsVisible = false; + _mainWindow.nowifiLogo.IsVisible = true; + } + } + else + { + _mainWindow.wifiLogo.IsVisible = false; + _mainWindow.nowifiLogo.IsVisible = false; + } + //if (!_mainWindow.warningMsg.Text.Contains("No Internet Access")) + //{ + // _mainWindow.warningMsg.Text += "\nNo Internet Access"; + // _mainWindow.warningLogo.IsVisible = true; + + //} + + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.ContentArea.Content is Home || _mainWindow.ContentArea.Content is Admin) + { + if (!_mainWindow.wifiLogo.IsVisible) + { + _mainWindow.nowifiLogo.IsVisible = false; + _mainWindow.wifiLogo.IsVisible = true; + } + } + else + { + _mainWindow.wifiLogo.IsVisible = false; + _mainWindow.nowifiLogo.IsVisible = false; + } + //if (_mainWindow.warningMsg.Text.Contains("No Internet Access")) + //{ + // _mainWindow.warningMsg.Text=_mainWindow.warningMsg.Text.Replace("\nNo Internet Access", ""); + //} + }); + + } + if (!string.IsNullOrEmpty(_mainWindow.warningMessage)) + { + Dispatcher.UIThread.Post(() => + { + if (!_mainWindow.warningMsg.Text.Contains($"\n-{_mainWindow.warningMessage}")) + { + textToDelete = _mainWindow.warningMessage; + _mainWindow.warningMsg.Text += $"\n-{_mainWindow.warningMessage}"; + _mainWindow.warningLogo.IsVisible = true; + + } + + }); + } + else + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.warningMsg.Text.Contains($"-{textToDelete}")) + { + _mainWindow.warningMsg.Text= _mainWindow.warningMsg.Text.Replace($"\n-{textToDelete}", ""); + } + + }); + } + if ( string.IsNullOrEmpty(_mainWindow.warningMessage)) + { + Dispatcher.UIThread.Post(() => + { + _mainWindow.warningLogo.IsVisible = false; + + }); + } + Thread.Sleep(10); + } + } + + } +} diff --git a/DaireApplication/Loops/InteractiveUILoop.cs b/DaireApplication/Loops/InteractiveUILoop.cs new file mode 100644 index 0000000..67523d0 --- /dev/null +++ b/DaireApplication/Loops/InteractiveUILoop.cs @@ -0,0 +1,100 @@ +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.ViewModels; +using DaireApplication.DataBase; +using DaireApplication.Views; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.Loops +{ + public class InteractiveUILoop + { + public static async void Flashing(MainWindow _mainWindow) + { + while (true) + { + // Flashing Pre Heater on + if (_mainWindow.isFlashPreHeating) + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.PreHeatingBtn.Foreground == Brushes.Transparent) + { + _mainWindow.PreHeatingBtn.Foreground = Brushes.White; + } + else + { + _mainWindow.PreHeatingBtn.Foreground = Brushes.Transparent; + } + + }); + } + // Flashing Pre Heater off + if (!_mainWindow.isFlashPreHeating) + { + Dispatcher.UIThread.Post(() => + { + _mainWindow.PreHeatingBtn.Foreground = Brushes.White; + }); + } + // Flashing Mixer on + if (_mainWindow.startMixerMotorFlashing == 1) + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.ContentArea.Content is Settings result) + { + var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label; + var motorRectangel = result.MixerSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + if (motorLable.Foreground.ToString() == "#ff231f20") + { + motorLable.Foreground = Brushes.Transparent ; + motorRectangel.Fill = Brushes.Transparent; + } + else + { + motorLable.Foreground = Brush.Parse("#ff231f20"); + motorRectangel.Fill = Brush.Parse(_mainWindow.PassiveColor); + + + } + } + + + }); + } + + // Flashing Fountain on (only when not in pedal auto mode) + if (_mainWindow.startFountainMotorFlashing == 1 && !_mainWindow.isPedalAutoMode) + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + if (fountainLable.Foreground.ToString() == "#ff231f20") + { + fountainLable.Foreground = Brushes.Transparent; + fountainRectangel.Fill = Brushes.Transparent; + } + else + { + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(_mainWindow.PassiveColor); + + + } + } + }); + } + Thread.Sleep(250); + } + } + } +} diff --git a/DaireApplication/Loops/ScreenLoop.cs b/DaireApplication/Loops/ScreenLoop.cs new file mode 100644 index 0000000..524c213 --- /dev/null +++ b/DaireApplication/Loops/ScreenLoop.cs @@ -0,0 +1,172 @@ +using Avalonia.Threading; +using DaireApplication.Views; +using System; +using System.Linq; +using System.Threading.Tasks; + +namespace DaireApplication.Loops; + +public class ScreenLoop +{ + static void SetBrightness(int value) + { + //File.WriteAllText("/sys/class/backlight/backlight/brightness", value.ToString()); + } + public static async void Screen(MainWindow _mainWindow) + { + var screenData = _mainWindow._screeen.ReadScreens()?[0]; + SetBrightness((int)(screenData.brightness / 100 * 255)); + while (true) + { + try + { + screenData = _mainWindow._screeen.ReadScreens()?[0]; + + if ((DateTime.Now - _mainWindow.lastActivity).TotalSeconds >= screenData?.offSec) + { + if (!MainWindow.isOff) + { + MainWindow.isOff = true; + SetBrightness(0); + } + + } + else if ((DateTime.Now - _mainWindow.lastActivity).TotalSeconds >= screenData?.dimSec) + { + MainWindow.isOff = false; + SetBrightness(51); // 20% of 255 + } + + if (MainWindow.errors.Count > 0) + { + foreach (var item in MainWindow.errors.ToList()) + { + + if ((DateTime.Now - item.errorDate).TotalSeconds >= 2.5) + { + if (!item.isShowen) + { + Dispatcher.UIThread.Post(() => + { + if (_mainWindow.errorMsg.Text.Contains($"- {item.GetDisplayNames(item.Condition)}")) + { + item.isShowen = true; + + } + else + { + _mainWindow.errorMsg.Text += $"\n- {item.GetDisplayNames(item.Condition)}"; + item.isShowen = true; + } + + }); + } + if (item.isDeleted) + { + Dispatcher.UIThread.Post(() => + { + _mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text + .Replace($"- {item.GetDisplayNames(item.Condition)}", ""); + MainWindow.errors.Remove(item); + }); + } + + Dispatcher.UIThread.Post(() => + { + _mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text.Trim(); + if (_mainWindow.ContentArea.Content is Settings settings && MainWindow.errors.Count > 0) + { + //_mainWindow.footerMsg.Text = ""; + settings.mixerBtn.IsEnabled = false; + settings.fountainBtn.IsEnabled = false; + settings.moldHeaterBtn.IsEnabled = false; + settings.vibrationBtn.IsEnabled = false; + settings.vibHeaterBtn.IsEnabled = false; + _mainWindow.PreHeatingBtn.IsEnabled = false; + //_mainWindow.recipeStartBtn.IsEnabled = false; + } + }); + + } + } + + if (MainWindow.errors.Count > 0) + { + if ((DateTime.Now - MainWindow.errors.Min(x => x.errorDate)).TotalSeconds >= 3.5) + { + Dispatcher.UIThread.Post(() => + { + _mainWindow.errorLogo.IsVisible = true; + + _mainWindow.errorTitel.Text = $"Error Number: {MainWindow.errors.Count}"; + _mainWindow.errorMsg.Text = _mainWindow.errorMsg.Text.Trim(); + + //_mainWindow.footerMsg.Text = $"Error Numbers: {MainWindow.errors.Count}"; + //_mainWindow.errorLogoBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + }); + } + + + } + + } + else + { + Dispatcher.UIThread.Post(() => + { + + //MainWindow.errors.Clear(); + _mainWindow.errorLogo.IsVisible = false; + _mainWindow.errorPopupOverlay.IsVisible = false; + if (_mainWindow.ContentArea.Content is Settings settings) + { + //_mainWindow.footerMsg.Text = "Ready"; + + settings.moldHeaterBtn.IsEnabled = true; + settings.vibrationBtn.IsEnabled = true; + settings.vibHeaterBtn.IsEnabled = true; + _mainWindow.recipeStartBtn.IsEnabled = true; + if (_mainWindow.startRecipe != 1) + { + _mainWindow.PreHeatingBtn.IsEnabled = true; + settings.mixerBtn.IsEnabled = true; + settings.fountainBtn.IsEnabled = true; + + } + var isFountOn = false; + var isMixerOn = false; + var fountainMotor =_mainWindow._mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + var mixerMotor =_mainWindow._mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (isFountOn !=fountainMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0)) + { + isFountOn = fountainMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0); + } + if (isMixerOn != mixerMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0)) + { + isMixerOn = mixerMotor.BitNumbers.All(bit => (_mainWindow.holdingRegister.motor & (1 << bit)) != 0); + } + if (isFountOn && isMixerOn) // both motores are on + { + if (_mainWindow.startRecipe == 1 && (_mainWindow.Heating == 10 || _mainWindow.cooling == 10 || _mainWindow.pouring == 10)) + { + _mainWindow.unPause = true; + } + } + + + } + }); + } + + + await Task.Delay(10); + } + catch (Exception) + { + + } + } + + } + +} diff --git a/DaireApplication/Loops/TouchLoop.cs b/DaireApplication/Loops/TouchLoop.cs new file mode 100644 index 0000000..e99ed45 --- /dev/null +++ b/DaireApplication/Loops/TouchLoop.cs @@ -0,0 +1,54 @@ +using DaireApplication.Views; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.Loops +{ + public class TouchLoop + { + static void SetBrightness(int value) + { + //File.WriteAllText("/sys/class/backlight/backlight/brightness", value.ToString()); + } + public static async void Touch(MainWindow _mainWindow) + { + static void WatchInput(int bright, MainWindow _mainWindow) + { + + string inputDevice = "/dev/input/event1"; // adjust based on your touch device + using (FileStream fs = new FileStream(inputDevice, FileMode.Open, FileAccess.Read)) + { + byte[] buffer = new byte[24]; + + fs.Read(buffer, 0, buffer.Length); + _mainWindow.lastActivity = DateTime.Now; + SetBrightness(bright); // Restore brightness if touch + } + } + + var screenData = _mainWindow._screeen.ReadScreens()?[0]; + + while (true) + { + try + { + screenData = _mainWindow._screeen.ReadScreens()?[0]; + int brightnessValue = (int)((screenData.brightness) / 100.0 * 255); + MainWindow.isOff = false; + //WatchInput(brightnessValue, _mainWindow); + Thread.Sleep(200); + } + catch (Exception) + { + + } + + } + } + } +} diff --git a/DaireApplication/Loops/serialThreadLoop.cs b/DaireApplication/Loops/serialThreadLoop.cs new file mode 100644 index 0000000..048a218 --- /dev/null +++ b/DaireApplication/Loops/serialThreadLoop.cs @@ -0,0 +1,504 @@ +using Avalonia.Threading; +using AvaloniaApplication1.ViewModels; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.Loops +{ + public class SerialRequest + { + public enum RequestType { Read, Write } + public RequestType Type { get; set; } + public byte[] Data { get; set; } + public int ExpectedLength { get; set; } + public TaskCompletionSource Completion { get; set; } = new(); + } + + public class serialThreadLoop + { + private static readonly ConcurrentQueue writeQueue = new(); + private static readonly ConcurrentQueue readQueue = new(); + private static bool keepSendingRunning = false; + + public static Task EnqueueWrite(byte[] data, int expectedLength) + { + var req = new SerialRequest { Type = SerialRequest.RequestType.Write, Data = data, ExpectedLength = expectedLength }; + writeQueue.Enqueue(req); + return req.Completion.Task; + } + public static Task EnqueueRead(byte[] data, int expectedLength) + { + var req = new SerialRequest { Type = SerialRequest.RequestType.Read, Data = data, ExpectedLength = expectedLength }; + readQueue.Enqueue(req); + return req.Completion.Task; + } + + public static async void SendViaSerial(MainWindow _mainWindow) + { + try + { + //Debug.WriteLine("SendViaSerial started"); + // Start the keepSending background task if not already running + if (!keepSendingRunning) + { + //Debug.WriteLine("Starting KeepSendingLoop"); + keepSendingRunning = true; + _ = Task.Run(() => KeepSendingLoop(_mainWindow)); + } + + List values = new List(); + while (_mainWindow.serialThreadRunning) + { + //Debug.WriteLine($"SendViaSerial loop iteration - Port status: {(_mainWindow._port?.IsOpen ?? false)}"); + if (_mainWindow._port != null && _mainWindow._port.IsOpen) + { + if (_mainWindow.reSendHolding) + { + values.Clear(); + _mainWindow._configrations = _mainWindow._config.ReadConfigrations(); + values.Add(_mainWindow.holdingRegister.resetError); + values.Add(_mainWindow.holdingRegister.hvOut); + values.Add(_mainWindow.holdingRegister.lvOut); + values.Add(_mainWindow.holdingRegister.motor); + values.Add(_mainWindow.holdingRegister.setTemp1); + values.Add(_mainWindow.holdingRegister.setTemp2); + values.Add(_mainWindow.holdingRegister.setTemp3); + values.Add(_mainWindow.holdingRegister.setTemp4); + values.Add((int)(_mainWindow._configrations[0].i_neut * 10)); + values.Add((int)(_mainWindow._configrations[0].i_mot1 * 10)); + values.Add((int)(_mainWindow._configrations[0].i_mot2 * 10)); + foreach (var item in _mainWindow._configrations) + { + values.Add(item.Max * 10); + values.Add(item.Min * 10); + values.Add(ConvertToDecimal(item.H_out.ToList())); + values.Add(ConvertToDecimal(item.FC_out.ToList())); + values.Add(ConvertToDecimal(item.SC_out.ToList())); + values.Add(item.FC_Threshold * 10); + values.Add(item.HeatConRange * 10); + values.Add(item.kp); + values.Add(item.ki); + values.Add(item.kd); + values.Add(item.kl); + } + _mainWindow._port.DiscardInBuffer(); + _mainWindow._port.DiscardOutBuffer(); + byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, values.ToArray()); + await EnqueueWrite(requstConfig, 7); + _mainWindow.reSendHolding = false; + } + if (_mainWindow.sendConfig) + { + values.Clear(); + _mainWindow._configrations = _mainWindow._config.ReadConfigrations(); + if (!_mainWindow.dontResetOutPuts) + { + values.Add(0); + values.Add(0); + values.Add(0); + values.Add(-10000); + values.Add(-10000); + values.Add(-10000); + values.Add(-10000); + } + values.Add((int)(_mainWindow._configrations[0].i_neut * 10)); + values.Add((int)(_mainWindow._configrations[0].i_mot1 * 10)); + values.Add((int)(_mainWindow._configrations[0].i_mot2 * 10)); + foreach (var item in _mainWindow._configrations) + { + values.Add(item.Max * 10); + values.Add(item.Min * 10); + values.Add(ConvertToDecimal(item.H_out.ToList())); + values.Add(ConvertToDecimal(item.FC_out.ToList())); + values.Add(ConvertToDecimal(item.SC_out.ToList())); + values.Add(item.FC_Threshold * 10); + values.Add(item.HeatConRange * 10); + values.Add(item.kp); + values.Add(item.ki); + values.Add(item.kd); + values.Add(item.kl); + } + + byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(_mainWindow.dontResetOutPuts ? (ushort)8 : (ushort)1, values.ToArray()); + await EnqueueWrite(requstConfig, 7); + _mainWindow.sendConfig = false; + _mainWindow.dontResetOutPuts = false; + } + if (_mainWindow.restBoard) + { + _mainWindow.holdingRegister.hvOut = 0; + _mainWindow.holdingRegister.lvOut = 0; + _mainWindow.holdingRegister.motor = 0; + _mainWindow.holdingRegister.setTemp1 = -10000; + _mainWindow.holdingRegister.setTemp2 = -10000; + _mainWindow.holdingRegister.setTemp3 = -10000; + _mainWindow.holdingRegister.setTemp4 = -10000; + + // Send reset data directly without using the async pattern + List resetValues = new List(); + resetValues.Add(_mainWindow.holdingRegister.resetError); + resetValues.Add(_mainWindow.holdingRegister.hvOut); + resetValues.Add(_mainWindow.holdingRegister.lvOut); + resetValues.Add(_mainWindow.holdingRegister.motor); + resetValues.Add(_mainWindow.holdingRegister.setTemp1); + resetValues.Add(_mainWindow.holdingRegister.setTemp2); + resetValues.Add(_mainWindow.holdingRegister.setTemp3); + resetValues.Add(_mainWindow.holdingRegister.setTemp4); + + byte[] resetRequest = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, resetValues.ToArray()); + await EnqueueWrite(resetRequest, 7); + + _mainWindow.restBoard = false; + } + // Check if there's a pending write request + if (_mainWindow._writeCompletionSource?.Task.Status == TaskStatus.WaitingForActivation) + { + List writingValues = new List(); + writingValues.Add(_mainWindow.holdingRegister.resetError); + writingValues.Add(_mainWindow.holdingRegister.hvOut); + writingValues.Add(_mainWindow.holdingRegister.lvOut); + writingValues.Add(_mainWindow.holdingRegister.motor); + writingValues.Add(_mainWindow.holdingRegister.setTemp1); + writingValues.Add(_mainWindow.holdingRegister.setTemp2); + writingValues.Add(_mainWindow.holdingRegister.setTemp3); + writingValues.Add(_mainWindow.holdingRegister.setTemp4); + byte[] requstConfig = await _mainWindow._modBusMaster.WriteMultipleRegisters(0, writingValues.ToArray()); + var result = await EnqueueWrite(requstConfig, 7); + // Signal completion + bool success = result.Length != 1 || result[0] != 0xFF; + _mainWindow.SetWriteComplete(success); + } + var requstReadingInputs = await _mainWindow._modBusMaster.ReadInputRegisters(0, 18); + await EnqueueRead(requstReadingInputs, 41); + } + } + } + catch (Exception ex) + { + + } + + } + + private static async Task KeepSendingLoop(MainWindow _mainWindow) + { + //Debug.WriteLine("KeepSendingLoop started"); + var startTime = DateTime.Now; + int intervalMs = _mainWindow.screenData.sendingTime; + int requestCount = 0; + + while (_mainWindow.serialThreadRunning) + { + try + { + _mainWindow.screenData = _mainWindow._screeen.ReadScreens()[0]; + //Debug.WriteLine($"KeepSendingLoop iteration - Port status: {(_mainWindow._port?.IsOpen ?? false)}, SendingTime: {_mainWindow.screenData.sendingTime}ms"); + + // Skip if port is not valid + if (_mainWindow._port == null || !_mainWindow._port.IsOpen) + { + //Debug.WriteLine("Port not valid, waiting..."); + await Task.Delay(100); // Wait a bit before checking again + continue; + } + + var scheduledTime = startTime.AddMilliseconds(requestCount * intervalMs); + var now = DateTime.Now; + var waitTime = (scheduledTime - now).TotalMilliseconds; + if (waitTime > 0) + await Task.Delay((int)waitTime); + + SerialRequest req = null; + if (!writeQueue.TryPeek(out req)) + readQueue.TryPeek(out req); + + if (req != null) + { + var requestStart = DateTime.Now; + var response = await keepSendingScenario(_mainWindow, req.Data, req.ExpectedLength,_mainWindow.screenData.sendingTime); + var requestEnd = DateTime.Now; + var requestElapsed = (requestEnd - requestStart).TotalMilliseconds; + if (response.Length != 1 || response[0] != 0xFF) + { + //Debug.WriteLine($"SUCCESS: Total time for request: {requestElapsed} ms"); + if (req.Type == SerialRequest.RequestType.Read) + { + _mainWindow.inputesResponse = response; + } + req.Completion.SetResult(response); + } + else // failed after retries or timeout + { + //Debug.WriteLine($"FAILED: Total time for request: {requestElapsed} ms"); + req.Completion.SetResult(response); // set failure result + } + if (req.Type == SerialRequest.RequestType.Write) + writeQueue.TryDequeue(out _); + else + readQueue.TryDequeue(out _); + } + + requestCount++; + // If we are behind schedule, catch up + if ((DateTime.Now - startTime).TotalMilliseconds > requestCount * intervalMs) + requestCount = (int)((DateTime.Now - startTime).TotalMilliseconds / intervalMs); + } + catch (Exception ex) + { + //Debug.WriteLine($"Error in KeepSendingLoop: {ex.Message}"); + await Task.Delay(100); // Wait a bit before retrying + } + } + } + + private static async Task keepSendingScenario(MainWindow _mainWindow, byte[] request, int expectedLength, int interval) + { + // Enforce minimum interval between packets + using var cts = new CancellationTokenSource(); + int SENDING_INTERVAL = interval; // Minimum interval between sends + + var now = DateTime.Now; + var elapsed = (now - _mainWindow._lastPacketSendTime).TotalMilliseconds; + if (elapsed < _mainWindow.screenData.sendingTime) + { + await Task.Delay((int)(SENDING_INTERVAL - elapsed)); + } + _mainWindow._lastPacketSendTime = DateTime.Now; + + //Debug.WriteLine("keepSending started"); + + // Calculate 4 character delay based on baud rate + double fourCharDelay = (1.0 / _mainWindow.screenData.boundRate) * 44000; + int noResponseRetryCount = 0; + const int MAX_NO_RESPONSE_RETRIES = 3; // Try 3 times, once per second + const int NO_RESPONSE_TIMEOUT = 1000; // 1 second between no-response retries + const int TOTAL_INVALID_RETRY_TIME = 3000; // 3 seconds total for invalid responses + + var startTime = DateTime.Now; + var lastSendTime = DateTime.Now; + var lastValidResponseTime = DateTime.Now; + bool hadValidResponse = false; + + while ((DateTime.Now - startTime).TotalMilliseconds < TOTAL_INVALID_RETRY_TIME) + { + // Calculate time since last send + var timeSinceLastSend = (DateTime.Now - lastSendTime).TotalMilliseconds; + var timeSinceLastValidResponse = (DateTime.Now - lastValidResponseTime).TotalMilliseconds; + + // Check for communication timeout + if (timeSinceLastValidResponse >= TOTAL_INVALID_RETRY_TIME && !hadValidResponse) + { + //Debug.WriteLine("No valid response received within 3 seconds"); + if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom)) + { + MainWindow.errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.NoBoardCom + }); + } + } + + // For no response case, check frequently for response + if (noResponseRetryCount > 0 && timeSinceLastSend < NO_RESPONSE_TIMEOUT) + { + // Check for response every 10ms + if (_mainWindow._port != null && _mainWindow._port.IsOpen) + { + if (_mainWindow._port.BytesToRead >= expectedLength) + { + // Wait 4-char delay when we have enough bytes + await Task.Delay((int)fourCharDelay); + var response = await TryReadOnce(_mainWindow, expectedLength, cts.Token); + //Debug.WriteLine($"Response received during wait after {timeSinceLastSend}ms"); + + if (response.Length == expectedLength && IsValidCrc(response)) + { + hadValidResponse = true; + lastValidResponseTime = DateTime.Now; // Reset valid response timer + var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom); + if (err != null) err.isDeleted = true; + + // For valid response, still respect minimum interval + //if (timeSinceLastSend < SENDING_INTERVAL) + //{ + // var remainingTime = SENDING_INTERVAL - timeSinceLastSend; + // Debug.WriteLine($"Valid response received before {SENDING_INTERVAL}ms, waiting {remainingTime}ms"); + // await Task.Delay((int)remainingTime); + //} + return response; + } + + // For any response (even invalid), increment retry count and continue immediately + noResponseRetryCount++; + if (noResponseRetryCount >= MAX_NO_RESPONSE_RETRIES) + { + //Debug.WriteLine("Max retries exceeded"); + if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom)) + { + MainWindow.errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.NoBoardCom + }); + } + return new byte[] { 0xFF }; + } + + // Break wait and send next retry immediately + lastSendTime = DateTime.Now.AddMilliseconds(-NO_RESPONSE_TIMEOUT); // Force immediate retry + break; + } + /*await Task.Delay(10);*/ // Small delay between checks + continue; + } + } + + // For invalid response case, wait minimum interval between retries + if (timeSinceLastSend < SENDING_INTERVAL) + { + await Task.Delay(1); // Minimal delay to prevent tight loop + continue; + } + + // Send the request + _mainWindow._port.Write(request, 0, request.Length); + lastSendTime = DateTime.Now; + //Debug.WriteLine($"Sent request at {lastSendTime:HH:mm:ss.fffffff}"); + + // Wait 4-char delay after sending + await Task.Delay((int)fourCharDelay); + + // Try to read response + if (_mainWindow._port != null && _mainWindow._port.IsOpen && _mainWindow._port.BytesToRead >= expectedLength) + { + // Wait another 4-char delay when we have enough bytes + await Task.Delay((int)fourCharDelay); + var response = await TryReadOnce(_mainWindow, expectedLength, cts.Token); + + // Handle valid response + if (response.Length >= expectedLength && IsValidCrc(response)) + { + hadValidResponse = true; + lastValidResponseTime = DateTime.Now; // Reset valid response timer + var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom); + if (err != null) err.isDeleted = true; + return response; + } + } + + // Handle invalid/no response + noResponseRetryCount++; + //Debug.WriteLine($"Invalid/No response, attempt {noResponseRetryCount} of {MAX_NO_RESPONSE_RETRIES}"); + if (noResponseRetryCount >= MAX_NO_RESPONSE_RETRIES) + { + //Debug.WriteLine("Max retries exceeded"); + if (!MainWindow.errors.Any(x => x.Condition == Error.GridCondition.NoBoardCom)) + { + MainWindow.errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.NoBoardCom + }); + } + return new byte[] { 0xFF }; + } + } + + return new byte[] { 0xFF }; + } + + private static async Task TryReadOnce(MainWindow _mainWindow, int expectedLength, CancellationToken token) + { + var buffer = new List(); + var startTime = DateTime.UtcNow; + var timeout = 3000; + while ((DateTime.UtcNow - startTime).TotalMilliseconds < timeout) + { + token.ThrowIfCancellationRequested(); + if (_mainWindow._port != null && _mainWindow._port.IsOpen) + { + int available = _mainWindow._port.BytesToRead; + if (available > 0) + { + byte[] temp = new byte[available]; + _mainWindow._port.Read(temp, 0, available); + buffer.AddRange(temp); + if (buffer.Count >= 3) + { + var response = buffer.ToArray(); + if (response.Length < expectedLength) + { + //Debug.WriteLine($"Invalid response length: got {response.Length}, expected {expectedLength}"); + return new byte[] { 0xFF }; + } + if (!IsValidCrc(response)) + { + //Debug.WriteLine("Invalid CRC in response"); + return new byte[] { 0xFF }; + } + var err = MainWindow.errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoBoardCom); + if (err != null) err.isDeleted = true; + return response; + } + } + } + await Task.Delay(1); + } + //Debug.WriteLine("Response timeout"); + return new byte[] { 0xFF }; + } + + private static bool IsValidCrc(byte[] data) + { + if (data.Length < 3) return false; + ushort calculated = ComputeCRC(data.AsSpan(0, data.Length - 2)); + ushort received = (ushort)(data[^2] | (data[^1] << 8)); + return calculated == received; + } + private static ushort ComputeCRC(ReadOnlySpan data) + { + ushort crc = 0xFFFF; + foreach (var b in data) + { + crc ^= b; + for (int i = 0; i < 8; i++) + { + if ((crc & 0x0001) != 0) + { + crc >>= 1; + crc ^= 0xA001; + } + else + { + crc >>= 1; + } + } + } + return crc; + } + static int ConvertToDecimal(List bitPositions) + { + int result = 0; + if (bitPositions.Count() == 1 && bitPositions[0] == -1) + { + return result; + } + foreach (var pos in bitPositions) + { + if (pos is >= 0 and < 16) + result |= 1 << pos; + } + return result; + } + } +} diff --git a/DaireApplication/Pedal_Based_Fountain_Control_Implementation.md b/DaireApplication/Pedal_Based_Fountain_Control_Implementation.md new file mode 100644 index 0000000..bd49fe1 --- /dev/null +++ b/DaireApplication/Pedal_Based_Fountain_Control_Implementation.md @@ -0,0 +1,247 @@ +# Pedal-Based Fountain Control Implementation + +## Overview + +This implementation replaces the previous automatic fountain control with a **direct pedal-based control system**. When the pedal is in AUTO mode, the chocolate fountain directly follows the pedal state - ON when pedal is active, OFF when pedal is inactive. + +## ✅ Expected Behavior + +When pedal is in **AUTO mode**: +- **Pedal ON** (pedalState = 0) → **Chocolate ON** (fountain flows) +- **Pedal OFF** (pedalState = 1) → **Chocolate OFF** (fountain stops) +- **No blinking/flashing** of the Chocolate button +- **Clean alternating ON/OFF** based on pedal timing settings + +## 🔧 Implementation Details + +### 1. Direct Fountain Control Logic + +Located in the main monitoring loop (`pedalMotor == 1` section): + +```csharp +else if (pedalMotor == 1) // auto Pedal +{ + // Set auto mode flag + isPedalAutoMode = true; + + // Direct fountain control based on pedal state + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null && fount.BitNumbers.Count > 0) + { + if (pedalState == 0) // Pedal ON - Turn fountain ON + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); // Set the motor bit ON + } + isFountainMotorOn = true; + startFountainMotor = 1; + sendComFountainMotor = 1; + startFountainMotorFlashing = -1; // No flashing + // ... UI updates and hardware commands + } + else if (pedalState == 1) // Pedal OFF - Turn fountain OFF + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); // Clear the motor bit OFF + } + isFountainMotorOn = false; + startFountainMotor = 0; + sendComFountainMotor = 0; + startFountainMotorFlashing = -1; // No flashing + // ... UI updates and hardware commands + } + } + + // Handle pedal timing (alternating ON/OFF based on recipe settings) + // ... timer management logic +} +``` + +### 2. Pedal Timing Configuration + +From the UI, users can configure: +- **PEDAL OFF TIME**: Duration fountain stays OFF (e.g., 1 unit) +- **PEDAL ON TIME**: Duration fountain stays ON (e.g., 2 seconds) + +The system automatically alternates between these states using timers. + +### 3. UI Feedback + +#### Chocolate Button State +- **ON**: Shows "ON" with active color (magenta underline) +- **OFF**: Shows "OFF" with passive color (gray) +- **No flashing/blinking** during automatic operation + +#### Temperature Display +When fountain is ON, the UI also shows: +- Current Temp: [actual temperature] +- Target Temp: [target temperature] + +### 4. Manual Override + +When user manually clicks the fountain button: +- **Resets pedal auto mode** (`isPedalAutoMode = false`) +- **Stops all pedal timers** +- **Switches to manual mode** (`pedalMotor = -1`) +- **User gains full manual control** + +### 5. Protection Logic + +#### Fountain Control Protection +Normal fountain control logic is disabled when pedal auto mode is active: + +```csharp +// Temperature-based control (disabled in pedal auto mode) +if (checkFountainTMT_PMT && !isPedalAutoMode) + +// Manual control (disabled in pedal auto mode) +if (!checkFountainTMT_PMT && !isPedalAutoMode) + +// Flashing processing (disabled in pedal auto mode) +if (startFountainMotorFlashing == 1 && !isPedalAutoMode) +``` + +#### UI Flashing Protection +The InteractiveUILoop prevents button flashing in pedal auto mode: + +```csharp +// Only flash when not in pedal auto mode +if (_mainWindow.startFountainMotorFlashing == 1 && !_mainWindow.isPedalAutoMode) +``` + +## 🔄 Control Flow + +1. **User sets pedal to AUTO mode** + - Pedal timers start alternating + - `isPedalAutoMode = true` + +2. **Pedal timer triggers state change** + - `pedalState = 0` (ON) or `pedalState = 1` (OFF) + +3. **Main monitoring loop processes state** + - Directly controls fountain motor based on pedal state + - Updates UI immediately + - Sends hardware commands + +4. **Fountain responds immediately** + - ON: Chocolate flows + - OFF: Chocolate stops + - No delays or intermediate states + +5. **Cycle repeats based on timing settings** + - OFF for configured duration + - ON for configured duration + +## 🛡️ Safety Features + +1. **Manual Override**: User can always take manual control +2. **Timer Cleanup**: Pedal timers are properly stopped when needed +3. **State Reset**: Pedal auto mode is reset when starting/stopping recipes +4. **No Conflicts**: Other fountain control mechanisms are disabled during pedal auto mode +5. **Immediate Response**: No delays or buffering - fountain responds instantly to pedal state + +## 🚫 Previous Logic Removed + +The following complex logic was removed and replaced with direct control: +- ❌ Temperature threshold-based fountain control in pedal auto mode +- ❌ Automatic fountain control based on second control box +- ❌ Complex state management with multiple flags +- ❌ Delayed or conditional fountain control +- ❌ Multiple control mechanisms that could conflict + +## 📱 User Interface + +### Settings Panel +Shows current pedal configuration: +- **PEDAL**: AUTO/MANUAL toggle button +- **PEDAL OFF TIME**: Adjustable duration (e.g., 1 unit) +- **PEDAL ON TIME**: Adjustable duration (e.g., 2 seconds) + +### Fountain Button +- **Steady state display** (ON/OFF) +- **Color coding**: Active (magenta) / Passive (gray) +- **No blinking/flashing** during automatic operation +- **Click to override** and take manual control + +## 🧪 Testing Scenarios + +### Scenario 1: Basic Auto Mode Operation +1. Set pedal to AUTO mode +2. Configure timing (e.g., 2s ON, 1 unit OFF) +3. **Expected**: Fountain alternates cleanly between ON/OFF states + +### Scenario 2: Manual Override +1. While in auto mode, click fountain button +2. **Expected**: Auto mode stops, user gains manual control + +### Scenario 3: Recipe Integration +1. Start recipe with pedal in AUTO mode +2. Complete all phases +3. **Expected**: Fountain follows pedal timing throughout + +### Scenario 4: Visual Feedback +1. Observe fountain button during auto operation +2. **Expected**: Clean ON/OFF display without blinking + +## 📋 Configuration + +### Pedal Timing Settings +- Configured through Settings UI +- **PEDAL OFF TIME**: How long fountain stays OFF +- **PEDAL ON TIME**: How long fountain stays ON +- Values are saved in recipe table + +### Control Mode +- **AUTO**: Fountain follows pedal timing automatically +- **MANUAL**: User controls fountain manually via button clicks + +## 🔧 Key Improvements + +### Simplified Logic ✅ +- **Direct control**: Pedal state directly controls fountain +- **No intermediate states** or complex decision trees +- **Immediate response** with no delays + +### User Experience ✅ +- **Predictable behavior**: ON when pedal ON, OFF when pedal OFF +- **Visual clarity**: Clean state display without blinking +- **Easy override**: Click fountain button to take manual control + +### Reliability ✅ +- **No conflicts**: Other control mechanisms properly disabled +- **Clean state management**: Single source of truth for pedal auto mode +- **Proper cleanup**: Timers and states reset when needed + +### Performance ✅ +- **Efficient processing**: Minimal logic overhead +- **Instant response**: No waiting or buffering +- **Resource management**: Proper timer lifecycle management + +## 📝 Technical Notes + +### Timer Management +- `pedalOnTimer`: Controls ON duration +- `pedalOffTimer`: Controls OFF duration +- Timers are properly disposed when not needed + +### State Variables +- `isPedalAutoMode`: Main flag indicating pedal auto mode is active +- `pedalState`: Current pedal state (0=ON, 1=OFF, -1=reset) +- `pedalMotor`: Pedal mode (1=AUTO, -1=MANUAL) + +### Hardware Control +- Direct bit manipulation of `holdingRegister.motor` +- Immediate serial communication with hardware +- Synchronized UI updates + +## ✅ Requirements Fulfilled + +✅ **Direct pedal control**: Fountain follows pedal state exactly +✅ **Timing-based operation**: Uses configured ON/OFF durations +✅ **No blinking**: Clean visual feedback without flashing +✅ **Manual override**: User can always take control +✅ **Proper integration**: Works with existing recipe system +✅ **Clean UI**: Professional appearance without distractions +✅ **Reliable operation**: No conflicts or unexpected behavior \ No newline at end of file diff --git a/DaireApplication/Program.cs b/DaireApplication/Program.cs new file mode 100644 index 0000000..930fc43 --- /dev/null +++ b/DaireApplication/Program.cs @@ -0,0 +1,33 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.ReactiveUI; +using AvaloniaApplication1.DataBase; +using System; +using System.Threading.Tasks; + +namespace DaireApplication +{ + internal sealed class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + public static UserTable? currentUser; + + public static int pouringMinTemp = -5; + public static int absoluteMaxTemp = 70; + public static int absoluteMinTemp = -10; + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace() + .UseReactiveUI(); + + + } +} diff --git a/DaireApplication/Properties/PublishProfiles/FolderProfile.pubxml b/DaireApplication/Properties/PublishProfiles/FolderProfile.pubxml new file mode 100644 index 0000000..813ca27 --- /dev/null +++ b/DaireApplication/Properties/PublishProfiles/FolderProfile.pubxml @@ -0,0 +1,17 @@ + + + + + Release + Any CPU + C:\Users\Swb\Desktop\test + FileSystem + <_TargetId>Folder + net8.0 + win-x64 + true + false + false + false + + \ No newline at end of file diff --git a/DaireApplication/Recipe_System_Enhancement_Summary.md b/DaireApplication/Recipe_System_Enhancement_Summary.md new file mode 100644 index 0000000..d9d62b4 --- /dev/null +++ b/DaireApplication/Recipe_System_Enhancement_Summary.md @@ -0,0 +1,225 @@ +# Recipe System Enhancement Summary + +## Overview +This document outlines the comprehensive enhancements made to the recipe system in the DaireApplication, implementing proper goal checking, timer initiation, and phase transitions as requested. + +## Key Features Implemented + +### 1. Goal Check and Validation +- **Input Validation**: Validates recipe parameters before starting +- **Temperature Goal Validation**: Ensures heating, cooling, and pouring goals are reasonable +- **Logical Validation**: Verifies cooling goal is less than heating goal +- **Real-time Monitoring**: Continuously monitors temperature goals during execution + +### 2. Timer Initiation Logic +- **Dual Goal Checking**: Checks both mixer (tank) and chocolate (fountain) heating goals +- **Conditional Timer Start**: Only starts timers when both goals are met +- **Phase-specific Timers**: Separate timers for heating, cooling, and pouring phases +- **Automatic Phase Transitions**: Seamless transitions between phases + +### 3. Temperature Monitoring and Phase Transitions +- **Continuous Temperature Tracking**: Monitors chocolate temperature throughout the process +- **Cooling Phase Logic**: + - If chocolate temperature equals cooling threshold → Shows cooling delay + - If chocolate temperature not at cooling threshold → Initiates cooling phase +- **Error Handling**: Comprehensive error handling for temperature deviations +- **Warning System**: Proactive warnings when temperatures approach limits + +## Implementation Details + +### Enhanced RecipeStartBtn Method +```csharp +public async void RecipeStartBtn(object? sender, RoutedEventArgs e) +{ + // 1. Initialize and validate recipe parameters + if (!await InitializeAndValidateRecipe()) return; + + // 2. Start goal monitoring and phase transitions + await StartRecipePhaseMonitoring(); + + // 3. Update UI and begin execution +} +``` + +### Goal Checking Methods +```csharp +// Check if mixer heating goal is reached +private async Task CheckMixerHeatingGoal() +{ + bool goalMet = comTankTemp >= recipeHeatingGoal - 3; + // Provides user feedback when goal is reached + return goalMet; +} + +// Check if chocolate heating goal is reached +private async Task CheckChocolateHeatingGoal() +{ + bool goalMet = comFountainTemp >= recipeHeatingGoal - 3; + // Provides user feedback when goal is reached + return goalMet; +} +``` + +### Phase Transition Logic +```csharp +// Handle cooling phase transition based on chocolate temperature +private async Task HandleCoolingPhaseTransition(Settings settings) +{ + bool chocolateAtCoolingTemp = Math.Abs(comFountainTemp - recipeCoolingGoal) <= 3; + + if (chocolateAtCoolingTemp && cooling == -1 && Heating == -1) + { + await ShowCoolingDelay(settings); // Show delay when at target + } + else if (!chocolateAtCoolingTemp && cooling == -1 && Heating == -1) + { + await InitiateCoolingPhase(settings); // Start cooling phase + } +} +``` + +## Enhanced Timer Methods + +### HeatingTimer +- **Improved Error Detection**: Better temperature range checking +- **Enhanced User Feedback**: Detailed status messages with current temperatures +- **Automatic Phase Transition**: Seamlessly transitions to cooling phase +- **Warning System**: Proactive warnings for temperature deviations + +### CoolingTimer +- **Conditional Phase Logic**: Handles both cooling delay and active cooling +- **Temperature Monitoring**: Continuous monitoring of chocolate temperature +- **UI Updates**: Shows/hides cooling delay indicators appropriately +- **Phase Completion**: Automatic transition to pouring phase + +### PouringTimer +- **Recipe Completion**: Handles final phase of recipe execution +- **Pedal Control**: Automatically configures pedal based on recipe settings +- **Success Feedback**: Provides clear completion status +- **Error Handling**: Comprehensive error handling for final phase + +## User Interface Enhancements + +### Real-time Status Updates +- **Temperature Display**: Shows current vs target temperatures +- **Phase Indicators**: Clear indication of current phase +- **Countdown Timers**: Visual countdown for delays +- **Error Messages**: Descriptive error messages with temperature details + +### Enhanced Feedback +- **Goal Achievement**: Notifications when heating goals are reached +- **Phase Transitions**: Clear messages for phase changes +- **Completion Status**: Success messages when recipe completes +- **Warning System**: Proactive warnings for potential issues + +## Error Handling and Safety + +### Comprehensive Validation +- **Recipe Data Validation**: Ensures recipe exists and is valid +- **Temperature Goal Validation**: Validates all temperature parameters +- **Logical Validation**: Ensures goals make logical sense +- **Runtime Validation**: Continuous validation during execution + +### Error Recovery +- **Temperature Error Handling**: Handles temperature deviations gracefully +- **Timer Error Recovery**: Proper cleanup of timers on errors +- **UI State Recovery**: Maintains consistent UI state during errors +- **User Feedback**: Clear error messages for troubleshooting + +## Performance Optimizations + +### Asynchronous Operations +- **Non-blocking UI**: All operations run asynchronously +- **Efficient Monitoring**: Optimized temperature monitoring loops +- **Resource Management**: Proper timer cleanup and resource disposal +- **Memory Management**: Efficient memory usage for long-running operations + +### Timer Management +- **Conditional Timer Creation**: Only creates timers when needed +- **Proper Cleanup**: Ensures all timers are properly disposed +- **State Management**: Maintains consistent timer states +- **Error Recovery**: Handles timer failures gracefully + +## Benefits of the Enhanced System + +### 1. Improved Reliability +- **Goal Validation**: Prevents invalid recipe execution +- **Error Detection**: Early detection of temperature issues +- **Automatic Recovery**: Self-healing from minor issues +- **Consistent Behavior**: Predictable phase transitions + +### 2. Better User Experience +- **Clear Feedback**: Users always know what's happening +- **Real-time Updates**: Live temperature and status information +- **Intuitive Flow**: Logical progression through phases +- **Error Clarity**: Clear error messages for troubleshooting + +### 3. Enhanced Safety +- **Temperature Monitoring**: Continuous safety monitoring +- **Automatic Stops**: Stops on critical temperature deviations +- **Validation**: Prevents dangerous recipe configurations +- **Recovery**: Graceful handling of unexpected conditions + +### 4. Maintainability +- **Modular Design**: Clear separation of concerns +- **Comprehensive Documentation**: Well-documented methods +- **Error Handling**: Robust error handling throughout +- **Code Organization**: Logical method organization + +## Usage Instructions + +### Starting a Recipe +1. **Select Recipe**: Choose a valid recipe with proper temperature goals +2. **Click Start**: Click "START RECIPE" button +3. **Monitor Progress**: Watch real-time temperature and phase updates +4. **Handle Errors**: Respond to any error messages that appear + +### Understanding Phases +1. **Heating Phase**: Waits for both mixer and chocolate to reach heating goal +2. **Cooling Phase**: Either shows delay (if at target) or actively cools +3. **Pouring Phase**: Final phase with temperature monitoring +4. **Completion**: Recipe finishes and prepares for pouring + +### Error Handling +- **Temperature Errors**: Check temperature sensors and heating systems +- **Validation Errors**: Verify recipe configuration +- **Timer Errors**: Restart recipe if timers fail +- **Phase Errors**: Check phase transition conditions + +## Technical Specifications + +### Temperature Tolerances +- **Goal Checking**: ±3°C tolerance for goal achievement +- **Error Limits**: Configurable via `screenData.errorLimit` +- **Warning Limits**: Configurable via `screenData.warningLimit` + +### Timer Intervals +- **Monitoring Frequency**: 1 second intervals for temperature checking +- **UI Updates**: Real-time UI updates via Dispatcher +- **Phase Transitions**: Immediate phase transitions when conditions are met + +### Memory Management +- **Timer Cleanup**: Automatic cleanup of completed timers +- **Resource Disposal**: Proper disposal of all resources +- **State Reset**: Complete state reset on recipe stop + +## Future Enhancements + +### Potential Improvements +1. **Recipe Templates**: Pre-configured recipe templates +2. **Advanced Monitoring**: Additional sensor monitoring +3. **Data Logging**: Recipe execution logging +4. **Remote Monitoring**: Remote recipe monitoring capabilities +5. **Machine Learning**: Predictive temperature control + +### Scalability Considerations +1. **Multiple Recipes**: Support for concurrent recipe execution +2. **Advanced Phases**: Additional recipe phases +3. **Custom Validations**: User-defined validation rules +4. **Integration**: Integration with external systems + +## Conclusion + +The enhanced recipe system provides a robust, reliable, and user-friendly solution for chocolate tempering operations. With comprehensive goal checking, intelligent phase transitions, and extensive error handling, the system ensures consistent, high-quality results while providing clear feedback to operators. + +The modular design and comprehensive documentation make the system maintainable and extensible for future enhancements. The asynchronous architecture ensures responsive user interface while maintaining system reliability and safety. \ No newline at end of file diff --git a/DaireApplication/Temperature_Error_Fix_Summary.md b/DaireApplication/Temperature_Error_Fix_Summary.md new file mode 100644 index 0000000..8212825 --- /dev/null +++ b/DaireApplication/Temperature_Error_Fix_Summary.md @@ -0,0 +1,217 @@ +# Temperature Error Fix Summary + +## Problem Analysis + +### Issue Identified +The system was incorrectly showing "Temperature Error!!" popup during the heating phase when temperatures were **above** the heating goal. This prevented the system from properly transitioning to the cooling phase. + +### Root Cause +The temperature error detection logic was using a **symmetric range** (±2°C around the target) for all phases, which is incorrect: + +- **Heating Phase**: Should only error if temperature is **below** the goal +- **Cooling Phase**: Should only error if temperature is **above** the goal +- **Pouring Phase**: Should error if temperature is outside the acceptable range + +### Example from Image +- **Current Temperature**: 51.0°C +- **Heating Goal**: 46°C +- **Error Limit**: 2°C +- **Old Logic**: Acceptable range = 44°C to 48°C ❌ +- **New Logic**: Acceptable range = 46°C and above ✅ + +## Fixes Implemented + +### 1. HeatingTimer - Fixed Temperature Error Logic + +**Before:** +```csharp +// Symmetric range check (incorrect for heating) +bool tempInRange = (comFountainTemp * 10 >= (recipeHeatingGoal * 10) - (screenData.errorLimit * 10)) && + (comFountainTemp * 10 <= (recipeHeatingGoal * 10) + (screenData.errorLimit * 10)); +``` + +**After:** +```csharp +// Only check if temperature is too low (correct for heating) +bool tempTooLow = comFountainTemp < (recipeHeatingGoal - screenData.errorLimit); +``` + +**Logic:** +- ✅ **Temperatures above goal**: Acceptable during heating +- ❌ **Temperatures below goal**: Show error +- ✅ **Goal achieved**: Proceed to cooling phase + +### 2. CoolingTimer - Fixed Temperature Error Logic + +**Before:** +```csharp +// Symmetric range check (incorrect for cooling) +bool tempInRange = (comFountainTemp * 10 >= (recipeCoolingGoal * 10) - (screenData.errorLimit * 10)) && + (comFountainTemp * 10 <= (recipeCoolingGoal * 10) + (screenData.errorLimit * 10)); +``` + +**After:** +```csharp +// Only check if temperature is too high (correct for cooling) +bool tempTooHigh = comFountainTemp > (recipeCoolingGoal + screenData.errorLimit); +``` + +**Logic:** +- ✅ **Temperatures below goal**: Acceptable during cooling +- ❌ **Temperatures above goal**: Show error +- ✅ **Goal achieved**: Proceed to pouring phase + +### 3. PouringTimer - Maintained Correct Logic + +**Before & After:** +```csharp +// Symmetric range check (correct for pouring) +bool tempInRange = (comFountainTemp >= (recipePouringGoal - screenData.errorLimit)) && + (comFountainTemp <= (recipePouringGoal + screenData.errorLimit)); +``` + +**Logic:** +- ✅ **Temperatures within range**: Acceptable for pouring +- ❌ **Temperatures outside range**: Show error +- ✅ **Goal achieved**: Recipe completed + +### 4. Goal Checking Methods - Updated Logic + +**Before:** +```csharp +// Using 3°C tolerance (too permissive) +bool goalMet = comFountainTemp >= recipeHeatingGoal - 3; +``` + +**After:** +```csharp +// Exact goal checking (more precise) +bool goalMet = comFountainTemp >= recipeHeatingGoal; +``` + +### 5. Cooling Phase Transition - Updated Logic + +**Before:** +```csharp +// Using 3°C tolerance around cooling goal +bool chocolateAtCoolingTemp = Math.Abs(comFountainTemp - recipeCoolingGoal) <= 3; +``` + +**After:** +```csharp +// Check if temperature is at or below cooling goal +bool chocolateAtCoolingTemp = comFountainTemp <= recipeCoolingGoal; +``` + +## Phase-Specific Logic Summary + +### Heating Phase +- **Goal**: Reach or exceed heating temperature +- **Error Condition**: Temperature below (goal - errorLimit) +- **Success Condition**: Temperature >= goal +- **Next Phase**: Cooling + +### Cooling Phase +- **Goal**: Reach or go below cooling temperature +- **Error Condition**: Temperature above (goal + errorLimit) +- **Success Condition**: Temperature <= goal +- **Next Phase**: Pouring + +### Pouring Phase +- **Goal**: Maintain temperature within range +- **Error Condition**: Temperature outside (goal ± errorLimit) +- **Success Condition**: Temperature within range +- **Next Phase**: Recipe completion + +## Error Messages Improved + +### Before +- Generic: "Temperature error: 51.0°C (Target: 46°C)" + +### After +- **Heating**: "Heating temperature too low: 51.0°C (Target: 46°C)" +- **Cooling**: "Cooling temperature too high: 51.0°C (Target: 27°C)" +- **Pouring**: "Pouring temperature out of range: 51.0°C (Target: 30°C)" + +## Warning Messages Improved + +### Before +- Generic: "Temperature approaching limits" + +### After +- **Heating**: "Heating temperature approaching minimum" +- **Cooling**: "Cooling temperature approaching maximum" +- **Pouring**: "Pouring temperature approaching limits" + +## Expected Behavior After Fix + +### Scenario from Image +1. **Current State**: Heating phase with 51.0°C (above 46°C goal) +2. **Old Behavior**: ❌ Shows error popup, prevents progression +3. **New Behavior**: ✅ Recognizes goal achieved, proceeds to cooling +4. **Next Step**: Cooling phase starts automatically + +### Complete Flow +1. **Heating Phase**: + - Wait for both mixer and chocolate to reach heating goal + - No error if temperature exceeds goal + - Proceed to cooling when goals met + +2. **Cooling Phase**: + - Check if chocolate temperature is at/below cooling goal + - If yes: Show cooling delay + - If no: Start active cooling + - Proceed to pouring when cooling complete + +3. **Pouring Phase**: + - Maintain temperature within pouring range + - Complete recipe when pouring timer finishes + +## Benefits of the Fix + +### 1. Correct Phase Progression +- ✅ Heating phase completes when goals are met +- ✅ Cooling phase starts automatically +- ✅ No false error popups + +### 2. Improved User Experience +- ✅ Clear, phase-specific error messages +- ✅ Logical temperature validation +- ✅ Smooth phase transitions + +### 3. Enhanced Safety +- ✅ Proper error detection for each phase +- ✅ Appropriate warnings for each condition +- ✅ Maintains safety while allowing progression + +### 4. Better Reliability +- ✅ Eliminates false error conditions +- ✅ Ensures recipe completion +- ✅ Maintains quality control + +## Testing Recommendations + +### Test Scenarios +1. **Normal Heating**: Temperature reaches and exceeds goal +2. **Slow Heating**: Temperature takes time to reach goal +3. **Fast Heating**: Temperature quickly exceeds goal +4. **Cooling Transition**: Verify cooling phase starts +5. **Error Conditions**: Test actual error scenarios + +### Validation Points +- ✅ No error popup when temperature exceeds heating goal +- ✅ Cooling phase starts after heating delay completes +- ✅ Cooling delay shows when temperature is at/below cooling goal +- ✅ Pouring phase starts after cooling completes +- ✅ Recipe completes successfully + +## Conclusion + +The fix addresses the core issue where the system incorrectly treated temperatures above the heating goal as errors. With the corrected phase-specific logic, the system now: + +1. **Recognizes heating success** when temperatures reach or exceed the goal +2. **Proceeds to cooling phase** automatically after heating delay +3. **Shows appropriate errors** only when temperatures are actually problematic +4. **Provides clear feedback** for each phase and condition + +This ensures the recipe system works as intended, providing reliable chocolate tempering with proper phase progression and error handling. \ No newline at end of file diff --git a/DaireApplication/ViewLocator.cs b/DaireApplication/ViewLocator.cs new file mode 100644 index 0000000..10e704d --- /dev/null +++ b/DaireApplication/ViewLocator.cs @@ -0,0 +1,32 @@ +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using DaireApplication.ViewModels; +using System; + +namespace DaireApplication +{ + public class ViewLocator : IDataTemplate + { + + public Control? Build(object? param) + { + if (param is null) + return null; + + var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); + + if (type != null) + { + return (Control)Activator.CreateInstance(type)!; + } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; + } + } +} diff --git a/DaireApplication/ViewModels/Error.cs b/DaireApplication/ViewModels/Error.cs new file mode 100644 index 0000000..aa553d6 --- /dev/null +++ b/DaireApplication/ViewModels/Error.cs @@ -0,0 +1,93 @@ +using Avalonia.Controls; +using Avalonia.Threading; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Text; +using System.Threading.Tasks; +using static DaireApplication.Views.MainWindow; + +namespace DaireApplication.ViewModels +{ + public class Error + { + public enum GridCondition + { + GridFrequencyHigh, + GridFrequencyLow, + GridVACHigh, + GridVACLow, + NoExternalPower, + MissingPhase, + PhaseSequence, + LoadDisconnection, + MotorDisconnection, + NoBoardCom, + NoInternetAccess, + ComPort1, + ComPort2, + HiCurrNeut, + HiCurrMot1, + HiCurrMot2, + } + public DateTime errorDate { get; set; } + public GridCondition Condition { get; set; } + public bool isShowen { get; set; } = false; + public bool isDeleted { get; set; } = false; + + public string GetDisplayNames(GridCondition condition) + { + return condition switch + { + GridCondition.GridFrequencyHigh => "Grid Frequency High", + GridCondition.GridFrequencyLow => "Grid Frequency Low", + GridCondition.GridVACHigh => "Grid VAC High", + GridCondition.GridVACLow => "Grid VAC Low", + GridCondition.NoExternalPower => "No External Power", + GridCondition.MissingPhase => "Missing Phase", + GridCondition.PhaseSequence => "Phase Sequence", + GridCondition.LoadDisconnection => "Load Disconnection", + GridCondition.MotorDisconnection => "Motor Disconnection", + GridCondition.NoBoardCom => "Communication Timeout", + GridCondition.NoInternetAccess => "No InternetAccess", + GridCondition.ComPort1 => "Com Port1", + GridCondition.ComPort2 => "Com Port2", + GridCondition.HiCurrNeut=> "Hi Curr Neut", + GridCondition.HiCurrMot1=> "Hi Curr Mot1", + GridCondition.HiCurrMot2=> "Hi Curr Mot2", + _ => string.Empty + }; + + + } + public static bool IsInternetAvailable() + { + try + { + var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); + + foreach (var networkInterface in networkInterfaces) + { + if (networkInterface.OperationalStatus == OperationalStatus.Up) + { + using (var ping = new Ping()) + { + var reply = ping.Send("8.8.8.8", 3000); // Pinging Google DNS server with a timeout of 3000ms + if (reply != null && reply.Status == IPStatus.Success) + { + return true; // Internet is available + } + } + } + } + } + catch (Exception) + { + return false; // Return false if there is any exception (e.g., no network interface found, or errors during checking) + } + + return false; // Return false if no network interfaces are available or no successful ping + } + } +} diff --git a/DaireApplication/ViewModels/HoldingRegister.cs b/DaireApplication/ViewModels/HoldingRegister.cs new file mode 100644 index 0000000..1cd2cd6 --- /dev/null +++ b/DaireApplication/ViewModels/HoldingRegister.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DaireApplication.ViewModels +{ + public class HoldingRegister + { + public ushort resetError { get; set; } = 0; + public ushort hvOut { get; set; } = 0; + public ushort lvOut { get; set; } = 0; + public ushort motor { get; set; } = 0; + public int setTemp1 { get; set; } = -10000; + public int setTemp2 { get; set; } = -10000; + public int setTemp3 { get; set; } = -10000; + public int setTemp4 { get; set; } = -10000; + } +} diff --git a/DaireApplication/ViewModels/MainWindowViewModel.cs b/DaireApplication/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..19227fb --- /dev/null +++ b/DaireApplication/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,7 @@ +namespace DaireApplication.ViewModels +{ + public class MainWindowViewModel : ViewModelBase + { + public string Greeting { get; } = "Welcome to Avalonia!"; + } +} diff --git a/DaireApplication/ViewModels/ModBusMaster.cs b/DaireApplication/ViewModels/ModBusMaster.cs new file mode 100644 index 0000000..d673249 --- /dev/null +++ b/DaireApplication/ViewModels/ModBusMaster.cs @@ -0,0 +1,306 @@ +using System; +using System.Collections.Generic; +using System.IO.Ports; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace AvaloniaApplication1.ViewModels +{ + public class ModBusMaster + { + public byte slaveId { get; set; } = 0x01; // Slave ID (your ESP slave ID) + //byte functionCode = 0x05; // Function code for Write Single Coil + //byte coilAddressHigh = 0x00; // Coil address (MSB) + //byte coilAddressLow = 0x00; // Coil address (LSB) + //byte coilValueHigh = 0x00; // Coil value (0xFF00 to turn on, 0x0000 to turn off) + //byte coilValueLow = 0x00; + + // Function to read coils + public async Task ReadCoils(SerialPort port, ushort startAddress, ushort numberOfCoils) + { + try + { + byte functionCode = 0x01; // Function code for Read Coils + byte[] frame = new byte[6]; // Request frame size (without CRC) + + // Construct the request frame + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code (0x01 for Read Coils) + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(numberOfCoils >> 8); // Number of coils high byte + frame[5] = (byte)(numberOfCoils & 0xFF); // Number of coils low byte + + // Calculate CRC and append it to the frame + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + // Send the frame over the serial port + port.DiscardOutBuffer(); + port.DiscardInBuffer(); + + port.Write(fullFrame, 0, fullFrame.Length); + Thread.Sleep(500); + Console.WriteLine("Read Coils request sent."); + + // Buffer for the response (modbus slave response size can vary) + byte[] response = new byte[256]; + int bytesRead = port.Read(response, 0, response.Length); + Console.WriteLine("Response Coils sent."); + + + // Ensure that the response is valid (check slave address and function code) + if (response[0] != slaveId || response[1] != functionCode) + { + Console.WriteLine("Invalid response or error in slave response."); + return null; + } + + // Calculate the number of bytes based on the number of coils + int expectedByteCount = (numberOfCoils + 7) / 8; + if (response[2] != expectedByteCount) + { + Console.WriteLine("Incorrect byte count in the response."); + return null; + } + + // The response bytes are in bit form, and we need to extract them + bool[] coilStates = new bool[numberOfCoils]; // Array to store the coil states + int byteIndex = 3; // Start reading from byte 3 (after slave ID and function code) + byte coilByte = response[byteIndex]; // The byte representing the coil states + + // Loop over all coils and check the corresponding bit + for (int coilIndex = 0; coilIndex < numberOfCoils; coilIndex++) + { + // Check the state of the coil by checking the corresponding bit in coilByte + coilStates[coilIndex] = coilByte == 1 ? true : false; /*(coilByte & (1 << (7 - coilIndex))) != 0;*/ + } + if (coilStates==null) + { + Console.WriteLine("status wael: null"); + + } + else + { + Console.WriteLine($"status: {coilStates[0]}"); + + } + + return coilStates; + } + catch (Exception ex) + { + Console.WriteLine($"error wael: {ex.Message}"); + return null; + } + + } + + + // Function to write a single coil + public async Task WriteSingleCoil(ushort coilAddress, bool state) + { + byte functionCode = 0x05; + byte[] frame = new byte[6]; + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(coilAddress >> 8); // Coil address high byte + frame[3] = (byte)(coilAddress & 0xFF); // Coil address low byte + frame[4] = (byte)(state ? 0xFF : 0x00); // Coil value (ON=0xFF, OFF=0x00) + frame[5] = (byte)(0x00); // Coil value (ON=0xFF, OFF=0x00) + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + + + + + // Function to write multiple coils + public byte[] WriteMultipleCoils( ushort startAddress, bool[] coilValues) + { + byte functionCode = 0x0F; + int byteCount = (coilValues.Length + 7) / 8; // Calculate the number of bytes needed + byte[] frame = new byte[5 + byteCount]; // Basic frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(coilValues.Length); // Number of coils + + frame[5] = (byte)byteCount; // Number of bytes to follow (coil values) + for (int i = 0; i < coilValues.Length; i++) + { + int byteIndex = 5 + 1 + (i / 8); // Start at byte 6, accounting for byte count + if (coilValues[i]) + { + frame[byteIndex] |= (byte)(1 << (i % 8)); // Set the bit corresponding to the coil + } + } + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + // Function to write multiple registers + public async Task WriteSingleRegister(ushort startAddress, int value) + { + byte functionCode = 0x06; // Function code for writing a single register + byte[] frame = new byte[6]; // Basic frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(value >> 8); // Register value high byte + frame[5] = (byte)(value & 0xFF); // Register value low byte + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + public async Task WriteSingleRegister(ushort startAddress, ushort value) + { + byte functionCode = 0x06; // Function code for writing a single register + byte[] frame = new byte[6]; // Basic frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(value >> 8); // Register value high byte + frame[5] = (byte)(value & 0xFF); // Register value low byte + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + public async Task ReadHoldingRegister(ushort startAddress, ushort numberOfRegisters) + { + byte functionCode = 0x03; // Function code for reading holding registers + byte[] frame = new byte[6]; // Basic frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(numberOfRegisters >> 8); // Number of registers high byte + frame[5] = (byte)(numberOfRegisters & 0xFF); // Number of registers low byte + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + + + + public async Task ReadInputRegisters(ushort startAddress, ushort numberOfRegisters) + { + byte functionCode = 0x04; // Function code for reading input registers + byte[] frame = new byte[6]; // Basic frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(numberOfRegisters >> 8); // Number of registers high byte + frame[5] = (byte)(numberOfRegisters & 0xFF); // Number of registers low byte + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + + + public async Task WriteMultipleRegisters(ushort startAddress, float[] values) + { + byte functionCode = 0x10; // Function code for writing multiple registers + byte byteCount = (byte)(values.Length * 2); // Total number of bytes for values + byte[] frame = new byte[7 + byteCount]; // Frame without CRC + + frame[0] = slaveId; // Slave address + frame[1] = functionCode; // Function code + frame[2] = (byte)(startAddress >> 8); // Start address high byte + frame[3] = (byte)(startAddress & 0xFF); // Start address low byte + frame[4] = (byte)(values.Length >> 8); // Number of registers high byte + frame[5] = (byte)(values.Length & 0xFF); // Number of registers low byte + frame[6] = byteCount; // Byte count + + for (int i = 0; i < values.Length; i++) + { + short val = unchecked((short)values[i]); + frame[7 + i * 2] = (byte)(val >> 8); // Register value high byte + frame[8 + i * 2] = (byte)(val & 0xFF); // Register value low byte1 + } + + // Calculate CRC and append it + byte[] crc = CalculateCRC(frame); + byte[] fullFrame = new byte[frame.Length + crc.Length]; + Array.Copy(frame, fullFrame, frame.Length); + Array.Copy(crc, 0, fullFrame, frame.Length, crc.Length); + + return fullFrame; + } + + + + // Function to calculate CRC16 for Modbus RTU frame + public byte[] CalculateCRC(byte[] data) + { + ushort crc = 0xFFFF; + + foreach (byte byteData in data) + { + crc ^= byteData; + + for (int i = 8; i > 0; i--) + { + if ((crc & 0x0001) == 0x0001) + { + crc >>= 1; + crc ^= 0xA001; + } + else + { + crc >>= 1; + } + } + } + + return new byte[] { (byte)(crc & 0xFF), (byte)((crc >> 8) & 0xFF) }; + } + + + } +} diff --git a/DaireApplication/ViewModels/ViewModelBase.cs b/DaireApplication/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..5ff6581 --- /dev/null +++ b/DaireApplication/ViewModels/ViewModelBase.cs @@ -0,0 +1,8 @@ +using ReactiveUI; + +namespace DaireApplication.ViewModels +{ + public class ViewModelBase : ReactiveObject + { + } +} diff --git a/DaireApplication/ViewModels/X11CursorHider.cs b/DaireApplication/ViewModels/X11CursorHider.cs new file mode 100644 index 0000000..f9cd303 --- /dev/null +++ b/DaireApplication/ViewModels/X11CursorHider.cs @@ -0,0 +1,69 @@ +using System; +using System.Runtime.InteropServices; + + public class X11CursorHider +{ + const string X11Lib = "libX11.so"; + + [DllImport(X11Lib)] + static extern IntPtr XOpenDisplay(IntPtr display); + + [DllImport(X11Lib)] + static extern int XCloseDisplay(IntPtr display); + + [DllImport(X11Lib)] + static extern IntPtr XCreatePixmap(IntPtr display, IntPtr drawable, uint width, uint height, uint depth); + + [DllImport(X11Lib)] + static extern IntPtr XCreateBitmapFromData(IntPtr display, IntPtr drawable, byte[] data, uint width, uint height); + + [DllImport(X11Lib)] + static extern IntPtr XCreatePixmapCursor(IntPtr display, IntPtr source, IntPtr mask, ref XColor foreground, ref XColor background, uint x, uint y); + + [DllImport(X11Lib)] + static extern int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor); + + [DllImport(X11Lib)] + static extern int XFreeCursor(IntPtr display, IntPtr cursor); + + [DllImport(X11Lib)] + static extern int XFlush(IntPtr display); + + [DllImport(X11Lib)] + static extern IntPtr XDefaultRootWindow(IntPtr display); + + [StructLayout(LayoutKind.Sequential)] + struct XColor + { + public ulong pixel; + public ushort red, green, blue; + public byte flags; + public byte pad; + } + + public static void HideCursor() + { + IntPtr display = XOpenDisplay(IntPtr.Zero); + if (display == IntPtr.Zero) + { + Console.WriteLine("Cannot open X display"); + return; + } + + IntPtr root = XDefaultRootWindow(display); + + byte[] emptyData = new byte[1] { 0 }; // 1x1 empty bitmap + IntPtr pixmap = XCreateBitmapFromData(display, root, emptyData, 1, 1); + + XColor dummy = new XColor(); + + IntPtr invisibleCursor = XCreatePixmapCursor(display, pixmap, pixmap, ref dummy, ref dummy, 0, 0); + + XDefineCursor(display, root, invisibleCursor); + XFlush(display); + + // Keep the cursor hidden until app closes, remember to call: + // XFreeCursor(display, invisibleCursor); + // XCloseDisplay(display); + } +} diff --git a/DaireApplication/Views/MainWindow.axaml b/DaireApplication/Views/MainWindow.axaml new file mode 100644 index 0000000..8949f9c --- /dev/null +++ b/DaireApplication/Views/MainWindow.axaml @@ -0,0 +1,487 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + V0.6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/MainWindow.axaml.cs b/DaireApplication/Views/MainWindow.axaml.cs new file mode 100644 index 0000000..9e0c342 --- /dev/null +++ b/DaireApplication/Views/MainWindow.axaml.cs @@ -0,0 +1,4917 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Interactivity; +using Avalonia.Layout; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.ViewModels; +using DaireApplication.DataBase; +using DaireApplication.Loops; +using DaireApplication.ViewModels; +using DynamicData; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO.Ports; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +namespace DaireApplication.Views; + +public partial class MainWindow : Window +{ + #region properties + List buffer = new List(); + public ModBusMaster _modBusMaster = new ModBusMaster(); + public MachineTable _machine = new MachineTable(); + public ConfigrationTable _config = new ConfigrationTable(); + public List _configrations = new List(); + public Mapping _map = new Mapping(); + public ScreeenTable _screeen = new(); + public ErrorSettingsTable _error = new(); + public List _mapping = new List(); + public static bool isOff { get; set; } + const double deadZone = 1.5; // Changeable based on stability needs + bool shouldRunFountain = false; + public readonly SemaphoreSlim _keepSendingLock = new(1, 1); + + public SerialPort _port { get; set; } + private static Thread monitorThread; + private static Thread screenThread; + private static Thread touchThread; + private static Thread internetThread; + private static Thread InteractiveUIThread; + private static Thread serialThread; + public bool serialThreadRunning = true; + public bool isRunning = true; + public bool restBoard { get; set; } + public bool sendConfig { get; set; } = true; + public bool reSendHolding { get; set; } + public bool dontResetOutPuts { get; set; } + + bool allBitsOn = false; + bool allPedalBitsOn = false; + public int pedalState { get; set; } = -1; + public int pedalStateChanged { get; set; } = -1; + public float recipeHeatingGoal { get; set; } + public float recipeCoolingGoal { get; set; } + public float recipePouringGoal { get; set; } + + public string ActiveColor { get; set; } = "#A4275D"; + public string PassiveColor { get; set; } = "#666666"; + //Pre Heating + public bool isFlashPreHeating { get; set; } = false; + public bool isReadingTemp { get; set; } = true; + public int startPreHeating { get; set; } = -1; + public int writingMaxTemp { get; set; } = -1; + + //Mixer Motor + private Timer mixerTimer; + private Timer preMixerTimer; + private Timer unifiedMotorTimer; + + private static int mixerSeconds = 1; + private static int preMixerSeconds = 1; + public bool setMixerTimerOnce { get; set; } = false; + public bool checkMixerTWT_HWTH { get; set; } = false; + public bool isMixerMotorOn { get; set; } = false; + public int startMixerMotor { get; set; } = -1; + public int startMixerMotorFlashing { get; set; } = -1; + public int sendComMixerMotor { get; set; } = -1; + + //Fountain Motor + private Timer fountainTimer; + private Timer fountainPauseTimer; + private Timer noChoiceChoosenTimer; + + private static int fountainSeconds = 1; + private static int fountainPauseSeconds = 1; + private static int noChoiceChoosenSeconds = 0; + public bool setFountainTimerOnce { get; set; } = false; + public bool checkFountainTMT_PMT { get; set; } = false; + public bool isFountainMotorOn { get; set; } = false; + public int startFountainMotor { get; set; } = -1; + public int startFountainMotorFlashing { get; set; } = -1; + public int sendComFountainMotor { get; set; } = -1; + + public double comTankTemp { get; set; } = 0; + public double comFountainTemp { get; set; } = 0; + public double comPumpTemp { get; set; } = 0; + + //MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1) + public int moldHeaterMotor { get; set; } = -1; + public int vibrationMotor { get; set; } = -1; + public int vibHeaterMotor { get; set; } = -1; + + //Pedal(manual=0,auto=1) + public int pedalMotor { get; set; } = -1; + + //Recipe Start + + public int startRecipe { get; set; } = 0; + public int sendComTankTemp { get; set; } = -1; + //phase 1 heating + public int Heating { get; set; } = -1; + public int sendComHeating { get; set; } = -1; + public int setHeatingTimerOnce { get; set; } = -1; + public Timer heatingTimer; + public int heatingSeconds { get; set; } = 0; + //phase 2 cooling + public int cooling { get; set; } = -1; + public int sendComCooling { get; set; } = -1; + public int setCoolingTimerOnce { get; set; } = -1; + public Timer coolingTimer; + public int coolingSeconds { get; set; } = 0; + + //phase 3 pouring + public int pouring { get; set; } = -1; + public int sendComPouring { get; set; } = -1; + public int setPouringTimerOnce { get; set; } = -1; + public Timer pouringTimer; + public int pouringSeconds { get; set; } = 0; + + //start the pumb + public int PumbOn { get; set; } = -1; + public Timer pedalOnTimer; + public Timer pedalOffTimer; + public int pedalOnSeconds { get; set; } = 0; + public int pedalOffSeconds { get; set; } = 0; + // 1 turn off ,0 turn on + public int setPedalTimerOnce { get; set; } = -1; + + //Board + + public bool resetPort { get; set; } = false; + public bool keepSendingFlag { get; set; } = false; + + public DateTime lastActivity = DateTime.Now; + + public ScreeenTable screenData = new(); + public static List errors = new(); + public bool pause { get; set; } + public bool unPause { get; set; } + public bool isPaused { get; set; } + public bool pauseTimer { get; set; } + public bool pauseTempTracking { get; set; } + public string warningMessage { get; set; } + + public HoldingRegister holdingRegister = new HoldingRegister(); + + public bool turnOnFountainMotor { get; set; } + public bool stopRecipeFlag { get; set; } + public bool isCoolingDelayMode { get; set; } = false; + public bool isPouringDelayMode { get; set; } = false; + public bool tempWarningAccepted { get; set; } = false; + public bool isPedalAutoMode { get; set; } = false; + public bool isAutomaticFountainControlActive { get; set; } = false; + + // Recipe phase tracking for footer message management + private enum RecipePhase + { + None, + PreHeating, + HeatingDelay, + CoolingPhase, + CoolingDelay, + PouringPhase, + Completed + } + private RecipePhase currentRecipePhase = RecipePhase.None; + + /// + /// Safely update footer message based on current recipe phase + /// + private string lastFooterMessage = ""; + private void UpdateFooterMessage(RecipePhase phase, string message) + { + // Don't update if recipe is completed (unless setting to completed) + if (currentRecipePhase == RecipePhase.Completed && phase != RecipePhase.Completed) + { + return; + } + + // Only update if message has actually changed + if (lastFooterMessage == message) + { + return; + } + + // Only update if we're in the correct phase or transitioning to it + if (currentRecipePhase == phase || phase != RecipePhase.None) + { + currentRecipePhase = phase; + lastFooterMessage = message; + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = message; + }); + } + } + + public Timer stopMixerTimer; + public int stopMixerSecondes { get; set; } + public Timer stopFountainTimer; + public int stopFountainSecondes { get; set; } + + public DateTime _lastPacketSendTime = DateTime.MinValue; + public byte[] inputesResponse = new byte[] { 0xFF }; + + // Replace isWriting flag with async method + public TaskCompletionSource _writeCompletionSource = new TaskCompletionSource(); + #endregion + public Task WriteToSerialAsync(string caller) + { + _writeCompletionSource = new TaskCompletionSource(); + // Optionally log or store the caller for debugging + Debug.WriteLine($"WriteToSerialAsync called by: {caller}"); + return _writeCompletionSource.Task; + } + public void SetWriteComplete(bool success = true) + { + _writeCompletionSource?.TrySetResult(success); + } + + + + #region Construction + public MainWindow() + { + InitializeComponent(); + // Hide cursor using unclutter + try + { + var process = new System.Diagnostics.Process(); + process.StartInfo.FileName = "unclutter"; + process.StartInfo.Arguments = "-idle 0"; // Hide immediately + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.Start(); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to start unclutter: {ex.Message}"); + } + + ContentArea.Content = new Home(this); + this.Closing += OnClosingWindow; + + _machine = _machine.ReadMachine(); + + _configrations = _config.ReadConfigrations(); + _mapping = _map.ReadMappings(); + serialThread = new Thread(() => serialThreadLoop.SendViaSerial(this)) + { + IsBackground = true + }; + serialThread.Start(); + internetThread = new Thread(() => CheckInterNetLoop.CheckInterNet(this)) + { + IsBackground = true + }; + internetThread.Start(); + + screenThread = new Thread(() => ScreenLoop.Screen(this)) + { + IsBackground = true + }; + screenThread.Start(); + InteractiveUIThread = new Thread(() => InteractiveUILoop.Flashing(this)) + { + IsBackground = true + }; + InteractiveUIThread.Start(); + touchThread = new Thread(() => TouchLoop.Touch(this)) + { + IsBackground = true + }; + touchThread.Start(); + monitorThread = new Thread(() => MonitorPortsLoop()) + { + IsBackground = true, + Priority = ThreadPriority.Highest + }; + monitorThread.Start(); + + + } + #endregion + + private async void MonitorPortsLoop() + { + byte[] tankeResponse = new byte[256]; + var fountainResponse = new byte[256]; + + double tankBottomTempValue = -1; + double tankWallTempValue = -1; + double pumpTempValue = -1; + double fountainTempValue = -1; + var tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + var tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + var pump = _mapping.Find(x => x.Name == "Pump Temp"); + var fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + + + static List ToBinary(int number) + { + return Convert.ToString(number, 2) + .PadLeft(16, '0') + .Reverse() + .Select(c => c == '1') + .ToList(); + } + + + while (true) + { + if (isRunning) + { + Dispatcher.UIThread.Post(() => + { + footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + }); + screenData = _screeen.ReadScreens()?[0]; + + try + { + if (!SerialPort.GetPortNames().Contains(screenData.port)) + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + } + _port = null; + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected:Port Name Not Found"; + //Debug.WriteLine("port name not found"); + footerMsg.Foreground = Avalonia.Media.Brushes.DarkRed; + footerMsg.IsVisible = true; + }); + } + else + { + if (resetPort) + { + Debug.WriteLine("Port reset initiated"); + resetAll(); + if (_port != null && _port.IsOpen) + { + Debug.WriteLine("Closing existing port"); + _port.Close(); + } + _port = null; + if (ConnectToSerialPort()) + { + Debug.WriteLine("Port reconnected successfully"); + Dispatcher.UIThread.Post(() => + { + //Conntected + footerMsg.Text = "Connected"; + footerMsg.IsVisible = true; + sendConfig = true; + }); + } + else + { + Debug.WriteLine("Failed to reconnect port"); + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected"; + footerMsg.IsVisible = true; + }); + } + resetPort = false; + Debug.WriteLine("Port reset completed"); + } + if (_port == null) + { + // Connect to the found device + if (!ConnectToSerialPort()) + { + + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected"; + + }); + } + else + { + serialThreadRunning = true; + + sendConfig = true; + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Connected"; + }); + } + } + else + { + try + { + if (!_port.IsOpen) + { + _port.Open(); + } + + + List inputValues = new List(); + + if (isReadingTemp) + { + if (!_port.IsOpen) + { + _port.Open(); + } + // reading inputes + + var requstReadingInputs = await _modBusMaster.ReadInputRegisters(0, 18); + + + + if (inputesResponse.Length != 1 && inputesResponse[0] != 0xFF) + { + var result = inputesResponse.Skip(3).Take(inputesResponse.Count() - 5).ToArray(); + for (int i = 0; i < result.Length; i = i + 2) + { + inputValues.Add(((result[i] << 8) | result[i + 1])); + } + var brdFlags = ToBinary(inputValues[0]); + var inputes = ToBinary(inputValues[1]); + + #region Errors + //Errors + try + { + // Grid Vac + if (inputValues[2] > 220 * 1.1 || inputValues[3] > 220 * 1.1 || inputValues[4] > 220 * 1.1) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridVACHigh + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridVACHigh).isDeleted = true; + } + + } + if (inputValues[2] < 220 * 0.9 || inputValues[3] < 220 * 0.9 || inputValues[4] < 220 * 0.9) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridVACLow + }); + } + + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridVACLow).isDeleted = true; + } + } + //// Grid Freq + _error = _error.ReadErrorSettings()[0]; + if (inputValues[17] > (_error.gridFreq * 10) * 1.1) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridFrequencyHigh + }); + } + + } + else + { + + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridFrequencyHigh).isDeleted = true; + } + } + if (inputValues[17] < (_error.gridFreq * 10) * 0.9) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridFrequencyLow + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridFrequencyLow).isDeleted = true; + } + } + //// Ext Power + if (brdFlags[3]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.NoExternalPower + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) != null) + { + errors.First(x => x.Condition == Error.GridCondition.NoExternalPower).isDeleted = true; + } + } + //// missing Phase + if (brdFlags[5] && _error.ReadErrorSettings()[0].phaseNumber == 3) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.MissingPhase + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) != null) + { + errors.First(x => x.Condition == Error.GridCondition.MissingPhase).isDeleted = true; + } + } + //// Phase sequence + if (brdFlags[4] && _error.ReadErrorSettings()[0].phaseNumber == 3) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.PhaseSequence + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) != null) + { + errors.First(x => x.Condition == Error.GridCondition.PhaseSequence).isDeleted = true; + } + } + //com port1 + if (brdFlags[1]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.ComPort1 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) != null) + { + errors.First(x => x.Condition == Error.GridCondition.ComPort1).isDeleted = true; + } + } + //com port2 + if (brdFlags[2]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.ComPort2 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) != null) + { + errors.First(x => x.Condition == Error.GridCondition.ComPort2).isDeleted = true; + } + } + //hi curr neut + if (brdFlags[6]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrNeut + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrNeut).isDeleted = true; + } + } + //hi curr mot1 + if (brdFlags[7]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrMot1 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrMot1).isDeleted = true; + } + } + //hi curr mot2 + if (brdFlags[8]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrMot2 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrMot2).isDeleted = true; + } + } + } + catch (Exception) + { + + } + #endregion + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + //Board Falgs + foreach (var item in diagnostics.flagRectangles) + { + if (brdFlags[int.Parse(item.Tag.ToString())]) + { + item.Fill = Brush.Parse(diagnostics.RedColor); + } + else + { + item.Fill = Brush.Parse(diagnostics.GrayColor); + + } + } + //power Inputes + diagnostics.ph1.Text = inputValues[2].ToString(); + diagnostics.ph2.Text = inputValues[3].ToString(); + diagnostics.ph3.Text = inputValues[4].ToString(); + + diagnostics.i_nut.Text = (inputValues[5] / 10.0).ToString("0.0"); + diagnostics.gridFreq.Text = (inputValues[17] / 10.0).ToString("0.0"); + // Inputes + foreach (var item in diagnostics.InputesElements.OfType().ToList()) + { + var text = item.Children[0] as TextBlock; + var border = item.Children[1] as Border; + if (inputes[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ACTIVE"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.InputesElements.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "PASSIVE"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.InputesElements.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + //Analog + diagnostics.an1.Text = inputValues[12].ToString(); + diagnostics.an2.Text = inputValues[13].ToString(); + //Temp + diagnostics.t1.Text = ((short)inputValues[8] / 10f).ToString("0.0"); + diagnostics.t2.Text = ((short)inputValues[9] / 10f).ToString("0.0"); + diagnostics.t3.Text = ((short)inputValues[10] / 10f).ToString("0.0"); + diagnostics.t4.Text = ((short)inputValues[11] / 10f).ToString("0.0"); + //InternalTemp + diagnostics.internalTemp.Text = (inputValues[15] / 10.0).ToString("0.0"); + diagnostics.hsTemp.Text = (inputValues[14] / 10.0).ToString("0.0"); + if (inputValues[16] > 40) + { + diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.RedColor); + } + else + { + diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.GrayColor); + } + diagnostics.ExtPwr.Text = (inputValues[16] / 10.0).ToString("0.0"); + + } + + if (ContentArea.Content is Settings settings) + { + if (settings.pedalStateTxt.Text != "AUTO") + { + var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal"); + + ushort registerValue = (ushort)inputValues[1]; + if (allBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0)) + { + allBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0); + } + if (!allBitsOn) + { + settings.pedalUnderLine.Fill = Brush.Parse(settings.PassiveColor); + + } + else + { + settings.pedalUnderLine.Fill = Brush.Parse(settings.ActiveColor); + + } + + } + if (startFountainMotorFlashing != 1) + { + //fountain + + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + + + if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + var fountainLable = settings.FountainSP.Children[1] as Avalonia.Controls.Label; + var fontainRectangel = settings.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + if (!allBitsOn) + { + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(PassiveColor); + //isFountainMotorOn = false; + } + else + { + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(ActiveColor); + //isFountainMotorOn = true; + } + } + + if (startMixerMotorFlashing != 1) + { + //mixer + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + + + if (allBitsOn != mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + var mixerLable = settings.MixerSP.Children[1] as Avalonia.Controls.Label; + var mixerRectangel = settings.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + if (!allBitsOn) + { + mixerLable.Content = "OFF"; + mixerLable.Foreground = Brush.Parse("#ff231f20"); + mixerRectangel.Fill = Brush.Parse(PassiveColor); + //isMixerMotorOn = false; + } + else + { + mixerLable.Content = "ON"; + mixerLable.Foreground = Brush.Parse("#ff231f20"); + mixerRectangel.Fill = Brush.Parse(ActiveColor); + //isMixerMotorOn = true; + } + } + + } + if (ContentArea.Content is ManualControl manual) + { + manual.pumbRealTemp.Text = comPumpTemp.ToString("0.0"); + manual.ChocolateRealTemp.Text = comFountainTemp.ToString("0.0"); + manual.tankWallRealTemp.Text = tankWallTempValue.ToString("0.0"); + manual.pumbRealTemp.Text = comTankTemp.ToString("0.0"); + } + }); + _mapping = _map.ReadMappings(); + //reading Tank Bottom + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + tankBottomTempValue = 0; + foreach (var item in tankBottom.BitNumbers) + { + tankBottomTempValue += ((short)inputValues[item] / 10f); + } + tankBottomTempValue /= tankBottom.BitNumbers.Count; + tankBottomTempValue = Math.Round(tankBottomTempValue, 1); + } + } + //reading Tank Wall + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + tankWallTempValue = 0; + foreach (var item in tankWall.BitNumbers) + { + tankWallTempValue += ((short)inputValues[item] / 10f); + } + tankWallTempValue /= tankWall.BitNumbers.Count; + tankWallTempValue = Math.Round(tankWallTempValue, 1); + } + } + //reading Pump + pump = _mapping.Find(x => x.Name == "Pump Temp"); + + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + pumpTempValue = 0; + + foreach (var item in pump.BitNumbers) + { + pumpTempValue += ((short)inputValues[item] / 10f); + } + pumpTempValue /= pump.BitNumbers.Count; + pumpTempValue = Math.Round(pumpTempValue, 1); + } + } + //reading Fountain + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + fountainTempValue = 0; + + foreach (var item in fountain.BitNumbers) + { + fountainTempValue += ((short)inputValues[item] / 10f); + } + fountainTempValue /= fountain.BitNumbers.Count; + fountainTempValue = Math.Round(fountainTempValue, 1); + } + } + Dispatcher.UIThread.Post(() => + { + if (tankBottomTempValue == -1 && tankWallTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Tank Data To Read"; + tankBottomTempValue = 0; + tankWallTempValue = 0; + } + } + else + { + //comTankTemp = tankBottomTempValue < tankWallTempValue ? tankBottomTempValue : tankWallTempValue; + comTankTemp = tankBottomTempValue; + comTankTemp = comTankTemp == -1 ? 0 : comTankTemp; + } + if (pumpTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Pump Data To Read"; + pumpTempValue = 0; + } + + } + else + { + comPumpTemp = pumpTempValue; + } + if (fountainTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Chocolate Data To Read"; + fountainTempValue = 0; + } + + } + else + { + comFountainTemp = fountainTempValue; + } + if (ContentArea.Content is Settings result) + { + if (result.TankTempValue.Content?.ToString() != comTankTemp.ToString() || result.FountainTempValue.Content?.ToString() != comFountainTemp.ToString()) + { + result.TankTempValue.Content = (comTankTemp).ToString("0.0"); + result.FountainTempValue.Content = (comFountainTemp).ToString("0.0"); + } + } + //if (comTankTemp >= _machine.TankMaxHeat && comFountainTemp >= _machine.PumbMaxHeat) + //{ + // if (preMixerTimer==null) + // { + // preMixerTimer = new Timer(PreMixerTimer, null, 0, 1000); + // } + // mixerSeconds++; + //} + //else + //{ + // if (preMixerTimer != null) + // { + // preMixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + // preMixerTimer = null; + // } + + + //} + } + ); + } + + //read mot val + + if (inputValues.Count != 0) + { + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + diagnostics.curr1.Text = (inputValues[6] / 10.0).ToString("0.0"); + diagnostics.curr2.Text = (inputValues[7] / 10.0).ToString("0.0"); + } + }); + } + } + + + //Pre Heating + if (startPreHeating == 1) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + + if (writingMaxTemp == 1) + { + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + foreach (var item in tankBottom.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + + pump = _mapping.Find(x => x.Name == "Pump Temp"); + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + foreach (var item in pump.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10; + + } + } + + + } + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + foreach (var item in fountain.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + await WriteToSerialAsync("PreHeating"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + + result.recipeSettings.IsEnabled = false; + isFlashPreHeating = true; + footerMsg.Text = "Pre-Heating Active"; + } + }); + writingMaxTemp = -1; + } + + } + if (startPreHeating == 0) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + if (writingMaxTemp == 0) + { + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + foreach (var item in tankBottom.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + + } + + } + + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = -10000; + } + + } + + + } + + pump = _mapping.Find(x => x.Name == "Pump Temp"); + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + foreach (var item in pump.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + foreach (var item in fountain.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + await WriteToSerialAsync("PreHeating"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.recipeSettings.IsEnabled = true; + if (!stopRecipeFlag) + { + footerMsg.Text = "Pre-Heating Stopped"; + + } + } + }); + writingMaxTemp = -1; + } + + } + //Mixer Motor + //Mixer Motorf + if (checkMixerTWT_HWTH) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + } + + if ((comTankTemp >= _machine.TankMaxHeat - screenData.warningLimit) && (comTankTemp <= _machine.TankMaxHeat + screenData.warningLimit)) + { + if (startMixerMotor != 1) + { + if (mixerTimer == null) + { + if (mixerSeconds == 1) + { + mixerSeconds = _machine.MixerDelay; + } + mixerTimer = new Timer(MixerTimer, null, 0, 1000); + //setMixerTimerOnce = false; + } + } + } + + else if (comTankTemp <= recipeCoolingGoal - 3 && startMixerMotor == 1) + { + if (startMixerMotor != 0) + { + if (stopMixerTimer == null) + { + stopMixerSecondes = 5; + stopMixerTimer = new Timer(StopMixerTimer, null, 0, 1000); + } + } + startMixerMotorFlashing = 1; + } + else if (startMixerMotor != 1) + { + if (startMixerMotor != 0) + { + sendComMixerMotor = 0; + } + startMixerMotorFlashing = 1; + } + }); + } + if (!checkMixerTWT_HWTH) + { + if (sendComMixerMotor == 0 && startMixerMotorFlashing == 0) + { + startMixerMotor = -1; + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + + + foreach (var bit in mixer.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Mixer Off due Clicking"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label; + var motorRectangel = result.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + motorLable.Content = "OFF"; + motorLable.Foreground = Brush.Parse("#ff231f20"); + motorRectangel.Fill = Brush.Parse(PassiveColor); + if (startRecipe != 1 && !stopRecipeFlag) + { + footerMsg.Text = "Mixer is OFF"; + } + } + }); + sendComMixerMotor = -1; + startMixerMotorFlashing = -1; + } + } + } + } + if (startMixerMotorFlashing == 1) + { + if (sendComMixerMotor == 0) + { + //turn the motor off + startMixerMotor = 0; + + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + + foreach (var bit in mixer.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Mixer Off due to drop in temp"); + Dispatcher.UIThread.Post(() => + { + if (startRecipe != 1) + { + footerMsg.Text = "waiting for tank target temperature"; + } + }); + sendComMixerMotor = -1; + } + } + } + } + if (startMixerMotorFlashing == 0 && sendComMixerMotor == 1 && !isPaused) + { + startMixerMotor = 1; + //turn the motor on and make the button stable + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + foreach (var bit in mixer.BitNumbers) + { + + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Mixer On"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label; + var motorRectangel = result.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + motorLable.Content = "ON"; + motorLable.Foreground = Brush.Parse("#ff231f20"); + motorRectangel.Fill = Brush.Parse(ActiveColor); + if (startRecipe != 1) + { + footerMsg.Text = "Temperature is OK,Mixer is on"; + } + //if (comTankTemp < result._recipeTable.PouringGoal || + // comFountainTemp < result._recipeTable.PouringGoal) + //{ + // mixerSeconds = 1; + // //checkTMT_PMT = true; + // setMixerTimerOnce = true; + //} + //else + //{ + // //checkTMT_PMT = true; + // setMixerTimerOnce = true; + //} + + } + + }); + + + startMixerMotorFlashing = -1; + sendComMixerMotor = -1; + + } + } + + + } + + //Fountain Motor - Normal temperature-based control (when not in pedal auto mode) + if (checkFountainTMT_PMT && !isPedalAutoMode) + { + Dispatcher.UIThread.Post(() => + { + + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + + + } + + if ((comPumpTemp >= _machine.PumbMaxHeat - screenData.warningLimit) && (comPumpTemp <= _machine.PumbMaxHeat + screenData.warningLimit)) // check the temp and make it stop only if it below cooling temp - 3 degrees + { + if (startFountainMotor != 1) + { + if (fountainTimer is null) + { + if (fountainSeconds == 1) + { + fountainSeconds = _machine.PumbDelay; + } + fountainTimer = new Timer(FountainTimer, null, 0, 1000); + //setFountainTimerOnce = false; + } + } + } + + else if (comPumpTemp <= recipeCoolingGoal - 3 && startFountainMotor == 1) + { + if (startFountainMotor != 0) + { + if (stopFountainTimer == null) + { + stopFountainSecondes = 5; + stopFountainTimer = new Timer(StopFountainTimer, null, 0, 1000); + } + } + if (!isPedalAutoMode) + { + startFountainMotorFlashing = 1; + } + } + else if (startFountainMotor != 1) + { + if (startFountainMotor != 0) + { + sendComFountainMotor = 0; + } + if (!isPedalAutoMode) + { + startFountainMotorFlashing = 1; + } + } + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + if (startFountainMotor != 1 && fountainTimer == null) + { + if (!result.fountainDelayCounter.Text.Equals(comPumpTemp.ToString("0.0"))) + { + result.fountainDelayTxt.Text = "Current Temp:"; + result.fountainDelayCounter.Text = comPumpTemp.ToString("0.0"); + result.fountainTargetTxt.Text = "Target Temp:"; + result.fountainTagetTemp.Text = _machine.PumbMaxHeat.ToString("0.0"); + result.fountainDelayTxt.IsVisible = true; + result.fountainDelayCounter.IsVisible = true; + result.fountainTargetTxt.IsVisible = true; + result.fountainTagetTemp.IsVisible = true; + } + + } + } + + }); + }); + } + //Fountain Motor - Manual control (when not in pedal auto mode) + if (!checkFountainTMT_PMT && !isPedalAutoMode) + { + if (sendComFountainMotor == 0 && startFountainMotorFlashing == 0) + { + startFountainMotor = -1; + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Fountain Off due to click"); + //waitting for 10 sec before pause + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.fountainDelayCounter.Text = "-1"; + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fontainRectangel = result.FountainSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(PassiveColor); + if (startRecipe != 1 && !stopRecipeFlag) + { + footerMsg.Text = "Chocolate is OFF"; + } + stopRecipeFlag = false; + } + }); + + + sendComFountainMotor = -1; + startFountainMotorFlashing = -1; + } + } + + } + } + if (startFountainMotorFlashing == 1 && !isPedalAutoMode) + { + if (sendComFountainMotor == 0) + { + startFountainMotor = 0; + + //turn the motor off + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Fountain Off due to drop in temp"); + //pause the recipe if it started + //waitting for 10 sec before pause + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + + Dispatcher.UIThread.Post(() => + { + if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1)) + { + //footerMsg.Text = "Recipe Paused... waiting for target temperature"; + } + else if (startRecipe != 1) + { + footerMsg.Text = "waiting for pump target temperature"; + + } + }); + //checkTMT_PMT = true; + sendComFountainMotor = -1; + } + } + + } + } + if (startFountainMotorFlashing == 0 && sendComFountainMotor == 1 && errors.Count == 0 && !isPaused) + { + startFountainMotor = 1; + //turn the motor on and make the button stable + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Fountain On"); + if (isPaused) + { + unPause = true; + } + //if (startRecipe == 1 && (Heating == 10 || cooling == 10 || pouring == 10)) + //{ + // if (Heating == 10) + // { + // Heating = 1; + // sendComHeating = 1; + // } + // else if (cooling == 10) + // { + // cooling = 1; + // sendComCooling = 1; + // } + // else if (pouring == 10) + // { + // pouring = 1; + // sendComPouring = 1; + // } + //} + if (fountainPauseTimer != null) + { + fountainPauseTimer = null; + fountainPauseSeconds = 10; + } + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(ActiveColor); + if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1)) + { + if (Heating == 1) + { + footerMsg.Text = "Heating phase"; + + } + else if (cooling == 1) + { + footerMsg.Text = "Cooling phase"; + + } + else if (pouring == 1) + { + footerMsg.Text = "Prepare for pouring"; + } + } + else if (startRecipe != 1) + { + footerMsg.Text = "Temperature is OK,Chocolate is on"; + } + //if (comTankTemp < result._recipeTable.PouringGoal || + // comFountainTemp < result._recipeTable.PouringGoal) + //{ + // fountainSeconds = 1; + // setFountainTimerOnce = true; + //} + //else + //{ + // setFountainTimerOnce = true; + //} + } + }); + + startFountainMotorFlashing = -1; + sendComFountainMotor = -1; + } + } + + } + + // Fountain Motor - Direct control is now handled by pedal state in auto mode + + if (moldHeaterMotor == 0) // off MOLD HEATER + { + var moldHeater = _mapping.Find(x => x.Name == "Mold Heater"); + if (moldHeater != null) + { + if (moldHeater.BitNumbers.Count > 0) + { + foreach (var bit in moldHeater.BitNumbers) + { + holdingRegister.lvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("MoldHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.moldHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.MoldHeaterStatus.Text = "OFF"; + manual.MoldHeaterUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + + moldHeaterMotor = -1; + } + else if (moldHeaterMotor == 1) // on MOLD HEATER + { + var moldHeater = _mapping.Find(x => x.Name == "Mold Heater"); + if (moldHeater != null) + { + if (moldHeater.BitNumbers.Count > 0) + { + foreach (var bit in moldHeater.BitNumbers) + { + + holdingRegister.lvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("MoldHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.moldHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.MoldHeaterStatus.Text = "ON"; + manual.MoldHeaterUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + moldHeaterMotor = -1; + } + if (vibrationMotor == 0) // off VIBRATION + { + var vibrator = _mapping.Find(x => x.Name == "Vibrator"); + + if (vibrator != null) + { + if (vibrator.BitNumbers.Count > 0) + { + + foreach (var bit in vibrator.BitNumbers) + { + holdingRegister.hvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Vibrator"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibrationBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibrationStatus.Text = "OFF"; + manual.VibrationUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + vibrationMotor = -1; + } + else if (vibrationMotor == 1) // on VIBRATION + { + var vibrator = _mapping.Find(x => x.Name == "Vibrator"); + + if (vibrator != null) + { + if (vibrator.BitNumbers.Count > 0) + { + foreach (var bit in vibrator.BitNumbers) + { + holdingRegister.hvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Vibrator"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibrationBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibrationStatus.Text = "ON"; + manual.VibrationUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + + + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + vibrationMotor = -1; + } + if (vibHeaterMotor == 0) // off VIB. HEATER + { + var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater"); + if (vibHeater != null) + { + if (vibHeater.BitNumbers.Count > 0) + { + + foreach (var bit in vibHeater.BitNumbers) + { + + holdingRegister.lvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("VibratorHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibHeaterStatus.Text = "OFF"; + manual.VibHeaterUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + vibHeaterMotor = -1; + } + else if (vibHeaterMotor == 1) // on VIB. HEATER + { + var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater"); + if (vibHeater != null) + { + if (vibHeater.BitNumbers.Count > 0) + { + foreach (var bit in vibHeater.BitNumbers) + { + holdingRegister.lvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("VibratorHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibHeaterStatus.Text = "ON"; + manual.VibHeaterUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + vibHeaterMotor = -1; + } + + + //Start Recipe + if (startRecipe == 1) + { + var tankBtm = _mapping.Find(x => x.Name.ToLower() == "Tank Bottom Temp".ToLower()); + tankWall = _mapping.Find(x => x.Name.ToLower() == "Tank Wall Temp".ToLower()); + var pumb = _mapping.Find(x => x.Name.ToLower() == "Pump Temp".ToLower()); + var fount = _mapping.Find(x => x.Name.ToLower() == "Fountain Temp".ToLower()); + var fountainMotor = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + var mixerMotor = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + + if (tankBtm != null && tankWall != null && pumb != null && fount != null) + { + if (tankBtm.BitNumbers.Count > 0 && tankWall.BitNumbers.Count > 0 && pumb.BitNumbers.Count > 0 && fount.BitNumbers.Count > 0) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + byte[] response = new byte[] { 0xFF }; + + var isFountOn = false; + var isMixerOn = false; + if (isFountOn != fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + isFountOn = fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (isMixerOn != mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + isMixerOn = mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (isFountOn && isMixerOn) // both motors are on + { + // Check if both mixer and chocolate have reached heating goal + bool mixerGoalMet = comTankTemp >= recipeHeatingGoal; + bool chocolateGoalMet = comFountainTemp >= recipeHeatingGoal; + bool bothGoalsMet = mixerGoalMet && chocolateGoalMet; + + if (bothGoalsMet && (cooling != 1 && pouring != 1)) + { + // Both goals met - check temperature before starting heating timer + bool tempTooHigh = comFountainTemp > (recipeHeatingGoal + screenData.warningLimit); + + if (tempTooHigh && !tempWarningAccepted && heatingTimer == null) + { + // Show error window when temperature is too high before starting heating delay + if (noChoiceChoosenTimer == null) + { + noChoiceChoosenSeconds = 0; + noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000); + } + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.tempErrorPopupOverlay.IsVisible = true; + } + // Don't change footer message - keep showing pre-heating status + }); + } + else if (heatingTimer == null) + { + // Temperature is acceptable OR user accepted warning - start heating timer + heatingTimer = new Timer(HeatingTimer, null, 1000, 1000); + heatingSeconds = _machine.HeatingDelay; + + + } + } + else if ((Heating != 1) && (cooling != 1 || cooling != 10) && (pouring != 1 || pouring != 10) && heatingTimer == null && coolingTimer == null && pouringTimer == null && startRecipe == 1) + { + // Goals not met yet - continue heating (only if recipe is still running) + sendComTankTemp = 1; + Heating = 1; + sendComHeating = 1; + setHeatingTimerOnce = 1; + + // Only update footer if we're in pre-heating phase + UpdateFooterMessage(RecipePhase.PreHeating, + $"Pre-heating"); + } + } + //if (comPumpTemp>=_machine.PumbMaxHeat) + //{ + // //start timer + // if (fountainTimer==null) + // { + // if (fountainSeconds == 1) + // { + // fountainSeconds = _machine.PumbDelay; + // } + // fountainTimer = new Timer(FountainTimer, null, 0, 1000); + // } + // if (turnOnFountainMotor) + // { + // fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + // if (fount != null) + // { + // if (fount.BitNumbers.Count > 0) + // { + // foreach (var bit in fount.BitNumbers) + // { + // holdingRegister.motor |= (ushort)(1 << bit); + // } + // isWriting = true; + + // } + // } + + // turnOnFountainMotor = false; + // } + //} + //else + //{ + // startFountainMotorFlashing = 1; + //} + if (sendComTankTemp == 1) + { + sendComTankTemp = -1; + } + if (pause) + { + isPaused = true; + if (Heating == 1) + { + Heating = 10; + } + else if (cooling == 1) + { + cooling = 10; + } + else if (pouring == 1) + { + pouring = 10; + } + //PumbOn = -1; + if (tankBtm != null) + { + if (tankBtm.BitNumbers.Count > 0) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + + if (pumb != null) + { + if (pumb.BitNumbers.Count > 0) + { + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10; + + } + } + + + } + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + holdingRegister.motor = 0; + + await WriteToSerialAsync("RecipePause"); + startMixerMotor = 0; + startFountainMotor = 0; + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Recipe Paused"; + + }); + pause = false; + } + else if (unPause) + { + isPaused = false; + if (Heating == 10) + { + Heating = 1; + sendComHeating = 1; + } + else if (cooling == 10) + { + cooling = 1; + sendComCooling = 1; + } + else if (pouring == 10) + { + pouring = 1; + sendComPouring = 1; + } + PumbOn = 1; + + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Recipe Continued"; + }); + unPause = false; + } + if (Heating == 1) + { + if (errors.Count > 0) + { + if ((DateTime.Now - errors.Min(x => x.errorDate)).TotalSeconds >= 3.5) + { + if (!isPaused) + { + pause = true; + + } + } + + } + else + { + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + // Only start heating delay timer when temperature reaches or exceeds the heating goal + if (comFountainTemp * 10 >= (result._recipeTable?.HeatingGoal * 10) - (screenData.warningLimit * 10)) + { + if (setHeatingTimerOnce == 1) + { + heatingTimer = new Timer(HeatingTimer, null, 1000, 1000); + heatingSeconds = _machine.HeatingDelay; + setHeatingTimerOnce = -1; + + } + } + else if (sendComHeating == 1) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + } + }); + + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat; + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipeHeatingGoal; + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("HeatingPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Heating phase"; + + }); + + sendComHeating = -1; + + } + } + }); + } + + + } + else if (cooling == 1) + { + if (errors.Count > 0) + { + if (!isPaused) + { + //pause = true; + + } + } + else + { + if (sendComCooling == 1) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = -1000; + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = -1000; + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMinHeat; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipeCoolingGoal; + + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("CoolingPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Cooling phase"; + }); + sendComCooling = -1; + + + } + + Dispatcher.UIThread.Post(async () => + { + + if (ContentArea.Content is Settings result) + { + // Check if current temperature is already at pouring goal - skip cooling phase + if (Math.Abs((double)(comFountainTemp * 10) - (double)(result._recipeTable?.PouringGoal * 10 ?? 0)) <= (screenData.warningLimit * 10)) + { + if (setCoolingTimerOnce == 1) + { + // Skip cooling phase, go directly to pouring + cooling = -1; + pouring = 1; + sendComPouring = 1; + setPouringTimerOnce = 1; + setCoolingTimerOnce = -1; + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Already at pouring temperature - starting pouring phase"; + }); + } + } + // Only start cooling delay timer when temperature reaches or goes below the cooling goal + else if (comFountainTemp * 10 <= (result._recipeTable?.CoolingGoal * 10) + (screenData.warningLimit * 10)) + { + if (setCoolingTimerOnce == 1) + { + if (coolingTimer == null) + { + coolingTimer = new Timer(CoolingTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + coolingTimer.Change(1000, 1000); + } + coolingSeconds = _machine.CoolingDelay; + setCoolingTimerOnce = -1; + + } + } + } + }); + } + + + } + else if (pouring == 1) + { + if (errors.Count > 0) + { + if (!isPaused) + { + //pause = true; + + } + } + else + { + if (sendComPouring == 1) + { + + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipePouringGoal; + + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("PouringPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Prepare for pouring"; + }); + sendComPouring = -1; + + } + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + // Only start pouring delay timer when temperature reaches the pouring goal (within tolerance) + if (Math.Abs((double)(comFountainTemp * 10) - (double)(result._recipeTable?.PouringGoal * 10 ?? 0)) <= (screenData.warningLimit * 10)) + { + if (setPouringTimerOnce == 1) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp); + + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp); + + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = -1000; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipePouringGoal; + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + } + } + await WriteToSerialAsync("PouringPhase"); + if (pouringTimer == null) + { + pouringTimer = new Timer(PouringTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + pouringTimer.Change(1000, 1000); + } + pouringSeconds = _machine.PouringDelay; + setPouringTimerOnce = -1; + + } + } + } + }); + } + + + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + + + } + + + if (PumbOn == 1) + { + //Dispatcher.UIThread.Post(() => + //{ + // recipeStartBtn.IsEnabled = true; + + //}); + if (pedalMotor == 0) // Manual Pedal + { + // Reset auto mode flag and stop timers + isPedalAutoMode = false; + + // Stop pedal timers + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnTimer.Dispose(); + pedalOnTimer = null; + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffTimer.Dispose(); + pedalOffTimer = null; + } + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.pedalDelayTxt.IsVisible = false; + settings.pedalDelayCounter.IsVisible = false; + } + }); + + var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal"); + if (pedal != null) + { + // READING THE INPUT REGISTER + if (errors.Count == 0) + { + ushort registerValue = (ushort)inputValues[1]; + if (allPedalBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0)) + { + allPedalBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0); + pedalStateChanged = 1; + } + else + { + pedalStateChanged = 0; + } + + if (!allPedalBitsOn) + { + pedalState = 1;// All bits ON + } + else + { + pedalState = 0; // At least one bit is OFF + } + + // READING THE motor REGISTER + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + bool valueChanged = false; + if (pedalState == 1) // If all monitored bits are ON + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.pedalUnderLine.Fill = Brush.Parse(result.PassiveColor); + } + }); + if (!(comPumpTemp <= recipeCoolingGoal - 3)) + { + foreach (var bit in fount.BitNumbers) + { + if (!ToBinary(holdingRegister.motor)[bit]) + { + //Debug.WriteLine("input value:" + registerValue); + //Debug.WriteLine("pedal on:" + allBitsOn); + holdingRegister.motor |= (ushort)(1 << bit); + valueChanged = true; + + } + } + if (valueChanged) + { + await WriteToSerialAsync("PedalManual"); + valueChanged = false; + if (isPaused) + { + unPause = true; + } + } + + } + + } + else // If at least one monitored bit is OFF + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.pedalUnderLine.Fill = Brush.Parse(result.ActiveColor); + } + }); + if (pedalStateChanged == 1) + { + foreach (var bit in fount.BitNumbers) + { + if (ToBinary(holdingRegister.motor)[bit]) + { + holdingRegister.motor &= (ushort)~(1 << bit); + valueChanged = true; + } + + } + if (valueChanged) + { + await WriteToSerialAsync("PedalManual"); + valueChanged = false; + } + + } + + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + + } + + if (pedalStateChanged == 1) + { + // WRITE UPDATED VALUE TO HVO REGISTER + //isWriting = true; + } + + } + + } + } + + + } + } + + else if (pedalMotor == 1) // auto Pedal + { + // Set auto mode flag + isPedalAutoMode = true; + + // Direct fountain control based on pedal state + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null && fount.BitNumbers.Count > 0) + { + if (pedalState == 0) // Pedal ON - Turn fountain ON + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); // Set the motor bit ON + } + isFountainMotorOn = true; + startFountainMotor = 1; + sendComFountainMotor = 1; + startFountainMotorFlashing = -1; // No flashing + await WriteToSerialAsync("Pedal Auto - Fountain ON"); + + // Update UI to show fountain is ON + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(ActiveColor); + } + }); + } + else if (pedalState == 1) // Pedal OFF - Turn fountain OFF + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); // Clear the motor bit OFF + } + isFountainMotorOn = false; + startFountainMotor = 0; + sendComFountainMotor = 0; + startFountainMotorFlashing = -1; // No flashing + await WriteToSerialAsync("Pedal Auto - Fountain OFF"); + + // Update UI to show fountain is OFF + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(PassiveColor); + } + }); + } + } + + // Reset pedal state and handle timing + pedalState = -1; + + // Handle pedal timing (alternating ON/OFF based on recipe settings) + if (setPedalTimerOnce == 1) // Start OFF timer + { + if (pedalOffTimer == null) + { + pedalOffTimer = new Timer(PedalOffTimer, null, 1000, 1000); + } + else + { + pedalOffTimer.Change(1000, 1000); + } + setPedalTimerOnce = -1; + } + else if (setPedalTimerOnce == 0) // Start ON timer + { + if (pedalOnTimer == null) + { + pedalOnTimer = new Timer(PedalOnTimer, null, 1000, 1000); + } + else + { + pedalOnTimer.Change(1000, 1000); + } + setPedalTimerOnce = -1; + } + } + + //change diag UI + var hvo = ToBinary(holdingRegister.hvOut); + var lvo = ToBinary(holdingRegister.lvOut); + var motor = ToBinary(holdingRegister.motor); + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + foreach (var item in diagnostics.MotoreState.OfType().ToList()) + { + var stackPanel = item.Children[0] as StackPanel; + var text = stackPanel.Children[1] as TextBlock; + var border = item.Children[1] as Border; + if (motor[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.MotoreState.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.MotoreState.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + + // HVO + foreach (var item in diagnostics.hvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (hvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.hvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.hvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + + // LVO + foreach (var item in diagnostics.lvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (lvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + foreach (var item in diagnostics.lvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (lvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + } + }); + + await Task.Delay(100); + + } + } + catch (Exception e) + { + + } + + } + } + } + catch + { + } + finally + { + + } + + } + + + + } + } + + + + + public bool ConnectToSerialPort() + { + screenData = _screeen.ReadScreens()?[0]; + try + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + } + _port = null; + _port = new SerialPort(screenData.port, screenData.boundRate); + switch (screenData.parity) + { + case 0: + _port.Parity = Parity.None; + break; + case 1: + _port.Parity = Parity.Odd; + break; + case 2: + _port.Parity = Parity.Even; + break; + case 3: + _port.Parity = Parity.Mark; + break; + case 4: + _port.Parity = Parity.Space; + break; + default: + _port.Parity = Parity.None; + break; + } + switch (screenData.stopBits) + { + case 2: + _port.StopBits = StopBits.Two; + break; + default: + _port.StopBits = StopBits.One; + break; + } + _port.DataBits = 8; + _port.Handshake = Handshake.None; + _port.DtrEnable = true; + + // Open the serial port + + _port.Open(); + return true; + + } + catch (Exception ex) + { + + Console.WriteLine($"Error connecting to port {screenData.port}: {ex.Message}"); + _port = null; + return false; + } + } + + + + + public void closeConnection() + { + isRunning = false; + monitorThread.Abort(); + } + private async void OnClosing1(object? sender, CancelEventArgs e) + { + closeConnection(); + + } + private void OnClosingWindow(object? sender, WindowClosingEventArgs e) + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + //_port = null; + } + // Example: Cancel the close if needed + // e.Cancel = true; + } + + + + + + //Main Window Functions + private void errorLogoClick(object? sender, RoutedEventArgs e) + { + errorPopupOverlay.IsVisible = true; + //errorTitel.Text = errorLogo.Tag.ToString(); + errorMsg.Text = errorMsg.Text.Trim(); + } + private void warningLogoClick(object? sender, RoutedEventArgs e) + { + warningPopupOverlay.IsVisible = true; + warningTitel.Text = warningLogo.Tag.ToString(); + warningMsg.Text = warningMsg.Text.Trim(); + } + private void HomeTraclBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + result.DeletePopupOverlay.IsVisible = true; + result.DeletePopupOverlay.Tag = "home"; + + } + else if (ContentArea.Content is Diagnostics diagnostics) + { + restBoard = true; + + this.UserName.Content = "Select User"; + footerMsg.Text = ""; + ContentArea.Content = new Home(this); + } + else + { + this.UserName.Content = "Select User"; + footerMsg.Text = ""; + ContentArea.Content = new Home(this); + } + } + private void DiagnosticsBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is AdvanceSettings advanceSettings) + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this, true); + } + else if (ContentArea.Content is ManualControl) + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this, false, true); + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this); + } + + } + private void ChefManualBtn(object? sender, RoutedEventArgs e) + { + footerMsg.Text = ""; + ContentArea.Content = new ManualControl(this); + + } + public void AdvanceSettingsView(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Diagnostics) + { + ContentArea.Content = new AdvanceSettings(this, true, false); + + } + else if (ContentArea.Content is Software) + { + ContentArea.Content = new AdvanceSettings(this, false, true); + + } + else + { + ContentArea.Content = new AdvanceSettings(this); + + } + + } + private void RecipeSelTrackBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + result.DeletePopupOverlay.IsVisible = true; + result.DeletePopupOverlay.Tag = "recipeSel"; + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Recipe(this, Program.currentUser); + } + + + } + private void SettingTrackBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Diagnostics diagnostics) + { + restBoard = true; + } + footerMsg.Text = ""; + ContentArea.Content = new Admin(this, Program.currentUser); + } + private void SoftwareBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is AdvanceSettings) + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this, true); + } + else if (ContentArea.Content is ManualControl) + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this, false, true); + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this); + } + + + } + + private async void PreHeatingClick(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + if (result.recipeSettings.IsEnabled) + { + startPreHeating = 1; + writingMaxTemp = 1; + //if (!isMixerMotorOn) + //{ + // result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + //} + //if (!isFountainMotorOn) + //{ + // result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + //} + } + else + { + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + } + } + + } + //Mixer + public async void MotorClick(object? sender, RoutedEventArgs e) + { + if (!isMixerMotorOn) + { + isMixerMotorOn = true; + checkMixerTWT_HWTH = true; + setMixerTimerOnce = true; + } + else + { + isMixerMotorOn = false; + checkMixerTWT_HWTH = false; + startMixerMotorFlashing = 0; + sendComMixerMotor = 0; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + } + }); + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + + } + } + private void MixerTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comTankTemp >= recipeCoolingGoal - 3) + { + mixerSeconds--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (mixerSeconds <= 0) + { + // Stop the timer after 15 seconds + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + startMixerMotorFlashing = 0; + sendComMixerMotor = 1; + return; + } + if (mixerSeconds <= _machine.MixerDelay) + { + settings.mixerDelayTxt.IsVisible = true; + settings.mixerDelayCounter.Text = mixerSeconds.ToString(); + settings.mixerDelayCounter.IsVisible = true; + + } + } + + }); + + + + } + private void StopMixerTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comTankTemp <= recipeCoolingGoal - 3) + { + stopMixerSecondes--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (stopMixerSecondes <= 0) + { + sendComMixerMotor = 0; + + + + stopMixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + stopMixerTimer = null; + return; + } + } + + }); + + + + } + //Fountain + public async void FountainClick(object? sender, RoutedEventArgs e) + { + // Reset pedal auto mode when user manually controls fountain + if (isPedalAutoMode) + { + isPedalAutoMode = false; + // Stop pedal timers when user takes manual control + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnTimer.Dispose(); + pedalOnTimer = null; + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffTimer.Dispose(); + pedalOffTimer = null; + } + pedalMotor = -1; // Reset to manual mode + } + + if (!isFountainMotorOn) + { + isFountainMotorOn = true; + checkFountainTMT_PMT = true; + setFountainTimerOnce = true; + } + else + { + isFountainMotorOn = false; + + checkFountainTMT_PMT = false; + startFountainMotorFlashing = 0; + sendComFountainMotor = 0; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + } + }); + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + + } + + } + } + private void FountainTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comPumpTemp >= recipeCoolingGoal - 3) + { + fountainSeconds--; + } + else + { + //fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + if (fountainSeconds <= 0) + { + // Stop the timer after 15 seconds + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + startFountainMotorFlashing = 0; + sendComFountainMotor = 1; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + if (startRecipe == 1 && !isPaused) + { + PumbOn = 1; + + } + if (result._recipeTable.Pedal.Value) + { + pedalMotor = 0; + } + else + { + pedalMotor = 1; + pedalState = 0; + setPedalTimerOnce = 1; + } + } + + }); + + return; + } + if (fountainSeconds <= _machine.PumbDelay) + { + + + settings.fountainDelayTxt.Text = "Chocolate Delay: "; + settings.fountainDelayTxt.IsVisible = true; + settings.fountainDelayCounter.Text = fountainSeconds.ToString(); + settings.fountainDelayCounter.IsVisible = true; + settings.fountainTagetTemp.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + + } + } + + + + }); + + + } + private void StopFountainTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comPumpTemp <= recipeCoolingGoal - 3) + { + stopFountainSecondes--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (stopFountainSecondes <= 0) + { + sendComFountainMotor = 0; + + + stopFountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + stopFountainTimer = null; + return; + } + } + + }); + + + + } + private void FountainPauseTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + + if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (fountainPauseSeconds <= 0) + { + pause = true; + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseTimer = null; + } + + return; + } + if (!allBitsOn) + { + //motor is off + //increase the counter + fountainPauseSeconds--; + //footerMsg.Text ="Fountain is off recipe will pause after: "+ fountainPauseSeconds.ToString(); + } + else + { + //motor is on + //cancel the timer + if (fountainPauseTimer != null) + { + + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseTimer = null; + } + } + + //if the counter greater than 10 then pause the recipe + }); + + + } + private void NoChoiceChoosenTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + //increase the coiunter + if (ContentArea.Content is Settings settings) + { + if (settings.tempErrorPopupOverlay.IsVisible) + { + noChoiceChoosenSeconds++; + //footerMsg.Text = "sec" + noChoiceChoosenSeconds.ToString(); + } + else + { + //stop the timer + if (noChoiceChoosenTimer != null) + { + noChoiceChoosenTimer.Change(Timeout.Infinite, Timeout.Infinite); + noChoiceChoosenTimer = null; + } + } + if (noChoiceChoosenSeconds >= 180)//change to 3 min + { + //if it reach the 3 min then stop the recipe + startRecipe = 0; + Heating = 0; + cooling = 0; + pouring = 0; + PumbOn = -1; + pedalMotor = -1; + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + } + } + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + holdingRegister.setTemp1 = -10000; + holdingRegister.setTemp2 = -10000; + holdingRegister.setTemp3 = -10000; + holdingRegister.setTemp4 = -10000; + settings.tempErrorPopupOverlay.IsVisible = false; + Dispatcher.UIThread.Post(async () => + { + await WriteToSerialAsync("NoChoiceChoosenTimer"); + + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + footerMsg.Text = "waitting for too long... Recipe Stoped"; + recipeStartBtn.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + }); + + + } + } + + + }); + + + } + /// + /// Enhanced heating timer with improved goal checking and phase transition logic + /// + private void HeatingTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + if (!pauseTimer) + { + // Continue heating delay countdown + if (heatingSeconds > 0) + { + heatingSeconds--; + } + Heating = 1; + warningMessage = ""; // Clear any previous warnings + } + + // Clear warning message during heating phase + warningMessage = ""; + + // Check if heating phase is complete + if (heatingSeconds <= 0) + { + // Heating phase complete - stop heating timer first + warningMessage = ""; + heatingTimer?.Change(Timeout.Infinite, Timeout.Infinite); + heatingTimer?.Dispose(); + heatingTimer = null; + pauseTimer = false; + pauseTempTracking = false; + Heating = -1; + + // Check if chocolate temperature equals cooling goal (within tolerance) + // Using a small tolerance (0.5°C) for floating point comparison + bool chocolateAtCoolingTemp = Math.Abs(comFountainTemp - recipeCoolingGoal) <= 0.5; + + if (chocolateAtCoolingTemp) + { + // Chocolate is already at cooling temperature - show cooling delay + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + // Hide cooling delay display + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + settings.coolingDelayCounter.Text = _machine.CoolingDelay.ToString(); + UpdateFooterMessage(RecipePhase.CoolingDelay, + $"Cooling delay: {_machine.CoolingDelay} seconds"); + } + }); + + // Start cooling timer for delay countdown + cooling = 1; + sendComCooling = 1; + setCoolingTimerOnce = 1; + coolingSeconds = _machine.CoolingDelay; + + // Set flag to indicate we're in cooling delay mode + isCoolingDelayMode = true; + + if (coolingTimer == null) + { + coolingTimer = new Timer(CoolingTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + coolingTimer.Change(1000, 1000); + } + } + else + { + // Chocolate needs to cool down - start cooling phase + UpdateFooterMessage(RecipePhase.CoolingPhase, "Cooling phase"); + + cooling = 1; + sendComCooling = 1; + setCoolingTimerOnce = 1; + coolingSeconds = 0; // No countdown during cooling phase + + // Set flag to indicate we're in cooling phase mode (not delay mode) + isCoolingDelayMode = false; + + if (coolingTimer == null) + { + coolingTimer = new Timer(CoolingTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + coolingTimer.Change(1000, 1000); + } + } + } + else if (heatingSeconds <= _machine.HeatingDelay && !pauseTimer) + { + // Show heating delay countdown + UpdateFooterMessage(RecipePhase.HeatingDelay, $"Heating delay: {heatingSeconds} seconds"); + } + else if (heatingSeconds > _machine.HeatingDelay) + { + // Show heating phase status with current temperature + footerMsg.Text = $"Heating phase"; + } + } + } + }); + } + /// + /// Enhanced cooling timer with improved goal checking and conditional phase transitions + /// Timer runs every 1000ms (1 second) to count down seconds properly + /// + private void CoolingTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + // Check if we're in cooling phase and chocolate has reached cooling goal + // Using same tolerance as heating phase for consistency + if (!isCoolingDelayMode && Math.Abs(comFountainTemp - recipeCoolingGoal) <= 0.5) + { + // Chocolate reached cooling goal during cooling phase - switch to cooling delay + isCoolingDelayMode = true; + coolingSeconds = _machine.CoolingDelay; // Reset timer for cooling delay + + // Hide cooling delay display + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + settings.coolingDelayCounter.Text = coolingSeconds.ToString(); + UpdateFooterMessage(RecipePhase.CoolingDelay, + $"Cooling delay: {coolingSeconds} seconds"); + } + + if (!pauseTimer && isCoolingDelayMode && coolingSeconds > 0) + { + // Only count down during cooling DELAY, not during cooling PHASE + coolingSeconds--; + warningMessage = ""; // Clear any previous warnings + + // Update the display to show the current countdown + settings.coolingDelayCounter.Text = coolingSeconds.ToString(); + } + else if (!pauseTimer && !isCoolingDelayMode) + { + // During cooling PHASE, just monitor temperature, don't count down + warningMessage = ""; // Clear any previous warnings + } + + // Check for warning conditions - only warn if temperature is too high + bool tempTooHighForWarning = comFountainTemp > (recipeCoolingGoal + screenData.warningLimit); + + if (tempTooHighForWarning) + { + // Show warning when temperature is approaching the upper limit + if (warningMessage != "Cooling temperature approaching maximum") + { + warningMessage = "Cooling temperature approaching maximum"; + } + } + else + { + warningMessage = ""; + } + + // Check if cooling phase is complete (only when in delay mode) + if (isCoolingDelayMode && coolingSeconds <= 0) + { + // Cooling phase complete - transition to pouring phase + warningMessage = ""; + + // Safely stop the cooling timer + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingTimer.Dispose(); + coolingTimer = null; + } + + pauseTimer = false; + pauseTempTracking = false; + cooling = -1; + + // Check if chocolate temperature equals pouring goal + bool chocolateAtPouringTemp = Math.Abs(comFountainTemp - recipePouringGoal) <= 0.5; + + if (chocolateAtPouringTemp) + { + // Chocolate is already at pouring temperature - show pouring delay + pouring = 1; + sendComPouring = 1; + setPouringTimerOnce = 1; + pouringSeconds = _machine.PouringDelay; + isPouringDelayMode = true; + + // Start pouring timer + if (pouringTimer == null) + { + pouringTimer = new Timer(PouringTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + pouringTimer.Change(1000, 1000); + } + + UpdateFooterMessage(RecipePhase.PouringPhase, + $"Pouring delay: {pouringSeconds} seconds"); + } + else + { + // Chocolate needs to reach pouring temperature - start pouring phase + pouring = 1; + sendComPouring = 1; + setPouringTimerOnce = 1; + pouringSeconds = 0; // No countdown during pouring phase + isPouringDelayMode = false; + + // Start pouring timer + if (pouringTimer == null) + { + pouringTimer = new Timer(PouringTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + pouringTimer.Change(1000, 1000); + } + + UpdateFooterMessage(RecipePhase.PouringPhase, "Pouring phase"); + } + + coolingTimer = null; + + // Hide cooling delay labels when cooling phase completes + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + isCoolingDelayMode = false; // Reset the flag + } + else if (isCoolingDelayMode && !pauseTimer) + { + // Show cooling delay countdown when chocolate is already at cooling temperature + // Hide cooling delay display + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + settings.coolingDelayCounter.Text = coolingSeconds.ToString(); + UpdateFooterMessage(RecipePhase.CoolingDelay, + $"Cooling delay: {coolingSeconds} seconds"); + } + else if (!isCoolingDelayMode && !pauseTimer) + { + // Show cooling phase status when chocolate needs to cool down + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + UpdateFooterMessage(RecipePhase.CoolingPhase, "Cooling phase"); + } + } + } + }); + } + /// + /// Enhanced pouring timer with improved goal checking and recipe completion logic + /// Timer runs every 1000ms (1 second) to count down seconds properly + /// + private void PouringTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + try + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + // For pouring phase: Check if temperature is within acceptable range around the goal + // Both too high and too low are problematic for pouring + bool tempInRange = (comFountainTemp >= (recipePouringGoal - screenData.errorLimit)) && + (comFountainTemp <= (recipePouringGoal + screenData.errorLimit)); + + // Check if we're in pouring phase and chocolate has reached pouring goal + if (!isPouringDelayMode && Math.Abs(comFountainTemp - recipePouringGoal) <= 0.5) + { + // Chocolate reached pouring goal during pouring phase - switch to pouring delay + isPouringDelayMode = true; + pouringSeconds = _machine.PouringDelay; // Reset timer for pouring delay + + UpdateFooterMessage(RecipePhase.PouringPhase, + $"Pouring delay: {pouringSeconds} seconds"); + } + + if (!pauseTimer && isPouringDelayMode && pouringSeconds > 0) + { + // Only count down during pouring DELAY + pouringSeconds--; + warningMessage = ""; // Clear any previous warnings + + // Update the display to show the current countdown + UpdateFooterMessage(RecipePhase.PouringPhase, + $"Pouring delay: {pouringSeconds} seconds"); + } + else if (!pauseTimer && !isPouringDelayMode) + { + // During pouring PHASE, just monitor temperature + warningMessage = ""; // Clear any previous warnings + } + + // Check for warning conditions - warn if approaching limits + bool tempInWarningRange = (comFountainTemp >= (recipePouringGoal - screenData.warningLimit)) && + (comFountainTemp <= (recipePouringGoal + screenData.warningLimit)); + + if (!tempInWarningRange) + { + // Show warning when temperature is approaching limits + if (warningMessage != "Pouring temperature approaching limits") + { + warningMessage = "Pouring temperature approaching limits"; + } + } + else + { + warningMessage = ""; + } + + // Check if pouring phase is complete (only when in delay mode) + if (isPouringDelayMode && pouringSeconds <= 0) + { + // Pouring phase complete - recipe finished + warningMessage = ""; + + // Safely stop the pouring timer + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringTimer.Dispose(); + pouringTimer = null; + } + + pauseTimer = false; + pauseTempTracking = false; + pouring = -1; + isPouringDelayMode = false; // Reset the flag + + // Recipe completed successfully + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + // Handle pedal control based on recipe settings + if (result._recipeTable.Pedal.Value) + { + pedalMotor = 0; // Manual mode + } + else + { + pedalMotor = 1; // Auto mode + pedalState = 0; + setPedalTimerOnce = 1; + } + + // Fountain control is now handled directly by pedal state in auto mode + + UpdateFooterMessage(RecipePhase.Completed, "Ready for pouring"); + startRecipe = 0; // Mark recipe as completed + } + }); + } + else if (isPouringDelayMode && !pauseTimer) + { + // Show pouring delay countdown + UpdateFooterMessage(RecipePhase.PouringPhase, $"Pouring delay: {pouringSeconds} seconds"); + } + else if (!isPouringDelayMode && !pauseTimer) + { + // Show pouring phase status + UpdateFooterMessage(RecipePhase.PouringPhase, "Pouring phase"); + } + + } + } + } + catch (Exception ex) + { + footerMsg.Text = $"Error: {ex.Message}"; + } + + + }); + + + + } + /// + /// Pedal OFF timer - counts down the OFF time and then switches to ON mode + /// Timer runs every 1000ms (1 second) to count down seconds properly + /// + private void PedalOffTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + pedalOffSeconds++; + + // Show countdown during OFF time + if (pedalOffSeconds <= result._recipeTable.PedalOffTime) + { + result.pedalDelayTxt.Text = "Pedal OFF: "; + result.pedalDelayCounter.Text = (result._recipeTable.PedalOffTime - pedalOffSeconds + 1).ToString(); + result.pedalDelayTxt.IsVisible = true; + result.pedalDelayCounter.IsVisible = true; + } + + // When OFF time is complete, switch to ON mode + if (pedalOffSeconds >= result._recipeTable.PedalOffTime) + { + pedalOffSeconds = 0; + PumbOn = 1; + pedalMotor = 1; + pedalState = 1; // Set to ON state + + // Stop the OFF timer + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffTimer.Dispose(); + pedalOffTimer = null; + } + + // If still in auto mode, continue the cycle by starting the ON timer + if (isPedalAutoMode) + { + setPedalTimerOnce = 0; + } + } + } + }); + } + /// + /// Pedal ON timer - counts down the ON time and then switches to OFF mode + /// Timer runs every 1000ms (1 second) to count down seconds properly + /// + private void PedalOnTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + pedalOnSeconds++; + + // Show countdown during ON time + if (pedalOnSeconds <= result._recipeTable.PedalOnTime) + { + result.pedalDelayTxt.Text = "Pedal ON: "; + result.pedalDelayCounter.Text = (result._recipeTable.PedalOnTime - pedalOnSeconds + 1).ToString(); + result.pedalDelayTxt.IsVisible = true; + result.pedalDelayCounter.IsVisible = true; + } + + // When ON time is complete, switch to OFF mode + if (pedalOnSeconds >= result._recipeTable.PedalOnTime) + { + pedalOnSeconds = 0; + PumbOn = 1; + pedalMotor = 1; + pedalState = 0; // Set to OFF state + + // Stop the ON timer + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnTimer.Dispose(); + pedalOnTimer = null; + } + + // If still in auto mode, continue the cycle by starting the OFF timer + if (isPedalAutoMode) + { + setPedalTimerOnce = 1; + } + } + } + }); + } + //Recipe Start + public async void RecipeStartBtn(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (startRecipe == 0) + { + // Initialize and validate recipe parameters + if (!await InitializeAndValidateRecipe()) + { + return; // Exit if validation fails + } + + startRecipe = 1; + stopRecipeFlag = false; + tempWarningAccepted = false; // Reset temperature warning acceptance for new recipe + currentRecipePhase = RecipePhase.PreHeating; // Start with pre-heating phase + isPedalAutoMode = false; // Reset pedal auto mode for new recipe + + if (ContentArea.Content is Settings result) + { + // Retrieve recipe goals from settings + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + + // Check if pre-heating is required + if (comPumpTemp * 10 < _machine.PumbMaxHeat * 10 || comTankTemp * 10 < _machine.TankMaxHeat * 10) + { + startPreHeating = 1; + writingMaxTemp = 1; + footerMsg.Text = "Pre-heating in progress..."; + } + + // Ensure motors are running if needed + if (!isMixerMotorOn) + { + result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + if (!isFountainMotorOn) + { + result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + + // Start goal monitoring and phase transitions + await StartRecipePhaseMonitoring(); + + // Update UI to indicate recipe is running + Dispatcher.UIThread.Post(() => + { + result.mixerBtn.IsEnabled = false; + result.fountainBtn.IsEnabled = false; + PreHeatingBtn.IsEnabled = false; + recipeStartBtn.IsEnabled = true; + button.Background = Avalonia.Media.Brushes.Red; + button.Content = "STOP RECIPE"; + }); + } + } + else if (startRecipe == 1) + { + // Stop recipe execution + await StopRecipeExecution(button); + } + } + } + + /// + /// Initialize and validate recipe parameters before starting + /// + private async Task InitializeAndValidateRecipe() + { + try + { + if (ContentArea.Content is Settings result) + { + // Validate recipe data exists + if (result._recipeTable == null) + { + footerMsg.Text = "Error: No recipe selected"; + return false; + } + + // Validate temperature goals are reasonable + if (result._recipeTable.HeatingGoal <= 0 || result._recipeTable.CoolingGoal <= 0 || result._recipeTable.PouringGoal <= 0) + { + footerMsg.Text = "Error: Invalid temperature goals in recipe"; + return false; + } + + // Validate cooling goal is less than heating goal + if (result._recipeTable.CoolingGoal >= result._recipeTable.HeatingGoal) + { + footerMsg.Text = "Error: Cooling goal must be less than heating goal"; + return false; + } + + footerMsg.Text = "Ready"; + return true; + } + + footerMsg.Text = "Error: Settings not available"; + return false; + } + catch (Exception ex) + { + footerMsg.Text = $"Error initializing recipe: {ex.Message}"; + return false; + } + } + + /// + /// Start monitoring recipe phases and handle goal checking + /// + private async Task StartRecipePhaseMonitoring() + { + try + { + // Start continuous monitoring of temperature goals + await Task.Run(async () => + { + while (startRecipe == 1 && !stopRecipeFlag) + { + await CheckAndHandlePhaseTransitions(); + await Task.Delay(1000); // Check every second + } + }); + } + catch (Exception ex) + { + // Log error silently - don't show in UI since recipe is working + // Console.WriteLine($"Phase monitoring error: {ex.Message}"); + } + } + + /// + /// Check current temperatures and handle phase transitions based on goals + /// + private async Task CheckAndHandlePhaseTransitions() + { + try + { + if (ContentArea.Content is Settings settings) + { + // Check if heating goals are met for both mixer and chocolate + bool mixerHeatingGoalMet = await CheckMixerHeatingGoal(); + bool chocolateHeatingGoalMet = await CheckChocolateHeatingGoal(); + + // If both heating goals are met, start timers + if (mixerHeatingGoalMet && chocolateHeatingGoalMet) + { + await StartHeatingPhaseTimers(); + } + + // Check chocolate temperature for cooling phase transition + await HandleCoolingPhaseTransition(settings); + } + } + catch (Exception ex) + { + footerMsg.Text = $"Error in phase transition: {ex.Message}"; + } + } + + /// + /// Check if mixer heating goal is reached + /// + private async Task CheckMixerHeatingGoal() + { + // Check if tank temperature (mixer) has reached heating goal + // For heating: temperature should be at or above the goal + bool goalMet = comTankTemp >= recipeHeatingGoal; + + if (goalMet && Heating == -1) + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = $"Mixer heating goal reached: {comTankTemp:F1}°C (Target: {recipeHeatingGoal}°C)"; + }); + } + + return goalMet; + } + + /// + /// Check if chocolate heating goal is reached + /// + private async Task CheckChocolateHeatingGoal() + { + // Check if fountain temperature (chocolate) has reached heating goal + // For heating: temperature should be at or above the goal + bool goalMet = comFountainTemp >= recipeHeatingGoal; + + if (goalMet && Heating == -1) + { + + } + + return goalMet; + } + + /// + /// Start heating phase timers when goals are met + /// + private async Task StartHeatingPhaseTimers() + { + if (Heating == -1 && setHeatingTimerOnce == -1) + { + Heating = 1; + sendComHeating = 1; + setHeatingTimerOnce = 1; + heatingSeconds = _machine.HeatingDelay; + + // Start heating timer + if (heatingTimer == null) + { + heatingTimer = new Timer(HeatingTimer, null, 1000, 1000); + } + + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Heating phase started - timers initiated"; + }); + } + } + + /// + /// Handle cooling phase transition based on chocolate temperature + /// + private async Task HandleCoolingPhaseTransition(Settings settings) + { + // Check if chocolate temperature has reached cooling threshold + // For cooling: temperature should be at or below the cooling goal + bool chocolateAtCoolingTemp = comFountainTemp <= recipeCoolingGoal; + + if (chocolateAtCoolingTemp && cooling == -1 && Heating == -1) + { + // Chocolate temperature equals or is below cooling threshold - show cooling delay + await ShowCoolingDelay(settings); + } + else if (!chocolateAtCoolingTemp && cooling == -1 && Heating == -1) + { + // Chocolate temperature not at cooling threshold - initiate cooling phase + await InitiateCoolingPhase(settings); + } + } + + /// + /// Show cooling delay when chocolate temperature equals cooling goal + /// + private async Task ShowCoolingDelay(Settings settings) + { + Dispatcher.UIThread.Post(() => + { + settings.coolingDelayTxt.IsVisible = true; + settings.coolingDelayCounter.IsVisible = true; + settings.coolingDelayCounter.Text = "0"; + footerMsg.Text = $"Cooling delay: Chocolate at target temperature ({comFountainTemp:F1}°C)"; + }); + } + + /// + /// Initiate cooling phase when chocolate temperature is not at cooling goal + /// + private async Task InitiateCoolingPhase(Settings settings) + { + if (setCoolingTimerOnce == -1) + { + cooling = 1; + sendComCooling = 1; + setCoolingTimerOnce = 1; + coolingSeconds = _machine.CoolingDelay; + + // Start cooling timer + if (coolingTimer == null) + { + coolingTimer = new Timer(CoolingTimer, null, 1000, 1000); + } + else + { + // Ensure the timer is running at the correct interval + coolingTimer.Change(1000, 1000); + } + + Dispatcher.UIThread.Post(() => + { + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + footerMsg.Text = $"Cooling phase initiated - Target: {recipeCoolingGoal}°C, Current: {comFountainTemp:F1}°C"; + }); + } + } + + /// + /// Stop recipe execution and clean up resources + /// + private async Task StopRecipeExecution(Button button) + { + startRecipe = 0; + stopRecipeFlag = true; + Heating = -1; + cooling = -1; + pouring = -1; + PumbOn = -1; + pedalMotor = -1; + isCoolingDelayMode = false; // Reset the cooling delay mode flag + isPouringDelayMode = false; // Reset the pouring delay mode flag + tempWarningAccepted = false; // Reset temperature warning acceptance + currentRecipePhase = RecipePhase.None; // Reset recipe phase + lastFooterMessage = ""; // Reset last footer message + isPedalAutoMode = false; // Reset pedal auto mode + + // Stop all timers + await StopAllRecipeTimers(); + + // Reset UI elements + await ResetRecipeUI(button); + + // Reset temperature settings + holdingRegister.setTemp1 = -10000; + holdingRegister.setTemp2 = -10000; + holdingRegister.setTemp3 = -10000; + holdingRegister.setTemp4 = -10000; + holdingRegister.motor = 0; + + await WriteToSerialAsync("RecipeStop"); + footerMsg.Text = "Recipe Stopped"; + } + + /// + /// Stop all recipe-related timers + /// + private async Task StopAllRecipeTimers() + { + // Stop heating timer + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + + // Stop cooling timer + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + } + + // Stop pouring timer + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + } + + // Stop pedal timers + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + + // Stop fountain timers + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + + // Stop mixer timer + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + } + + /// + /// Reset UI elements when recipe is stopped + /// + private async Task ResetRecipeUI(Button button) + { + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + // Turn off motors if they were on + if (isMixerMotorOn) + { + settings.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + if (isFountainMotorOn) + { + settings.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + + // Hide delay indicators + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + settings.coolingDelayTxt.IsVisible = false; + settings.coolingDelayCounter.IsVisible = false; + settings.pedalDelayTxt.IsVisible = false; + settings.pedalDelayCounter.IsVisible = false; + + // Re-enable buttons + settings.mixerBtn.IsEnabled = true; + settings.fountainBtn.IsEnabled = true; + } + + // Reset recipe start button + button.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + }); + } + + public void resetAll() + { + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + + + + pedalState = -1; + pedalStateChanged = -1; + recipeHeatingGoal = 0; + recipeCoolingGoal = 0; + recipePouringGoal = 0; + //pre Heating + isFlashPreHeating = false; + startPreHeating = -1; + writingMaxTemp = -1; + // mixer + mixerSeconds = 1; + setMixerTimerOnce = false; + checkMixerTWT_HWTH = false; + isMixerMotorOn = false; + startMixerMotor = -1; + startMixerMotorFlashing = -1; + sendComMixerMotor = -1; + //Fountain Motor + fountainSeconds = 1; + setFountainTimerOnce = false; + checkFountainTMT_PMT = false; + isFountainMotorOn = false; + startFountainMotor = -1; + startFountainMotorFlashing = -1; + sendComFountainMotor = -1; + //MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1) + moldHeaterMotor = -1; + vibrationMotor = -1; + vibHeaterMotor = -1; + //Pedal(manual=0,auto=1) + pedalMotor = -1; + //Recipe Start + startRecipe = 0; + sendComTankTemp = -1; + //phase 1 heating + Heating = -1; + sendComHeating = -1; + setHeatingTimerOnce = -1; + heatingSeconds = 0; + //phase 2 cooling + cooling = -1; + sendComCooling = -1; + setCoolingTimerOnce = -1; + coolingSeconds = 0; + //phase 3 pouring + pouring = -1; + sendComPouring = -1; + setPouringTimerOnce = -1; + pouringSeconds = 0; + //start the pumb + PumbOn = -1; + pedalOffSeconds = 0; + pedalOnSeconds = 0; + setPedalTimerOnce = -1; + Dispatcher.UIThread.Post(() => + { + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + recipeStartBtn.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + }); + + + + + } + + + private async void ResetErrors(object? sender, RoutedEventArgs e) + { + holdingRegister.resetError = (ushort)(1 << 0); + await WriteToSerialAsync("ResetErrors"); + + } + private async void OnWarningPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + warningPopupOverlay.IsVisible = false; + + } + private async void OnErrorPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + errorPopupOverlay.IsVisible = false; + + } + + + + public static class MessageBox + { + public static async Task Show(Window owner, string message, string title) + { + var dialog = new Window + { + Title = title, + Width = 300, + Height = 150, + WindowStartupLocation = WindowStartupLocation.CenterOwner, + Topmost = false, + Content = new StackPanel + { + Children = + { + new TextBlock + { + Text = message, + Margin = new Thickness(10), + HorizontalAlignment = HorizontalAlignment.Center + }, + new Button + { + Content = "OK", + Margin = new Thickness(10), + HorizontalAlignment = HorizontalAlignment.Center + } + } + } + }; + + var button = (Button)((StackPanel)dialog.Content).Children[1]; + button.Click += (s, e) => dialog.Close(); + + owner.Topmost = false; + await dialog.ShowDialog(owner); + owner.Topmost = true; + owner.Activate(); + + // Restart keyboard to bring it on top + var (fileName, args) = GetKeyboardCommand(); + if (!string.IsNullOrEmpty(fileName)) + { + try + { + Process.Start(fileName, args); + } + catch + { + // Handle exceptions if needed + } + } + } + + private static (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + } + + /// + /// Handles automatic fountain control after pouring phase completion based on recipe settings + /// + private async Task HandleAutomaticFountainControlAfterPouring(Settings settings) + { + try + { + // Only proceed if pedal is in Auto mode + if (!settings._recipeTable.Pedal.Value) // Pedal.Value = false means Auto mode + { + // Set flag to indicate automatic fountain control is active + isAutomaticFountainControlActive = true; + + // Check the second control box (RecipeTable.Fountain) to determine fountain state + if (settings._recipeTable.Fountain.Value) + { + // Second box is checked/enabled - Turn ON the fountain + await TurnOnFountainAutomatically(); + } + else + { + // Second box is unchecked/disabled - Keep fountain OFF + await TurnOffFountainAutomatically(); + } + + Debug.WriteLine($"Automatic fountain control activated after pouring phase. Fountain state: {(settings._recipeTable.Fountain.Value ? "ON" : "OFF")}"); + } + } + catch (Exception ex) + { + Debug.WriteLine($"Error in HandleAutomaticFountainControlAfterPouring: {ex.Message}"); + } + } + + /// + /// Automatically turns on the fountain motor + /// + private async Task TurnOnFountainAutomatically() + { + try + { + // Set fountain motor state to ON + isFountainMotorOn = true; + startFountainMotor = 1; + startFountainMotorFlashing = 0; + sendComFountainMotor = 1; + + // Actually send the command to turn ON the fountain motor + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null && fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Automatic Fountain On"); + Debug.WriteLine("Fountain motor command sent to hardware - ON"); + } + + // Update UI to show fountain is ON + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(ActiveColor); + } + }); + + Debug.WriteLine("Fountain automatically turned ON after pouring phase completion"); + } + catch (Exception ex) + { + Debug.WriteLine($"Error turning on fountain automatically: {ex.Message}"); + } + } + + /// + /// Automatically turns off the fountain motor + /// + private async Task TurnOffFountainAutomatically() + { + try + { + // Set fountain motor state to OFF + isFountainMotorOn = false; + startFountainMotor = 0; + startFountainMotorFlashing = -1; // Prevent flashing in automatic mode + sendComFountainMotor = 0; + + // Actually send the command to turn OFF the fountain motor + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null && fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Automatic Fountain Off"); + Debug.WriteLine("Fountain motor command sent to hardware - OFF"); + } + + // Update UI to show fountain is OFF + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fontainRectangel = result.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(PassiveColor); + } + }); + + Debug.WriteLine("Fountain automatically turned OFF after pouring phase completion"); + } + catch (Exception ex) + { + Debug.WriteLine($"Error turning off fountain automatically: {ex.Message}"); + } + } + + /// + /// Resets the automatic fountain control flag to allow normal fountain control + /// + public void ResetAutomaticFountainControl() + { + isAutomaticFountainControlActive = false; + Debug.WriteLine("Automatic fountain control flag reset - normal fountain control restored"); + } +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/Admin.axaml b/DaireApplication/Views/UserController/Admin.axaml new file mode 100644 index 0000000..b5be190 --- /dev/null +++ b/DaireApplication/Views/UserController/Admin.axaml @@ -0,0 +1,1517 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + IN-1 + + + + + + + + + + + + + + + + + + IN-2 + + + + + + + + + + + + + + + + + IN-3 + + + + + + + + + + + + + + + + + IN-4 + + + + + + + + + + + + + + + + + IN-5 + + + + + + + + + + + + + + + + + IN-6 + + + + + + + + + + + + + + + + + + + LOV-1 + + + + + + + + + + + + + + + + + + LOV-2 + + + + + + + + + + + + + + + + + + LOV-3 + + + + + + + + + + + + + + + + + + LOV-4 + + + + + + + + + + + + + + + + + + LOV-5 + + + + + + + + + + + + + + + + + + LOV-6 + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + + T-1 + + + + + + + + + + + + + + + + + + + + T-2 + + + + + + + + + + + + + + + + + + + + T-3 + + + + + + + + + + + + + + + + + + + + T-4 + + + + + + + + + + + + + + + + + + + + + + HVO-1 + + + + + + + + + + + + + + + + + + + + HVO-2 + + + + + + + + + + + + + + + + + + + + + HVO-3 + + + + + + + + + + + + + + + + + + + + HVO-4 + + + + + + + + + + + + + + + + + + + + HVO-5 + + + + + + + + + + + + + + + + + + + + HVO-6 + + + + + + + + + + + + + + + + + + + + + + MOT-1 + + + + + + + + + + + + + + + + + MOT-2 + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + + AN-1 + + + + + + + + + + + + + + + AN-2 + + + + + + + + + + + + + + + + + + + + + VALUES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/UserController/AdvanceSettings.axaml.cs b/DaireApplication/Views/UserController/AdvanceSettings.axaml.cs new file mode 100644 index 0000000..0f461e6 --- /dev/null +++ b/DaireApplication/Views/UserController/AdvanceSettings.axaml.cs @@ -0,0 +1,1077 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.LogicalTree; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using DynamicData; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static DaireApplication.Views.MainWindow; + +namespace DaireApplication; + +public partial class AdvanceSettings : UserControl +{ + public Mapping _mapping; + public ConfigrationTable _configration; + public List _mappingRecordes; + MainWindow _mainWindow; + private Process? _keyboardProcess; + public ErrorSettingsTable _error = new(); + TextBlock targetText = new TextBlock(); + float oldValue = 0; + bool _isDiag; + bool _isSoftware; + public AdvanceSettings(MainWindow mainWindow,bool isDiag=false,bool isSoftware=false) + { + InitializeComponent(); + _mainWindow = mainWindow; + _mapping = new Mapping(); + _mappingRecordes = _mapping.ReadMappings(); + _configration = new(); + _isDiag = isDiag; + _isSoftware = isSoftware; + + setDefaultValues(); + // Remove the old text box event handlers since we're using sliders now + // kp.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // ki.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // kd.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // kl.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + // Remove the old border event handlers since we're using sliders now + // kpBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // kiBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // kdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // klBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + AttachHandlers(_mainWindow.UserName, CloseApplication); + + setDefaultSettings(); + + } + public AdvanceSettings() + { + InitializeComponent(); + } + public void AttachHandlers(Button button, System.EventHandler func) + { + if (button != null) + { + button.Holding += func; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + public static void CloseApplication(object? sender, RoutedEventArgs e) + { + var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; + lifetime?.Shutdown(); // This should correctly shut down the application + } + private void HVOChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result= _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false).Find(c=>c.Name==selectedItem.Content.ToString()); + if (result!=null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord!=null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + var configrations = _configration.ReadConfigrations(); + var compressor = _mappingRecordes.Find(x => x.Name == "Compressor"); + var water = _mappingRecordes.Find(x => x.Name == "Water"); + if (compressor != null && water != null) + { + if (compressor.BitNumbers.Count > 0 ) + { + configrations[2].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList(); + configrations[3].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList(); + + } + else + { + configrations[2].FC_out = [-1]; + configrations[3].FC_out = [-1]; + + } + if (water.BitNumbers.Count > 0) + { + configrations[2].SC_out = water.BitNumbers; + configrations[3].SC_out = water.BitNumbers; + } + else + { + configrations[2].SC_out = [-1]; + configrations[3].SC_out = [-1]; + } + _configration.UpdateConfigration(configrations[2]); + _configration.UpdateConfigration(configrations[3]); + + } + foreach (var item in configrations) + { + var namedMap = _mappingRecordes.Find(x => x.Name == item.name); + if (namedMap!=null) + { + if (namedMap.BitNumbers.Count>0) + { + item.H_out = namedMap.BitNumbers; + if (namedMap.Name!= "HELIX Heater") + { + item.FC_out = [-1]; + item.SC_out = [-1]; + } + _configration.UpdateConfigration(item); + } + else + { + item.H_out =[-1]; + if (namedMap.Name != "HELIX Heater") + { + item.FC_out = [-1]; + item.SC_out = [-1]; + } + _configration.UpdateConfigration(item); + } + } + else + { + + } + } + configrations[3].H_out = configrations[2].H_out; + _configration.UpdateConfigration(configrations[3]); + + + _mainWindow.sendConfig = true; + } + + } + } + + private void TChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result = _mappingRecordes.Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void LOVChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + var result = _mappingRecordes.FindAll(x => x.Address == "2").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void InChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result = _mappingRecordes.FindAll(x => x.Address == "1" &&x.IsRead==true).Find(c => c.Name.ToLower() == selectedItem.Content.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void MotChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + var result = _mappingRecordes.FindAll(x => x.Address == "3").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + + + + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true, + WorkingDirectory = "/usr/bin" + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox = border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + + } + catch + { + // fail silently if keyboard not found + } + } + + + private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + + + + } + private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = false; + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configration = _configration.ReadConfigrationById(header.Tag.ToString()); + if (configration!=null) + { + // Read values from sliders instead of text boxes + configration.kp = (int)kpSlider.Value; + configration.ki = (int)kiSlider.Value; + configration.kd = (int)kdSlider.Value; + configration.kl = (int)klSlider.Value; + + if (string.IsNullOrEmpty(fcThreshold.Text)) + { + configration.FC_Threshold = 0; + } + else + { + configration.FC_Threshold = float.Parse(fcThreshold.Text); + + } + if (string.IsNullOrEmpty(heatConRange.Text)) + { + configration.HeatConRange = 1.0F; + } + else + { + if (float.TryParse(heatConRange.Text, out float value)) + { + if (value<1.0) + { + configration.HeatConRange = 1.0F; + } + else + { + configration.HeatConRange = float.Parse(heatConRange.Text); + } + } + else + { + configration.HeatConRange = 1.0F; + } + + } + + _configration.UpdateConfigration(configration); + _mainWindow.sendConfig = true; + CloseKeyboard(); + + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + + } + } + + + + } + + private async void showPidPopUp(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = true; + + } + private async void showInnerPid(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configratipn = _configration.ReadConfigrationById(button.Tag.ToString()); + pidPopupOverlay.IsVisible = false; + header.Text = button.Content.ToString(); + header.Tag = button.Tag; + + // Set slider values instead of text box values + kpSlider.Value = configratipn.kp; + kiSlider.Value = configratipn.ki; + kdSlider.Value = configratipn.kd; + klSlider.Value = configratipn.kl; + + // Update the display values + kpSliderValue.Text = configratipn.kp.ToString(); + kiSliderValue.Text = configratipn.ki.ToString(); + kdSliderValue.Text = configratipn.kd.ToString(); + klSliderValue.Text = configratipn.kl.ToString(); + + fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0"); + heatConRange.Text = configratipn.HeatConRange.ToString("0.0"); + innerPidPopupOverlay.IsVisible = true; + + } + + } + + // KP Slider and Button Event Handlers + private void KpSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kpSliderValue != null && sender is Slider slider) + { + kpSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KpMinusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value > kpSlider.Minimum) + { + kpSlider.Value--; + } + } + + private void KpPlusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value < kpSlider.Maximum) + { + kpSlider.Value++; + } + } + + // KI Slider and Button Event Handlers + private void KiSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kiSliderValue != null && sender is Slider slider) + { + kiSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KiMinusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value > kiSlider.Minimum) + { + kiSlider.Value--; + } + } + + private void KiPlusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value < kiSlider.Maximum) + { + kiSlider.Value++; + } + } + + // KD Slider and Button Event Handlers + private void KdSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kdSliderValue != null && sender is Slider slider) + { + kdSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KdMinusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value > kdSlider.Minimum) + { + kdSlider.Value--; + } + } + + private void KdPlusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value < kdSlider.Maximum) + { + kdSlider.Value++; + } + } + + // KL Slider and Button Event Handlers + private void KlSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (klSliderValue != null && sender is Slider slider) + { + klSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KlMinusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value > klSlider.Minimum) + { + klSlider.Value--; + } + } + + private void KlPlusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value < klSlider.Maximum) + { + klSlider.Value++; + } + } + + private void OnTextInput(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*\.?\d*$")) + { + e.Handled = true; + } + } + } + private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*$")) + { + e.Handled = true; + } + } + } + + private async void gridButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + if (gridValue.Text == "50Hz") + { + error.gridFreq = 60; + _error.UpdateError(error); + setDefaultValues(); + + } + else + { + error.gridFreq = 50; + _error.UpdateError(error); + setDefaultValues(); + } + + } + private async void supplyButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + int bit = 11; + + if (phasesNumberValue.Text == "3-Phases") + { + error.phaseNumber = 1; + _error.UpdateError(error); + setDefaultValues(); + _mainWindow.holdingRegister.resetError |= (ushort)(1 << bit); + } + else + { + error.phaseNumber = 3; + _error.UpdateError(error); + _mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit); + + + setDefaultValues(); + + } + await _mainWindow.WriteToSerialAsync("supplyButtonClick"); + } + private async void voltageButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + int bit = 12; + + if (voltageNumberValue.Text.Contains("220")) + { + error.phaseVoltage = 110; + _error.UpdateError(error); + setDefaultValues(); + _mainWindow.holdingRegister.resetError |= (ushort)(1 << bit); + } + else + { + error.phaseVoltage =220; + _error.UpdateError(error); + _mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit); + + + setDefaultValues(); + + } + await _mainWindow.WriteToSerialAsync("voltageButtonClick"); + } + + private async void extPowerClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + if (extPowerValue.Text == "Yes") + { + error.extPower = false; + _error.UpdateError(error); + setDefaultValues(); + + + } + else + { + error.extPower = true; + _error.UpdateError(error); + setDefaultValues(); + + } + } + private void setDefaultValues() + { + _mappingRecordes = _mapping.ReadMappings(); + var allHVOComboBox= this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("HVO")) + .ToList(); + //HVO + for (int i = 0; i < allHVOComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false ).Find(c => c.BitNumbers.Contains(int.Parse(allHVOComboBox[i].Tag.ToString()))); + if (result != null) + { + allHVOComboBox[i].SelectedIndex = result.Id - 11; + } + else + { + allHVOComboBox[i].SelectedIndex = 6; + + } + } + // IN + var allINComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("in")) + .ToList(); + for (int i = 0; i < allINComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "1"&&x.IsRead==true).Find(c => c.BitNumbers.Contains(int.Parse(allINComboBox[i].Tag.ToString()))); + if (result != null) + { + allINComboBox[i].SelectedIndex = result.Id - 1; + } + else + { + allINComboBox[i].SelectedIndex = 3; + + } + } + + //LOV + var allLOVComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("lov")) + .ToList(); + for (int i = 0; i < allLOVComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "2" && x.IsRead == false).Find(c => c.BitNumbers.Contains(int.Parse(allLOVComboBox[i].Tag.ToString()))); + if (result != null) + { + allLOVComboBox[i].SelectedIndex = result.Id - 8; + } + else + { + allLOVComboBox[i].SelectedIndex = 3; + + } + } + // T + + var allTComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("T")) + .ToList(); + for (int i = 0; i < allTComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Name.EndsWith("Temp")).Find(c => c.BitNumbers.Contains(int.Parse(allTComboBox[i].Tag.ToString()))); + + if (result != null) + { + allTComboBox[i].SelectedIndex = result.Id - 4; + } + else + { + allTComboBox[i].SelectedIndex = 5; + + } + } + // MOT + var allMotComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("mot")) + .ToList(); + for (int i = 0; i < allMotComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "3" && x.IsRead==false).Find(c => c.BitNumbers.Contains(int.Parse(allMotComboBox[i].Tag.ToString()))); + if (result != null) + { + allMotComboBox[i].SelectedIndex = result.Id - 17; + } + else + { + allMotComboBox[i].SelectedIndex = 2; + + } + } + var error = _error.ReadErrorSettings()[0]; + + phasesNumberValue.Text = $"{error.phaseNumber}-Phases"; + voltageNumberValue.Text = $"{error.phaseVoltage} V"; + gridValue.Text = $"{error.gridFreq}Hz"; + extPowerValue.Text = error.extPower ? "Yes" : "No"; + var config = _configration.ReadConfigrations()[0]; + i_neutValue.Text = config.i_neut.ToString("0.0"); + i_mot1Value.Text = config.i_mot1.ToString("0.0"); + i_mot2Value.Text = config.i_mot2.ToString("0.0"); + + + + } + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + targetText.Text = oldValue.ToString("0.0"); + keyBoardPopup.IsVisible = false; + } + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (button.Content == ".") + { + if (Char.IsDigit(targetText.Text[0]) && !targetText.Text.Contains(button.Content.ToString())) + { + targetText.Text += button.Content; + + } + } + else + { + targetText.Text += button.Content; + if (float.Parse(targetText.Text) > 20.0) + { + targetText.Text = "20.0"; + } + } + + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1); + //number = number.Remove(number.Length - 1); + } + + } + private void EnterClick(object? sender, RoutedEventArgs e) + { + var config = _configration.ReadConfigrations()[0]; + if (targetText.Name== "i_mot2Value") + { + config.i_mot2 = float.Parse(targetText.Text); + } + else if (targetText.Name == "i_mot1Value") + { + config.i_mot1 = float.Parse(targetText.Text); + } + else + { + config.i_neut = float.Parse(targetText.Text); + } + _configration.UpdateConfigration(config); + setDefaultValues(); + _mainWindow.sendConfig = true; + keyBoardPopup.IsVisible = false; + + + } + private void ShowNumberKeyBoard(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (button.Name=="i_mot2") + { + targetText = i_mot2Value; + } + else if (button.Name == "i_mot1") + { + targetText = i_mot1Value; + + } + else if (button.Name== "i_neut") + { + targetText = i_neutValue; + + } + oldValue = float.Parse(targetText.Text); + targetText.Text = ""; + keyBoardPopup.IsVisible = true; + + } + + } + + private void OnKeyUp(object? sender, KeyEventArgs e) + { + if (sender is TextBox textBox) + { + if (textBox != null && float.TryParse(textBox.Text, out float value)) + { + if (textBox.Name== "heatConRange") + { + if (value > 25.0) + { + textBox.Text = "25.0"; + } + + } + else + { + if (value > 100) + { + textBox.Text = "100"; + } + } + // Check if the value exceeds 100 and reset to 100 if necessary. + + } + } + + } + + private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e) + { + e.Handled = true; + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + private void setDefaultSettings() + { + _mainWindow.minimizeBtn.IsVisible = false; + var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel; + + + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + if (_isDiag||_isSoftware) + { + if (_isDiag) + { + _mainWindow.DiagnosticsTrack.IsVisible = true; + _mainWindow.DiagnosticsPolygon.Stroke = Avalonia.Media.Brushes.Black; + + } + else if (_isSoftware) + { + _mainWindow.SoftwareTrack.IsVisible = true; + _mainWindow.SoftwarePolygon.Stroke = Avalonia.Media.Brushes.Black; + } + _mainWindow.SettingTrack.IsVisible = false; + } + else + { + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.SoftwareTrack.IsVisible = false; + + _mainWindow.SettingTrack.IsVisible = true; + _mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black; + } + // Remove the button from its current position + stackPanel.Children.Remove(_mainWindow.AdvanceSettingsTrack); + + // Add it back at the end of the StackPanel + stackPanel.Children.Add(_mainWindow.AdvanceSettingsTrack); + _mainWindow.AdvanceSettingsTrack.IsVisible = true; + _mainWindow.AdvanceSettingsPolygon.Stroke = Brush.Parse("#A4275D"); + + + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = "DR-62664A"; + //Set Footer + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.footerMsg.Text = "Map Inputs And Outputs, And Set The Board Internal Values"; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footer.Background = Brush.Parse("#f2f2f2"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/Diagnostics.axaml b/DaireApplication/Views/UserController/Diagnostics.axaml new file mode 100644 index 0000000..cbf542e --- /dev/null +++ b/DaireApplication/Views/UserController/Diagnostics.axaml @@ -0,0 +1,2393 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-1 = + +0.0 + °C + + + + + + + + + + + + + T-2 = + +0.0 + °C + + + + + + + + + + + + + T-3 = + +0.0 + °C + + + + + + + + + + + + + T-4 = + +0.0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-Board + + 0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-Cooler + + 0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temps Control + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CALIP. Not Done + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temp Max: + + + + + + + + + + + Temp Min: + + + + + + + + + + + + + Currents + Calibration: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/UserController/Diagnostics.axaml.cs b/DaireApplication/Views/UserController/Diagnostics.axaml.cs new file mode 100644 index 0000000..2d1cf25 --- /dev/null +++ b/DaireApplication/Views/UserController/Diagnostics.axaml.cs @@ -0,0 +1,1037 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Controls.Shapes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.LogicalTree; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Tracing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace DaireApplication; + +public partial class Diagnostics : UserControl +{ + private MainWindow? _mainWindow; + private ErrorSettingsTable _error=new(); + public ConfigrationTable _configration; + private Process? _keyboardProcess; + + + public string GrayColor="#666666"; + public string RedColor= "#FF0000"; + public string GreenColor= "#71C837"; + public string PinkColor= "#AF196F"; + public string OrangeColor= "#FF6600"; + public List flagRectangles { get; set; } + public List InputesElements { get; set; } + public List MotoreState { get; set; } + public List hvoOutPuts { get; set; } + public List lvoOutPuts { get; set; } + TextBlock targetText = new TextBlock(); + Button targetButton = new Button(); + float oldValue = 0; + bool isNegative = false; + bool _isAdvSettings; + bool _isFromManualControl; + public MachineTable _machine { get; set; } + + + public Diagnostics() + { + + InitializeComponent(); + + } + public Diagnostics(MainWindow mainWindow,bool isAdvSettings=false, bool isFromManualControl=false) + { + _mainWindow = mainWindow; + _machine = new MachineTable(); + _configration = new(); + _isAdvSettings = isAdvSettings; + _isFromManualControl = isFromManualControl; + + InitializeComponent(); + setDefaultSettings(); + getUiElementes(); + fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + + AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView); + } + public void AttachHandlers(Button button, System.EventHandler func) + { + if (button != null) + { + button.Holding += func; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + public void AdvanceSettingsView(object? sender, RoutedEventArgs e) + { + if (_mainWindow.ContentArea.Content == this) + { + _mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow,true,false); + } + + } + public void ResendConfig(object? sender, RoutedEventArgs e) + { + if (!_mainWindow.sendConfig) + { + _mainWindow.reSendHolding = true; + } + } + public static void CloseApplication(object? sender, RoutedEventArgs e) + { + var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; + lifetime?.Shutdown(); // This should correctly shut down the application + } + private async void motorClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var stackPanel = grid.Children[0] as StackPanel; + var text = stackPanel.Children[1] as TextBlock; + if (text.Text=="ON") + { + _mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor | (1 << int.Parse(grid.Tag.ToString()))); + } + await _mainWindow.WriteToSerialAsync("motorClick"); + + } + + } + private async void hvoClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var text = grid.Children[1] as TextBlock; + if (text.Text=="ON") + { + _mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut | (1 << int.Parse(grid.Tag.ToString()))); + + } + await _mainWindow.WriteToSerialAsync("hvoClick"); + + } + + } + private async void lvoClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var stack= button.Content as StackPanel; + if (grid!=null) + { + var text = grid.Children[1] as TextBlock; + if (text.Text == "ON") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(grid.Tag.ToString()))); + } + + } + else if(stack != null) + { + var text = stack.Children[1] as TextBlock; + if (text.Text == "ON") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(stack.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(stack.Tag.ToString()))); + } + } + await _mainWindow.WriteToSerialAsync("lvoClick"); + + + } + + } + + private async void resetErrorClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + _mainWindow.holdingRegister.resetError = (ushort)(_mainWindow.holdingRegister.resetError | (1 << 0)); + await _mainWindow.WriteToSerialAsync("resetErrorClick"); + } + } + + private async void ChangeTempMode(object sender, RoutedEventArgs e) + { + float number =0; + + if (sender is Border border) + { + if (border.Tag.ToString()=="t1") + { + number = float.Parse(t1Text.Text); + } + else if(border.Tag.ToString() == "t2") + { + number = float.Parse(t2Text.Text); + } + else if (border.Tag.ToString() == "t3") + { + number = float.Parse(t3Text.Text); + } + else if (border.Tag.ToString() == "t4") + { + number = float.Parse(t4Text.Text); + } + var parent = border.Parent as StackPanel; + var brother = parent.Children[1] as Border; + + List allTexts= new (); + if (brother.Tag?.ToString() == "t1") + { + allTexts.Add(t1Container.Children[0] as TextBlock); + allTexts.Add(t1Container.Children[1] as TextBlock); + allTexts.Add(t1Container.Children[2] as TextBlock); + + } + else if (brother.Tag?.ToString() == "t2") + { + allTexts.Add(t2Container.Children[0] as TextBlock); + allTexts.Add(t2Container.Children[1] as TextBlock); + allTexts.Add(t2Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t3") + { + allTexts.Add(t3Container.Children[0] as TextBlock); + allTexts.Add(t3Container.Children[1] as TextBlock); + allTexts.Add(t3Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t4") + { + allTexts.Add(t4Container.Children[0] as TextBlock); + allTexts.Add(t4Container.Children[1] as TextBlock); + allTexts.Add(t4Container.Children[2] as TextBlock); + } + + var button=border.Child as Button; + if (button.Content.ToString()=="M") + { + allTexts[0].Foreground = Brush.Parse("#231f20"); // black + allTexts[1].Foreground = Brush.Parse("#af196f"); // pink + allTexts[2].Foreground = Brush.Parse("#231f20"); // black + button.Foreground = Brush.Parse("#af196f"); + button.Content = "A"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + } + else + { + foreach (var item in allTexts) + { + item.Foreground = Brush.Parse("#808080"); //gray + } + + button.Foreground = Brush.Parse("#4d4d4d"); + button.Content = "M"; + if (button.Tag.ToString()=="t1") + { + _mainWindow.holdingRegister.setTemp1 = -10000; + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = -10000; + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = -10000; + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = -10000; + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + + } + } + else if(sender is Button btn) + { + if (btn.Tag.ToString() == "t1") + { + number = float.Parse(t1Text.Text); + } + else if (btn.Tag.ToString() == "t2") + { + number = float.Parse(t2Text.Text); + } + else if (btn.Tag.ToString() == "t3") + { + number = float.Parse(t3Text.Text); + } + else if (btn.Tag.ToString() == "t4") + { + number = float.Parse(t4Text.Text); + } + var border1 = btn.Parent as Border; + var parent = border1.Parent as StackPanel; + + var brother = parent.Children[1] as Border; + + List allTexts = new(); + if (brother.Tag?.ToString() == "t1") + { + allTexts.Add(t1Container.Children[0] as TextBlock); + allTexts.Add(t1Container.Children[1] as TextBlock); + allTexts.Add(t1Container.Children[2] as TextBlock); + + } + else if (brother.Tag?.ToString() == "t2") + { + allTexts.Add(t2Container.Children[0] as TextBlock); + allTexts.Add(t2Container.Children[1] as TextBlock); + allTexts.Add(t2Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t3") + { + allTexts.Add(t3Container.Children[0] as TextBlock); + allTexts.Add(t3Container.Children[1] as TextBlock); + allTexts.Add(t3Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t4") + { + allTexts.Add(t4Container.Children[0] as TextBlock); + allTexts.Add(t4Container.Children[1] as TextBlock); + allTexts.Add(t4Container.Children[2] as TextBlock); + } + + var button = border1.Child as Button; + if (button.Content.ToString() == "M") + { + allTexts[0].Foreground = Brush.Parse("#231f20"); // black + allTexts[1].Foreground = Brush.Parse("#af196f"); // pink + allTexts[2].Foreground = Brush.Parse("#231f20"); // black + button.Foreground = Brush.Parse("#af196f"); + button.Content = "A"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + + } + else + { + foreach (var item in allTexts) + { + item.Foreground = Brush.Parse("#808080"); //gray + } + + button.Foreground = Brush.Parse("#4d4d4d"); + button.Content = "M"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = -10000; + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = -10000; + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = -10000; + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = -10000; + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + } + } + } + + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + if (isNegative) + { + targetText.Text = "-" + oldValue.ToString("0.0"); + } + else + { + targetText.Text = "+" + oldValue.ToString("0.0"); + } + keyBoardPopup.IsVisible = false; + } + private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e) + { + e.Handled = true; + } + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if ((button.Content=="+"|| button.Content == "-")&& targetText.Text.Length>0) + { + + } + else if((targetText.Text.Length==0 && button.Content == ".")||(targetText.Text.Contains(".")&& button.Content == ".")) + { + + } + else + { + targetText.Text += button.Content; + } + + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1); + //number = number.Remove(number.Length - 1); + } + + } + private async void EnterClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + bool canEdit = targetButton.Content == "A"; + if (!string.IsNullOrEmpty(targetText.Text)) + { + float number = float.Parse(targetText.Text); + + if (char.IsDigit(targetText.Text[0])) + { + targetText.Text = "+" + number.ToString("0.0"); + } + else + { + targetText.Text = number.ToString("0.0"); + } + + var machine = _machine.ReadMachine(); + if (button.Tag.ToString() == "t1") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + machine.setTemp1 = number; + + } + else if (button.Tag.ToString() == "t2") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + } + machine.setTemp2 = number; + + + } + else if (button.Tag.ToString() == "t3") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + } + machine.setTemp3 = number; + } + else if (button.Tag.ToString() == "t4") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + } + machine.setTemp4 = number; + } + _machine.UpdateMachine(machine); + getUiElementes(); + if (canEdit) + { + await _mainWindow.WriteToSerialAsync("DiagnosticsEnter"); + + } + + keyBoardPopup.IsVisible = false; + } + + } + + } + private void ShowNumberKeyBoard(object? sender, PointerPressedEventArgs e) + { + if (sender is Border border) + { + var parent = border.Parent as StackPanel; + var brother = parent.Children[0] as Border; + targetButton = brother.Child as Button; + if (border.Tag?.ToString() == "t1") + { + targetText = t1Text; + } + else if (border.Tag?.ToString() == "t2") + { + targetText = t2Text; + } + else if (border.Tag?.ToString() == "t3") + { + targetText = t3Text; + } + else if (border.Tag?.ToString() == "t4") + { + targetText = t4Text; + } + enterBtn.Tag = border.Tag; + + isNegative = targetText.Text.StartsWith("-"); + + oldValue = float.Parse(targetText.Text.Substring(1)); + targetText.Text = ""; + keyBoardPopup.IsVisible = true; + + } + + } + + private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = false; + } + private async void showInnerPid(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configratipn = _configration.ReadConfigrationById(button.Tag.ToString()); + pidPopupOverlay.IsVisible = false; + header.Text = button.Content.ToString(); + header.Tag = button.Tag; + + // Set slider values instead of text box values + kpSlider.Value = configratipn.kp; + kiSlider.Value = configratipn.ki; + kdSlider.Value = configratipn.kd; + klSlider.Value = configratipn.kl; + + // Update the display values + kpSliderValue.Text = configratipn.kp.ToString(); + kiSliderValue.Text = configratipn.ki.ToString(); + kdSliderValue.Text = configratipn.kd.ToString(); + klSliderValue.Text = configratipn.kl.ToString(); + + fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0"); + heatConRange.Text = configratipn.HeatConRange.ToString("0.0"); + innerPidPopupOverlay.IsVisible = true; + } + } + private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + } + private void OnKeyUp(object? sender, KeyEventArgs e) + { + if (sender is TextBox textBox) + { + if (textBox != null && float.TryParse(textBox.Text, out float value)) + { + if (textBox.Name == "heatConRange") + { + if (value > 25.0) + { + textBox.Text = "25.0"; + } + + } + else + { + if (value > 100) + { + textBox.Text = "100"; + } + } + // Check if the value exceeds 100 and reset to 100 if necessary. + + } + } + + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configration = _configration.ReadConfigrationById(header.Tag.ToString()); + if (configration!=null) + { + // Read values from sliders instead of text boxes + configration.kp = (int)kpSlider.Value; + configration.ki = (int)kiSlider.Value; + configration.kd = (int)kdSlider.Value; + configration.kl = (int)klSlider.Value; + + if (string.IsNullOrEmpty(fcThreshold.Text)) + { + configration.FC_Threshold = 0; + } + else + { + configration.FC_Threshold = float.Parse(fcThreshold.Text); + } + if (string.IsNullOrEmpty(heatConRange.Text)) + { + configration.HeatConRange = 1.0F; + } + else + { + if (float.TryParse(heatConRange.Text, out float value)) + { + if (value<1.0) + { + configration.HeatConRange = 1.0F; + } + else + { + configration.HeatConRange = float.Parse(heatConRange.Text); + } + } + else + { + configration.HeatConRange = 1.0F; + } + } + + _configration.UpdateConfigration(configration); + _mainWindow.reSendHolding = true; + CloseKeyboard(); + + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + } + } + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true, + WorkingDirectory = "/usr/bin" + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox = border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + + } + catch + { + // fail silently if keyboard not found + } + } + private void OnTextInput(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*\.?\d*$")) + { + e.Handled = true; + } + } + } + private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*$")) + { + e.Handled = true; + } + } + } + private async void showPidPopUp(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = true; + + } + + + private void getUiElementes() + { + var error = _error.ReadErrorSettings()[0]; + + if (error.phaseNumber == 1) + { + phaseContainer.Background = Avalonia.Media.Brushes.Gray; + phaseContainer.IsEnabled = false; + } + else + { + phaseContainer.Background = Brush.Parse("#E6E6E6"); + phaseContainer.IsEnabled = true; + } + + flagRectangles = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("flag")) + .ToList(); + + InputesElements = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("in") && (c is Grid || c is Ellipse)) + .ToList(); + MotoreState = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("motorState") && (c is Grid || c is Ellipse)) + .ToList(); + hvoOutPuts = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("hvo") && (c is Grid || c is Ellipse)) + .ToList(); + lvoOutPuts = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("lvo") && (c is Grid||c is StackPanel || c is Ellipse)) + .ToList(); + var machine=_machine.ReadMachine(); + t1Text.Text = char.IsDigit(machine.setTemp1.ToString()[0])?"+"+ machine.setTemp1.ToString(): machine.setTemp1.ToString(); + t2Text.Text = char.IsDigit(machine.setTemp2.ToString()[0]) ? "+" + machine.setTemp2.ToString() : machine.setTemp2.ToString(); + t3Text.Text = char.IsDigit(machine.setTemp3.ToString()[0]) ? "+" + machine.setTemp3.ToString() : machine.setTemp3.ToString(); + t4Text.Text = char.IsDigit(machine.setTemp4.ToString()[0]) ? "+" + machine.setTemp4.ToString() : machine.setTemp4.ToString(); + + + } + private void setDefaultSettings() + { + var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel; + _mainWindow.minimizeBtn.IsVisible = false; + + if (_isFromManualControl) + { + // Special UI setup when called from ManualControl + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.AdvanceSettingsTrack.IsVisible = false; + _mainWindow.ManualControlTrack.IsVisible = true; + _mainWindow.ManualControlPolygon.Stroke = Avalonia.Media.Brushes.Black; + } + else + { + // Original logic for other callers + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + if (_isAdvSettings) + { + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.AdvanceSettingsTrack.IsVisible = true; + _mainWindow.AdvanceSettingsPolygon.Stroke = Avalonia.Media.Brushes.Black; + + } + else + { + _mainWindow.SettingTrack.IsVisible = true; + _mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.AdvanceSettingsTrack.IsVisible = false; + + } + } + + _mainWindow.DiagnosticsTrack.IsVisible = true; + _mainWindow.DiagnosticsPolygon.Stroke = Brush.Parse("#A4275D"); + // Remove the button from its current position + stackPanel.Children.Remove(_mainWindow.DiagnosticsTrack); + + // Add it back at the end of the StackPanel + stackPanel.Children.Add(_mainWindow.DiagnosticsTrack); + + _mainWindow.TitleBtn.IsVisible = false; + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = "DMC7A"; + //Set Footer + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.footerMsg.Text= "Read Values, And Control Outputs Manually"; + _mainWindow.footerMsg.Foreground= Brush.Parse("#A4275D"); + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } + + // KP Slider and Button Event Handlers + private void KpSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kpSliderValue != null && sender is Slider slider) + { + kpSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KpMinusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value > kpSlider.Minimum) + { + kpSlider.Value--; + } + } + + private void KpPlusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value < kpSlider.Maximum) + { + kpSlider.Value++; + } + } + + // KI Slider and Button Event Handlers + private void KiSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kiSliderValue != null && sender is Slider slider) + { + kiSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KiMinusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value > kiSlider.Minimum) + { + kiSlider.Value--; + } + } + + private void KiPlusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value < kiSlider.Maximum) + { + kiSlider.Value++; + } + } + + // KD Slider and Button Event Handlers + private void KdSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kdSliderValue != null && sender is Slider slider) + { + kdSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KdMinusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value > kdSlider.Minimum) + { + kdSlider.Value--; + } + } + + private void KdPlusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value < kdSlider.Maximum) + { + kdSlider.Value++; + } + } + + // KL Slider and Button Event Handlers + private void KlSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (klSliderValue != null && sender is Slider slider) + { + klSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KlMinusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value > klSlider.Minimum) + { + klSlider.Value--; + } + } + + private void KlPlusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value < klSlider.Maximum) + { + klSlider.Value++; + } + } +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/Home.axaml b/DaireApplication/Views/UserController/Home.axaml new file mode 100644 index 0000000..d3b9f02 --- /dev/null +++ b/DaireApplication/Views/UserController/Home.axaml @@ -0,0 +1,140 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/UserController/Recipe.axaml.cs b/DaireApplication/Views/UserController/Recipe.axaml.cs new file mode 100644 index 0000000..2936265 --- /dev/null +++ b/DaireApplication/Views/UserController/Recipe.axaml.cs @@ -0,0 +1,719 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.Views; +using ReactiveUI; +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace DaireApplication; + +public partial class Recipe : UserControl +{ + Button recipeButton = new Button(); + private bool _isLongPress; + + private MainWindow? _mainWindow; + private UserTable? _currentUser; + private RecipeTable _recipeTable=new RecipeTable(); + private Process? _keyboardProcess; + + public Recipe() + { + InitializeComponent(); + + } + public Recipe(MainWindow mainWindow,UserTable currentUser) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + InitializeComponent(); + nameBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + updateBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + setDefaultSettings(); + addDynamicButtons(); + } + + + private async void OnRecipeClick(object? sender, RoutedEventArgs e) + { + if (_isLongPress) + { + // Reset the flag for future interactions. + _isLongPress = false; + // Ignore this click since a long press was detected. + return; + } + + if (sender is Button button) + { + if (_currentUser.CanEdit) + { + _mainWindow.FindControl("ContentArea").Content = new RecipeEdit(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name)); + + } + else + { + _mainWindow.FindControl("ContentArea").Content = new Settings(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name)); + _mainWindow.restBoard = true; + } + + + } + + + + + } + private async void deleteActionClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + deleteMsg.Text = $"You are about to delete {button.Tag}"; + DeletePopupOverlay.IsVisible = true; + + } + + } + private async void UpdateActionClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var text = recipeButton.Content as TextBlock; + updateInput.Text = $"{text.Text}"; + updatePopupOverlay.IsVisible = true; + + } + + } + private void OnLongRecipeClick(object? sender, RoutedEventArgs e) + { + if (e is HoldingRoutedEventArgs args) + { + if (args.HoldingState == HoldingState.Started) + { + _isLongPress = true; + + if (sender is Button button) + { + var targetText= button.Content as TextBlock; + deleteActionBtn.Tag = targetText.Text; + managePopupOverlay.IsVisible = true; + recipeButton = button; + + //recipeButton = button; + //if (button.Content is TextBlock targetText) + //{ + // deleteMsg.Text = $"You are about to delete {targetText.Text}"; + //} + } + + args.Handled = true; + } + else if (args.HoldingState == HoldingState.Completed) + { + _isLongPress = false; + } + } + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + + public void AttachHandlers(Button button) + { + if (button != null) + { + button.Holding += OnLongRecipeClick; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + private async void OnAddRecipeClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + PopupOverlay.IsVisible = true; + } + + } + private async void OnPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + PopupOverlay.IsVisible = false; + + + + } + private async void OnDeletePopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + DeletePopupOverlay.IsVisible = false; + managePopupOverlay.IsVisible = false; + updatePopupOverlay.IsVisible = false; + + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + var result = _recipeTable.DeleteRecipe(recipeButton.Name); + if (result) + { + addDynamicButtons(); + DeletePopupOverlay.IsVisible= false; + managePopupOverlay.IsVisible = false; + + } + else + { + + } + + + } + private async void SaveUpdateClick(object? sender, RoutedEventArgs e) + { + if (!_recipeTable.DoesNameExist(updateInput.Text)) + { + var recipe = _recipeTable.ReadRecipesById(recipeButton.Name); + recipe.Name = updateInput.Text; + var result = _recipeTable.UpdateRecipe(recipe); + if (result) + { + addDynamicButtons(); + managePopupOverlay.IsVisible = false; + updatePopupOverlay.IsVisible = false; + CloseKeyboard(); + + + } + else + { + + } + } + else + { + CloseKeyboard(); + await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error"); + _mainWindow.Topmost = false; + _mainWindow.Focus(); + _mainWindow.Activate(); + + } + + + + } + private void showPopUp(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + recipeButton = button; + button.Foreground = Brush.Parse("#A4275D"); + PopupOverlay.IsVisible = true; + // Append the button's content to the input box + //InputTextBox.Text += button.Content?.ToString(); + } + + } + private async void saveRecipeClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (!string.IsNullOrEmpty(NameInput.Text)) + { + if (!_recipeTable.DoesNameExist(NameInput.Text)) + { + RecipeTable data = new RecipeTable(); + data.Name = NameInput.Text; + data.Mixer = false; + data.Fountain = false; + data.MoldHeater = false; + data.Vibration = false; + data.VibHeater = false; + data.Pedal = false; + var result = _recipeTable.AddRecipe(data); + if (result) + { + addDynamicButtons(); + CloseKeyboard(); + NameInput.Text = ""; + PopupOverlay.IsVisible = false; + + } + else + { + + } + } + else + { + CloseKeyboard(); + await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error"); + _mainWindow.Topmost = false; + _mainWindow.Activate(); + + } + } + + + } + + } + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox= border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + } + catch + { + // fail silently if keyboard not found + } + } + + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + // Close the popup when clicking outside of it + recipeButton.Foreground = Avalonia.Media.Brushes.Black; + + PopupOverlay.IsVisible = false; + } + + private void setDefaultSettings() + { + + //set recipe title + if (_currentUser.CanEdit) + { + RecipeTitle.Content = "RECIPE EDIT/ADD PANEL"; + } + else + { + RecipeTitle.Content = "RECIPE SELECTION"; + } + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + + + if (_currentUser.CanEdit) + { + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Brush.Parse("#A4275D"); + } + else + { + _mainWindow.RecipeSelTrack.IsVisible = true; + _mainWindow.RecipeSelPolygon.Stroke = Brush.Parse("#A4275D"); + } + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.TitleBtn.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.SoftwareTrack.IsVisible = false; + + + //Set Footer + if (_currentUser.CanEdit) + { + _mainWindow.footerMsg.Text = "Long press to delete recipe"; + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.chefBtns.IsVisible = true; + + } + else + { + _mainWindow.footerMsg.Text = "Select a recipe to start"; + _mainWindow.footerMsg.IsVisible = true; + + + } + _mainWindow.ManualControlTrack.IsVisible = false; + + _mainWindow.footerMsg.MaxWidth = 1000; + + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } + private void addDynamicButtons() + { + var recipes= _recipeTable.ReadRecipes(); + var grid = this.FindControl("DynamicGrid"); + grid.Children.Clear(); + int lastRow = 0; + int lastCol = 0; + int colIndexForExtraData = 0; + int recipeIndex = 0; + + try + { + if (recipes.Count<3) + { + // Add dynamic rows + for (int i = 0; i < (int)Math.Ceiling((double)recipes.Count / 3); i++) // Example: 20 rows + { + lastRow = i; + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + // Add content for each column + for (int col = 0; col < recipes.Count; col++) + { + + lastCol = col; + + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + col].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight=FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + col].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + //button.DoubleTapped += OnDoubleRecipeClick; + + } + + grid.Children.Add(button); + Grid.SetRow(button, i); + Grid.SetColumn(button, col); + } + recipeIndex += 3; + } + if (_currentUser.CanEdit) + { + var Plus = new TextBlock + { + Padding = new Thickness(10), + Text = "+", + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 100, + Foreground = Brush.Parse("#A4275D") + + }; + var AddButtun = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = Plus, + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center, + Padding = new Thickness(0, 0, 0, 15), + + }; + AddButtun.Click += OnAddRecipeClick; + if (lastCol < 2) + { + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow); + Grid.SetColumn(AddButtun, lastCol + 1); + } + else + { + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow + 1); + Grid.SetColumn(AddButtun, 0); + } + } + + + + + } + else + { + // Add dynamic rows + for (int i = 0; i < (int)Math.Floor((double)recipes.Count / 3); i++) // Example: 20 rows + { + lastRow = i; + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + // Add content for each column + for (int col = 0; col < 3; col++) + { + + + lastCol = col; + + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + col].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight = FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + col].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + + //button.DoubleTapped += OnDoubleRecipeClick; + + } + + grid.Children.Add(button); + Grid.SetRow(button, i); + Grid.SetColumn(button, col); + } + recipeIndex += 3; + } + for (int i = 0; i < recipes.Count -recipeIndex; i++) + { + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + i].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight = FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + i].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + + //button.DoubleTapped += OnDoubleRecipeClick; + + } + if (lastCol < 2) + { + lastCol += 1; + + + + + grid.Children.Add(button); + Grid.SetRow(button,lastRow); + Grid.SetColumn(button, lastCol); + } + else + { + + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(button); + Grid.SetRow(button, lastRow + 1); + Grid.SetColumn(button, colIndexForExtraData); + colIndexForExtraData += 1; + } + } + if (_currentUser.CanEdit) + { + var Plus = new TextBlock + { + Padding = new Thickness(10), + Text = "+", + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 100, + Foreground = Brush.Parse("#A4275D"), + + + }; + var AddButtun = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = Plus, + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + Padding = new Thickness(0,0,0,15), + }; + + AddButtun.Click += OnAddRecipeClick; + + if (lastCol < 2) + { + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow); + Grid.SetColumn(AddButtun, lastCol + 1); + } + else + { + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow + 1); + Grid.SetColumn(AddButtun, colIndexForExtraData); + } + } + + } + + } + catch (Exception) + { + } + + + + } + + +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/RecipeEdit.axaml b/DaireApplication/Views/UserController/RecipeEdit.axaml new file mode 100644 index 0000000..adbcf8b --- /dev/null +++ b/DaireApplication/Views/UserController/RecipeEdit.axaml @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/UserController/RecipeEdit.axaml.cs b/DaireApplication/Views/UserController/RecipeEdit.axaml.cs new file mode 100644 index 0000000..25bcfa1 --- /dev/null +++ b/DaireApplication/Views/UserController/RecipeEdit.axaml.cs @@ -0,0 +1,253 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using AvaloniaApplication1.DataBase; +using DaireApplication.Views; +using System; + +namespace DaireApplication; + +public partial class RecipeEdit : UserControl +{ + Button controllButton = new Button(); + private MainWindow? _mainWindow; + private UserTable? _currentUser; + private RecipeTable? _recipeTable; + + + public RecipeEdit() + { + InitializeComponent(); + } + public RecipeEdit(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + _recipeTable=recipeTable; + InitializeComponent(); + setDefaultSettings(); + } + + string oldNumber = ""; + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + //number += button.Content?.ToString(); + targetText.Text += button.Content ; + } + // Append the button's content to the input box + //InputTextBox.Text += button.Content?.ToString(); + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length -1, 1); + //number = number.Remove(number.Length - 1); + } + } + + } + private void EnterClick(object? sender, RoutedEventArgs e) + { + // + RecipeTable recipe = new RecipeTable + { + Id = _recipeTable.Id, + Name = _recipeTable.Name, + TankTemp = _recipeTable.TankTemp, + FountainTemp = _recipeTable.FountainTemp, + Mixer = _recipeTable.Mixer ?? false, + Fountain = _recipeTable.Fountain ?? false, + MoldHeater = _recipeTable.MoldHeater ?? false, + Vibration = _recipeTable.Vibration ?? false, + VibHeater = _recipeTable.VibHeater ?? false, + Pedal = _recipeTable.Pedal ?? false, + PedalOnTime = _recipeTable.PedalOnTime, + PedalOffTime = _recipeTable.PedalOffTime, + HeatingGoal = _recipeTable.HeatingGoal, + CoolingGoal = _recipeTable.CoolingGoal, + PouringGoal = _recipeTable.PouringGoal + }; + + var heatingStackPanel = heatingBtn.Content as StackPanel; + var heatingText = (heatingStackPanel?.Children[1] as TextBlock)?.Text; + + var coolingStackPanel = coolingBtn.Content as StackPanel; + var coolingText = (coolingStackPanel?.Children[1] as TextBlock)?.Text; + + var stackPanel = controllButton.Content as StackPanel; + var label = stackPanel?.Children; + var targetText = label?[1] as TextBlock; + var activeTxt = label?[0] as TextBlock; + + if (activeTxt == null || targetText == null) + return; + + switch (activeTxt.Text) + { + case "HEATING:": + if (!string.IsNullOrEmpty(targetText.Text) && int.TryParse(targetText.Text, out int heatingValue)) + { + if (heatingValue > 60) + { + tempErrorMsg.Text = "Heating Temperature must be lower than 60 C"; + return; + } + else if (heatingValue < 40) + { + tempErrorMsg.Text = "Heating Temperature must be greater than 40 C"; + return; + } + + recipe.HeatingGoal = heatingValue; + } + break; + + case "POURING:": + if (!string.IsNullOrEmpty(targetText.Text) && int.TryParse(targetText.Text, out int pouringValue)) + { + if (string.IsNullOrEmpty(heatingText) || string.IsNullOrEmpty(coolingText)) + { + tempErrorMsg.Text = "Enter heating and cooling temperature first"; + return; + } + + if (!int.TryParse(heatingText, out int heatingTemp) || !int.TryParse(coolingText, out int coolingTemp)) + { + tempErrorMsg.Text = "Invalid temperature values"; + return; + } + + if (pouringValue > heatingTemp) + { + tempErrorMsg.Text = $"Pouring Temperature must be lower than Heating Temperature ({heatingTemp}C)"; + return; + } + else if (pouringValue < coolingTemp) + { + tempErrorMsg.Text = $"Pouring Temperature must be greater than Cooling Temperature ({coolingTemp}C)"; + return; + } + + recipe.PouringGoal = pouringValue; + } + break; + + case "COOLING:": + if (!string.IsNullOrEmpty(targetText.Text) && int.TryParse(targetText.Text, out int coolingValue)) + { + if (coolingValue > 40) + { + tempErrorMsg.Text = "Cooling Temperature must be lower than 40 C"; + return; + } + else if (coolingValue < 20) + { + tempErrorMsg.Text = "Cooling Temperature must be greater than 20 C"; + return; + } + + recipe.CoolingGoal = coolingValue; + } + break; + } + + _recipeTable.UpdateRecipe(recipe); + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + PopupOverlay.IsVisible = false; + setDefaultSettings(); + } + + + private void showPopUp(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + heatingBtn.IsEnabled = false; + coolingBtn.IsEnabled = false; + pouringBtn.IsEnabled = false; + button.IsEnabled = true; + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + oldNumber = targetText.Text; + } + controllButton = button; + PopupOverlay.IsVisible = true; + } + + } + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + // Close the popup when clicking outside of it + //controllButton.Foreground = Avalonia.Media.Brushes.Black; + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + //number += button.Content?.ToString(); + targetText.Text = oldNumber; + } + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + + PopupOverlay.IsVisible = false; + } + + private void setDefaultSettings() + { + //set Values + _recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString()); + heatingValue.Text = _recipeTable?.HeatingGoal == 0 ? "" : _recipeTable?.HeatingGoal.ToString(); + coolingValue.Text = _recipeTable?.CoolingGoal == 0 ? "" : _recipeTable?.CoolingGoal.ToString(); + pouringValue.Text = _recipeTable?.PouringGoal == 0 ? "" : _recipeTable?.PouringGoal.ToString(); + + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeEditTrack.IsVisible = true; + _mainWindow.RecipeEditPolygon.Stroke = Brush.Parse("#A4275D"); + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = _recipeTable.Name; + + //Set Footer + _mainWindow.footerMsg.Text = "Select the tempereture to edit it"; + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/Settings.axaml b/DaireApplication/Views/UserController/Settings.axaml new file mode 100644 index 0000000..af87eae --- /dev/null +++ b/DaireApplication/Views/UserController/Settings.axaml @@ -0,0 +1,513 @@ + + + + + + + + + + + + + + + + + Mixer + Delay: + 120 + + + + + + + + Pedal OFF: + + 120 + + + + + + Cooling Delay: + 120 + + + + + + Fountain Delay: + 120 + + Target Temp: + 120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DaireApplication/Views/UserController/Settings.axaml.cs b/DaireApplication/Views/UserController/Settings.axaml.cs new file mode 100644 index 0000000..597cc06 --- /dev/null +++ b/DaireApplication/Views/UserController/Settings.axaml.cs @@ -0,0 +1,388 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Documents; +using Avalonia.Controls.Shapes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Drawing; +using System.Reflection.PortableExecutable; +using System.Threading; + +namespace DaireApplication; + +public partial class Settings : UserControl +{ + Button controllButton = new Button(); + private MainWindow? _mainWindow; + private UserTable? _currentUser; + public RecipeTable? _recipeTable; + private MachineTable _machine; + public string ActiveColor { get; set; } = "#A4275D"; + public string PassiveColor { get; set; } = "#666666"; + + public Settings() + { + InitializeComponent(); + } + public Settings(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + _recipeTable = recipeTable; + _machine = new MachineTable(); + _machine = _machine.ReadMachine(); + + InitializeComponent(); + + setDefaultSettings(); + + setDafaultValues(); + mixerBtn.Click += _mainWindow.MotorClick; + fountainBtn.Click += _mainWindow.FountainClick; + } + + + private void toggelOnOffClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var titelLable = Label[0] as Label; + + + + if (Label[1] is Label targetLable) + { + if (targetLable.Content == "ON") + { + if (titelLable.Content == "MOLD HEATER") + { + _mainWindow.moldHeaterMotor = 0; + } + if (titelLable.Content == "VIBRATION") + { + _mainWindow.vibrationMotor = 0; + + } + if (titelLable.Content == "VIB. HEATER") + { + _mainWindow.vibHeaterMotor = 0; + + } + + + } + else + { + if (titelLable.Content == "MOLD HEATER") + { + _mainWindow.moldHeaterMotor = 1; + } + if (titelLable.Content == "VIBRATION") + { + _mainWindow.vibrationMotor = 1; + + } + if (titelLable.Content == "VIB. HEATER") + { + _mainWindow.vibHeaterMotor = 1; + + } + + } + } + } + + } + private void PedalBtn(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[1] as Avalonia.Controls.Shapes.Rectangle; + if (Label[0] is TextBlock targetLable) + { + if (targetLable.Text == "AUTO") + { + if (_mainWindow.pedalOnTimer!=null ) + { + _mainWindow.pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pedalOnTimer = null; + _mainWindow.pedalOnSeconds = 0; + } + if (_mainWindow.pedalOffTimer!=null) + { + _mainWindow.pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pedalOffTimer = null; + _mainWindow.pedalOffSeconds = 0; + } + _mainWindow.pedalMotor = 0; + targetLable.Text = "MANUAL"; + underLine.Fill = Brush.Parse("#666666"); + PedalAutoContainer.IsEnabled = false; + _recipeTable.Pedal = true; + } + else + { + _mainWindow.pedalMotor = 1; + _mainWindow.pedalState = -1; + _mainWindow.setPedalTimerOnce = 1; + _mainWindow.pedalOnSeconds = 0; + _mainWindow.pedalOffSeconds = 0; + targetLable.Text = "AUTO"; + underLine.Fill = Brush.Parse("#A4275D"); + PedalAutoContainer.IsEnabled = true; + _recipeTable.Pedal = false; + + } + _recipeTable.UpdateRecipe(_recipeTable); + } + } + + } + private void adjustPedalTime(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (button.Classes[0].ToString()== "PedalOff") + { + if (button.Content == "−") + { + if (Int32.Parse(PedalOffTime.Text) > 0) + { + PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) - 1).ToString(); + } + + } + else if (button.Content == "+") + { + + PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) + 1).ToString(); + } + _recipeTable.PedalOffTime = Int32.Parse(PedalOffTime.Text); + _recipeTable.UpdateRecipe(_recipeTable); + } + else + { + if (button.Content == "−") + { + if (Int32.Parse(PedalOnTime.Text) > 0) + { + PedalOnTime.Text = (Int32.Parse(PedalOnTime.Text) - 1).ToString(); + } + + } + else if (button.Content == "+") + { + if (int.TryParse(PedalOnTime.Text, out int value)) + { + if (value < 9) + { + PedalOnTime.Text = (value + 1).ToString(); + } + } + } + _recipeTable.PedalOnTime = Int32.Parse(PedalOnTime.Text); + _recipeTable.UpdateRecipe(_recipeTable); + } + _recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString()); + + } + + } + + private async void OnIgnorePopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + DeletePopupOverlay.IsVisible = false; + + + + } + private async void HideTempErrorPopUp(object? sender, RoutedEventArgs e) + { + _mainWindow.pauseTimer = false; + _mainWindow.pauseTempTracking = false; // Allow process to continue after clicking "No" + _mainWindow.tempWarningAccepted = true; // User accepted the temperature warning + tempErrorPopupOverlay.IsVisible = false; + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (DeletePopupOverlay.Tag=="home") + { + + _mainWindow.resetAll(); + // rest the board + _mainWindow.restBoard = true; + _mainWindow.UserName.Content = "Select User"; + _mainWindow.footerMsg.Text = ""; + _mainWindow.ContentArea.Content = new Home(_mainWindow); + } + else if (DeletePopupOverlay.Tag == "recipeSel") + { + _mainWindow.resetAll(); + // rest the board + _mainWindow.restBoard = true; + _mainWindow.footerMsg.Text = ""; + _mainWindow.ContentArea.Content = new Recipe(_mainWindow, Program.currentUser); + } + } + + + + } + private async void ErrorYesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + //_mainWindow.pause = true; + //_mainWindow.pauseTempTracking = true; + //_mainWindow.pauseTimer = true; + + // stop the recipe + _mainWindow.startRecipe = 0; + _mainWindow.Heating = 0; + _mainWindow.cooling = 0; + _mainWindow.pouring = 0; + _mainWindow.PumbOn = -1; + _mainWindow.pedalMotor = -1; + if (_mainWindow.heatingTimer != null) + { + _mainWindow.heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.heatingSeconds = 0; + } + if (_mainWindow.coolingTimer != null) + { + _mainWindow.coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.coolingSeconds = 0; + } + if (_mainWindow.pouringTimer != null) + { + _mainWindow.pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pouringSeconds = 0; + } + var fount = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Pump".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + _mainWindow.holdingRegister.motor &= (ushort)~(1 << bit); + } + } + } + _mainWindow.holdingRegister.setTemp1 = -10000; + _mainWindow.holdingRegister.setTemp2 = -10000; + _mainWindow.holdingRegister.setTemp3 = -10000; + _mainWindow.holdingRegister.setTemp4 = -10000; + await _mainWindow.WriteToSerialAsync("ErrorYesBtnClick"); + tempErrorPopupOverlay.IsVisible = false; + _mainWindow.footerMsg.Text = "Recipe Stoped"; + _mainWindow.recipeStartBtn.Content = "START RECIPE"; + } + } + + + + private void setDefaultSettings() + { + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = true; + _mainWindow.RecipeSelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RunInterfaceTrack.IsVisible = true; + _mainWindow.RunInterfacePolygon.Stroke = Brush.Parse("#A4275D"); + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = _recipeTable.Name; + + //Set Footer + _mainWindow.footerMsg.Text = "Ready"; + _mainWindow.footerMsg.MaxWidth = 500; + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Avalonia.Media.Brushes.Green; + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = true; + _mainWindow.adminBtns.IsVisible = false; + } + private void setDafaultValues() + { + //Recipe Settings + heatingValue.Content = _recipeTable.HeatingGoal; + coolingValue.Content = _recipeTable.CoolingGoal; + pouringValue.Content = _recipeTable.PouringGoal; + //tankTemp + TankTempValue.Content = _recipeTable?.TankTemp; + //mixer + var mixerChildren= MixerSP.Children; + var mixerLable = mixerChildren[1] as Label; + mixerLable.Content = _recipeTable.Mixer.Value ? "ON" : "OFF"; + var mixerUnderLine = mixerChildren[2] as Avalonia.Controls.Shapes.Rectangle; + mixerUnderLine.Fill = _recipeTable.Mixer.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + //pedal + var pedalChildren = PedalSP.Children; + var pedalText = pedalChildren[0] as TextBlock; + var pedalUnderLine = pedalChildren[1] as Avalonia.Controls.Shapes.Rectangle; + if (_recipeTable.Pedal.Value) + { + pedalText.Text = "MANUAL"; + pedalUnderLine.Fill = Brush.Parse(PassiveColor); + PedalAutoContainer.IsEnabled = false; + } + else + { + pedalText.Text = "AUTO"; + pedalUnderLine.Fill = Brush.Parse(ActiveColor); + PedalAutoContainer.IsEnabled = true; + } + PedalOffTime.Text = _recipeTable.PedalOffTime.ToString(); + PedalOnTime.Text = _recipeTable.PedalOnTime.ToString(); + //fountain Temp + FountainTempValue.Content = _recipeTable?.FountainTemp; + //fountain + var fountainChildren = FountainSP.Children; + var fountainLable = fountainChildren[1] as Label; + fountainLable.Content = _recipeTable.Fountain.Value ? "ON" : "OFF"; + var fountainUnderLine = fountainChildren[2] as Avalonia.Controls.Shapes.Rectangle; + fountainUnderLine.Fill = _recipeTable.Fountain.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + //mold Heater + var moldHeaterChildren = MoldHeaterSP.Children; + var moldHeaterLable = moldHeaterChildren[1] as Label; + moldHeaterLable.Content = _recipeTable.MoldHeater.Value ? "ON" : "OFF"; + var moldHeaterUnderLine = moldHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle; + moldHeaterUnderLine.Fill = _recipeTable.MoldHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + // vibration + var vibrationChildren = VibrationSP.Children; + var vibrationLable = vibrationChildren[1] as Label; + vibrationLable.Content = _recipeTable.Vibration.Value ? "ON" : "OFF"; + var vibrationUnderLine = vibrationChildren[2] as Avalonia.Controls.Shapes.Rectangle; + vibrationUnderLine.Fill = _recipeTable.Vibration.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + // vib heater + var vibHeaterChildren = VibHeaterSP.Children; + var vibHeaterLable = vibHeaterChildren[1] as Label; + vibHeaterLable.Content = _recipeTable.VibHeater.Value ? "ON" : "OFF"; + var vibHeaterUnderLine = vibHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle; + vibHeaterUnderLine.Fill = _recipeTable.VibHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + + + } +} \ No newline at end of file diff --git a/DaireApplication/Views/UserController/Software.axaml b/DaireApplication/Views/UserController/Software.axaml new file mode 100644 index 0000000..47749d7 --- /dev/null +++ b/DaireApplication/Views/UserController/Software.axaml @@ -0,0 +1,783 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PASSWORDS RESET + + + + + + + + + + + + + + + + + + + + + + + + + + SCREEN SETTINGS + + + + + + + + + + + + + + + + + + + + + + + + + + COM SETTINGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bound Rate: + + + + + + + + + + + + + + + + + + Stop Bits: + + + + + + + + + + + + Parity: + + + + + + + + + + + Packets Sending Intervals : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Warning Limit : + + + + + + + Error Limit : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + IN-1 + + + + + + + + + + + + + + + + + + IN-2 + + + + + + + + + + + + + + + + + IN-3 + + + + + + + + + + + + + + + + + IN-4 + + + + + + + + + + + + + + + + + IN-5 + + + + + + + + + + + + + + + + + IN-6 + + + + + + + + + + + + + + + + + + + LOV-1 + + + + + + + + + + + + + + + + + + LOV-2 + + + + + + + + + + + + + + + + + + LOV-3 + + + + + + + + + + + + + + + + + + LOV-4 + + + + + + + + + + + + + + + + + + LOV-5 + + + + + + + + + + + + + + + + + + LOV-6 + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + + T-1 + + + + + + + + + + + + + + + + + + + + T-2 + + + + + + + + + + + + + + + + + + + + T-3 + + + + + + + + + + + + + + + + + + + + T-4 + + + + + + + + + + + + + + + + + + + + + + HVO-1 + + + + + + + + + + + + + + + + + + + + HVO-2 + + + + + + + + + + + + + + + + + + + + + HVO-3 + + + + + + + + + + + + + + + + + + + + HVO-4 + + + + + + + + + + + + + + + + + + + + HVO-5 + + + + + + + + + + + + + + + + + + + + HVO-6 + + + + + + + + + + + + + + + + + + + + + + MOT-1 + + + + + + + + + + + + + + + + + MOT-2 + + + + + + + + + + + + + + + + + + + + + + + + INs/OUTs MAPPING + + + + + + + + AN-1 + + + + + + + + + + + + + + + AN-2 + + + + + + + + + + + + + + + + + + + + + VALUES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/UserController/AdvanceSettings.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.LogicalTree; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using DynamicData; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using static DaireApplication.Views.MainWindow; + +namespace DaireApplication; + +public partial class AdvanceSettings : UserControl +{ + public Mapping _mapping; + public ConfigrationTable _configration; + public List _mappingRecordes; + MainWindow _mainWindow; + private Process? _keyboardProcess; + public ErrorSettingsTable _error = new(); + TextBlock targetText = new TextBlock(); + float oldValue = 0; + bool _isDiag; + bool _isSoftware; + public AdvanceSettings(MainWindow mainWindow,bool isDiag=false,bool isSoftware=false) + { + InitializeComponent(); + _mainWindow = mainWindow; + _mapping = new Mapping(); + _mappingRecordes = _mapping.ReadMappings(); + _configration = new(); + _isDiag = isDiag; + _isSoftware = isSoftware; + + setDefaultValues(); + // Remove the old text box event handlers since we're using sliders now + // kp.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // ki.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // kd.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + // kl.AddHandler(TextInputEvent, OnTextInputOnlyInteager, RoutingStrategies.Tunnel); + fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + // Remove the old border event handlers since we're using sliders now + // kpBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // kiBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // kdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + // klBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + AttachHandlers(_mainWindow.UserName, CloseApplication); + + setDefaultSettings(); + + } + public AdvanceSettings() + { + InitializeComponent(); + } + public void AttachHandlers(Button button, System.EventHandler func) + { + if (button != null) + { + button.Holding += func; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + public static void CloseApplication(object? sender, RoutedEventArgs e) + { + var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; + lifetime?.Shutdown(); // This should correctly shut down the application + } + private void HVOChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result= _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false).Find(c=>c.Name==selectedItem.Content.ToString()); + if (result!=null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord!=null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == false && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + var configrations = _configration.ReadConfigrations(); + var compressor = _mappingRecordes.Find(x => x.Name == "Compressor"); + var water = _mappingRecordes.Find(x => x.Name == "Water"); + if (compressor != null && water != null) + { + if (compressor.BitNumbers.Count > 0 ) + { + configrations[2].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList(); + configrations[3].FC_out = compressor.BitNumbers.Concat(water.BitNumbers).ToList(); + + } + else + { + configrations[2].FC_out = [-1]; + configrations[3].FC_out = [-1]; + + } + if (water.BitNumbers.Count > 0) + { + configrations[2].SC_out = water.BitNumbers; + configrations[3].SC_out = water.BitNumbers; + } + else + { + configrations[2].SC_out = [-1]; + configrations[3].SC_out = [-1]; + } + _configration.UpdateConfigration(configrations[2]); + _configration.UpdateConfigration(configrations[3]); + + } + foreach (var item in configrations) + { + var namedMap = _mappingRecordes.Find(x => x.Name == item.name); + if (namedMap!=null) + { + if (namedMap.BitNumbers.Count>0) + { + item.H_out = namedMap.BitNumbers; + if (namedMap.Name!= "HELIX Heater") + { + item.FC_out = [-1]; + item.SC_out = [-1]; + } + _configration.UpdateConfigration(item); + } + else + { + item.H_out =[-1]; + if (namedMap.Name != "HELIX Heater") + { + item.FC_out = [-1]; + item.SC_out = [-1]; + } + _configration.UpdateConfigration(item); + } + } + else + { + + } + } + configrations[3].H_out = configrations[2].H_out; + _configration.UpdateConfigration(configrations[3]); + + + _mainWindow.sendConfig = true; + } + + } + } + + private void TChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result = _mappingRecordes.Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Name.EndsWith("Temp") && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void LOVChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + var result = _mappingRecordes.FindAll(x => x.Address == "2").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "2" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void InChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + // Get the displayed content + + //HVO + var result = _mappingRecordes.FindAll(x => x.Address == "1" &&x.IsRead==true).Find(c => c.Name.ToLower() == selectedItem.Content.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "1" && x.IsRead == true && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + private void MotChanged(object? sender, RoutedEventArgs e) + { + if (sender is ComboBox comboBox) + { + if (comboBox.SelectedItem is ComboBoxItem selectedItem) + { + var result = _mappingRecordes.FindAll(x => x.Address == "3").Find(c => c.Name.ToLower() == selectedItem.Tag.ToString().ToLower()); + if (result != null) + { + if (!result.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))) + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + + } + result.BitNumbers.Add(int.Parse(comboBox.Tag.ToString())); + _mapping.UpdateMapping(result); + setDefaultValues(); + } + + } + else + { + var oldRecord = _mappingRecordes.Find(x => x.Address == "3" && x.BitNumbers.Contains(int.Parse(comboBox.Tag.ToString()))); + if (oldRecord != null) + { + _mapping.DeleteBitNumber(oldRecord.Id, int.Parse(comboBox.Tag.ToString())); + setDefaultValues(); + + + } + } + + + _mappingRecordes = _mapping.ReadMappings(); + _mainWindow._mapping = _mappingRecordes; + + } + + } + } + + + + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true, + WorkingDirectory = "/usr/bin" + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox = border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + + } + catch + { + // fail silently if keyboard not found + } + } + + + private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + + + + } + private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = false; + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configration = _configration.ReadConfigrationById(header.Tag.ToString()); + if (configration!=null) + { + // Read values from sliders instead of text boxes + configration.kp = (int)kpSlider.Value; + configration.ki = (int)kiSlider.Value; + configration.kd = (int)kdSlider.Value; + configration.kl = (int)klSlider.Value; + + if (string.IsNullOrEmpty(fcThreshold.Text)) + { + configration.FC_Threshold = 0; + } + else + { + configration.FC_Threshold = float.Parse(fcThreshold.Text); + + } + if (string.IsNullOrEmpty(heatConRange.Text)) + { + configration.HeatConRange = 1.0F; + } + else + { + if (float.TryParse(heatConRange.Text, out float value)) + { + if (value<1.0) + { + configration.HeatConRange = 1.0F; + } + else + { + configration.HeatConRange = float.Parse(heatConRange.Text); + } + } + else + { + configration.HeatConRange = 1.0F; + } + + } + + _configration.UpdateConfigration(configration); + _mainWindow.sendConfig = true; + CloseKeyboard(); + + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + + } + } + + + + } + + private async void showPidPopUp(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = true; + + } + private async void showInnerPid(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configratipn = _configration.ReadConfigrationById(button.Tag.ToString()); + pidPopupOverlay.IsVisible = false; + header.Text = button.Content.ToString(); + header.Tag = button.Tag; + + // Set slider values instead of text box values + kpSlider.Value = configratipn.kp; + kiSlider.Value = configratipn.ki; + kdSlider.Value = configratipn.kd; + klSlider.Value = configratipn.kl; + + // Update the display values + kpSliderValue.Text = configratipn.kp.ToString(); + kiSliderValue.Text = configratipn.ki.ToString(); + kdSliderValue.Text = configratipn.kd.ToString(); + klSliderValue.Text = configratipn.kl.ToString(); + + fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0"); + heatConRange.Text = configratipn.HeatConRange.ToString("0.0"); + innerPidPopupOverlay.IsVisible = true; + + } + + } + + // KP Slider and Button Event Handlers + private void KpSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kpSliderValue != null && sender is Slider slider) + { + kpSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KpMinusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value > kpSlider.Minimum) + { + kpSlider.Value--; + } + } + + private void KpPlusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value < kpSlider.Maximum) + { + kpSlider.Value++; + } + } + + // KI Slider and Button Event Handlers + private void KiSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kiSliderValue != null && sender is Slider slider) + { + kiSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KiMinusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value > kiSlider.Minimum) + { + kiSlider.Value--; + } + } + + private void KiPlusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value < kiSlider.Maximum) + { + kiSlider.Value++; + } + } + + // KD Slider and Button Event Handlers + private void KdSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kdSliderValue != null && sender is Slider slider) + { + kdSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KdMinusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value > kdSlider.Minimum) + { + kdSlider.Value--; + } + } + + private void KdPlusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value < kdSlider.Maximum) + { + kdSlider.Value++; + } + } + + // KL Slider and Button Event Handlers + private void KlSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (klSliderValue != null && sender is Slider slider) + { + klSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KlMinusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value > klSlider.Minimum) + { + klSlider.Value--; + } + } + + private void KlPlusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value < klSlider.Maximum) + { + klSlider.Value++; + } + } + + private void OnTextInput(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*\.?\d*$")) + { + e.Handled = true; + } + } + } + private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*$")) + { + e.Handled = true; + } + } + } + + private async void gridButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + if (gridValue.Text == "50Hz") + { + error.gridFreq = 60; + _error.UpdateError(error); + setDefaultValues(); + + } + else + { + error.gridFreq = 50; + _error.UpdateError(error); + setDefaultValues(); + } + + } + private async void supplyButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + int bit = 11; + + if (phasesNumberValue.Text == "3-Phases") + { + error.phaseNumber = 1; + _error.UpdateError(error); + setDefaultValues(); + _mainWindow.holdingRegister.resetError |= (ushort)(1 << bit); + } + else + { + error.phaseNumber = 3; + _error.UpdateError(error); + _mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit); + + + setDefaultValues(); + + } + await _mainWindow.WriteToSerialAsync("supplyButtonClick"); + } + private async void voltageButtonClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + int bit = 12; + + if (voltageNumberValue.Text.Contains("220")) + { + error.phaseVoltage = 110; + _error.UpdateError(error); + setDefaultValues(); + _mainWindow.holdingRegister.resetError |= (ushort)(1 << bit); + } + else + { + error.phaseVoltage =220; + _error.UpdateError(error); + _mainWindow.holdingRegister.resetError &= (ushort)~(1 << bit); + + + setDefaultValues(); + + } + await _mainWindow.WriteToSerialAsync("voltageButtonClick"); + } + + private async void extPowerClick(object? sender, RoutedEventArgs e) + { + var error = _error.ReadErrorSettings()[0]; + if (extPowerValue.Text == "Yes") + { + error.extPower = false; + _error.UpdateError(error); + setDefaultValues(); + + + } + else + { + error.extPower = true; + _error.UpdateError(error); + setDefaultValues(); + + } + } + private void setDefaultValues() + { + _mappingRecordes = _mapping.ReadMappings(); + var allHVOComboBox= this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("HVO")) + .ToList(); + //HVO + for (int i = 0; i < allHVOComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "1" && x.IsRead==false ).Find(c => c.BitNumbers.Contains(int.Parse(allHVOComboBox[i].Tag.ToString()))); + if (result != null) + { + allHVOComboBox[i].SelectedIndex = result.Id - 11; + } + else + { + allHVOComboBox[i].SelectedIndex = 6; + + } + } + // IN + var allINComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("in")) + .ToList(); + for (int i = 0; i < allINComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "1"&&x.IsRead==true).Find(c => c.BitNumbers.Contains(int.Parse(allINComboBox[i].Tag.ToString()))); + if (result != null) + { + allINComboBox[i].SelectedIndex = result.Id - 1; + } + else + { + allINComboBox[i].SelectedIndex = 3; + + } + } + + //LOV + var allLOVComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("lov")) + .ToList(); + for (int i = 0; i < allLOVComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "2" && x.IsRead == false).Find(c => c.BitNumbers.Contains(int.Parse(allLOVComboBox[i].Tag.ToString()))); + if (result != null) + { + allLOVComboBox[i].SelectedIndex = result.Id - 8; + } + else + { + allLOVComboBox[i].SelectedIndex = 3; + + } + } + // T + + var allTComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("T")) + .ToList(); + for (int i = 0; i < allTComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Name.EndsWith("Temp")).Find(c => c.BitNumbers.Contains(int.Parse(allTComboBox[i].Tag.ToString()))); + + if (result != null) + { + allTComboBox[i].SelectedIndex = result.Id - 4; + } + else + { + allTComboBox[i].SelectedIndex = 5; + + } + } + // MOT + var allMotComboBox = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("mot")) + .ToList(); + for (int i = 0; i < allMotComboBox.Count; i++) + { + var result = _mappingRecordes.FindAll(x => x.Address == "3" && x.IsRead==false).Find(c => c.BitNumbers.Contains(int.Parse(allMotComboBox[i].Tag.ToString()))); + if (result != null) + { + allMotComboBox[i].SelectedIndex = result.Id - 17; + } + else + { + allMotComboBox[i].SelectedIndex = 2; + + } + } + var error = _error.ReadErrorSettings()[0]; + + phasesNumberValue.Text = $"{error.phaseNumber}-Phases"; + voltageNumberValue.Text = $"{error.phaseVoltage} V"; + gridValue.Text = $"{error.gridFreq}Hz"; + extPowerValue.Text = error.extPower ? "Yes" : "No"; + var config = _configration.ReadConfigrations()[0]; + i_neutValue.Text = config.i_neut.ToString("0.0"); + i_mot1Value.Text = config.i_mot1.ToString("0.0"); + i_mot2Value.Text = config.i_mot2.ToString("0.0"); + + + + } + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + targetText.Text = oldValue.ToString("0.0"); + keyBoardPopup.IsVisible = false; + } + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (button.Content == ".") + { + if (Char.IsDigit(targetText.Text[0]) && !targetText.Text.Contains(button.Content.ToString())) + { + targetText.Text += button.Content; + + } + } + else + { + targetText.Text += button.Content; + if (float.Parse(targetText.Text) > 20.0) + { + targetText.Text = "20.0"; + } + } + + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1); + //number = number.Remove(number.Length - 1); + } + + } + private void EnterClick(object? sender, RoutedEventArgs e) + { + var config = _configration.ReadConfigrations()[0]; + if (targetText.Name== "i_mot2Value") + { + config.i_mot2 = float.Parse(targetText.Text); + } + else if (targetText.Name == "i_mot1Value") + { + config.i_mot1 = float.Parse(targetText.Text); + } + else + { + config.i_neut = float.Parse(targetText.Text); + } + _configration.UpdateConfigration(config); + setDefaultValues(); + _mainWindow.sendConfig = true; + keyBoardPopup.IsVisible = false; + + + } + private void ShowNumberKeyBoard(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (button.Name=="i_mot2") + { + targetText = i_mot2Value; + } + else if (button.Name == "i_mot1") + { + targetText = i_mot1Value; + + } + else if (button.Name== "i_neut") + { + targetText = i_neutValue; + + } + oldValue = float.Parse(targetText.Text); + targetText.Text = ""; + keyBoardPopup.IsVisible = true; + + } + + } + + private void OnKeyUp(object? sender, KeyEventArgs e) + { + if (sender is TextBox textBox) + { + if (textBox != null && float.TryParse(textBox.Text, out float value)) + { + if (textBox.Name== "heatConRange") + { + if (value > 25.0) + { + textBox.Text = "25.0"; + } + + } + else + { + if (value > 100) + { + textBox.Text = "100"; + } + } + // Check if the value exceeds 100 and reset to 100 if necessary. + + } + } + + } + + private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e) + { + e.Handled = true; + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + private void setDefaultSettings() + { + _mainWindow.minimizeBtn.IsVisible = false; + var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel; + + + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + if (_isDiag||_isSoftware) + { + if (_isDiag) + { + _mainWindow.DiagnosticsTrack.IsVisible = true; + _mainWindow.DiagnosticsPolygon.Stroke = Avalonia.Media.Brushes.Black; + + } + else if (_isSoftware) + { + _mainWindow.SoftwareTrack.IsVisible = true; + _mainWindow.SoftwarePolygon.Stroke = Avalonia.Media.Brushes.Black; + } + _mainWindow.SettingTrack.IsVisible = false; + } + else + { + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.SoftwareTrack.IsVisible = false; + + _mainWindow.SettingTrack.IsVisible = true; + _mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black; + } + // Remove the button from its current position + stackPanel.Children.Remove(_mainWindow.AdvanceSettingsTrack); + + // Add it back at the end of the StackPanel + stackPanel.Children.Add(_mainWindow.AdvanceSettingsTrack); + _mainWindow.AdvanceSettingsTrack.IsVisible = true; + _mainWindow.AdvanceSettingsPolygon.Stroke = Brush.Parse("#A4275D"); + + + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = "DR-62664A"; + //Set Footer + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.footerMsg.Text = "Map Inputs And Outputs, And Set The Board Internal Values"; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footer.Background = Brush.Parse("#f2f2f2"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } +} + +============================================================ +FILE: DaireApplication/Views/UserController/Diagnostics.axaml +============================================================ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-1 = + +0.0 + °C + + + + + + + + + + + + + T-2 = + +0.0 + °C + + + + + + + + + + + + + T-3 = + +0.0 + °C + + + + + + + + + + + + + T-4 = + +0.0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-Board + + 0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T-Cooler + + 0 + °C + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temps Control + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CALIP. Not Done + + + + + + + + + + + + + + + + + + + + + + + + + + + + Temp Max: + + + + + + + + + + + Temp Min: + + + + + + + + + + + + + Currents + Calibration: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/UserController/Diagnostics.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Controls.Shapes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.LogicalTree; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Diagnostics.Tracing; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text.RegularExpressions; +using static System.Runtime.InteropServices.JavaScript.JSType; + +namespace DaireApplication; + +public partial class Diagnostics : UserControl +{ + private MainWindow? _mainWindow; + private ErrorSettingsTable _error=new(); + public ConfigrationTable _configration; + private Process? _keyboardProcess; + + + public string GrayColor="#666666"; + public string RedColor= "#FF0000"; + public string GreenColor= "#71C837"; + public string PinkColor= "#AF196F"; + public string OrangeColor= "#FF6600"; + public List flagRectangles { get; set; } + public List InputesElements { get; set; } + public List MotoreState { get; set; } + public List hvoOutPuts { get; set; } + public List lvoOutPuts { get; set; } + TextBlock targetText = new TextBlock(); + Button targetButton = new Button(); + float oldValue = 0; + bool isNegative = false; + bool _isAdvSettings; + bool _isFromManualControl; + public MachineTable _machine { get; set; } + + + public Diagnostics() + { + + InitializeComponent(); + + } + public Diagnostics(MainWindow mainWindow,bool isAdvSettings=false, bool isFromManualControl=false) + { + _mainWindow = mainWindow; + _machine = new MachineTable(); + _configration = new(); + _isAdvSettings = isAdvSettings; + _isFromManualControl = isFromManualControl; + + InitializeComponent(); + setDefaultSettings(); + getUiElementes(); + fcThreshold.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + heatConRange.AddHandler(TextInputEvent, OnTextInput, RoutingStrategies.Tunnel); + fcThresholdBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + heatConRangeBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + + AttachHandlers(_mainWindow.logoBtn, AdvanceSettingsView); + } + public void AttachHandlers(Button button, System.EventHandler func) + { + if (button != null) + { + button.Holding += func; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + func(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + public void AdvanceSettingsView(object? sender, RoutedEventArgs e) + { + if (_mainWindow.ContentArea.Content == this) + { + _mainWindow.ContentArea.Content = new AdvanceSettings(_mainWindow,true,false); + } + + } + public void ResendConfig(object? sender, RoutedEventArgs e) + { + if (!_mainWindow.sendConfig) + { + _mainWindow.reSendHolding = true; + } + } + public static void CloseApplication(object? sender, RoutedEventArgs e) + { + var lifetime = Application.Current?.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime; + lifetime?.Shutdown(); // This should correctly shut down the application + } + private async void motorClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var stackPanel = grid.Children[0] as StackPanel; + var text = stackPanel.Children[1] as TextBlock; + if (text.Text=="ON") + { + _mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.motor = (ushort)(_mainWindow.holdingRegister.motor | (1 << int.Parse(grid.Tag.ToString()))); + } + await _mainWindow.WriteToSerialAsync("motorClick"); + + } + + } + private async void hvoClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var text = grid.Children[1] as TextBlock; + if (text.Text=="ON") + { + _mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.hvOut = (ushort)(_mainWindow.holdingRegister.hvOut | (1 << int.Parse(grid.Tag.ToString()))); + + } + await _mainWindow.WriteToSerialAsync("hvoClick"); + + } + + } + private async void lvoClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var grid= button.Content as Grid; + var stack= button.Content as StackPanel; + if (grid!=null) + { + var text = grid.Children[1] as TextBlock; + if (text.Text == "ON") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(grid.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(grid.Tag.ToString()))); + } + + } + else if(stack != null) + { + var text = stack.Children[1] as TextBlock; + if (text.Text == "ON") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut & ~(1 << int.Parse(stack.Tag.ToString()))); + + } + else if (text.Text == "OFF") + { + _mainWindow.holdingRegister.lvOut = (ushort)(_mainWindow.holdingRegister.lvOut | (1 << int.Parse(stack.Tag.ToString()))); + } + } + await _mainWindow.WriteToSerialAsync("lvoClick"); + + + } + + } + + private async void resetErrorClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + _mainWindow.holdingRegister.resetError = (ushort)(_mainWindow.holdingRegister.resetError | (1 << 0)); + await _mainWindow.WriteToSerialAsync("resetErrorClick"); + } + } + + private async void ChangeTempMode(object sender, RoutedEventArgs e) + { + float number =0; + + if (sender is Border border) + { + if (border.Tag.ToString()=="t1") + { + number = float.Parse(t1Text.Text); + } + else if(border.Tag.ToString() == "t2") + { + number = float.Parse(t2Text.Text); + } + else if (border.Tag.ToString() == "t3") + { + number = float.Parse(t3Text.Text); + } + else if (border.Tag.ToString() == "t4") + { + number = float.Parse(t4Text.Text); + } + var parent = border.Parent as StackPanel; + var brother = parent.Children[1] as Border; + + List allTexts= new (); + if (brother.Tag?.ToString() == "t1") + { + allTexts.Add(t1Container.Children[0] as TextBlock); + allTexts.Add(t1Container.Children[1] as TextBlock); + allTexts.Add(t1Container.Children[2] as TextBlock); + + } + else if (brother.Tag?.ToString() == "t2") + { + allTexts.Add(t2Container.Children[0] as TextBlock); + allTexts.Add(t2Container.Children[1] as TextBlock); + allTexts.Add(t2Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t3") + { + allTexts.Add(t3Container.Children[0] as TextBlock); + allTexts.Add(t3Container.Children[1] as TextBlock); + allTexts.Add(t3Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t4") + { + allTexts.Add(t4Container.Children[0] as TextBlock); + allTexts.Add(t4Container.Children[1] as TextBlock); + allTexts.Add(t4Container.Children[2] as TextBlock); + } + + var button=border.Child as Button; + if (button.Content.ToString()=="M") + { + allTexts[0].Foreground = Brush.Parse("#231f20"); // black + allTexts[1].Foreground = Brush.Parse("#af196f"); // pink + allTexts[2].Foreground = Brush.Parse("#231f20"); // black + button.Foreground = Brush.Parse("#af196f"); + button.Content = "A"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + } + else + { + foreach (var item in allTexts) + { + item.Foreground = Brush.Parse("#808080"); //gray + } + + button.Foreground = Brush.Parse("#4d4d4d"); + button.Content = "M"; + if (button.Tag.ToString()=="t1") + { + _mainWindow.holdingRegister.setTemp1 = -10000; + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = -10000; + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = -10000; + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = -10000; + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + + } + } + else if(sender is Button btn) + { + if (btn.Tag.ToString() == "t1") + { + number = float.Parse(t1Text.Text); + } + else if (btn.Tag.ToString() == "t2") + { + number = float.Parse(t2Text.Text); + } + else if (btn.Tag.ToString() == "t3") + { + number = float.Parse(t3Text.Text); + } + else if (btn.Tag.ToString() == "t4") + { + number = float.Parse(t4Text.Text); + } + var border1 = btn.Parent as Border; + var parent = border1.Parent as StackPanel; + + var brother = parent.Children[1] as Border; + + List allTexts = new(); + if (brother.Tag?.ToString() == "t1") + { + allTexts.Add(t1Container.Children[0] as TextBlock); + allTexts.Add(t1Container.Children[1] as TextBlock); + allTexts.Add(t1Container.Children[2] as TextBlock); + + } + else if (brother.Tag?.ToString() == "t2") + { + allTexts.Add(t2Container.Children[0] as TextBlock); + allTexts.Add(t2Container.Children[1] as TextBlock); + allTexts.Add(t2Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t3") + { + allTexts.Add(t3Container.Children[0] as TextBlock); + allTexts.Add(t3Container.Children[1] as TextBlock); + allTexts.Add(t3Container.Children[2] as TextBlock); + } + else if (brother.Tag?.ToString() == "t4") + { + allTexts.Add(t4Container.Children[0] as TextBlock); + allTexts.Add(t4Container.Children[1] as TextBlock); + allTexts.Add(t4Container.Children[2] as TextBlock); + } + + var button = border1.Child as Button; + if (button.Content.ToString() == "M") + { + allTexts[0].Foreground = Brush.Parse("#231f20"); // black + allTexts[1].Foreground = Brush.Parse("#af196f"); // pink + allTexts[2].Foreground = Brush.Parse("#231f20"); // black + button.Foreground = Brush.Parse("#af196f"); + button.Content = "A"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + + } + else + { + foreach (var item in allTexts) + { + item.Foreground = Brush.Parse("#808080"); //gray + } + + button.Foreground = Brush.Parse("#4d4d4d"); + button.Content = "M"; + if (button.Tag.ToString() == "t1") + { + _mainWindow.holdingRegister.setTemp1 = -10000; + + } + else if (button.Tag.ToString() == "t2") + { + _mainWindow.holdingRegister.setTemp2 = -10000; + + } + else if (button.Tag.ToString() == "t3") + { + _mainWindow.holdingRegister.setTemp3 = -10000; + + } + else if (button.Tag.ToString() == "t4") + { + _mainWindow.holdingRegister.setTemp4 = -10000; + + } + await _mainWindow.WriteToSerialAsync("DiagnosticsTemp"); + + } + } + } + + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + if (isNegative) + { + targetText.Text = "-" + oldValue.ToString("0.0"); + } + else + { + targetText.Text = "+" + oldValue.ToString("0.0"); + } + keyBoardPopup.IsVisible = false; + } + private void InnerPopupPointerPressed(object? sender, PointerPressedEventArgs e) + { + e.Handled = true; + } + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if ((button.Content=="+"|| button.Content == "-")&& targetText.Text.Length>0) + { + + } + else if((targetText.Text.Length==0 && button.Content == ".")||(targetText.Text.Contains(".")&& button.Content == ".")) + { + + } + else + { + targetText.Text += button.Content; + } + + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length - 1, 1); + //number = number.Remove(number.Length - 1); + } + + } + private async void EnterClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + bool canEdit = targetButton.Content == "A"; + if (!string.IsNullOrEmpty(targetText.Text)) + { + float number = float.Parse(targetText.Text); + + if (char.IsDigit(targetText.Text[0])) + { + targetText.Text = "+" + number.ToString("0.0"); + } + else + { + targetText.Text = number.ToString("0.0"); + } + + var machine = _machine.ReadMachine(); + if (button.Tag.ToString() == "t1") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp1 = (int)(number * 10); + + } + machine.setTemp1 = number; + + } + else if (button.Tag.ToString() == "t2") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp2 = (int)(number * 10); + + } + machine.setTemp2 = number; + + + } + else if (button.Tag.ToString() == "t3") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp3 = (int)(number * 10); + } + machine.setTemp3 = number; + } + else if (button.Tag.ToString() == "t4") + { + if (canEdit) + { + _mainWindow.holdingRegister.setTemp4 = (int)(number * 10); + } + machine.setTemp4 = number; + } + _machine.UpdateMachine(machine); + getUiElementes(); + if (canEdit) + { + await _mainWindow.WriteToSerialAsync("DiagnosticsEnter"); + + } + + keyBoardPopup.IsVisible = false; + } + + } + + } + private void ShowNumberKeyBoard(object? sender, PointerPressedEventArgs e) + { + if (sender is Border border) + { + var parent = border.Parent as StackPanel; + var brother = parent.Children[0] as Border; + targetButton = brother.Child as Button; + if (border.Tag?.ToString() == "t1") + { + targetText = t1Text; + } + else if (border.Tag?.ToString() == "t2") + { + targetText = t2Text; + } + else if (border.Tag?.ToString() == "t3") + { + targetText = t3Text; + } + else if (border.Tag?.ToString() == "t4") + { + targetText = t4Text; + } + enterBtn.Tag = border.Tag; + + isNegative = targetText.Text.StartsWith("-"); + + oldValue = float.Parse(targetText.Text.Substring(1)); + targetText.Text = ""; + keyBoardPopup.IsVisible = true; + + } + + } + + private async void OnIgnorePidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = false; + } + private async void showInnerPid(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configratipn = _configration.ReadConfigrationById(button.Tag.ToString()); + pidPopupOverlay.IsVisible = false; + header.Text = button.Content.ToString(); + header.Tag = button.Tag; + + // Set slider values instead of text box values + kpSlider.Value = configratipn.kp; + kiSlider.Value = configratipn.ki; + kdSlider.Value = configratipn.kd; + klSlider.Value = configratipn.kl; + + // Update the display values + kpSliderValue.Text = configratipn.kp.ToString(); + kiSliderValue.Text = configratipn.ki.ToString(); + kdSliderValue.Text = configratipn.kd.ToString(); + klSliderValue.Text = configratipn.kl.ToString(); + + fcThreshold.Text = configratipn.FC_Threshold.ToString("0.0"); + heatConRange.Text = configratipn.HeatConRange.ToString("0.0"); + innerPidPopupOverlay.IsVisible = true; + } + } + private async void OnIgnoreInnerPidPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + } + private void OnKeyUp(object? sender, KeyEventArgs e) + { + if (sender is TextBox textBox) + { + if (textBox != null && float.TryParse(textBox.Text, out float value)) + { + if (textBox.Name == "heatConRange") + { + if (value > 25.0) + { + textBox.Text = "25.0"; + } + + } + else + { + if (value > 100) + { + textBox.Text = "100"; + } + } + // Check if the value exceeds 100 and reset to 100 if necessary. + + } + } + + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var configration = _configration.ReadConfigrationById(header.Tag.ToString()); + if (configration!=null) + { + // Read values from sliders instead of text boxes + configration.kp = (int)kpSlider.Value; + configration.ki = (int)kiSlider.Value; + configration.kd = (int)kdSlider.Value; + configration.kl = (int)klSlider.Value; + + if (string.IsNullOrEmpty(fcThreshold.Text)) + { + configration.FC_Threshold = 0; + } + else + { + configration.FC_Threshold = float.Parse(fcThreshold.Text); + } + if (string.IsNullOrEmpty(heatConRange.Text)) + { + configration.HeatConRange = 1.0F; + } + else + { + if (float.TryParse(heatConRange.Text, out float value)) + { + if (value<1.0) + { + configration.HeatConRange = 1.0F; + } + else + { + configration.HeatConRange = float.Parse(heatConRange.Text); + } + } + else + { + configration.HeatConRange = 1.0F; + } + } + + _configration.UpdateConfigration(configration); + _mainWindow.reSendHolding = true; + CloseKeyboard(); + + innerPidPopupOverlay.IsVisible = false; + pidPopupOverlay.IsVisible = true; + } + } + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true, + WorkingDirectory = "/usr/bin" + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox = border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + + } + catch + { + // fail silently if keyboard not found + } + } + private void OnTextInput(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*\.?\d*$")) + { + e.Handled = true; + } + } + } + private void OnTextInputOnlyInteager(object? sender, TextInputEventArgs e) + { + if (sender is TextBox textBox) + { + string newText = textBox.Text + e.Text; + if (!Regex.IsMatch(newText, @"^\d*$")) + { + e.Handled = true; + } + } + } + private async void showPidPopUp(object? sender, RoutedEventArgs e) + { + pidPopupOverlay.IsVisible = true; + + } + + + private void getUiElementes() + { + var error = _error.ReadErrorSettings()[0]; + + if (error.phaseNumber == 1) + { + phaseContainer.Background = Avalonia.Media.Brushes.Gray; + phaseContainer.IsEnabled = false; + } + else + { + phaseContainer.Background = Brush.Parse("#E6E6E6"); + phaseContainer.IsEnabled = true; + } + + flagRectangles = this.GetLogicalDescendants() + .OfType() + .Where(cb => cb.Classes.Contains("flag")) + .ToList(); + + InputesElements = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("in") && (c is Grid || c is Ellipse)) + .ToList(); + MotoreState = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("motorState") && (c is Grid || c is Ellipse)) + .ToList(); + hvoOutPuts = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("hvo") && (c is Grid || c is Ellipse)) + .ToList(); + lvoOutPuts = this.GetLogicalDescendants() + .OfType() + .Where(c => c.Classes.Contains("lvo") && (c is Grid||c is StackPanel || c is Ellipse)) + .ToList(); + var machine=_machine.ReadMachine(); + t1Text.Text = char.IsDigit(machine.setTemp1.ToString()[0])?"+"+ machine.setTemp1.ToString(): machine.setTemp1.ToString(); + t2Text.Text = char.IsDigit(machine.setTemp2.ToString()[0]) ? "+" + machine.setTemp2.ToString() : machine.setTemp2.ToString(); + t3Text.Text = char.IsDigit(machine.setTemp3.ToString()[0]) ? "+" + machine.setTemp3.ToString() : machine.setTemp3.ToString(); + t4Text.Text = char.IsDigit(machine.setTemp4.ToString()[0]) ? "+" + machine.setTemp4.ToString() : machine.setTemp4.ToString(); + + + } + private void setDefaultSettings() + { + var stackPanel = _mainWindow.HomeTrack.Parent as StackPanel; + _mainWindow.minimizeBtn.IsVisible = false; + + if (_isFromManualControl) + { + // Special UI setup when called from ManualControl + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.AdvanceSettingsTrack.IsVisible = false; + _mainWindow.ManualControlTrack.IsVisible = true; + _mainWindow.ManualControlPolygon.Stroke = Avalonia.Media.Brushes.Black; + } + else + { + // Original logic for other callers + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + if (_isAdvSettings) + { + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.AdvanceSettingsTrack.IsVisible = true; + _mainWindow.AdvanceSettingsPolygon.Stroke = Avalonia.Media.Brushes.Black; + + } + else + { + _mainWindow.SettingTrack.IsVisible = true; + _mainWindow.SettingPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.AdvanceSettingsTrack.IsVisible = false; + + } + } + + _mainWindow.DiagnosticsTrack.IsVisible = true; + _mainWindow.DiagnosticsPolygon.Stroke = Brush.Parse("#A4275D"); + // Remove the button from its current position + stackPanel.Children.Remove(_mainWindow.DiagnosticsTrack); + + // Add it back at the end of the StackPanel + stackPanel.Children.Add(_mainWindow.DiagnosticsTrack); + + _mainWindow.TitleBtn.IsVisible = false; + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = "DMC7A"; + //Set Footer + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.footerMsg.Text= "Read Values, And Control Outputs Manually"; + _mainWindow.footerMsg.Foreground= Brush.Parse("#A4275D"); + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } + + // KP Slider and Button Event Handlers + private void KpSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kpSliderValue != null && sender is Slider slider) + { + kpSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KpMinusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value > kpSlider.Minimum) + { + kpSlider.Value--; + } + } + + private void KpPlusClick(object? sender, RoutedEventArgs e) + { + if (kpSlider.Value < kpSlider.Maximum) + { + kpSlider.Value++; + } + } + + // KI Slider and Button Event Handlers + private void KiSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kiSliderValue != null && sender is Slider slider) + { + kiSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KiMinusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value > kiSlider.Minimum) + { + kiSlider.Value--; + } + } + + private void KiPlusClick(object? sender, RoutedEventArgs e) + { + if (kiSlider.Value < kiSlider.Maximum) + { + kiSlider.Value++; + } + } + + // KD Slider and Button Event Handlers + private void KdSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (kdSliderValue != null && sender is Slider slider) + { + kdSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KdMinusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value > kdSlider.Minimum) + { + kdSlider.Value--; + } + } + + private void KdPlusClick(object? sender, RoutedEventArgs e) + { + if (kdSlider.Value < kdSlider.Maximum) + { + kdSlider.Value++; + } + } + + // KL Slider and Button Event Handlers + private void KlSliderValueChanged(object? sender, RoutedEventArgs e) + { + if (klSliderValue != null && sender is Slider slider) + { + klSliderValue.Text = ((int)slider.Value).ToString(); + } + } + + private void KlMinusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value > klSlider.Minimum) + { + klSlider.Value--; + } + } + + private void KlPlusClick(object? sender, RoutedEventArgs e) + { + if (klSlider.Value < klSlider.Maximum) + { + klSlider.Value++; + } + } +} + +============================================================ +FILE: DaireApplication/Views/UserController/Home.axaml +============================================================ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/UserController/Recipe.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.DataBase; +using DaireApplication.Views; +using ReactiveUI; +using System; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace DaireApplication; + +public partial class Recipe : UserControl +{ + Button recipeButton = new Button(); + private bool _isLongPress; + + private MainWindow? _mainWindow; + private UserTable? _currentUser; + private RecipeTable _recipeTable=new RecipeTable(); + private Process? _keyboardProcess; + + public Recipe() + { + InitializeComponent(); + + } + public Recipe(MainWindow mainWindow,UserTable currentUser) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + InitializeComponent(); + nameBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + updateBorder.AddHandler(InputElement.PointerPressedEvent, OnTextBoxFocused, RoutingStrategies.Tunnel, handledEventsToo: true); + setDefaultSettings(); + addDynamicButtons(); + } + + + private async void OnRecipeClick(object? sender, RoutedEventArgs e) + { + if (_isLongPress) + { + // Reset the flag for future interactions. + _isLongPress = false; + // Ignore this click since a long press was detected. + return; + } + + if (sender is Button button) + { + if (_currentUser.CanEdit) + { + _mainWindow.FindControl("ContentArea").Content = new RecipeEdit(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name)); + + } + else + { + _mainWindow.FindControl("ContentArea").Content = new Settings(_mainWindow, _currentUser, _recipeTable.ReadRecipesById(button.Name)); + _mainWindow.restBoard = true; + } + + + } + + + + + } + private async void deleteActionClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + deleteMsg.Text = $"You are about to delete {button.Tag}"; + DeletePopupOverlay.IsVisible = true; + + } + + } + private async void UpdateActionClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var text = recipeButton.Content as TextBlock; + updateInput.Text = $"{text.Text}"; + updatePopupOverlay.IsVisible = true; + + } + + } + private void OnLongRecipeClick(object? sender, RoutedEventArgs e) + { + if (e is HoldingRoutedEventArgs args) + { + if (args.HoldingState == HoldingState.Started) + { + _isLongPress = true; + + if (sender is Button button) + { + var targetText= button.Content as TextBlock; + deleteActionBtn.Tag = targetText.Text; + managePopupOverlay.IsVisible = true; + recipeButton = button; + + //recipeButton = button; + //if (button.Content is TextBlock targetText) + //{ + // deleteMsg.Text = $"You are about to delete {targetText.Text}"; + //} + } + + args.Handled = true; + } + else if (args.HoldingState == HoldingState.Completed) + { + _isLongPress = false; + } + } + } + private void CloseKeyboard() + { + try + { + if (_keyboardProcess != null) + { + // Kill the keyboard process + _keyboardProcess.Kill(); + _keyboardProcess.Dispose(); + _keyboardProcess = null; + + // Force kill any remaining keyboard processes + var processKill = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "killall", + Arguments = "-9 onboard matchbox-keyboard florence", // Common Linux on-screen keyboards + UseShellExecute = false, + CreateNoWindow = true + } + }; + processKill.Start(); + processKill.WaitForExit(1000); + processKill.Dispose(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error closing keyboard: {ex.Message}"); + } + } + + public void AttachHandlers(Button button) + { + if (button != null) + { + button.Holding += OnLongRecipeClick; + + button.PointerPressed += (sender, e) => + { + // Simulate a long press on any pointer (mouse or touch) + var point = e.GetPosition(button); + OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Started, point, e.Pointer.Type)); + }; + + button.PointerReleased += (sender, e) => + { + // End simulated long press + var point = e.GetPosition(button); + OnLongRecipeClick(sender, new HoldingRoutedEventArgs(HoldingState.Completed, point, e.Pointer.Type)); + }; + } + } + private async void OnAddRecipeClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + PopupOverlay.IsVisible = true; + } + + } + private async void OnPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + PopupOverlay.IsVisible = false; + + + + } + private async void OnDeletePopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + DeletePopupOverlay.IsVisible = false; + managePopupOverlay.IsVisible = false; + updatePopupOverlay.IsVisible = false; + + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + var result = _recipeTable.DeleteRecipe(recipeButton.Name); + if (result) + { + addDynamicButtons(); + DeletePopupOverlay.IsVisible= false; + managePopupOverlay.IsVisible = false; + + } + else + { + + } + + + } + private async void SaveUpdateClick(object? sender, RoutedEventArgs e) + { + if (!_recipeTable.DoesNameExist(updateInput.Text)) + { + var recipe = _recipeTable.ReadRecipesById(recipeButton.Name); + recipe.Name = updateInput.Text; + var result = _recipeTable.UpdateRecipe(recipe); + if (result) + { + addDynamicButtons(); + managePopupOverlay.IsVisible = false; + updatePopupOverlay.IsVisible = false; + CloseKeyboard(); + + + } + else + { + + } + } + else + { + CloseKeyboard(); + await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error"); + _mainWindow.Topmost = false; + _mainWindow.Focus(); + _mainWindow.Activate(); + + } + + + + } + private void showPopUp(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + recipeButton = button; + button.Foreground = Brush.Parse("#A4275D"); + PopupOverlay.IsVisible = true; + // Append the button's content to the input box + //InputTextBox.Text += button.Content?.ToString(); + } + + } + private async void saveRecipeClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (!string.IsNullOrEmpty(NameInput.Text)) + { + if (!_recipeTable.DoesNameExist(NameInput.Text)) + { + RecipeTable data = new RecipeTable(); + data.Name = NameInput.Text; + data.Mixer = false; + data.Fountain = false; + data.MoldHeater = false; + data.Vibration = false; + data.VibHeater = false; + data.Pedal = false; + var result = _recipeTable.AddRecipe(data); + if (result) + { + addDynamicButtons(); + CloseKeyboard(); + NameInput.Text = ""; + PopupOverlay.IsVisible = false; + + } + else + { + + } + } + else + { + CloseKeyboard(); + await MainWindow.MessageBox.Show(_mainWindow, "this name is already in use", "Error"); + _mainWindow.Topmost = false; + _mainWindow.Activate(); + + } + } + + + } + + } + private (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + private async void OnTextBoxFocused(object? sender, PointerPressedEventArgs e) + { + if (_keyboardProcess is { HasExited: false }) + return; + + var (fileName, args) = GetKeyboardCommand(); + if (fileName is null) + return; + + _keyboardProcess = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = fileName, + Arguments = args, + UseShellExecute = true + }, + EnableRaisingEvents = true + }; + + + try + { + _keyboardProcess.Start(); + + Dispatcher.UIThread.Post(() => + { + if (sender is Border border) + { + var textbox= border.Child as TextBox; + textbox.SelectionStart = 0; + textbox.SelectionEnd = textbox.Text?.Length ?? 0; + } + }); + } + catch + { + // fail silently if keyboard not found + } + } + + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + // Close the popup when clicking outside of it + recipeButton.Foreground = Avalonia.Media.Brushes.Black; + + PopupOverlay.IsVisible = false; + } + + private void setDefaultSettings() + { + + //set recipe title + if (_currentUser.CanEdit) + { + RecipeTitle.Content = "RECIPE EDIT/ADD PANEL"; + } + else + { + RecipeTitle.Content = "RECIPE SELECTION"; + } + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.RecipePanelTrack.IsVisible = false; + + + if (_currentUser.CanEdit) + { + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Brush.Parse("#A4275D"); + } + else + { + _mainWindow.RecipeSelTrack.IsVisible = true; + _mainWindow.RecipeSelPolygon.Stroke = Brush.Parse("#A4275D"); + } + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.TitleBtn.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.SoftwareTrack.IsVisible = false; + + + //Set Footer + if (_currentUser.CanEdit) + { + _mainWindow.footerMsg.Text = "Long press to delete recipe"; + _mainWindow.footerMsg.IsVisible = true; + _mainWindow.chefBtns.IsVisible = true; + + } + else + { + _mainWindow.footerMsg.Text = "Select a recipe to start"; + _mainWindow.footerMsg.IsVisible = true; + + + } + _mainWindow.ManualControlTrack.IsVisible = false; + + _mainWindow.footerMsg.MaxWidth = 1000; + + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } + private void addDynamicButtons() + { + var recipes= _recipeTable.ReadRecipes(); + var grid = this.FindControl("DynamicGrid"); + grid.Children.Clear(); + int lastRow = 0; + int lastCol = 0; + int colIndexForExtraData = 0; + int recipeIndex = 0; + + try + { + if (recipes.Count<3) + { + // Add dynamic rows + for (int i = 0; i < (int)Math.Ceiling((double)recipes.Count / 3); i++) // Example: 20 rows + { + lastRow = i; + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + // Add content for each column + for (int col = 0; col < recipes.Count; col++) + { + + lastCol = col; + + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + col].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight=FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + col].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + //button.DoubleTapped += OnDoubleRecipeClick; + + } + + grid.Children.Add(button); + Grid.SetRow(button, i); + Grid.SetColumn(button, col); + } + recipeIndex += 3; + } + if (_currentUser.CanEdit) + { + var Plus = new TextBlock + { + Padding = new Thickness(10), + Text = "+", + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 100, + Foreground = Brush.Parse("#A4275D") + + }; + var AddButtun = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = Plus, + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center, + Padding = new Thickness(0, 0, 0, 15), + + }; + AddButtun.Click += OnAddRecipeClick; + if (lastCol < 2) + { + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow); + Grid.SetColumn(AddButtun, lastCol + 1); + } + else + { + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow + 1); + Grid.SetColumn(AddButtun, 0); + } + } + + + + + } + else + { + // Add dynamic rows + for (int i = 0; i < (int)Math.Floor((double)recipes.Count / 3); i++) // Example: 20 rows + { + lastRow = i; + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + // Add content for each column + for (int col = 0; col < 3; col++) + { + + + lastCol = col; + + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + col].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight = FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + col].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + + //button.DoubleTapped += OnDoubleRecipeClick; + + } + + grid.Children.Add(button); + Grid.SetRow(button, i); + Grid.SetColumn(button, col); + } + recipeIndex += 3; + } + for (int i = 0; i < recipes.Count -recipeIndex; i++) + { + var text = new TextBlock + { + Padding = new Thickness(10), + Text = recipes[recipeIndex + i].Name, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 31, + FontWeight = FontWeight.Normal, + Foreground = Avalonia.Media.Brushes.Black + + }; + var button = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = text, + Name = recipes[recipeIndex + i].Id.ToString(), + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + + }; + button.Click += OnRecipeClick; + + if (_currentUser.CanEdit) + { + //button.Holding += OnLongRecipeClick; + AttachHandlers(button); + + //button.DoubleTapped += OnDoubleRecipeClick; + + } + if (lastCol < 2) + { + lastCol += 1; + + + + + grid.Children.Add(button); + Grid.SetRow(button,lastRow); + Grid.SetColumn(button, lastCol); + } + else + { + + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(button); + Grid.SetRow(button, lastRow + 1); + Grid.SetColumn(button, colIndexForExtraData); + colIndexForExtraData += 1; + } + } + if (_currentUser.CanEdit) + { + var Plus = new TextBlock + { + Padding = new Thickness(10), + Text = "+", + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + FontSize = 100, + Foreground = Brush.Parse("#A4275D"), + + + }; + var AddButtun = new Button + { + Width = 210, + Height = 160, + Margin = new Thickness(3), + Content = Plus, + CornerRadius = new CornerRadius(10), + Background = Avalonia.Media.Brushes.White, + VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center, + HorizontalContentAlignment = Avalonia.Layout.HorizontalAlignment.Center, + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + Padding = new Thickness(0,0,0,15), + }; + + AddButtun.Click += OnAddRecipeClick; + + if (lastCol < 2) + { + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow); + Grid.SetColumn(AddButtun, lastCol + 1); + } + else + { + grid.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); + + grid.Children.Add(AddButtun); + Grid.SetRow(AddButtun, lastRow + 1); + Grid.SetColumn(AddButtun, colIndexForExtraData); + } + } + + } + + } + catch (Exception) + { + } + + + + } + + +} + +============================================================ +FILE: DaireApplication/Views/UserController/RecipeEdit.axaml +============================================================ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/UserController/RecipeEdit.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using AvaloniaApplication1.DataBase; +using DaireApplication.Views; +using System; + +namespace DaireApplication; + +public partial class RecipeEdit : UserControl +{ + Button controllButton = new Button(); + private MainWindow? _mainWindow; + private UserTable? _currentUser; + private RecipeTable? _recipeTable; + + + public RecipeEdit() + { + InitializeComponent(); + } + public RecipeEdit(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + _recipeTable=recipeTable; + InitializeComponent(); + setDefaultSettings(); + } + + string oldNumber = ""; + private void OnKeyClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + //number += button.Content?.ToString(); + targetText.Text += button.Content ; + } + // Append the button's content to the input box + //InputTextBox.Text += button.Content?.ToString(); + } + + } + private void OnBackClick(object? sender, RoutedEventArgs e) + { + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + if (!string.IsNullOrEmpty(targetText.Text)) + { + // Remove the last character from the text box + targetText.Text = targetText.Text.Remove(targetText.Text.Length -1, 1); + //number = number.Remove(number.Length - 1); + } + } + + } + private void EnterClick(object? sender, RoutedEventArgs e) + { + RecipeTable recipe = new RecipeTable(); + recipe.Id = _recipeTable.Id; + recipe.Mixer = null; + recipe.Fountain = null; + recipe.MoldHeater = null; + recipe.Vibration = null; + recipe.VibHeater = null; + recipe.Pedal = null; + //getting the btn value + var heatingStackPanel = heatingBtn.Content as StackPanel; + var heatingLabel = heatingStackPanel.Children; + var heatingText = heatingLabel[1] as TextBlock; + + var coolingStackPanel = coolingBtn.Content as StackPanel; + var coolingLabel = coolingStackPanel.Children; + var coolingText = coolingLabel[1] as TextBlock; + + + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + var targetText = Label[1] as TextBlock; + var activeTxt= Label[0] as TextBlock; + switch (activeTxt.Text) + { + case "HEATING:": + if (!string.IsNullOrEmpty(targetText.Text)) + { + int value = Int32.Parse(targetText.Text); + if (value>60) + { + tempErrorMsg.Text = "Heating Tempreature must be lower than 60 �C"; + return; + } + else if (value<40) + { + tempErrorMsg.Text = "Heating Tempreature must be greater than 40 �C"; + return; + + } + else + { + recipe.CoolingGoal = 0; + recipe.PouringGoal = 0; + recipe.HeatingGoal = value; + _recipeTable.UpdateRecipe(recipe); + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + PopupOverlay.IsVisible = false; + setDefaultSettings(); + + } + } + break; + case "POURING:": + if (!string.IsNullOrEmpty(targetText.Text)) + { + int value = Int32.Parse(targetText.Text); + if (string.IsNullOrEmpty(heatingText.Text)||string.IsNullOrEmpty(coolingText.Text)) + { + tempErrorMsg.Text = $"Enter heating and cooling tempreature first"; + return; + } + if (value > Int32.Parse(heatingText.Text)) + { + tempErrorMsg.Text = $"Pouring Tempreature must be lower than Heating Tempreatur({heatingText.Text}�C)"; + return; + } + else if (value < Int32.Parse(coolingText.Text)) + { + tempErrorMsg.Text = $"Pouring Tempreature must be greater than Cooling Tempreatur({coolingText.Text}�C)"; + return; + + + } + else + { + recipe.HeatingGoal = 0; + recipe.CoolingGoal = 0; + recipe.PouringGoal = value; + _recipeTable.UpdateRecipe(recipe); + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + PopupOverlay.IsVisible = false; + setDefaultSettings(); + + } + } + break; + case "COOLING:": + if (!string.IsNullOrEmpty(targetText.Text)) + { + int value = Int32.Parse(targetText.Text); + if (value > 40) + { + tempErrorMsg.Text = "Cooling Tempreature must be lower than 40 �C"; + return; + + } + else if (value < 20) + { + tempErrorMsg.Text = "Cooling Tempreature must be greater than 20 �C"; + return; + + } + else + { + recipe.HeatingGoal = 0; + recipe.PouringGoal = 0; + recipe.CoolingGoal = value; + _recipeTable.UpdateRecipe(recipe); + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + PopupOverlay.IsVisible = false; + setDefaultSettings(); + + } + } + break; + } + + + + + + } + private void showPopUp(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + heatingBtn.IsEnabled = false; + coolingBtn.IsEnabled = false; + pouringBtn.IsEnabled = false; + button.IsEnabled = true; + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + oldNumber = targetText.Text; + } + controllButton = button; + PopupOverlay.IsVisible = true; + } + + } + private void OnPopupOverlayPointerPressed(object sender, PointerPressedEventArgs e) + { + // Close the popup when clicking outside of it + //controllButton.Foreground = Avalonia.Media.Brushes.Black; + var StackPanel = controllButton.Content as StackPanel; + var Label = StackPanel.Children; + if (Label[1] is TextBlock targetText) + { + //number += button.Content?.ToString(); + targetText.Text = oldNumber; + } + tempErrorMsg.Text = ""; + heatingBtn.IsEnabled = true; + coolingBtn.IsEnabled = true; + pouringBtn.IsEnabled = true; + + PopupOverlay.IsVisible = false; + } + + private void setDefaultSettings() + { + //set Values + _recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString()); + heatingValue.Text = _recipeTable?.HeatingGoal == 0 ? "" : _recipeTable?.HeatingGoal.ToString(); + coolingValue.Text = _recipeTable?.CoolingGoal == 0 ? "" : _recipeTable?.CoolingGoal.ToString(); + pouringValue.Text = _recipeTable?.PouringGoal == 0 ? "" : _recipeTable?.PouringGoal.ToString(); + + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipePanelTrack.IsVisible = true; + _mainWindow.RecipePanelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeEditTrack.IsVisible = true; + _mainWindow.RecipeEditPolygon.Stroke = Brush.Parse("#A4275D"); + _mainWindow.RunInterfaceTrack.IsVisible = false; + _mainWindow.RecipeSelTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = _recipeTable.Name; + + //Set Footer + _mainWindow.footerMsg.Text = "Select the tempereture to edit it"; + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Brush.Parse("#A4275D"); + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = false; + _mainWindow.adminBtns.IsVisible = false; + } +} + +============================================================ +FILE: DaireApplication/Views/UserController/Settings.axaml +============================================================ + + + + + + + + + + + + + + + + + Mixer + Delay: + 120 + + + + + + + + Pedal OFF: + + 120 + + + + + + + + + Fountain Delay: + 120 + + Target Temp: + 120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/UserController/Settings.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Documents; +using Avalonia.Controls.Shapes; +using Avalonia.Input; +using Avalonia.Interactivity; +using Avalonia.Markup.Xaml; +using Avalonia.Media; +using AvaloniaApplication1.DataBase; +using DaireApplication.DataBase; +using DaireApplication.ViewModels; +using DaireApplication.Views; +using System; +using System.Drawing; +using System.Reflection.PortableExecutable; +using System.Threading; + +namespace DaireApplication; + +public partial class Settings : UserControl +{ + Button controllButton = new Button(); + private MainWindow? _mainWindow; + private UserTable? _currentUser; + public RecipeTable? _recipeTable; + private MachineTable _machine; + public string ActiveColor { get; set; } = "#A4275D"; + public string PassiveColor { get; set; } = "#666666"; + + public Settings() + { + InitializeComponent(); + } + public Settings(MainWindow mainWindow, UserTable currentUser,RecipeTable recipeTable) + { + _currentUser = currentUser; + _mainWindow = mainWindow; + _recipeTable = recipeTable; + _machine = new MachineTable(); + _machine = _machine.ReadMachine(); + + InitializeComponent(); + + setDefaultSettings(); + + setDafaultValues(); + mixerBtn.Click += _mainWindow.MotorClick; + fountainBtn.Click += _mainWindow.FountainClick; + } + + + private void toggelOnOffClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var titelLable = Label[0] as Label; + + + + if (Label[1] is Label targetLable) + { + if (targetLable.Content == "ON") + { + if (titelLable.Content == "MOLD HEATER") + { + _mainWindow.moldHeaterMotor = 0; + } + if (titelLable.Content == "VIBRATION") + { + _mainWindow.vibrationMotor = 0; + + } + if (titelLable.Content == "VIB. HEATER") + { + _mainWindow.vibHeaterMotor = 0; + + } + + + } + else + { + if (titelLable.Content == "MOLD HEATER") + { + _mainWindow.moldHeaterMotor = 1; + } + if (titelLable.Content == "VIBRATION") + { + _mainWindow.vibrationMotor = 1; + + } + if (titelLable.Content == "VIB. HEATER") + { + _mainWindow.vibHeaterMotor = 1; + + } + + } + } + } + + } + private void PedalBtn(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + RecipeTable recipe = new RecipeTable(); + recipe.Id = _recipeTable.Id; + var StackPanel = button.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[1] as Avalonia.Controls.Shapes.Rectangle; + if (Label[0] is TextBlock targetLable) + { + if (targetLable.Text == "AUTO") + { + if (_mainWindow.pedalOnTimer!=null ) + { + _mainWindow.pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pedalOnTimer = null; + _mainWindow.pedalOnSeconds = 0; + + + } + if (_mainWindow.pedalOffTimer!=null) + { + _mainWindow.pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pedalOffTimer = null; + _mainWindow.pedalOffSeconds = 0; + } + _mainWindow.pedalMotor = 0; + + targetLable.Text = "MANUAL"; + underLine.Fill = Brush.Parse("#666666"); + PedalAutoContainer.IsEnabled = false; + recipe.Pedal = true; + } + else + { + _mainWindow.pedalMotor = 1; + _mainWindow.pedalState = -1; + _mainWindow.setPedalTimerOnce = 1; + _mainWindow.pedalOnSeconds = 0; + _mainWindow.pedalOffSeconds = 0; + targetLable.Text = "AUTO"; + underLine.Fill = Brush.Parse("#A4275D"); + PedalAutoContainer.IsEnabled = true; + recipe.Pedal = false; + + } + _recipeTable.UpdateRecipe(recipe); + } + } + + } + private void adjustPedalTime(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + RecipeTable recipe = new RecipeTable(); + recipe.Id = _recipeTable.Id; + + if (button.Classes[0].ToString()== "PedalOff") + { + if (button.Content == "−") + { + if (Int32.Parse(PedalOffTime.Text) > 0) + { + PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) - 1).ToString(); + } + + } + else if (button.Content == "+") + { + + PedalOffTime.Text = (Int32.Parse(PedalOffTime.Text) + 1).ToString(); + } + recipe.PedalOffTime = Int32.Parse(PedalOffTime.Text); + _recipeTable.UpdateRecipe(recipe); + } + else + { + if (button.Content == "−") + { + if (Int32.Parse(PedalOnTime.Text) > 0) + { + PedalOnTime.Text = (Int32.Parse(PedalOnTime.Text) - 1).ToString(); + } + + } + else if (button.Content == "+") + { + if (int.TryParse(PedalOnTime.Text, out int value)) + { + if (value < 9) + { + PedalOnTime.Text = (value + 1).ToString(); + } + } + } + recipe.PedalOnTime = Int32.Parse(PedalOnTime.Text); + _recipeTable.UpdateRecipe(recipe); + } + _recipeTable = _recipeTable.ReadRecipesById(_recipeTable.Id.ToString()); + + } + + } + + private async void OnIgnorePopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + DeletePopupOverlay.IsVisible = false; + + + + } + private async void HideTempErrorPopUp(object? sender, RoutedEventArgs e) + { + _mainWindow.pauseTimer = false; + _mainWindow.pauseTempTracking = true; + tempErrorPopupOverlay.IsVisible = false; + } + private async void YesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (DeletePopupOverlay.Tag=="home") + { + + _mainWindow.resetAll(); + // rest the board + _mainWindow.restBoard = true; + _mainWindow.UserName.Content = "Select User"; + _mainWindow.footerMsg.Text = ""; + _mainWindow.ContentArea.Content = new Home(_mainWindow); + } + else if (DeletePopupOverlay.Tag == "recipeSel") + { + _mainWindow.resetAll(); + // rest the board + _mainWindow.restBoard = true; + _mainWindow.footerMsg.Text = ""; + _mainWindow.ContentArea.Content = new Recipe(_mainWindow, Program.currentUser); + } + } + + + + } + private async void ErrorYesBtnClick(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + //_mainWindow.pause = true; + //_mainWindow.pauseTempTracking = true; + //_mainWindow.pauseTimer = true; + + // stop the recipe + _mainWindow.startRecipe = 0; + _mainWindow.Heating = 0; + _mainWindow.cooling = 0; + _mainWindow.pouring = 0; + _mainWindow.PumbOn = -1; + _mainWindow.pedalMotor = -1; + if (_mainWindow.heatingTimer != null) + { + _mainWindow.heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.heatingSeconds = 0; + } + if (_mainWindow.coolingTimer != null) + { + _mainWindow.coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.coolingSeconds = 0; + } + if (_mainWindow.pouringTimer != null) + { + _mainWindow.pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + _mainWindow.pouringSeconds = 0; + } + var fount = _mainWindow._mapping.Find(x => x.Name.ToLower() == "Pump".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + _mainWindow.holdingRegister.motor &= (ushort)~(1 << bit); + } + } + } + _mainWindow.holdingRegister.setTemp1 = -10000; + _mainWindow.holdingRegister.setTemp2 = -10000; + _mainWindow.holdingRegister.setTemp3 = -10000; + _mainWindow.holdingRegister.setTemp4 = -10000; + await _mainWindow.WriteToSerialAsync("ErrorYesBtnClick"); + tempErrorPopupOverlay.IsVisible = false; + _mainWindow.footerMsg.Text = "Recipe Stoped"; + _mainWindow.recipeStartBtn.Content = "START RECIPE"; + } + } + + + + private void setDefaultSettings() + { + //Set Track Up + _mainWindow.HomeTrack.IsVisible = true; + //_mainWindow.HomePolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RecipeSelTrack.IsVisible = true; + _mainWindow.RecipeSelPolygon.Stroke = Avalonia.Media.Brushes.Black; + _mainWindow.RunInterfaceTrack.IsVisible = true; + _mainWindow.RunInterfacePolygon.Stroke = Brush.Parse("#A4275D"); + _mainWindow.RecipePanelTrack.IsVisible = false; + _mainWindow.RecipeEditTrack.IsVisible = false; + _mainWindow.SettingTrack.IsVisible = false; + _mainWindow.DiagnosticsTrack.IsVisible = false; + _mainWindow.TitleBtn.IsVisible = true; + _mainWindow.Title.Text = _recipeTable.Name; + + //Set Footer + _mainWindow.footerMsg.Text = "Ready"; + _mainWindow.footerMsg.MaxWidth = 500; + _mainWindow.footer.Background = Avalonia.Media.Brushes.WhiteSmoke; + _mainWindow.footerMsg.Foreground = Avalonia.Media.Brushes.Green; + _mainWindow.footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + _mainWindow.footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + _mainWindow.footerDateContainer.IsVisible = true; + _mainWindow.footerStartBtn.IsVisible = true; + _mainWindow.adminBtns.IsVisible = false; + } + private void setDafaultValues() + { + //Recipe Settings + heatingValue.Content = _recipeTable.HeatingGoal; + coolingValue.Content = _recipeTable.CoolingGoal; + pouringValue.Content = _recipeTable.PouringGoal; + //tankTemp + TankTempValue.Content = _recipeTable?.TankTemp; + //mixer + var mixerChildren= MixerSP.Children; + var mixerLable = mixerChildren[1] as Label; + mixerLable.Content = _recipeTable.Mixer.Value ? "ON" : "OFF"; + var mixerUnderLine = mixerChildren[2] as Avalonia.Controls.Shapes.Rectangle; + mixerUnderLine.Fill = _recipeTable.Mixer.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + //pedal + var pedalChildren = PedalSP.Children; + var pedalText = pedalChildren[0] as TextBlock; + var pedalUnderLine = pedalChildren[1] as Avalonia.Controls.Shapes.Rectangle; + if (_recipeTable.Pedal.Value) + { + pedalText.Text = "MANUAL"; + pedalUnderLine.Fill = Brush.Parse(PassiveColor); + PedalAutoContainer.IsEnabled = false; + } + else + { + pedalText.Text = "AUTO"; + pedalUnderLine.Fill = Brush.Parse(ActiveColor); + PedalAutoContainer.IsEnabled = true; + } + PedalOffTime.Text = _recipeTable.PedalOffTime.ToString(); + PedalOnTime.Text = _recipeTable.PedalOnTime.ToString(); + //fountain Temp + FountainTempValue.Content = _recipeTable?.FountainTemp; + //fountain + var fountainChildren = FountainSP.Children; + var fountainLable = fountainChildren[1] as Label; + fountainLable.Content = _recipeTable.Fountain.Value ? "ON" : "OFF"; + var fountainUnderLine = fountainChildren[2] as Avalonia.Controls.Shapes.Rectangle; + fountainUnderLine.Fill = _recipeTable.Fountain.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + //mold Heater + var moldHeaterChildren = MoldHeaterSP.Children; + var moldHeaterLable = moldHeaterChildren[1] as Label; + moldHeaterLable.Content = _recipeTable.MoldHeater.Value ? "ON" : "OFF"; + var moldHeaterUnderLine = moldHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle; + moldHeaterUnderLine.Fill = _recipeTable.MoldHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + // vibration + var vibrationChildren = VibrationSP.Children; + var vibrationLable = vibrationChildren[1] as Label; + vibrationLable.Content = _recipeTable.Vibration.Value ? "ON" : "OFF"; + var vibrationUnderLine = vibrationChildren[2] as Avalonia.Controls.Shapes.Rectangle; + vibrationUnderLine.Fill = _recipeTable.Vibration.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + // vib heater + var vibHeaterChildren = VibHeaterSP.Children; + var vibHeaterLable = vibHeaterChildren[1] as Label; + vibHeaterLable.Content = _recipeTable.VibHeater.Value ? "ON" : "OFF"; + var vibHeaterUnderLine = vibHeaterChildren[2] as Avalonia.Controls.Shapes.Rectangle; + vibHeaterUnderLine.Fill = _recipeTable.VibHeater.Value ? Brush.Parse(ActiveColor) : Brush.Parse(PassiveColor); + + + } +} + +============================================================ +FILE: DaireApplication/Views/UserController/Software.axaml +============================================================ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PASSWORDS RESET + + + + + + + + + + + + + + + + + + + + + + + + + + SCREEN SETTINGS + + + + + + + + + + + + + + + + + + + + + + + + + + COM SETTINGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + Bound Rate: + + + + + + + + + + + + + + + + + + Stop Bits: + + + + + + + + + + + + Parity: + + + + + + + + + + + Packets Sending Intervals : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Warning Limit : + + + + + + + Error Limit : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + V0.6 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Views/MainWindow.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Shapes; +using Avalonia.Interactivity; +using Avalonia.Layout; +using Avalonia.Media; +using Avalonia.Threading; +using AvaloniaApplication1.ViewModels; +using DaireApplication.DataBase; +using DaireApplication.Loops; +using DaireApplication.ViewModels; +using DynamicData; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Diagnostics; +using System.IO; +using System.IO.Ports; +using System.Linq; +using System.Management; +using System.Runtime.InteropServices; +using System.Security.Cryptography.X509Certificates; +using System.Threading; +using System.Threading.Tasks; +using static DaireApplication.ViewModels.Error; + +namespace DaireApplication.Views +{ + public partial class MainWindow : Window + { + List buffer = new List(); + public ModBusMaster _modBusMaster = new ModBusMaster(); + public MachineTable _machine = new MachineTable(); + public ConfigrationTable _config = new ConfigrationTable(); + public List _configrations = new List(); + public Mapping _map = new Mapping(); + public ScreeenTable _screeen = new(); + public ErrorSettingsTable _error = new(); + public List _mapping = new List(); + public static bool isOff { get; set; } + const double deadZone = 1.5; // Changeable based on stability needs + bool shouldRunFountain = false; + public readonly SemaphoreSlim _keepSendingLock = new(1, 1); + + public SerialPort _port { get; set; } + private static Thread monitorThread; + private static Thread screenThread; + private static Thread touchThread; + private static Thread internetThread; + private static Thread InteractiveUIThread; + private static Thread serialThread; + public bool serialThreadRunning = true; + public bool isRunning = true; + public bool restBoard { get; set; } + public bool sendConfig { get; set; } = true; + public bool reSendHolding { get; set; } + public bool dontResetOutPuts { get; set; } + + bool allBitsOn = false; + bool allPedalBitsOn = false; + public int pedalState { get; set; } = -1; + public int pedalStateChanged { get; set; } = -1; + public float recipeHeatingGoal { get; set; } + public float recipeCoolingGoal { get; set; } + public float recipePouringGoal { get; set; } + + public string ActiveColor { get; set; } = "#A4275D"; + public string PassiveColor { get; set; } = "#666666"; + //Pre Heating + public bool isFlashPreHeating { get; set; } = false; + public bool isReadingTemp { get; set; } = true; + public int startPreHeating { get; set; } = -1; + public int writingMaxTemp { get; set; } = -1; + + //Mixer Motor + private Timer mixerTimer; + private Timer preMixerTimer; + + private static int mixerSeconds = 1; + private static int preMixerSeconds = 1; + public bool setMixerTimerOnce { get; set; } = false; + public bool checkMixerTWT_HWTH { get; set; } = false; + public bool isMixerMotorOn { get; set; } = false; + public int startMixerMotor { get; set; } = -1; + public int startMixerMotorFlashing { get; set; } = -1; + public int sendComMixerMotor { get; set; } = -1; + + //Fountain Motor + private Timer fountainTimer; + private Timer fountainPauseTimer; + private Timer noChoiceChoosenTimer; + + private static int fountainSeconds = 1; + private static int fountainPauseSeconds = 1; + private static int noChoiceChoosenSeconds = 0; + public bool setFountainTimerOnce { get; set; } = false; + public bool checkFountainTMT_PMT { get; set; } = false; + public bool isFountainMotorOn { get; set; } = false; + public int startFountainMotor { get; set; } = -1; + public int startFountainMotorFlashing { get; set; } = -1; + public int sendComFountainMotor { get; set; } = -1; + + public double comTankTemp { get; set; } = 0; + public double comFountainTemp { get; set; } = 0; + public double comPumpTemp { get; set; } = 0; + + //MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1) + public int moldHeaterMotor { get; set; } = -1; + public int vibrationMotor { get; set; } = -1; + public int vibHeaterMotor { get; set; } = -1; + + //Pedal(manual=0,auto=1) + public int pedalMotor { get; set; } = -1; + + //Recipe Start + + public int startRecipe { get; set; } = 0; + public int sendComTankTemp { get; set; } = -1; + //phase 1 heating + public int Heating { get; set; } = -1; + public int sendComHeating { get; set; } = -1; + public int setHeatingTimerOnce { get; set; } = -1; + public Timer heatingTimer; + public int heatingSeconds { get; set; } = 0; + //phase 2 cooling + public int cooling { get; set; } = -1; + public int sendComCooling { get; set; } = -1; + public int setCoolingTimerOnce { get; set; } = -1; + public Timer coolingTimer; + public int coolingSeconds { get; set; } = 0; + + //phase 3 pouring + public int pouring { get; set; } = -1; + public int sendComPouring { get; set; } = -1; + public int setPouringTimerOnce { get; set; } = -1; + public Timer pouringTimer; + public int pouringSeconds { get; set; } = 0; + + //start the pumb + public int PumbOn { get; set; } = -1; + public Timer pedalOnTimer; + public Timer pedalOffTimer; + public int pedalOnSeconds { get; set; } = 0; + public int pedalOffSeconds { get; set; } = 0; + // 1 turn off ,0 turn on + public int setPedalTimerOnce { get; set; } = -1; + + //Board + + public bool resetPort { get; set; } = false; + public bool keepSendingFlag { get; set; } = false; + + public DateTime lastActivity = DateTime.Now; + + public ScreeenTable screenData = new(); + public static List errors = new(); + public bool pause { get; set; } + public bool unPause { get; set; } + public bool isPaused { get; set; } + public bool pauseTimer { get; set; } + public bool pauseTempTracking { get; set; } + public string warningMessage { get; set; } + + public HoldingRegister holdingRegister = new HoldingRegister(); + + public bool turnOnFountainMotor { get; set; } + public bool stopRecipeFlag { get; set; } + + public Timer stopMixerTimer; + public int stopMixerSecondes { get; set; } + public Timer stopFountainTimer; + public int stopFountainSecondes { get; set; } + + public DateTime _lastPacketSendTime = DateTime.MinValue; + public byte[] inputesResponse = new byte[] { 0xFF }; + + // Replace isWriting flag with async method + public TaskCompletionSource _writeCompletionSource = new TaskCompletionSource(); + public Task WriteToSerialAsync(string caller) + { + _writeCompletionSource = new TaskCompletionSource(); + // Optionally log or store the caller for debugging + Debug.WriteLine($"WriteToSerialAsync called by: {caller}"); + return _writeCompletionSource.Task; + } + public void SetWriteComplete(bool success = true) + { + _writeCompletionSource?.TrySetResult(success); + } + + + + + public MainWindow() + { + InitializeComponent(); + // Hide cursor using unclutter + try + { + var process = new System.Diagnostics.Process(); + process.StartInfo.FileName = "unclutter"; + process.StartInfo.Arguments = "-idle 0"; // Hide immediately + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + process.Start(); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to start unclutter: {ex.Message}"); + } + + ContentArea.Content = new Home(this); + this.Closing += OnClosingWindow; + + _machine = _machine.ReadMachine(); + + _configrations = _config.ReadConfigrations(); + _mapping = _map.ReadMappings(); + serialThread = new Thread(() => serialThreadLoop.SendViaSerial(this)) + { + IsBackground = true + }; + serialThread.Start(); + internetThread = new Thread(() => CheckInterNetLoop.CheckInterNet(this)) + { + IsBackground = true + }; + internetThread.Start(); + + screenThread = new Thread(() => ScreenLoop.Screen(this)) + { + IsBackground = true + }; + screenThread.Start(); + InteractiveUIThread = new Thread(() => InteractiveUILoop.Flashing(this)) + { + IsBackground = true + }; + InteractiveUIThread.Start(); + touchThread = new Thread(() => TouchLoop.Touch(this)) + { + IsBackground = true + }; + touchThread.Start(); + monitorThread = new Thread(() => MonitorPortsLoop()) + { + IsBackground = true, + Priority = ThreadPriority.Highest + }; + monitorThread.Start(); + + + } + + private async void MonitorPortsLoop() + { + byte[] tankeResponse = new byte[256]; + var fountainResponse = new byte[256]; + + double tankBottomTempValue = -1; + double tankWallTempValue = -1; + double pumpTempValue = -1; + double fountainTempValue = -1; + var tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + var tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + var pump = _mapping.Find(x => x.Name == "Pump Temp"); + var fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + + + static List ToBinary(int number) + { + return Convert.ToString(number, 2) + .PadLeft(16, '0') + .Reverse() + .Select(c => c == '1') + .ToList(); + } + + + while (true) + { + if (isRunning) + { + Dispatcher.UIThread.Post(() => + { + footerDate.Text = DateTime.Now.ToString("dd/MM/yyyy"); + footerTime.Text = DateTime.Now.ToString("hh:mm tt"); + }); + screenData = _screeen.ReadScreens()?[0]; + + try + { + if (!SerialPort.GetPortNames().Contains(screenData.port)) + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + } + _port = null; + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected:Port Name Not Found"; + //Debug.WriteLine("port name not found"); + footerMsg.Foreground = Avalonia.Media.Brushes.DarkRed; + footerMsg.IsVisible = true; + }); + } + else + { + if (resetPort) + { + Debug.WriteLine("Port reset initiated"); + resetAll(); + if (_port != null && _port.IsOpen) + { + Debug.WriteLine("Closing existing port"); + _port.Close(); + } + _port = null; + if (ConnectToSerialPort()) + { + Debug.WriteLine("Port reconnected successfully"); + Dispatcher.UIThread.Post(() => + { + //Conntected + footerMsg.Text = "Connected"; + footerMsg.IsVisible = true; + sendConfig = true; + }); + } + else + { + Debug.WriteLine("Failed to reconnect port"); + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected"; + footerMsg.IsVisible = true; + }); + } + resetPort = false; + Debug.WriteLine("Port reset completed"); + } + if (_port == null) + { + // Connect to the found device + if (!ConnectToSerialPort()) + { + + Dispatcher.UIThread.Post(() => + { + errors.Clear(); + footerMsg.Text = "Not Connected"; + + }); + } + else + { + serialThreadRunning = true; + + sendConfig = true; + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Connected"; + }); + } + } + else + { + try + { + if (!_port.IsOpen) + { + _port.Open(); + } + + + List inputValues = new List(); + + if (isReadingTemp) + { + if (!_port.IsOpen) + { + _port.Open(); + } + // reading inputes + + var requstReadingInputs = await _modBusMaster.ReadInputRegisters(0, 18); + + + + if (inputesResponse.Length != 1 && inputesResponse[0] != 0xFF) + { + var result = inputesResponse.Skip(3).Take(inputesResponse.Count() - 5).ToArray(); + for (int i = 0; i < result.Length; i = i + 2) + { + inputValues.Add(((result[i] << 8) | result[i + 1])); + } + var brdFlags = ToBinary(inputValues[0]); + var inputes = ToBinary(inputValues[1]); + + // Errors + try + { + // Grid Vac + if (inputValues[2] > 220 * 1.1 || inputValues[3] > 220 * 1.1 || inputValues[4] > 220 * 1.1) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridVACHigh + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACHigh) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridVACHigh).isDeleted = true; + } + + } + if (inputValues[2] < 220 * 0.9 || inputValues[3] < 220 * 0.9 || inputValues[4] < 220 * 0.9) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridVACLow + }); + } + + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridVACLow) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridVACLow).isDeleted = true; + } + } + //// Grid Freq + _error = _error.ReadErrorSettings()[0]; + if (inputValues[17] > (_error.gridFreq * 10) * 1.1) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridFrequencyHigh + }); + } + + } + else + { + + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyHigh) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridFrequencyHigh).isDeleted = true; + } + } + if (inputValues[17] < (_error.gridFreq * 10) * 0.9) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.GridFrequencyLow + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.GridFrequencyLow) != null) + { + errors.First(x => x.Condition == Error.GridCondition.GridFrequencyLow).isDeleted = true; + } + } + //// Ext Power + if (brdFlags[3]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.NoExternalPower + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.NoExternalPower) != null) + { + errors.First(x => x.Condition == Error.GridCondition.NoExternalPower).isDeleted = true; + } + } + //// missing Phase + if (brdFlags[5] && _error.ReadErrorSettings()[0].phaseNumber == 3) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.MissingPhase + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.MissingPhase) != null) + { + errors.First(x => x.Condition == Error.GridCondition.MissingPhase).isDeleted = true; + } + } + //// Phase sequence + if (brdFlags[4] && _error.ReadErrorSettings()[0].phaseNumber == 3) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.PhaseSequence + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.PhaseSequence) != null) + { + errors.First(x => x.Condition == Error.GridCondition.PhaseSequence).isDeleted = true; + } + } + //com port1 + if (brdFlags[1]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.ComPort1 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort1) != null) + { + errors.First(x => x.Condition == Error.GridCondition.ComPort1).isDeleted = true; + } + } + //com port2 + if (brdFlags[2]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.ComPort2 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.ComPort2) != null) + { + errors.First(x => x.Condition == Error.GridCondition.ComPort2).isDeleted = true; + } + } + //hi curr neut + if (brdFlags[6]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrNeut + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrNeut) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrNeut).isDeleted = true; + } + } + //hi curr mot1 + if (brdFlags[7]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrMot1 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot1) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrMot1).isDeleted = true; + } + } + //hi curr mot2 + if (brdFlags[8]) + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) == null) + { + errors.Add(new Error + { + errorDate = DateTime.Now, + Condition = Error.GridCondition.HiCurrMot2 + }); + } + } + else + { + if (errors.FirstOrDefault(x => x.Condition == Error.GridCondition.HiCurrMot2) != null) + { + errors.First(x => x.Condition == Error.GridCondition.HiCurrMot2).isDeleted = true; + } + } + } + catch (Exception) + { + + } + + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + //Board Falgs + foreach (var item in diagnostics.flagRectangles) + { + if (brdFlags[int.Parse(item.Tag.ToString())]) + { + item.Fill = Brush.Parse(diagnostics.RedColor); + } + else + { + item.Fill = Brush.Parse(diagnostics.GrayColor); + + } + } + //power Inputes + diagnostics.ph1.Text = inputValues[2].ToString(); + diagnostics.ph2.Text = inputValues[3].ToString(); + diagnostics.ph3.Text = inputValues[4].ToString(); + + diagnostics.i_nut.Text = (inputValues[5] / 10.0).ToString("0.0"); + diagnostics.gridFreq.Text = (inputValues[17] / 10.0).ToString("0.0"); + // Inputes + foreach (var item in diagnostics.InputesElements.OfType().ToList()) + { + var text = item.Children[0] as TextBlock; + var border = item.Children[1] as Border; + if (inputes[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ACTIVE"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.InputesElements.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "PASSIVE"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.InputesElements.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + //Analog + diagnostics.an1.Text = inputValues[12].ToString(); + diagnostics.an2.Text = inputValues[13].ToString(); + //Temp + diagnostics.t1.Text = ((short)inputValues[8] / 10f).ToString("0.0"); + diagnostics.t2.Text = ((short)inputValues[9] / 10f).ToString("0.0"); + diagnostics.t3.Text = ((short)inputValues[10] / 10f).ToString("0.0"); + diagnostics.t4.Text = ((short)inputValues[11] / 10f).ToString("0.0"); + //InternalTemp + diagnostics.internalTemp.Text = (inputValues[15] / 10.0).ToString("0.0"); + diagnostics.hsTemp.Text = (inputValues[14] / 10.0).ToString("0.0"); + if (inputValues[16] > 40) + { + diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.RedColor); + } + else + { + diagnostics.extPowerLed.Fill = Brush.Parse(diagnostics.GrayColor); + } + diagnostics.ExtPwr.Text = (inputValues[16] / 10.0).ToString("0.0"); + + } + if (ContentArea.Content is Settings settings) + { + if (settings.pedalStateTxt.Text != "AUTO") + { + var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal"); + + ushort registerValue = (ushort)inputValues[1]; + if (allBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0)) + { + allBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0); + } + if (!allBitsOn) + { + settings.pedalUnderLine.Fill = Brush.Parse(settings.PassiveColor); + + } + else + { + settings.pedalUnderLine.Fill = Brush.Parse(settings.ActiveColor); + + } + + } + if (startFountainMotorFlashing != 1) + { + //fountain + + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + + + if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + var fountainLable = settings.FountainSP.Children[1] as Avalonia.Controls.Label; + var fontainRectangel = settings.FountainSP.Children[2] as Avalonia.Controls.Shapes.Rectangle; + if (!allBitsOn) + { + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(PassiveColor); + //isFountainMotorOn = false; + } + else + { + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(ActiveColor); + //isFountainMotorOn = true; + } + } + + if (startMixerMotorFlashing != 1) + { + //mixer + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + + + if (allBitsOn != mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = mixer.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + var mixerLable = settings.MixerSP.Children[1] as Avalonia.Controls.Label; + var mixerRectangel = settings.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + if (!allBitsOn) + { + mixerLable.Content = "OFF"; + mixerLable.Foreground = Brush.Parse("#ff231f20"); + mixerRectangel.Fill = Brush.Parse(PassiveColor); + //isMixerMotorOn = false; + } + else + { + mixerLable.Content = "ON"; + mixerLable.Foreground = Brush.Parse("#ff231f20"); + mixerRectangel.Fill = Brush.Parse(ActiveColor); + //isMixerMotorOn = true; + } + } + + } + if (ContentArea.Content is ManualControl manual) + { + manual.pumbRealTemp.Text = comPumpTemp.ToString("0.0"); + manual.ChocolateRealTemp.Text = comFountainTemp.ToString("0.0"); + manual.tankWallRealTemp.Text = tankWallTempValue.ToString("0.0"); + manual.pumbRealTemp.Text = comTankTemp.ToString("0.0"); + } + }); + _mapping = _map.ReadMappings(); + //reading Tank Bottom + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + tankBottomTempValue = 0; + foreach (var item in tankBottom.BitNumbers) + { + tankBottomTempValue += ((short)inputValues[item] / 10f); + } + tankBottomTempValue /= tankBottom.BitNumbers.Count; + tankBottomTempValue = Math.Round(tankBottomTempValue, 1); + } + } + //reading Tank Wall + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + tankWallTempValue = 0; + foreach (var item in tankWall.BitNumbers) + { + tankWallTempValue += ((short)inputValues[item] / 10f); + } + tankWallTempValue /= tankWall.BitNumbers.Count; + tankWallTempValue = Math.Round(tankWallTempValue, 1); + } + } + //reading Pump + pump = _mapping.Find(x => x.Name == "Pump Temp"); + + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + pumpTempValue = 0; + + foreach (var item in pump.BitNumbers) + { + pumpTempValue += ((short)inputValues[item] / 10f); + } + pumpTempValue /= pump.BitNumbers.Count; + pumpTempValue = Math.Round(pumpTempValue, 1); + } + } + //reading Fountain + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + fountainTempValue = 0; + + foreach (var item in fountain.BitNumbers) + { + fountainTempValue += ((short)inputValues[item] / 10f); + } + fountainTempValue /= fountain.BitNumbers.Count; + fountainTempValue = Math.Round(fountainTempValue, 1); + } + } + Dispatcher.UIThread.Post(() => + { + if (tankBottomTempValue == -1 && tankWallTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Tank Data To Read"; + tankBottomTempValue = 0; + tankWallTempValue = 0; + } + } + else + { + //comTankTemp = tankBottomTempValue < tankWallTempValue ? tankBottomTempValue : tankWallTempValue; + comTankTemp = tankBottomTempValue; + comTankTemp = comTankTemp == -1 ? 0 : comTankTemp; + } + if (pumpTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Pump Data To Read"; + pumpTempValue = 0; + } + + } + else + { + comPumpTemp = pumpTempValue; + } + if (fountainTempValue == -1) + { + if (ContentArea.Content is Settings) + { + footerMsg.Text = "No Chocolate Data To Read"; + fountainTempValue = 0; + } + + } + else + { + comFountainTemp = fountainTempValue; + } + if (ContentArea.Content is Settings result) + { + if (result.TankTempValue.Content?.ToString() != comTankTemp.ToString() || result.FountainTempValue.Content?.ToString() != comFountainTemp.ToString()) + { + result.TankTempValue.Content = (comTankTemp).ToString("0.0"); + result.FountainTempValue.Content = (comFountainTemp).ToString("0.0"); + } + } + //if (comTankTemp >= _machine.TankMaxHeat && comFountainTemp >= _machine.PumbMaxHeat) + //{ + // if (preMixerTimer==null) + // { + // preMixerTimer = new Timer(PreMixerTimer, null, 0, 1000); + // } + // mixerSeconds++; + //} + //else + //{ + // if (preMixerTimer != null) + // { + // preMixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + // preMixerTimer = null; + // } + + + //} + } + ); + } + + //read mot val + + if (inputValues.Count != 0) + { + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + diagnostics.curr1.Text = (inputValues[6] / 10.0).ToString("0.0"); + diagnostics.curr2.Text = (inputValues[7] / 10.0).ToString("0.0"); + } + }); + } + + } + + + //Pre Heating + if (startPreHeating == 1) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + + if (writingMaxTemp == 1) + { + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + foreach (var item in tankBottom.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + + pump = _mapping.Find(x => x.Name == "Pump Temp"); + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + foreach (var item in pump.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10; + + } + } + + + } + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + foreach (var item in fountain.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + await WriteToSerialAsync("PreHeating"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + + result.recipeSettings.IsEnabled = false; + isFlashPreHeating = true; + footerMsg.Text = "Pre-Heating Active"; + } + }); + writingMaxTemp = -1; + } + + } + if (startPreHeating == 0) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + if (writingMaxTemp == 0) + { + tankBottom = _mapping.Find(x => x.Name == "Tank Bottom Temp"); + if (tankBottom != null) + { + if (tankBottom.BitNumbers.Count > 0) + { + foreach (var item in tankBottom.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + + } + + } + + tankWall = _mapping.Find(x => x.Name == "Tank Wall Temp"); + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = -10000; + } + + } + + + } + + pump = _mapping.Find(x => x.Name == "Pump Temp"); + if (pump != null) + { + if (pump.BitNumbers.Count > 0) + { + foreach (var item in pump.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + fountain = _mapping.Find(x => x.Name == "Fountain Temp"); + if (fountain != null) + { + if (fountain.BitNumbers.Count > 0) + { + foreach (var item in fountain.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + await WriteToSerialAsync("PreHeating"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.recipeSettings.IsEnabled = true; + if (!stopRecipeFlag) + { + footerMsg.Text = "Pre-Heating Stopped"; + + } + } + }); + writingMaxTemp = -1; + } + + } + //Mixer Motor + //Mixer Motorf + if (checkMixerTWT_HWTH) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + } + + if ((comTankTemp >= _machine.TankMaxHeat - screenData.warningLimit) && (comTankTemp <= _machine.TankMaxHeat + screenData.warningLimit)) + { + if (startMixerMotor != 1) + { + if (mixerTimer == null) + { + if (mixerSeconds == 1) + { + mixerSeconds = _machine.MixerDelay; + } + mixerTimer = new Timer(MixerTimer, null, 0, 1000); + //setMixerTimerOnce = false; + } + } + } + + else if (comTankTemp <= recipeCoolingGoal - 3 && startMixerMotor == 1) + { + if (startMixerMotor != 0) + { + if (stopMixerTimer == null) + { + stopMixerSecondes = 5; + stopMixerTimer = new Timer(StopMixerTimer, null, 0, 1000); + } + } + startMixerMotorFlashing = 1; + } + else if (startMixerMotor != 1) + { + if (startMixerMotor != 0) + { + sendComMixerMotor = 0; + } + startMixerMotorFlashing = 1; + } + }); + } + if (!checkMixerTWT_HWTH) + { + if (sendComMixerMotor == 0 && startMixerMotorFlashing == 0) + { + startMixerMotor = -1; + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + + + foreach (var bit in mixer.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Mixer Off due Clicking"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label; + var motorRectangel = result.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + motorLable.Content = "OFF"; + motorLable.Foreground = Brush.Parse("#ff231f20"); + motorRectangel.Fill = Brush.Parse(PassiveColor); + if (startRecipe != 1 && !stopRecipeFlag) + { + footerMsg.Text = "Mixer is OFF"; + } + } + }); + sendComMixerMotor = -1; + startMixerMotorFlashing = -1; + } + } + } + } + if (startMixerMotorFlashing == 1) + { + if (sendComMixerMotor == 0) + { + //turn the motor off + startMixerMotor = 0; + + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + + foreach (var bit in mixer.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Mixer Off due to drop in temp"); + Dispatcher.UIThread.Post(() => + { + if (startRecipe != 1) + { + footerMsg.Text = "waiting for tank target temperature"; + } + }); + sendComMixerMotor = -1; + } + } + } + } + if (startMixerMotorFlashing == 0 && sendComMixerMotor == 1 && !isPaused) + { + startMixerMotor = 1; + //turn the motor on and make the button stable + var mixer = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + if (mixer != null) + { + if (mixer.BitNumbers.Count > 0) + { + foreach (var bit in mixer.BitNumbers) + { + + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Mixer On"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var motorLable = result.MixerSP.Children[1] as Avalonia.Controls.Label; + var motorRectangel = result.MixerSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + motorLable.Content = "ON"; + motorLable.Foreground = Brush.Parse("#ff231f20"); + motorRectangel.Fill = Brush.Parse(ActiveColor); + if (startRecipe != 1) + { + footerMsg.Text = "Temperature is OK,Mixer is on"; + } + //if (comTankTemp < result._recipeTable.PouringGoal || + // comFountainTemp < result._recipeTable.PouringGoal) + //{ + // mixerSeconds = 1; + // //checkTMT_PMT = true; + // setMixerTimerOnce = true; + //} + //else + //{ + // //checkTMT_PMT = true; + // setMixerTimerOnce = true; + //} + + } + + }); + + + startMixerMotorFlashing = -1; + sendComMixerMotor = -1; + + } + } + + + } + + //Fountain Motor + if (checkFountainTMT_PMT) + { + Dispatcher.UIThread.Post(() => + { + + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + + + } + + if ((comPumpTemp >= _machine.PumbMaxHeat - screenData.warningLimit) && (comPumpTemp <= _machine.PumbMaxHeat + screenData.warningLimit)) // check the temp and make it stop only if it below cooling temp - 3 degrees + { + if (startFountainMotor != 1) + { + if (fountainTimer == null) + { + if (fountainSeconds == 1) + { + fountainSeconds = _machine.PumbDelay; + } + fountainTimer = new Timer(FountainTimer, null, 0, 1000); + //setFountainTimerOnce = false; + } + } + } + + else if (comPumpTemp <= recipeCoolingGoal - 3 && startFountainMotor == 1) + { + if (startFountainMotor != 0) + { + if (stopFountainTimer == null) + { + stopFountainSecondes = 5; + stopFountainTimer = new Timer(StopFountainTimer, null, 0, 1000); + } + } + startFountainMotorFlashing = 1; + } + else if (startFountainMotor != 1) + { + if (startFountainMotor != 0) + { + sendComFountainMotor = 0; + } + startFountainMotorFlashing = 1; + } + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + if (startFountainMotor != 1 && fountainTimer == null) + { + if (!result.fountainDelayCounter.Text.Equals(comPumpTemp.ToString("0.0"))) + { + result.fountainDelayTxt.Text = "Current Temp:"; + result.fountainDelayCounter.Text = comPumpTemp.ToString("0.0"); + result.fountainTargetTxt.Text = "Target Temp:"; + result.fountainTagetTemp.Text = _machine.PumbMaxHeat.ToString("0.0"); + result.fountainDelayTxt.IsVisible = true; + result.fountainDelayCounter.IsVisible = true; + result.fountainTargetTxt.IsVisible = true; + result.fountainTagetTemp.IsVisible = true; + } + + } + } + + }); + }); + } + if (!checkFountainTMT_PMT) + { + if (sendComFountainMotor == 0 && startFountainMotorFlashing == 0) + { + startFountainMotor = -1; + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + //turn the motor off and make the button stable + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Fountain Off due to click"); + //waitting for 10 sec before pause + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.fountainDelayCounter.Text = "-1"; + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fontainRectangel = result.FountainSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "OFF"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fontainRectangel.Fill = Brush.Parse(PassiveColor); + if (startRecipe != 1 && !stopRecipeFlag) + { + footerMsg.Text = "Chocolate is OFF"; + } + stopRecipeFlag = false; + } + }); + + + sendComFountainMotor = -1; + startFountainMotorFlashing = -1; + } + } + + } + } + if (startFountainMotorFlashing == 1) + { + if (sendComFountainMotor == 0) + { + startFountainMotor = 0; + + //turn the motor off + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Fountain Off due to drop in temp"); + //pause the recipe if it started + //waitting for 10 sec before pause + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + + Dispatcher.UIThread.Post(() => + { + if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1)) + { + //footerMsg.Text = "Recipe Paused... waiting for target temperature"; + } + else if (startRecipe != 1) + { + footerMsg.Text = "waiting for pump target temperature"; + + } + }); + //checkTMT_PMT = true; + sendComFountainMotor = -1; + } + } + + } + } + if (startFountainMotorFlashing == 0 && sendComFountainMotor == 1 && errors.Count == 0 && !isPaused) + { + startFountainMotor = 1; + //turn the motor on and make the button stable + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Fountain On"); + if (isPaused) + { + unPause = true; + } + //if (startRecipe == 1 && (Heating == 10 || cooling == 10 || pouring == 10)) + //{ + // if (Heating == 10) + // { + // Heating = 1; + // sendComHeating = 1; + // } + // else if (cooling == 10) + // { + // cooling = 1; + // sendComCooling = 1; + // } + // else if (pouring == 10) + // { + // pouring = 1; + // sendComPouring = 1; + // } + //} + if (fountainPauseTimer != null) + { + fountainPauseTimer = null; + fountainPauseSeconds = 10; + } + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + var fountainLable = result.FountainSP.Children[1] as Avalonia.Controls.Label; + var fountainRectangel = result.FountainSP.Children[2] as + Avalonia.Controls.Shapes.Rectangle; + fountainLable.Content = "ON"; + fountainLable.Foreground = Brush.Parse("#ff231f20"); + fountainRectangel.Fill = Brush.Parse(ActiveColor); + if (startRecipe == 1 && (Heating == 1 || cooling == 1 || pouring == 1)) + { + if (Heating == 1) + { + footerMsg.Text = "Heating phase"; + + + } + else if (cooling == 1) + { + footerMsg.Text = "Cooling phase"; + + } + else if (pouring == 1) + { + footerMsg.Text = "Prepare for pouring"; + } + } + else if (startRecipe != 1) + { + footerMsg.Text = "Temperature is OK,Chocolate is on"; + } + //if (comTankTemp < result._recipeTable.PouringGoal || + // comFountainTemp < result._recipeTable.PouringGoal) + //{ + // fountainSeconds = 1; + // setFountainTimerOnce = true; + //} + //else + //{ + // setFountainTimerOnce = true; + //} + } + }); + + startFountainMotorFlashing = -1; + sendComFountainMotor = -1; + } + } + + } + + if (moldHeaterMotor == 0) // off MOLD HEATER + { + var moldHeater = _mapping.Find(x => x.Name == "Mold Heater"); + if (moldHeater != null) + { + if (moldHeater.BitNumbers.Count > 0) + { + foreach (var bit in moldHeater.BitNumbers) + { + holdingRegister.lvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("MoldHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.moldHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.MoldHeaterStatus.Text = "OFF"; + manual.MoldHeaterUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + + moldHeaterMotor = -1; + } + else if (moldHeaterMotor == 1) // on MOLD HEATER + { + var moldHeater = _mapping.Find(x => x.Name == "Mold Heater"); + if (moldHeater != null) + { + if (moldHeater.BitNumbers.Count > 0) + { + foreach (var bit in moldHeater.BitNumbers) + { + + holdingRegister.lvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("MoldHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.moldHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.MoldHeaterStatus.Text = "ON"; + manual.MoldHeaterUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + moldHeaterMotor = -1; + } + if (vibrationMotor == 0) // off VIBRATION + { + var vibrator = _mapping.Find(x => x.Name == "Vibrator"); + + if (vibrator != null) + { + if (vibrator.BitNumbers.Count > 0) + { + + foreach (var bit in vibrator.BitNumbers) + { + holdingRegister.hvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("Vibrator"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibrationBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibrationStatus.Text = "OFF"; + manual.VibrationUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + vibrationMotor = -1; + } + else if (vibrationMotor == 1) // on VIBRATION + { + var vibrator = _mapping.Find(x => x.Name == "Vibrator"); + + if (vibrator != null) + { + if (vibrator.BitNumbers.Count > 0) + { + foreach (var bit in vibrator.BitNumbers) + { + holdingRegister.hvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("Vibrator"); + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibrationBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibrationStatus.Text = "ON"; + manual.VibrationUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + + + + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + vibrationMotor = -1; + } + if (vibHeaterMotor == 0) // off VIB. HEATER + { + var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater"); + if (vibHeater != null) + { + if (vibHeater.BitNumbers.Count > 0) + { + + foreach (var bit in vibHeater.BitNumbers) + { + + holdingRegister.lvOut &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("VibratorHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "OFF"; + underLine.Fill = Brush.Parse("#666666"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibHeaterStatus.Text = "OFF"; + manual.VibHeaterUnderline.Fill = Brush.Parse("#666666"); + } + }); + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + + vibHeaterMotor = -1; + } + else if (vibHeaterMotor == 1) // on VIB. HEATER + { + var vibHeater = _mapping.Find(x => x.Name == "Vibrator Heater"); + if (vibHeater != null) + { + if (vibHeater.BitNumbers.Count > 0) + { + foreach (var bit in vibHeater.BitNumbers) + { + holdingRegister.lvOut |= (ushort)(1 << bit); + } + await WriteToSerialAsync("VibratorHeater"); + + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + var StackPanel = result.vibHeaterBtn.Content as StackPanel; + var Label = StackPanel.Children; + var underLine = Label[2] as Avalonia.Controls.Shapes.Rectangle; + var targetLable = Label[1] as Label; + targetLable.Content = "ON"; + underLine.Fill = Brush.Parse("#A4275D"); + } + else if (ContentArea.Content is ManualControl manual) + { + manual.VibHeaterStatus.Text = "ON"; + manual.VibHeaterUnderline.Fill = Brush.Parse("#A4275D"); + } + }); + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Programming Team"; + }); + } + vibHeaterMotor = -1; + } + + + //Start Recipe + if (startRecipe == 1) + { + var tankBtm = _mapping.Find(x => x.Name.ToLower() == "Tank Bottom Temp".ToLower()); + tankWall = _mapping.Find(x => x.Name.ToLower() == "Tank Wall Temp".ToLower()); + var pumb = _mapping.Find(x => x.Name.ToLower() == "Pump Temp".ToLower()); + var fount = _mapping.Find(x => x.Name.ToLower() == "Fountain Temp".ToLower()); + var fountainMotor = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + var mixerMotor = _mapping.Find(x => x.Name.ToLower() == "Mixer".ToLower()); + + if (tankBtm != null && tankWall != null && pumb != null && fount != null) + { + if (tankBtm.BitNumbers.Count > 0 && tankWall.BitNumbers.Count > 0 && pumb.BitNumbers.Count > 0 && fount.BitNumbers.Count > 0) + { + List setTempValues = new List(); + setTempValues.AddRange([holdingRegister.setTemp1, holdingRegister.setTemp2, holdingRegister.setTemp3, holdingRegister.setTemp4]); + byte[] response = new byte[] { 0xFF }; + + var isFountOn = false; + var isMixerOn = false; + if (isFountOn != fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + isFountOn = fountainMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (isMixerOn != mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + isMixerOn = mixerMotor.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (isFountOn && isMixerOn) // both motores are on + { + + if ((comFountainTemp * 10 >= (recipeHeatingGoal * 10)) && (cooling != 1 && pouring != 1)) + { + if (heatingTimer == null) + { + heatingTimer = new Timer(HeatingTimer, null, 0, 1000); + heatingSeconds = _machine.HeatingDelay; + } + } + else if ((Heating != 1) && (cooling != 1 || cooling != 10) && (pouring != 1 || pouring != 10)) + { + sendComTankTemp = 1; + Heating = 1; + sendComHeating = 1; + setHeatingTimerOnce = 1; + } + + } + //if (comPumpTemp>=_machine.PumbMaxHeat) + //{ + // //start timer + // if (fountainTimer==null) + // { + // if (fountainSeconds == 1) + // { + // fountainSeconds = _machine.PumbDelay; + // } + // fountainTimer = new Timer(FountainTimer, null, 0, 1000); + // } + // if (turnOnFountainMotor) + // { + // fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + // if (fount != null) + // { + // if (fount.BitNumbers.Count > 0) + // { + // foreach (var bit in fount.BitNumbers) + // { + // holdingRegister.motor |= (ushort)(1 << bit); + // } + // isWriting = true; + + // } + // } + + // turnOnFountainMotor = false; + // } + //} + //else + //{ + // startFountainMotorFlashing = 1; + //} + if (sendComTankTemp == 1) + { + sendComTankTemp = -1; + } + if (pause) + { + isPaused = true; + if (Heating == 1) + { + Heating = 10; + } + else if (cooling == 1) + { + cooling = 10; + } + else if (pouring == 1) + { + pouring = 10; + } + //PumbOn = -1; + if (tankBtm != null) + { + if (tankBtm.BitNumbers.Count > 0) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + if (tankWall != null) + { + if (tankWall.BitNumbers.Count > 0) + { + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat * 10; + } + + } + + + } + + if (pumb != null) + { + if (pumb.BitNumbers.Count > 0) + { + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat * 10; + + } + } + + + } + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = -10000; + + } + } + + + } + holdingRegister.setTemp1 = setTempValues[0]; + holdingRegister.setTemp2 = setTempValues[1]; + holdingRegister.setTemp3 = setTempValues[2]; + holdingRegister.setTemp4 = setTempValues[3]; + holdingRegister.motor = 0; + + await WriteToSerialAsync("RecipePause"); + startMixerMotor = 0; + startFountainMotor = 0; + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Recipe Paused"; + + }); + pause = false; + } + else if (unPause) + { + isPaused = false; + if (Heating == 10) + { + Heating = 1; + sendComHeating = 1; + } + else if (cooling == 10) + { + cooling = 1; + sendComCooling = 1; + } + else if (pouring == 10) + { + pouring = 1; + sendComPouring = 1; + } + PumbOn = 1; + + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Recipe Continued"; + }); + unPause = false; + } + if (Heating == 1) + { + if (errors.Count > 0) + { + if ((DateTime.Now - errors.Min(x => x.errorDate)).TotalSeconds >= 3.5) + { + if (!isPaused) + { + pause = true; + + } + } + + } + else + { + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + if (comFountainTemp * 10 <= (result._recipeTable?.HeatingGoal * 10) + screenData.warningLimit && + comFountainTemp * 10 >= (result._recipeTable?.HeatingGoal * 10) - screenData.warningLimit) + { + if (setHeatingTimerOnce == 1) + { + heatingTimer = new Timer(HeatingTimer, null, 0, 1000); + heatingSeconds = _machine.HeatingDelay; + setHeatingTimerOnce = -1; + } + } + else if (sendComHeating == 1) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + } + }); + + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat; + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipeHeatingGoal; + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("HeatingPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Heating phase"; + + }); + + sendComHeating = -1; + + } + } + }); + } + + + } + else if (cooling == 1) + { + if (errors.Count > 0) + { + if (!isPaused) + { + //pause = true; + + } + } + else + { + if (sendComCooling == 1) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = -1000; + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = -1000; + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMinHeat; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipeCoolingGoal; + + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("CoolingPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Cooling phase"; + }); + sendComCooling = -1; + + + } + + Dispatcher.UIThread.Post(async () => + { + + if (ContentArea.Content is Settings result) + { + if (comFountainTemp * 10 <= (result._recipeTable?.CoolingGoal * 10) + screenData.warningLimit && + comFountainTemp * 10 > (result._recipeTable?.CoolingGoal * 10) - screenData.warningLimit) + { + if (setCoolingTimerOnce == 1) + { + coolingTimer = new Timer(CoolingTimer, null, 0, 1000); + coolingSeconds = _machine.CoolingDelay; + setCoolingTimerOnce = -1; + } + } + } + }); + } + + + } + else if (pouring == 1) + { + if (errors.Count > 0) + { + if (!isPaused) + { + //pause = true; + + } + } + else + { + if (sendComPouring == 1) + { + + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.TankMaxHeat; + + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = (int)_machine.PumbMaxHeat; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipePouringGoal; + + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + + } + } + await WriteToSerialAsync("PouringPhase"); + Dispatcher.UIThread.Post(async () => + { + footerMsg.Text = "Prepare for pouring"; + }); + sendComPouring = -1; + + } + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Settings result) + { + if (comFountainTemp * 10 < (result._recipeTable?.PouringGoal * 10) + screenData.warningLimit && + comFountainTemp * 10 > (result._recipeTable?.PouringGoal * 10) - screenData.warningLimit) + { + if (setPouringTimerOnce == 1) + { + foreach (var item in tankBtm.BitNumbers) + { + setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp); + + } + foreach (var item in tankWall.BitNumbers) + { + setTempValues[item - 8] = (int)(recipePouringGoal + _machine.PreHeatingTemp); + + } + foreach (var item in pumb.BitNumbers) + { + setTempValues[item - 8] = -1000; + + } + foreach (var item in fount.BitNumbers) + { + setTempValues[item - 8] = (int)recipePouringGoal; + } + holdingRegister.setTemp1 = setTempValues[0] * 10; + holdingRegister.setTemp2 = setTempValues[1] * 10; + holdingRegister.setTemp3 = setTempValues[2] * 10; + holdingRegister.setTemp4 = setTempValues[3] * 10; + if (fountainMotor != null) + { + if (fountainMotor.BitNumbers.Count > 0) + { + foreach (var bit in fountainMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isFountainMotorOn = true; + } + } + if (mixerMotor != null) + { + if (mixerMotor.BitNumbers.Count > 0) + { + foreach (var bit in mixerMotor.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + } + isMixerMotorOn = true; + } + } + await WriteToSerialAsync("PouringPhase"); + pouringTimer = new Timer(PouringTimer, null, 0, 1000); + pouringSeconds = _machine.PouringDelay; + setPouringTimerOnce = -1; + } + } + } + }); + } + + + } + } + else + { + Dispatcher.UIThread.Post(() => + { + footerMsg.Text = "Contact Admin"; + }); + } + } + + + } + + + if (PumbOn == 1) + { + //Dispatcher.UIThread.Post(() => + //{ + // recipeStartBtn.IsEnabled = true; + + //}); + if (pedalMotor == 0) // Manual Pedal + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.pedalDelayTxt.IsVisible = false; + settings.pedalDelayCounter.IsVisible = false; + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffTimer = null; + } + + } + }); + + var pedal = _mapping.Find(x => x.Name.ToLower() == "pedal"); + if (pedal != null) + { + // READING THE INPUT REGISTER + if (errors.Count == 0) + { + ushort registerValue = (ushort)inputValues[1]; + if (allPedalBitsOn != pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0)) + { + allPedalBitsOn = pedal.BitNumbers.All(bit => (registerValue & (1 << bit)) != 0); + pedalStateChanged = 1; + } + else + { + pedalStateChanged = 0; + } + + if (!allPedalBitsOn) + { + pedalState = 1;// All bits ON + } + else + { + pedalState = 0; // At least one bit is OFF + } + + // READING THE motor REGISTER + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + bool valueChanged = false; + if (pedalState == 1) // If all monitored bits are ON + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.pedalUnderLine.Fill = Brush.Parse(result.PassiveColor); + } + }); + if (!(comPumpTemp <= recipeCoolingGoal - 3)) + { + foreach (var bit in fount.BitNumbers) + { + if (!ToBinary(holdingRegister.motor)[bit]) + { + //Debug.WriteLine("input value:" + registerValue); + //Debug.WriteLine("pedal on:" + allBitsOn); + holdingRegister.motor |= (ushort)(1 << bit); + valueChanged = true; + + } + } + if (valueChanged) + { + await WriteToSerialAsync("PedalManual"); + valueChanged = false; + if (isPaused) + { + unPause = true; + } + } + + } + + } + else // If at least one monitored bit is OFF + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.pedalUnderLine.Fill = Brush.Parse(result.ActiveColor); + } + }); + if (pedalStateChanged == 1) + { + foreach (var bit in fount.BitNumbers) + { + if (ToBinary(holdingRegister.motor)[bit]) + { + holdingRegister.motor &= (ushort)~(1 << bit); + valueChanged = true; + } + + } + if (valueChanged) + { + await WriteToSerialAsync("PedalManual"); + valueChanged = false; + } + + } + + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + + } + + if (pedalStateChanged == 1) + { + // WRITE UPDATED VALUE TO HVO REGISTER + //isWriting = true; + } + + } + + } + } + + + } + } + + else if (pedalMotor == 1) // auto Pedal + { + const double deadZone = 1.5; + if (pedalState == 0) // on + { + var fountt = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fountt != null) + { + if (fountt.BitNumbers.Count > 0) + { + if (!(comPumpTemp <= recipeCoolingGoal - 3 + deadZone)) + { + foreach (var bit in fountt.BitNumbers) + { + holdingRegister.motor |= (ushort)(1 << bit); + isFountainMotorOn = true; + } + await WriteToSerialAsync("PedalAuto"); + } + } + else + { + // Turn OFF only if it dropped below the lower threshold + if (comPumpTemp <= recipeCoolingGoal - 3 - deadZone) + { + foreach (var bit in fountt.BitNumbers) + holdingRegister.motor &= (ushort)~(1 << bit); + + isFountainMotorOn = false; + await WriteToSerialAsync("PedalAuto - OFF"); + } + + } + + } + else if (pedalState == 1) // off + { + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + + + foreach (var bit in fount.BitNumbers) + { + holdingRegister.motor &= (ushort)~(1 << bit); + } + await WriteToSerialAsync("PedalAuto"); + if (fountainPauseTimer == null && startRecipe == 1 && (Heating == 1 || heatingTimer != null || cooling == 1 || coolingTimer != null || pouring == 1 || pouringTimer != null + )) + { + fountainPauseSeconds = 10; + fountainPauseTimer = new Timer(FountainPauseTimer, null, 0, 1000); + } + } + } + + } + + pedalState = -1; + if (!(comPumpTemp <= recipeCoolingGoal - 3)) + { + if (setPedalTimerOnce == 1) + { + pedalOffTimer = new Timer(PedalOffTimer, null, 0, 1000); + setPedalTimerOnce = -1; + } + else if (setPedalTimerOnce == 0) + { + pedalOnTimer = new Timer(PedalOnTimer, null, 0, 1000); + setPedalTimerOnce = -1; + } + } + + } + + } + + //change diag UI + var hvo = ToBinary(holdingRegister.hvOut); + var lvo = ToBinary(holdingRegister.lvOut); + var motor = ToBinary(holdingRegister.motor); + + Dispatcher.UIThread.Post(async () => + { + if (ContentArea.Content is Diagnostics diagnostics) + { + foreach (var item in diagnostics.MotoreState.OfType().ToList()) + { + var stackPanel = item.Children[0] as StackPanel; + var text = stackPanel.Children[1] as TextBlock; + var border = item.Children[1] as Border; + if (motor[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.MotoreState.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.MotoreState.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + + // HVO + foreach (var item in diagnostics.hvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (hvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.hvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.OrangeColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.hvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + + // LVO + foreach (var item in diagnostics.lvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (lvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + foreach (var item in diagnostics.lvoOutPuts.OfType().ToList()) + { + var text = item.Children[1] as TextBlock; + var border = item.Children[2] as Border; + if (lvo[int.Parse(item.Tag.ToString())]) + { + + text.Text = "ON"; + border.Background = Brush.Parse(diagnostics.PinkColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GreenColor); + + } + else + { + text.Text = "OFF"; + border.Background = Brush.Parse(diagnostics.GrayColor); + diagnostics.lvoOutPuts.OfType().ToList().Find(x => x.Tag.ToString() == item.Tag.ToString()).Fill = Brush.Parse(diagnostics.GrayColor); + + + } + } + } + }); + + await Task.Delay(100); + + } + } + catch (Exception e) + { + + } + + } + } + } + catch + { + } + finally + { + + } + + } + + // Find the port name corresponding to this serial number + + Thread.Sleep(50); // Check every 1 seconds + } + } + + + + + public bool ConnectToSerialPort() + { + screenData = _screeen.ReadScreens()?[0]; + try + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + } + _port = null; + _port = new SerialPort(screenData.port, screenData.boundRate); + switch (screenData.parity) + { + case 0: + _port.Parity = Parity.None; + break; + case 1: + _port.Parity = Parity.Odd; + break; + case 2: + _port.Parity = Parity.Even; + break; + case 3: + _port.Parity = Parity.Mark; + break; + case 4: + _port.Parity = Parity.Space; + break; + default: + _port.Parity = Parity.None; + break; + } + switch (screenData.stopBits) + { + case 2: + _port.StopBits = StopBits.Two; + break; + default: + _port.StopBits = StopBits.One; + break; + } + _port.DataBits = 8; + _port.Handshake = Handshake.None; + _port.DtrEnable = true; + + // Open the serial port + + _port.Open(); + return true; + + } + catch (Exception ex) + { + + Console.WriteLine($"Error connecting to port {screenData.port}: {ex.Message}"); + _port = null; + return false; + } + } + + + + + public void closeConnection() + { + isRunning = false; + monitorThread.Abort(); + } + private async void OnClosing1(object? sender, CancelEventArgs e) + { + closeConnection(); + + } + private void OnClosingWindow(object? sender, WindowClosingEventArgs e) + { + if (_port != null && _port.IsOpen) + { + _port.Close(); + //_port = null; + } + // Example: Cancel the close if needed + // e.Cancel = true; + } + + + + + + //Main Window Functions + private void errorLogoClick(object? sender, RoutedEventArgs e) + { + errorPopupOverlay.IsVisible = true; + //errorTitel.Text = errorLogo.Tag.ToString(); + errorMsg.Text = errorMsg.Text.Trim(); + } + private void warningLogoClick(object? sender, RoutedEventArgs e) + { + warningPopupOverlay.IsVisible = true; + warningTitel.Text = warningLogo.Tag.ToString(); + warningMsg.Text = warningMsg.Text.Trim(); + } + private void HomeTraclBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + result.DeletePopupOverlay.IsVisible = true; + result.DeletePopupOverlay.Tag = "home"; + + } + else if (ContentArea.Content is Diagnostics diagnostics) + { + restBoard = true; + + this.UserName.Content = "Select User"; + footerMsg.Text = ""; + ContentArea.Content = new Home(this); + } + else + { + this.UserName.Content = "Select User"; + footerMsg.Text = ""; + ContentArea.Content = new Home(this); + } + } + private void DiagnosticsBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is AdvanceSettings advanceSettings) + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this, true); + } + else if (ContentArea.Content is ManualControl) + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this, false, true); + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Diagnostics(this); + } + + } + private void ChefManualBtn(object? sender, RoutedEventArgs e) + { + footerMsg.Text = ""; + ContentArea.Content = new ManualControl(this); + + } + public void AdvanceSettingsView(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Diagnostics) + { + ContentArea.Content = new AdvanceSettings(this, true, false); + + } + else if (ContentArea.Content is Software) + { + ContentArea.Content = new AdvanceSettings(this, false, true); + + } + else + { + ContentArea.Content = new AdvanceSettings(this); + + } + + } + private void RecipeSelTrackBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + result.DeletePopupOverlay.IsVisible = true; + result.DeletePopupOverlay.Tag = "recipeSel"; + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Recipe(this, Program.currentUser); + } + + + } + private void SettingTrackBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Diagnostics diagnostics) + { + restBoard = true; + } + footerMsg.Text = ""; + ContentArea.Content = new Admin(this, Program.currentUser); + } + private void SoftwareBtn(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is AdvanceSettings) + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this, true); + } + else if (ContentArea.Content is ManualControl) + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this, false, true); + } + else + { + footerMsg.Text = ""; + ContentArea.Content = new Software(this); + } + + + } + + private async void PreHeatingClick(object? sender, RoutedEventArgs e) + { + if (ContentArea.Content is Settings result) + { + if (result.recipeSettings.IsEnabled) + { + startPreHeating = 1; + writingMaxTemp = 1; + //if (!isMixerMotorOn) + //{ + // result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + //} + //if (!isFountainMotorOn) + //{ + // result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + //} + } + else + { + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + } + } + + } + //Mixer + public async void MotorClick(object? sender, RoutedEventArgs e) + { + if (!isMixerMotorOn) + { + isMixerMotorOn = true; + checkMixerTWT_HWTH = true; + setMixerTimerOnce = true; + } + else + { + isMixerMotorOn = false; + checkMixerTWT_HWTH = false; + startMixerMotorFlashing = 0; + sendComMixerMotor = 0; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + } + }); + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + + } + } + private void MixerTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comTankTemp >= recipeCoolingGoal - 3) + { + mixerSeconds--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (mixerSeconds <= 0) + { + // Stop the timer after 15 seconds + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + startMixerMotorFlashing = 0; + sendComMixerMotor = 1; + return; + } + if (mixerSeconds <= _machine.MixerDelay) + { + settings.mixerDelayTxt.IsVisible = true; + settings.mixerDelayCounter.Text = mixerSeconds.ToString(); + settings.mixerDelayCounter.IsVisible = true; + + } + } + + }); + + + + } + private void StopMixerTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comTankTemp <= recipeCoolingGoal - 3) + { + stopMixerSecondes--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (stopMixerSecondes <= 0) + { + sendComMixerMotor = 0; + + + + stopMixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + stopMixerTimer = null; + return; + } + } + + }); + + + + } + //Fountain + public async void FountainClick(object? sender, RoutedEventArgs e) + { + if (!isFountainMotorOn) + { + isFountainMotorOn = true; + checkFountainTMT_PMT = true; + setFountainTimerOnce = true; + } + else + { + isFountainMotorOn = false; + + checkFountainTMT_PMT = false; + startFountainMotorFlashing = 0; + sendComFountainMotor = 0; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + } + }); + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + + } + + } + } + private void FountainTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comPumpTemp >= recipeCoolingGoal - 3) + { + fountainSeconds--; + } + else + { + //fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + if (fountainSeconds <= 0) + { + // Stop the timer after 15 seconds + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + startFountainMotorFlashing = 0; + sendComFountainMotor = 1; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + if (startRecipe == 1 && !isPaused) + { + PumbOn = 1; + + } + if (result._recipeTable.Pedal.Value) + { + pedalMotor = 0; + } + else + { + pedalMotor = 1; + pedalState = 0; + setPedalTimerOnce = 1; + } + } + + }); + + return; + } + if (fountainSeconds <= _machine.PumbDelay) + { + + + settings.fountainDelayTxt.Text = "Chocolate Delay: "; + settings.fountainDelayTxt.IsVisible = true; + settings.fountainDelayCounter.Text = fountainSeconds.ToString(); + settings.fountainDelayCounter.IsVisible = true; + settings.fountainTagetTemp.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + + } + } + + + + }); + + + } + private void StopFountainTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (comPumpTemp <= recipeCoolingGoal - 3) + { + stopFountainSecondes--; + } + else + { + //mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + } + + if (stopFountainSecondes <= 0) + { + sendComFountainMotor = 0; + + + stopFountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + stopFountainTimer = null; + return; + } + } + + }); + + + + } + private void FountainPauseTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + + if (allBitsOn != fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0)) + { + allBitsOn = fount.BitNumbers.All(bit => (holdingRegister.motor & (1 << bit)) != 0); + } + if (fountainPauseSeconds <= 0) + { + pause = true; + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseTimer = null; + } + + return; + } + if (!allBitsOn) + { + //motor is off + //increase the counter + fountainPauseSeconds--; + //footerMsg.Text ="Fountain is off recipe will pause after: "+ fountainPauseSeconds.ToString(); + } + else + { + //motor is on + //cancel the timer + if (fountainPauseTimer != null) + { + + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseTimer = null; + } + } + + //if the counter greater than 10 then pause the recipe + }); + + + } + private void NoChoiceChoosenTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + //increase the coiunter + if (ContentArea.Content is Settings settings) + { + if (settings.tempErrorPopupOverlay.IsVisible) + { + noChoiceChoosenSeconds++; + //footerMsg.Text = "sec" + noChoiceChoosenSeconds.ToString(); + } + else + { + //stop the timer + if (noChoiceChoosenTimer != null) + { + noChoiceChoosenTimer.Change(Timeout.Infinite, Timeout.Infinite); + noChoiceChoosenTimer = null; + } + } + if (noChoiceChoosenSeconds >= 180)//change to 3 min + { + //if it reach the 3 min then stop the recipe + startRecipe = 0; + Heating = 0; + cooling = 0; + pouring = 0; + PumbOn = -1; + pedalMotor = -1; + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + if (fount != null) + { + if (fount.BitNumbers.Count > 0) + { + foreach (var bit in fount.BitNumbers) + { + + holdingRegister.motor &= (ushort)~(1 << bit); + } + } + } + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + holdingRegister.setTemp1 = -10000; + holdingRegister.setTemp2 = -10000; + holdingRegister.setTemp3 = -10000; + holdingRegister.setTemp4 = -10000; + settings.tempErrorPopupOverlay.IsVisible = false; + Dispatcher.UIThread.Post(async () => + { + await WriteToSerialAsync("NoChoiceChoosenTimer"); + + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + footerMsg.Text = "waitting for too long... Recipe Stoped"; + recipeStartBtn.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + }); + + + } + } + + + }); + + + } + private void HeatingTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + if ((comFountainTemp * 10 <= (recipeHeatingGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipeHeatingGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking) + { + // show error window + if (noChoiceChoosenTimer == null) + { + noChoiceChoosenSeconds = 0; + noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000); + } + settings.tempErrorPopupOverlay.IsVisible = true; + } + else if (!pauseTimer) + { + // emty error and warning temp is fine + //warningMessage = ""; + //continue counting + heatingSeconds--; + Heating = 1; + + } + //warning + + if (comFountainTemp * 10 <= (recipeHeatingGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipeHeatingGoal * 10) + (screenData.warningLimit * 10)) + { + // show waring and delet error if located + if (warningMessage != "Can Not Locate Temperature Correctly") + { + warningMessage = "Can Not Locate Temperature Correctly"; + } + } + else + { + warningMessage = ""; + } + + + if (heatingSeconds <= 0) + { + // Stop the timer after 15 seconds + warningMessage = ""; + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + pauseTimer = false; + pauseTempTracking = false; + startRecipe = 1; + Heating = -1; + cooling = 1; + sendComCooling = 1; + setCoolingTimerOnce = 1; + heatingTimer = null; + } + if (heatingSeconds <= _machine.HeatingDelay && !pauseTimer) + { + footerMsg.Text = "Heating delay: " + heatingSeconds.ToString(); + + } + } + } + + }); + + } + private void CoolingTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + if ((comFountainTemp * 10 <= (recipeCoolingGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipeCoolingGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking) + { + // show error window + if (noChoiceChoosenTimer == null) + { + noChoiceChoosenSeconds = 0; + noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000); + } + settings.tempErrorPopupOverlay.IsVisible = true; + } + else if (!pauseTimer) + { + // emty error and warning temp is fine + //warningMessage = ""; + //continue counting + coolingSeconds--; + } + //warning + if (comFountainTemp * 10 <= (recipeCoolingGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipeCoolingGoal * 10) + (screenData.warningLimit * 10)) + { + // show waring and delet error if located + if (warningMessage != "Can Not Locate Temperature Correctly") + { + warningMessage = "Can Not Locate Temperature Correctly"; + } + } + else + { + warningMessage = ""; + } + if (coolingSeconds <= 0) + { + // Stop the timer after 15 seconds + warningMessage = ""; + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + pauseTimer = false; + pauseTempTracking = false; + pouring = 1; + sendComPouring = 1; + setPouringTimerOnce = 1; + cooling = -1; + coolingTimer = null; + } + if (coolingSeconds <= _machine.CoolingDelay && !pauseTimer) + { + footerMsg.Text = "Cooling delay: " + coolingSeconds.ToString(); + + } + + } + + + } + + }); + + } + private void PouringTimer(object state) + { + + + Dispatcher.UIThread.Post(() => + { + try + { + if (ContentArea.Content is Settings settings) + { + if (fountainPauseTimer == null) + { + if ((comFountainTemp * 10 <= (recipePouringGoal * 10) - (screenData.errorLimit * 10) || comFountainTemp * 10 >= (recipePouringGoal * 10) + (screenData.errorLimit * 10)) && !pauseTempTracking) + { + // show error window + if (noChoiceChoosenTimer == null) + { + noChoiceChoosenSeconds = 0; + noChoiceChoosenTimer = new Timer(NoChoiceChoosenTimer, null, 0, 1000); + } + settings.tempErrorPopupOverlay.IsVisible = true; + } + else if (!pauseTimer) + { + // emty error and warning temp is fine + //warningMessage = ""; + //continue counting + pouringSeconds--; + } + //warning + if (comFountainTemp * 10 <= (recipePouringGoal * 10) - (screenData.warningLimit * 10) || comFountainTemp * 10 >= (recipePouringGoal * 10) + (screenData.warningLimit * 10)) + { + // show waring and delet error if located + if (warningMessage != "Can Not Locate Temperature Correctly") + { + warningMessage = "Can Not Locate Temperature Correctly"; + } + } + else + { + warningMessage = ""; + } + if (pouringSeconds <= 0) + { + // Stop the timer after 15 seconds + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringTimer = null; + + } + pauseTimer = false; + pauseTempTracking = false; + //pouring = -1; + //PumbOn = 1; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + //if (result._recipeTable.Pedal.Value) + //{ + // pedalMotor = 0; + //} + //else + //{ + // pedalMotor = 1; + // pedalState = 0; + // setPedalTimerOnce = 1; + //} + footerMsg.Text = "Ready for pouring"; + } + + }); + + } + if (pouringSeconds <= _machine.PouringDelay && !pauseTimer) + { + footerMsg.Text = "Pouring delay: " + pouringSeconds.ToString(); + + } + + } + } + } + catch (Exception ex) + { + footerMsg.Text = $"Error: {ex.Message}"; + } + + + }); + + + + } + private void PedalOffTimer(object state) + { + Dispatcher.UIThread.Post(() => + { + + // Stop the timer after 15 seconds + if (ContentArea.Content is Settings result) + { + pedalOffSeconds++; + + if (pedalOffSeconds <= result._recipeTable.PedalOffTime) + { + result.pedalDelayTxt.Text = "Pedal ON: "; + result.pedalDelayCounter.Text = pedalOffSeconds.ToString(); + result.pedalDelayTxt.IsVisible = true; + result.pedalDelayCounter.IsVisible = true; + + } + if (pedalOffSeconds >= result._recipeTable.PedalOffTime) + { + pedalOffSeconds = 0; + PumbOn = 1; + pedalMotor = 1; + pedalState = 1; + setPedalTimerOnce = 0; + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffTimer = null; + } + + + + } + } + }); + + + + + } + private void PedalOnTimer(object state) + { + Dispatcher.UIThread.Invoke(() => + { + if (ContentArea.Content is Settings result) + { + pedalOnSeconds++; + + if (pedalOnSeconds <= result._recipeTable.PedalOnTime) + { + result.pedalDelayTxt.Text = "Pedal OFF: "; + result.pedalDelayCounter.Text = pedalOnSeconds.ToString(); + result.pedalDelayTxt.IsVisible = true; + result.pedalDelayCounter.IsVisible = true; + + } + if (pedalOnSeconds >= result._recipeTable.PedalOnTime) + { + pedalOnSeconds = 0; + PumbOn = 1; + pedalMotor = 1; + pedalState = 0; + setPedalTimerOnce = 1; + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnTimer = null; + } + + + } + } + + + }); + + + + } + //Recipe Start + public async void RecipeStartBtn(object? sender, RoutedEventArgs e) + { + if (sender is Button button) + { + if (startRecipe == 0) + { + startRecipe = 1; + stopRecipeFlag = false; + + if (ContentArea.Content is Settings result) + { + recipeHeatingGoal = result._recipeTable.HeatingGoal; + recipeCoolingGoal = result._recipeTable.CoolingGoal; + recipePouringGoal = result._recipeTable.PouringGoal; + if (comPumpTemp * 10 < _machine.PumbMaxHeat * 10 || comTankTemp * 10 < _machine.TankMaxHeat * 10) + { + startPreHeating = 1; + writingMaxTemp = 1; + // Assuming you have a Button named myButton + } + if (!isMixerMotorOn) + { + result.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + if (!isFountainMotorOn) + { + result.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + + } + + Dispatcher.UIThread.Post(() => + { + result.mixerBtn.IsEnabled = false; + result.fountainBtn.IsEnabled = false; + PreHeatingBtn.IsEnabled = false; + recipeStartBtn.IsEnabled = true; + button.Background = Avalonia.Media.Brushes.Red; + button.Content = "STOP RECIPE"; + }); + } + + + + } + else if (startRecipe == 1) + { + startRecipe = 0; + stopRecipeFlag = true; + Heating = -1; + cooling = -1; + pouring = -1; + PumbOn = -1; + pedalMotor = -1; + + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + if (ContentArea.Content is Settings settings) + { + if (isMixerMotorOn) + { + settings.mixerBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + if (isFountainMotorOn) + { + settings.fountainBtn.RaiseEvent(new RoutedEventArgs(Button.ClickEvent)); + } + settings.mixerDelayTxt.IsVisible = false; + settings.mixerDelayCounter.IsVisible = false; + settings.fountainDelayTxt.IsVisible = false; + settings.fountainDelayCounter.IsVisible = false; + settings.fountainTargetTxt.IsVisible = false; + settings.fountainTagetTemp.IsVisible = false; + } + + //var fount = _mapping.Find(x => x.Name.ToLower() == "Helix".ToLower()); + //if (fount != null) + //{ + // if (fount.BitNumbers.Count > 0) + // { + // foreach (var bit in fount.BitNumbers) + // { + + // holdingRegister.motor &= (ushort)~(1 << bit); + // } + // } + //} + startPreHeating = 0; + writingMaxTemp = 0; + isFlashPreHeating = false; + holdingRegister.setTemp1 = -10000; + holdingRegister.setTemp2 = -10000; + holdingRegister.setTemp3 = -10000; + holdingRegister.setTemp4 = -10000; + holdingRegister.motor = 0; + await WriteToSerialAsync("RecipeStop"); + footerMsg.Text = "Recipe Stoped"; + button.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + Dispatcher.UIThread.Post(() => + { + if (ContentArea.Content is Settings result) + { + result.mixerBtn.IsEnabled = true; + result.fountainBtn.IsEnabled = true; + result.pedalDelayTxt.IsVisible = false; + result.pedalDelayCounter.IsVisible = false; + } + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + }); + } + } + + + } + + public void resetAll() + { + if (heatingTimer != null) + { + heatingTimer.Change(Timeout.Infinite, Timeout.Infinite); + heatingSeconds = _machine.HeatingDelay; + heatingTimer = null; + } + if (coolingTimer != null) + { + coolingTimer.Change(Timeout.Infinite, Timeout.Infinite); + coolingSeconds = _machine.CoolingDelay; + coolingTimer = null; + + } + if (pouringTimer != null) + { + pouringTimer.Change(Timeout.Infinite, Timeout.Infinite); + pouringSeconds = _machine.PouringDelay; + pouringTimer = null; + + } + if (pedalOffTimer != null) + { + pedalOffTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOffSeconds = 0; + } + if (pedalOnTimer != null) + { + pedalOnTimer.Change(Timeout.Infinite, Timeout.Infinite); + pedalOnSeconds = 0; + } + if (fountainPauseTimer != null) + { + fountainPauseTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainPauseSeconds = 10; + fountainPauseTimer = null; + } + if (fountainTimer != null) + { + fountainTimer.Change(Timeout.Infinite, Timeout.Infinite); + fountainTimer = null; + } + if (mixerTimer != null) + { + mixerTimer.Change(Timeout.Infinite, Timeout.Infinite); + mixerTimer = null; + } + + + + pedalState = -1; + pedalStateChanged = -1; + recipeHeatingGoal = 0; + recipeCoolingGoal = 0; + recipePouringGoal = 0; + //pre Heating + isFlashPreHeating = false; + startPreHeating = -1; + writingMaxTemp = -1; + // mixer + mixerSeconds = 1; + setMixerTimerOnce = false; + checkMixerTWT_HWTH = false; + isMixerMotorOn = false; + startMixerMotor = -1; + startMixerMotorFlashing = -1; + sendComMixerMotor = -1; + //Fountain Motor + fountainSeconds = 1; + setFountainTimerOnce = false; + checkFountainTMT_PMT = false; + isFountainMotorOn = false; + startFountainMotor = -1; + startFountainMotorFlashing = -1; + sendComFountainMotor = -1; + //MOLD HEATER(off:0,on:1) , VIBRATION(off:0,on:1) , VIB. HEATER(off:0,on:1) + moldHeaterMotor = -1; + vibrationMotor = -1; + vibHeaterMotor = -1; + //Pedal(manual=0,auto=1) + pedalMotor = -1; + //Recipe Start + startRecipe = 0; + sendComTankTemp = -1; + //phase 1 heating + Heating = -1; + sendComHeating = -1; + setHeatingTimerOnce = -1; + heatingSeconds = 0; + //phase 2 cooling + cooling = -1; + sendComCooling = -1; + setCoolingTimerOnce = -1; + coolingSeconds = 0; + //phase 3 pouring + pouring = -1; + sendComPouring = -1; + setPouringTimerOnce = -1; + pouringSeconds = 0; + //start the pumb + PumbOn = -1; + pedalOffSeconds = 0; + pedalOnSeconds = 0; + setPedalTimerOnce = -1; + Dispatcher.UIThread.Post(() => + { + recipeStartBtn.Foreground = Avalonia.Media.Brushes.White; + recipeStartBtn.Background = Brush.Parse("#008000"); + recipeStartBtn.Content = "START RECIPE"; + PreHeatingBtn.IsEnabled = true; + recipeStartBtn.IsEnabled = true; + }); + + + + + } + + + private async void ResetErrors(object? sender, RoutedEventArgs e) + { + holdingRegister.resetError = (ushort)(1 << 0); + await WriteToSerialAsync("ResetErrors"); + + } + private async void OnWarningPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + warningPopupOverlay.IsVisible = false; + + } + private async void OnErrorPopupOverlayPointerPressed(object? sender, RoutedEventArgs e) + { + errorPopupOverlay.IsVisible = false; + + } + + + + public static class MessageBox + { + public static async Task Show(Window owner, string message, string title) + { + var dialog = new Window + { + Title = title, + Width = 300, + Height = 150, + WindowStartupLocation = WindowStartupLocation.CenterOwner, + Topmost = false, + Content = new StackPanel + { + Children = + { + new TextBlock + { + Text = message, + Margin = new Thickness(10), + HorizontalAlignment = HorizontalAlignment.Center + }, + new Button + { + Content = "OK", + Margin = new Thickness(10), + HorizontalAlignment = HorizontalAlignment.Center + } + } + } + }; + + var button = (Button)((StackPanel)dialog.Content).Children[1]; + button.Click += (s, e) => dialog.Close(); + + owner.Topmost = false; + await dialog.ShowDialog(owner); + owner.Topmost = true; + owner.Activate(); + + // Restart keyboard to bring it on top + var (fileName, args) = GetKeyboardCommand(); + if (!string.IsNullOrEmpty(fileName)) + { + try + { + Process.Start(fileName, args); + } + catch + { + // Handle exceptions if needed + } + } + } + + private static (string? fileName, string args) GetKeyboardCommand() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + return ("osk.exe", ""); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + return ("onboard", ""); // or "florence", "matchbox-keyboard" + return (null, ""); + } + } + } +} + +============================================================ +FILE: DaireApplication/App.axaml +============================================================ + + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/App.axaml.cs +============================================================ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Markup.Xaml; +using DaireApplication.ViewModels; +using DaireApplication.Views; + +namespace DaireApplication +{ + public partial class App : Application + { + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + public override void OnFrameworkInitializationCompleted() + { + // Migrate CSV files by adding missing columns with default values + DataBase.DataPathManager.MigrateCsvFiles(); + + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } + + } +} + +============================================================ +FILE: DaireApplication/app.manifest +============================================================ + + + + + + + + + + + + + + + + +============================================================ +FILE: DaireApplication/Program.cs +============================================================ +using Avalonia; +using Avalonia.Controls; +using Avalonia.ReactiveUI; +using AvaloniaApplication1.DataBase; +using System; +using System.Threading.Tasks; + +namespace DaireApplication +{ + internal sealed class Program + { + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + public static UserTable? currentUser; + + public static int pouringMinTemp = -5; + public static int absoluteMaxTemp = 70; + public static int absoluteMinTemp = -10; + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace() + .UseReactiveUI(); + + + } +} + + +============================================================ +FILE: DaireApplication/ViewLocator.cs +============================================================ +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using DaireApplication.ViewModels; +using System; + +namespace DaireApplication +{ + public class ViewLocator : IDataTemplate + { + + public Control? Build(object? param) + { + if (param is null) + return null; + + var name = param.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); + + if (type != null) + { + return (Control)Activator.CreateInstance(type)!; + } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; + } + } +} + + +============================================================ +FILE: README.md +============================================================ +# copyVersoin + + + +## Getting started + +To make it easy for you to get started with GitLab, here's a list of recommended next steps. + +Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! + +## Add your files + +- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files +- [ ] [Add files using the command line](https://docs.gitlab.com/topics/git/add_files/#add-files-to-a-git-repository) or push an existing Git repository with the following command: + +``` +cd existing_repo +git remote add origin https://gitlab.com/wael.badawi2000/copyversoin.git +git branch -M main +git push -uf origin main +``` + +## Integrate with your tools + +- [ ] [Set up project integrations](https://gitlab.com/wael.badawi2000/copyversoin/-/settings/integrations) + +## Collaborate with your team + +- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) +- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) +- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) +- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) +- [ ] [Set auto-merge](https://docs.gitlab.com/user/project/merge_requests/auto_merge/) + +## Test and Deploy + +Use the built-in continuous integration in GitLab. + +- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/) +- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) +- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) +- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) +- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) + +*** + +# Editing this README + +When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. + +## Suggestions for a good README + +Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. + +## Name +Choose a self-explaining name for your project. + +## Description +Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. + +## Badges +On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. + +## Visuals +Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. + +## Installation +Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. + +## Usage +Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. + +## Support +Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. + +## Roadmap +If you have ideas for releases in the future, it is a good idea to list them in the README. + +## Contributing +State if you are open to contributions and what your requirements are for accepting them. + +For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. + +You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. + +## Authors and acknowledgment +Show your appreciation to those who have contributed to the project. + +## License +For open source projects, say how it is licensed. + +## Project status +If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. \ No newline at end of file