Browse Source

init proj

main
jkpete 4 weeks ago
commit
8a55b82509
  1. 15
      .gitignore
  2. 20
      Components/App.razor
  3. 23
      Components/Layout/MainLayout.razor
  4. 96
      Components/Layout/MainLayout.razor.css
  5. 30
      Components/Layout/NavMenu.razor
  6. 105
      Components/Layout/NavMenu.razor.css
  7. 19
      Components/Pages/Counter.razor
  8. 36
      Components/Pages/Error.razor
  9. 7
      Components/Pages/Home.razor
  10. 64
      Components/Pages/Weather.razor
  11. 6
      Components/Routes.razor
  12. 10
      Components/_Imports.razor
  13. 208
      EGFramework/EGFramework.cs
  14. 48
      EGFramework/EGPlatform.cs
  15. 21
      EGFramework/License_Third_Part/BACnet/MIT_license.txt
  16. 6
      EGFramework/License_Third_Part/Dapper/License.txt
  17. 23
      EGFramework/License_Third_Part/Dotnet/LICENSE.txt
  18. 7
      EGFramework/License_Third_Part/FluentFTP/LICENSE.TXT
  19. 21
      EGFramework/License_Third_Part/LiteDB/LICENSE.txt
  20. 22
      EGFramework/License_Third_Part/MQTTnet/LICENSE
  21. 21
      EGFramework/License_Third_Part/Makaretu_Dns_Multicast/LICENSE.txt
  22. 3
      EGFramework/License_Third_Part/Mysql_Data/Notice.txt
  23. 20
      EGFramework/License_Third_Part/NewtonSoft_Json/LICENSE.md
  24. 21
      EGFramework/License_Third_Part/QFramework/LICENSE
  25. 47
      EGFramework/License_Third_Part/StackExchange_Redis/LICENSE.txt
  26. 21
      EGFramework/License_Third_Part/WebDavClient/LICENSE.txt
  27. 96
      EGFramework/License_Third_Part/source_han_sans/LICENSE.txt
  28. 56
      EGFramework/Module/EGCQRS.cs
  29. 167
      EGFramework/Module/EGEvent.cs
  30. 65
      EGFramework/Module/EGObjects.cs
  31. 392
      EGFramework/Module/Extension/EGConvertExtension.cs
  32. 154
      EGFramework/Module/Extension/EGCrcExtension.cs
  33. 31
      EGFramework/Module/Extension/EGDateTimeExtension.cs
  34. 78
      EGFramework/Module/Extension/EGEncodingExtension.cs
  35. 54
      EGFramework/Module/Extension/EGIpExtension.cs
  36. 146
      EGFramework/Module/Extension/EGSqlExtension.cs
  37. 16
      EGFramework/Module/GenerateTools/EGGenerate.cs
  38. 34
      EGFramework/Module/GenerateTools/GenerateToolsInterface.cs
  39. 90
      EGFramework/Module/GenerateTools/Templete/Code/EGSvgGenerator.cs
  40. 11
      EGFramework/Module/GenerateTools/Templete/Code/EGSvgTempletes.cs
  41. 71
      EGFramework/Module/GenerateTools/Templete/Variant/EGDataStruct.cs
  42. 127
      EGFramework/Module/GenerateTools/Templete/Variant/EGTree.cs
  43. 127
      EGFramework/Module/GenerateTools/Templete/Variant/EGVariantGenerator.cs
  44. 280
      EGFramework/Module/OtherTools/EGModbus.cs
  45. 245
      EGFramework/Module/OtherTools/EGSqlite.cs
  46. 241
      EGFramework/Module/OtherTools/EGWebDav.cs
  47. 335
      EGFramework/Module/ProtocolTools/EGMessage.cs
  48. 58
      EGFramework/Module/ProtocolTools/EGProtocolSchedule.cs
  49. 573
      EGFramework/Module/ProtocolTools/Internet/EGBacnet.cs
  50. 96
      EGFramework/Module/ProtocolTools/Internet/EGHttpClient.cs
  51. 148
      EGFramework/Module/ProtocolTools/Internet/EGHttpServer.cs
  52. 163
      EGFramework/Module/ProtocolTools/Internet/EGMQTT.cs
  53. 179
      EGFramework/Module/ProtocolTools/Internet/EGSsh.cs
  54. 182
      EGFramework/Module/ProtocolTools/Internet/EGTCPClient.cs
  55. 167
      EGFramework/Module/ProtocolTools/Internet/EGTCPServer.cs
  56. 137
      EGFramework/Module/ProtocolTools/Internet/EGUDP.cs
  57. 139
      EGFramework/Module/ProtocolTools/Internet/EGWebSocketClient.cs
  58. 101
      EGFramework/Module/ProtocolTools/Other/EGFileStream.cs
  59. 124
      EGFramework/Module/ProtocolTools/Other/EGProcess.cs
  60. 299
      EGFramework/Module/ProtocolTools/ProtocolExtension/EGDnsExtension.cs
  61. 899
      EGFramework/Module/ProtocolTools/ProtocolExtension/EGModbusExtension.cs
  62. 19
      EGFramework/Module/ProtocolTools/ProtocolToolsInterface.cs
  63. 240
      EGFramework/Module/ProtocolTools/SerialPort/EGSerialPort.cs
  64. 499
      EGFramework/Module/SaveTools/Data/EGCsvSave.cs
  65. 336
      EGFramework/Module/SaveTools/Data/EGDapper.cs
  66. 162
      EGFramework/Module/SaveTools/Data/EGLiteDBSave.cs
  67. 29
      EGFramework/Module/SaveTools/Data/EGMysqlSave.cs
  68. 50
      EGFramework/Module/SaveTools/Data/EGSqliteSave.cs
  69. 79
      EGFramework/Module/SaveTools/EGSave.cs
  70. 116
      EGFramework/Module/SaveTools/File/EGFtpSave.cs
  71. 173
      EGFramework/Module/SaveTools/File/EGLocalFileSave.cs
  72. 98
      EGFramework/Module/SaveTools/File/EGSftpSave.cs
  73. 77
      EGFramework/Module/SaveTools/File/EGWebDavSave.cs
  74. 131
      EGFramework/Module/SaveTools/Object/EGByteSave.cs
  75. 136
      EGFramework/Module/SaveTools/Object/EGJsonSave.cs
  76. 88
      EGFramework/Module/SaveTools/Object/EGRedisSave.cs
  77. 151
      EGFramework/Module/SaveTools/SaveToolsInterface.cs
  78. 158
      InstallManual.md
  79. 23
      Program.cs
  80. 29
      Properties/launchSettings.json
  81. 41
      Script/Architecture/EGBlazorController.cs
  82. 14
      Script/Data/DataActionStatus.cs
  83. 19
      Script/Data/DataSetting.cs
  84. 98
      Script/Extension/ColorConvertExtension.cs
  85. 12
      Script/Interface/IEGBehavior.cs
  86. 41
      Script/Model/ModelActionStatus.cs
  87. 51
      Script/Model/ModelControlServer.cs
  88. 77
      Script/Model/ModelParamSetting.cs
  89. 56
      Script/Model/ModelSerialServer.cs
  90. 108
      Script/Model/ModelSerialTest.cs
  91. 317
      Script/Model/ModelTrackControl.cs
  92. 113
      Script/Protocol/RequestSerialServer.cs
  93. 31
      Script/Protocol/RequestTargetEngine.cs
  94. 103
      Script/Protocol/RequestTrackEngine.cs
  95. 59
      Script/Protocol/ResponseColorSensor.cs
  96. 105
      Script/Protocol/ResponseControl.cs
  97. 14
      SystemCtl/TrackTarget.service
  98. 51
      SystemCtl/install.sh
  99. 26
      TargetService.csproj
  100. 24
      TargetService.sln
  101. Some files were not shown because too many files have changed in this diff Show More

15
.gitignore vendored

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
#EGSave-Specific ignores
SaveData/
#Csharp Build
bin/
#CSharp Cache
obj/
# Web
# wwwroot/
*.pck
*.wasm

20
Components/App.razor

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="TargetService.styles.css" />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet />
</head>
<body>
<Routes />
<script src="_framework/blazor.web.js"></script>
</body>
</html>

23
Components/Layout/MainLayout.razor

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
@inherits LayoutComponentBase
<div class="page">
<div class="sidebar">
<NavMenu />
</div>
<main>
<div class="top-row px-4">
<a href="https://learn.microsoft.com/aspnet/core/" target="_blank">About</a>
</div>
<article class="content px-4">
@Body
</article>
</main>
</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">🗙</a>
</div>

96
Components/Layout/MainLayout.razor.css

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
.page {
position: relative;
display: flex;
flex-direction: column;
}
main {
flex: 1;
}
.sidebar {
background-image: linear-gradient(180deg, rgb(5, 39, 103) 0%, #3a0647 70%);
}
.top-row {
background-color: #f7f7f7;
border-bottom: 1px solid #d6d5d5;
justify-content: flex-end;
height: 3.5rem;
display: flex;
align-items: center;
}
.top-row ::deep a, .top-row ::deep .btn-link {
white-space: nowrap;
margin-left: 1.5rem;
text-decoration: none;
}
.top-row ::deep a:hover, .top-row ::deep .btn-link:hover {
text-decoration: underline;
}
.top-row ::deep a:first-child {
overflow: hidden;
text-overflow: ellipsis;
}
@media (max-width: 640.98px) {
.top-row {
justify-content: space-between;
}
.top-row ::deep a, .top-row ::deep .btn-link {
margin-left: 0;
}
}
@media (min-width: 641px) {
.page {
flex-direction: row;
}
.sidebar {
width: 250px;
height: 100vh;
position: sticky;
top: 0;
}
.top-row {
position: sticky;
top: 0;
z-index: 1;
}
.top-row.auth ::deep a:first-child {
flex: 1;
text-align: right;
width: 0;
}
.top-row, article {
padding-left: 2rem !important;
padding-right: 1.5rem !important;
}
}
#blazor-error-ui {
background: lightyellow;
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
display: none;
left: 0;
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
width: 100%;
z-index: 1000;
}
#blazor-error-ui .dismiss {
cursor: pointer;
position: absolute;
right: 0.75rem;
top: 0.5rem;
}

30
Components/Layout/NavMenu.razor

@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">TargetService</a>
</div>
</div>
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
</NavLink>
</div>
</nav>
</div>

105
Components/Layout/NavMenu.razor.css

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
.navbar-toggler {
appearance: none;
cursor: pointer;
width: 3.5rem;
height: 2.5rem;
color: white;
position: absolute;
top: 0.5rem;
right: 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}
.navbar-toggler:checked {
background-color: rgba(255, 255, 255, 0.5);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}
.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}
.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}
.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep .nav-link {
color: #d7d7d7;
background: none;
border: none;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
width: 100%;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}
.nav-item ::deep .nav-link:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
.nav-scrollable {
display: none;
}
.navbar-toggler:checked ~ .nav-scrollable {
display: block;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.nav-scrollable {
/* Never collapse the sidebar for wide screens */
display: block;
/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}

19
Components/Pages/Counter.razor

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
@page "/counter"
@rendermode InteractiveServer
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

36
Components/Pages/Error.razor

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@code{
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
private string? RequestId { get; set; }
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
protected override void OnInitialized() =>
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
}

7
Components/Pages/Home.razor

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

64
Components/Pages/Weather.razor

@ -0,0 +1,64 @@ @@ -0,0 +1,64 @@
@page "/weather"
@attribute [StreamRendering]
<PageTitle>Weather</PageTitle>
<h1>Weather</h1>
<p>This component demonstrates showing data.</p>
@if (forecasts == null)
{
<p><em>Loading...</em></p>
}
else
{
<table class="table">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
@foreach (var forecast in forecasts)
{
<tr>
<td>@forecast.Date.ToShortDateString()</td>
<td>@forecast.TemperatureC</td>
<td>@forecast.TemperatureF</td>
<td>@forecast.Summary</td>
</tr>
}
</tbody>
</table>
}
@code {
private WeatherForecast[]? forecasts;
protected override async Task OnInitializedAsync()
{
// Simulate asynchronous loading to demonstrate streaming rendering
await Task.Delay(500);
var startDate = DateOnly.FromDateTime(DateTime.Now);
var summaries = new[] { "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" };
forecasts = Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = startDate.AddDays(index),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = summaries[Random.Shared.Next(summaries.Length)]
}).ToArray();
}
private class WeatherForecast
{
public DateOnly Date { get; set; }
public int TemperatureC { get; set; }
public string? Summary { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
}
}

6
Components/Routes.razor

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="routeData" Selector="h1" />
</Found>
</Router>

10
Components/_Imports.razor

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using TargetService
@using TargetService.Components

208
EGFramework/EGFramework.cs

@ -0,0 +1,208 @@ @@ -0,0 +1,208 @@
using System;
using System.Collections.Generic;
namespace EGFramework
{
#region Architecture & Module
public class EGArchitecture<T> : IArchitecture where T : EGArchitecture<T>, new()
{
private static T Architecture;
public static IArchitecture Interface
{
get
{
if (Architecture == null)
{
MakeSureArchitecture();
}
return Architecture;
}
}
private static void MakeSureArchitecture()
{
if (Architecture == null)
{
Architecture = new T();
Architecture.Init();
}
}
protected virtual void Init()
{
}
private IOCContainer ModuleContainer = new IOCContainer();
public void RegisterModule<TModule>(TModule module) where TModule : IModule
{
ModuleContainer.Register<TModule>(module);
module.Init();
}
public TModule GetModule<TModule>() where TModule : class, IModule,new()
{
if (!ModuleContainer.self.ContainsKey(typeof(TModule)))
{
this.RegisterModule(new TModule());
}
return ModuleContainer.Get<TModule>();
}
public bool IsInitModule<TModule>() where TModule : class, IModule,new()
{
if (!ModuleContainer.self.ContainsKey(typeof(TModule)))
{
return true;
}else{
return false;
}
}
}
public abstract class EGModule:IModule{
IArchitecture IBelongToArchitecture.GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
void IModule.Init()
{
this.Init();
}
public abstract void Init();
}
#endregion
#region Interface
public interface IArchitecture
{
void RegisterModule<T>(T model) where T : IModule;
T GetModule<T>() where T : class, IModule,new();
bool IsInitModule<T>() where T : class, IModule,new();
}
public interface IModule : IBelongToArchitecture
{
void Init();
}
public interface IBelongToArchitecture
{
IArchitecture GetArchitecture();
}
#endregion
#region IOC
public class IOCContainer
{
private Dictionary<Type, object> Instances = new Dictionary<Type, object>();
public void Register<T>(T instance)
{
var key = typeof(T);
if (Instances.ContainsKey(key))
{
Instances[key] = instance;
}
else
{
Instances.Add(key, instance);
}
}
public T Get<T>() where T : class
{
var key = typeof(T);
if (Instances.TryGetValue(key, out var retInstance))
{
return retInstance as T;
}
return null;
}
public Dictionary<Type, object> self => Instances;
}
#endregion
#region Event
public interface IEasyEvent {
}
public interface IUnRegister
{
void UnRegister();
}
public class EasyEvent<T> : IEasyEvent
{
private Action<T> OnEvent = e => { };
public IUnRegister Register(Action<T> onEvent)
{
OnEvent += onEvent;
return new CustomUnRegister(() => { UnRegister(onEvent); });
}
public void UnRegister(Action<T> onEvent)
{
OnEvent -= onEvent;
}
public void Invoke(T t)
{
OnEvent?.Invoke(t);
}
}
public class EasyEvent : IEasyEvent
{
private Action OnEvent = () => { };
public IUnRegister Register(Action onEvent)
{
OnEvent += onEvent;
return new CustomUnRegister(() => { UnRegister(onEvent); });
}
public void UnRegister(Action onEvent)
{
OnEvent -= onEvent;
}
public void Invoke()
{
OnEvent?.Invoke();
}
}
public struct CustomUnRegister : IUnRegister
{
/// <summary>
/// delegate object
/// </summary>
private Action OnUnRegister { get; set; }
public CustomUnRegister(Action onUnRegister)
{
OnUnRegister = onUnRegister;
}
/// <summary>
/// release by parent;
/// </summary>
public void UnRegister()
{
OnUnRegister.Invoke();
OnUnRegister = null;
}
}
#endregion
#region FrameworkExtension
public interface IEGFramework{}
public class EGArchitectureImplement:EGArchitecture<EGArchitectureImplement>{
protected override void Init()
{
//base.Init();
}
}
public static class EGArchitectureImplementExtension{
public static T GetModule<T>(this IEGFramework self) where T : class, IModule,new()
{
return EGArchitectureImplement.Interface.GetModule<T>();
}
public static void RegisterModule<T>(this IEGFramework self,T model) where T : class, IModule,new()
{
EGArchitectureImplement.Interface.RegisterModule(model);
}
}
#endregion
}

48
EGFramework/EGPlatform.cs

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
using System;
using System.Diagnostics;
namespace EGFramework{
public interface IPlatform{
void Log(string message);
void Log(params object[] what);
}
// public class EGPlatformGodot : IPlatform{
// public void Log(string message){
// Godot.GD.Print(message);
// // Console.WriteLine(message);
// }
// public void Log(params object[] what){
// Godot.GD.Print(what);
// // Console.WriteLine(what);
// }
// }
// if not use please explain this
public class EGPlatformDotnet : IPlatform{
public void Log(string message){
Console.WriteLine(message);
}
public void Log(params object[] what){
Console.WriteLine(what);
}
}
public static class EG
{
public static EGPlatformDotnet Platform = new EGPlatformDotnet();
public static void Print(string message){
Platform.Log(message);
}
public static void Print(params object[] what){
Platform.Log(what);
}
}
// public enum SupportPlatform{
// Godot = 0x01,
// Unity = 0x02,
// WebApi = 0x03,
// WPF = 0x04,
// Form = 0x05,
// }
}

21
EGFramework/License_Third_Part/BACnet/MIT_license.txt

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Yabe project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

6
EGFramework/License_Third_Part/Dapper/License.txt

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
The Dapper library and tools are licenced under Apache 2.0: http://www.apache.org/licenses/LICENSE-2.0
The Dapper logo is copyright Marc Gravell 2021 onwards; it is fine to use the Dapper logo when referencing the Dapper library and utilities, but
the Dapper logo (including derivatives) must not be used in a way that misrepresents an external product or library as being affiliated or endorsed
with Dapper. For example, you must not use the Dapper logo as the package icon on your own external tool (even if it uses Dapper internally),
without written permission. If in doubt: ask.

23
EGFramework/License_Third_Part/Dotnet/LICENSE.txt

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

7
EGFramework/License_Third_Part/FluentFTP/LICENSE.TXT

@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
Copyright (c) 2015 Robin Rodricks and FluentFTP Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

21
EGFramework/License_Third_Part/LiteDB/LICENSE.txt

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014-2022 Mauricio David
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

22
EGFramework/License_Third_Part/MQTTnet/LICENSE

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) .NET Foundation and Contributors
All Rights Reserved
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

21
EGFramework/License_Third_Part/Makaretu_Dns_Multicast/LICENSE.txt

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Richard Schneider
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

3
EGFramework/License_Third_Part/Mysql_Data/Notice.txt

@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
GPL-2.0-only license licenseWITH license licenseUniversal-FOSS-exception-1.0 license
https://licenses.nuget.org/GPL-2.0-only
https://licenses.nuget.org/Universal-FOSS-exception-1.0

20
EGFramework/License_Third_Part/NewtonSoft_Json/LICENSE.md

@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright (c) 2007 James Newton-King
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

21
EGFramework/License_Third_Part/QFramework/LICENSE

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 凉鞋
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

47
EGFramework/License_Third_Part/StackExchange_Redis/LICENSE.txt

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
The MIT License (MIT)
Copyright (c) 2014 Stack Exchange
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
===============================================
Third Party Licenses:
The Redis project (https://redis.io/) is independent of this client library, and
is licensed separately under the three clause BSD license. The full license
information can be viewed here: https://redis.io/topics/license
This tool makes use of the "redis-doc" library from https://redis.io/documentation
in the intellisense comments, which is licensed under the
Creative Commons Attribution-ShareAlike 4.0 International license; full
details are available here:
https://github.com/antirez/redis-doc/blob/master/COPYRIGHT
The development solution uses the Redis-64 package from nuget
(https://www.nuget.org/packages/Redis-64) by Microsoft Open Technologies, inc.
This is licensed under the BSD license; full details are available here:
https://github.com/MSOpenTech/redis/blob/2.6/license.txt
This tool is not used in the release binaries.
The development solution uses the BookSleeve package from nuget
(https://code.google.com/p/booksleeve/) by Marc Gravell. This is licensed
under the Apache 2.0 license; full details are available here:
https://www.apache.org/licenses/LICENSE-2.0
This tool is not used in the release binaries.

21
EGFramework/License_Third_Part/WebDavClient/LICENSE.txt

@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Sergey Kazantsev
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

96
EGFramework/License_Third_Part/source_han_sans/LICENSE.txt

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font
Name 'Source'. Source is a trademark of Adobe in the United States
and/or other countries.
This Font Software is licensed under the SIL Open Font License,
Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font
creation efforts of academic and linguistic communities, and to
provide a free and open framework in which fonts may be shared and
improved in partnership with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply to
any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software
components as distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to,
deleting, or substituting -- in part or in whole -- any of the
components of the Original Version, by changing formats or by porting
the Font Software to a new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed,
modify, redistribute, and sell modified and unmodified copies of the
Font Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components, in
Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the
corresponding Copyright Holder. This restriction only applies to the
primary font name as presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created using
the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.

56
EGFramework/Module/EGCQRS.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
namespace EGFramework
{
#region Interface
public interface ICommand
{
void Execute();
}
public interface IQuery<TResult>
{
TResult Do();
}
public interface IEGCQRS
{
void SendCommand(ICommand command);
TResult DoQuery<TResult>(IQuery<TResult> query);
}
#endregion
public class EGCQRS :EGModule, IEGCQRS
{
public void SendCommand(ICommand command)
{
command.Execute();
}
public TResult DoQuery<TResult>(IQuery<TResult> query)
{
return query.Do();
}
public override void Init()
{
}
}
#region Extension
public static class CanSendCommandExtension
{
public static void EGSendCommand(this IEGFramework self, ICommand command)
{
EGArchitectureImplement.Interface.GetModule<EGCQRS>().SendCommand(command);
}
}
public static class CanQueryDataExtension
{
public static TResult EGQueryData<TResult>(this IEGFramework self, IQuery<TResult> query)
{
return EGArchitectureImplement.Interface.GetModule<EGCQRS>().DoQuery(query);
}
}
#endregion
}

167
EGFramework/Module/EGEvent.cs

@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
namespace EGFramework
{
public interface IEGEvent{
void SendEvent<T>() where T : new();
void SendEvent<T>(T e);
IUnRegister RegisterEvent<T>(Action<T> onEvent);
void UnRegisterEvent<T>(Action<T> onEvent);
}
public class EGEvent : EGModule,IEGEvent
{
public override void Init()
{
}
private readonly EasyEvents Events = new EasyEvents();
public void SendEvent<TEvent>() where TEvent : new()
{
Events.GetEvent<EasyEvent<TEvent>>()?.Invoke(new TEvent());
}
public void SendEvent<TEvent>(TEvent e)
{
Events.GetEvent<EasyEvent<TEvent>>()?.Invoke(e);
}
public IUnRegister RegisterEvent<TEvent>(Action<TEvent> onEvent)
{
var e = Events.GetOrAddEvent<EasyEvent<TEvent>>();
return e.Register(onEvent);
}
public void UnRegisterEvent<TEvent>(Action<TEvent> onEvent)
{
var e = Events.GetEvent<EasyEvent<TEvent>>();
if (e != null)
{
e.UnRegister(onEvent);
}
}
}
public class EasyEvents
{
private static EasyEvents GlobalEvents = new EasyEvents();
public static T Get<T>() where T : IEasyEvent
{
return GlobalEvents.GetEvent<T>();
}
public static void Register<T>() where T : IEasyEvent, new()
{
GlobalEvents.AddEvent<T>();
}
private Dictionary<Type, IEasyEvent> TypeEvents = new Dictionary<Type, IEasyEvent>();
public void AddEvent<T>() where T : IEasyEvent, new()
{
TypeEvents.Add(typeof(T), new T());
}
public T GetEvent<T>() where T : IEasyEvent
{
IEasyEvent e;
if (TypeEvents.TryGetValue(typeof(T), out e))
{
return (T)e;
}
return default;
}
public T GetOrAddEvent<T>() where T : IEasyEvent, new()
{
var eType = typeof(T);
if (TypeEvents.TryGetValue(eType, out var e))
{
return (T)e;
}
var t = new T();
TypeEvents.Add(eType, t);
return t;
}
}
/// <summary>
/// This EasyEvent will release all registered function while invoked.
/// </summary>
/// <typeparam name="T"></typeparam>
public class EasyEventOnce<T> : IEasyEvent
{
private Action<T> OnEvent = e => { };
private List<CustomUnRegister> AutoUnRegister = new List<CustomUnRegister>();
public IUnRegister Register(Action<T> onEvent)
{
OnEvent += onEvent;
CustomUnRegister unRegister = new CustomUnRegister(() => { UnRegister(onEvent); });
AutoUnRegister.Add(unRegister);
return unRegister;
}
public void UnRegister(Action<T> onEvent)
{
OnEvent -= onEvent;
}
public void Invoke(T t)
{
if(AutoUnRegister.Count>0){
OnEvent?.Invoke(t);
foreach(CustomUnRegister unRegister in AutoUnRegister){
unRegister.UnRegister();
}
AutoUnRegister.Clear();
}
}
}
/// <summary>
/// This EasyEvent will release all registered function while invoked.
/// </summary>
public class EasyEventOnce : IEasyEvent{
private Action OnEvent = () => { };
private List<CustomUnRegister> AutoUnRegister = new List<CustomUnRegister>();
public IUnRegister Register(Action onEvent)
{
OnEvent += onEvent;
CustomUnRegister unRegister = new CustomUnRegister(() => { UnRegister(onEvent); });
AutoUnRegister.Add(unRegister);
return unRegister;
}
public void UnRegister(Action onEvent)
{
OnEvent -= onEvent;
}
public void Invoke()
{
if(AutoUnRegister.Count>0){
OnEvent?.Invoke();
foreach(CustomUnRegister unRegister in AutoUnRegister){
unRegister.UnRegister();
}
AutoUnRegister.Clear();
}
}
}
public static class CanRegisterEventExtension
{
public static IUnRegister EGRegisterEvent<T>(this IEGFramework self, Action<T> onEvent)
{
return EGArchitectureImplement.Interface.GetModule<EGEvent>().RegisterEvent<T>(onEvent);
}
public static void EGUnRegisterEvent<T>(this IEGFramework self, Action<T> onEvent)
{
EGArchitectureImplement.Interface.GetModule<EGEvent>().UnRegisterEvent<T>(onEvent);
}
}
public static class CanSendEventExtension
{
public static void EGSendEvent<T>(this IEGFramework self) where T : new()
{
EGArchitectureImplement.Interface.GetModule<EGEvent>().SendEvent<T>();
}
public static void EGSendEvent<T>(this IEGFramework self, T e)
{
EGArchitectureImplement.Interface.GetModule<EGEvent>().SendEvent<T>(e);
}
}
}

65
EGFramework/Module/EGObjects.cs

@ -0,0 +1,65 @@ @@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
namespace EGFramework
{
public interface IEGObjects
{
void RegisterObject<T>(T object_);
T GetObject<T>() where T : class,new();
}
public class EGObjects : EGModule,IEGObjects
{
private IOCContainer ObjectContainer = new IOCContainer();
public override void Init()
{
}
public TObject GetObject<TObject>() where TObject : class,new()
{
if (!ObjectContainer.self.ContainsKey(typeof(TObject)))
{
this.RegisterObject(new TObject());
}
return ObjectContainer.Get<TObject>();
}
public void RegisterObject<TObject>(TObject object_)
{
ObjectContainer.Register(object_);
}
public bool ContainsObject<TObject>(){
return ObjectContainer.self.ContainsKey(typeof(TObject));
}
}
public static class CanGetObjectExtension
{
public static T EGGetObject<T>(this IEGFramework self) where T : class,new()
{
return EGArchitectureImplement.Interface.GetModule<EGObjects>().GetObject<T>();
}
}
public static class CanRegisterObjectExtension
{
public static void EGRegisterObject<T>(this IArchitecture self,T object_) where T : class,new()
{
self.GetModule<EGObjects>().RegisterObject(object_);
}
public static void EGRegisterObject<T>(this IEGFramework self,T object_) where T : class,new()
{
EGArchitectureImplement.Interface.GetModule<EGObjects>().RegisterObject(object_);
}
}
public static class CanContainsObjectExtension{
public static bool EGContainsObject<T>(this IEGFramework self)
{
return EGArchitectureImplement.Interface.GetModule<EGObjects>().ContainsObject<T>();
}
}
}

392
EGFramework/Module/Extension/EGConvertExtension.cs

@ -0,0 +1,392 @@ @@ -0,0 +1,392 @@
using System;
using System.Linq;
using System.Text;
namespace EGFramework {
//协议规则解析通用方法扩展
public static class EGConvertExtension
{
/// <summary>
/// Hex string data to byte array,such as a string like "0x00 0xff 0x06"
/// </summary>
/// <param name="self">Only include A-F,0-9,hex</param>
/// <returns></returns>
public static byte[] ToByteArrayByHex(this string self) {
int hexLen = self.Length;
byte[] result;
if (hexLen % 2 == 1)
{
//奇数
hexLen++;
result = new byte[(hexLen / 2)];
self += "0" ;
}
else
{
//偶数
result = new byte[(hexLen / 2)];
}
int j = 0;
for (int i = 0; i < hexLen; i += 2)
{
result[j] = (byte)int.Parse(self.Substring(i, 2), System.Globalization.NumberStyles.HexNumber);
j++;
}
return result;
}
/// <summary>
/// get string from hex array ,like hex array {0x0a,0x11} => "0x0a 0x11"
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static string ToStringByHex(this byte[] self)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in self)
{
sb.Append(b.ToString("X2") + " ");
}
string result = sb.ToString().Trim();
return result;
}
public static string ToStringByHex0x(this byte[] self)
{
StringBuilder sb = new StringBuilder();
foreach (byte b in self)
{
sb.Append("0x" + b.ToString("X2") + " ");
}
string result = sb.ToString().Trim();
return result;
}
/// <summary>
/// get hex from string ,like string "0x0a 0x11" => {0x0a,0x11}
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static byte[] ToHexByString(this string self)
{
string[] hexStrings = self.Split(' ');
byte[] byteArray = new byte[hexStrings.Length];
for (int i = 0; i < hexStrings.Length; i++)
{
byteArray[i] = Convert.ToByte(hexStrings[i], 16);
}
return byteArray;
}
public static byte[] ToHexByString0x(this string self)
{
if (self.Length <= 2 && self.Substring(0, 2) != "0x") {
return null;
}
return self.ToHexByString();
}
public static byte[] ToBytes(this ushort self){
byte[] byteArray = BitConverter.GetBytes(self);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(byteArray);
}
return byteArray;
}
public static ushort ToUShort(this byte[] self){
if (BitConverter.IsLittleEndian)
{
Array.Reverse(self);
}
return BitConverter.ToUInt16(self, 0);
}
public static ushort ToUShortLittleEndian(this byte[] self){
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(self);
}
return BitConverter.ToUInt16(self, 0);
}
public static byte[] ToBytes(this uint self){
byte[] byteArray = BitConverter.GetBytes(self);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(byteArray);
}
return byteArray;
}
public static byte[] ToBytesLittleEndian(this uint self){
byte[] byteArray = BitConverter.GetBytes(self);
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(byteArray);
}
return byteArray;
}
public static uint ToUINT(this byte[] self){
if (BitConverter.IsLittleEndian)
{
Array.Reverse(self);
}
return BitConverter.ToUInt32(self, 0);
}
public static uint ToUINTLittleEndian(this byte[] self){
if (!BitConverter.IsLittleEndian)
{
Array.Reverse(self);
}
return BitConverter.ToUInt32(self, 0);
}
public static byte[] ToBytes(this uint[] uintArray)
{
int byteCount = uintArray.Length * sizeof(uint);
byte[] byteArray = new byte[byteCount];
for (int i = 0; i < uintArray.Length; i++)
{
byte[] tempBytes = BitConverter.GetBytes(uintArray[i]);
Array.Copy(tempBytes, 0, byteArray, i * sizeof(uint), sizeof(uint));
}
return byteArray;
}
/// <summary>
/// convert and resize byte array,such as uint is 0x00FF7799 => byte array {0xFF,0x77,0x99}
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static byte[] ToBytesAndResizeArray(this uint self){
byte[] byteArray = BitConverter.GetBytes(self);
if (BitConverter.IsLittleEndian)
{
Array.Reverse(byteArray);
}
int startIndex = Array.FindIndex(byteArray, b => b != 0);
if (startIndex == -1)
{
byteArray = new byte[1];
}
else
{
byteArray = byteArray.Skip(startIndex).ToArray();
}
return byteArray;
}
public static byte[] ToByteArray(this bool[] boolArray)
{
int numBool = boolArray.Length;
int numBytes = (numBool + 7) / 8;
byte[] byteArray = new byte[numBytes];
for (int i = 0; i < numBool; i++)
{
int byteIndex = i / 8;
int bitIndex = i % 8;
if (boolArray[i])
{
byteArray[byteIndex] |= (byte)(1 << bitIndex);
}
}
return byteArray;
}
public static bool[] ToBoolArray(this byte[] byteArray)
{
bool[] boolArray = new bool[byteArray.Length * 8];
for (int i = 0; i < byteArray.Length; i++)
{
byte currentByte = byteArray[i];
for (int j = 0; j < 8; j++)
{
boolArray[i * 8 + j] = (currentByte & (1 << j)) != 0;
}
}
return boolArray;
}
public static bool[] ToBoolArray(this byte byteData)
{
bool[] boolArray = new bool[8];
byte currentByte = byteData;
for (int j = 0; j < 8; j++)
{
boolArray[j] = (currentByte & (1 << j)) != 0;
}
return boolArray;
}
public static bool[] ToBoolArray(this int value)
{
string binaryString = Convert.ToString(value, 2);
bool[] boolArray = new bool[binaryString.Length];
if(binaryString.Length < 8){
boolArray = new bool[8];
}
for (int i = 0; i < binaryString.Length; i++)
{
boolArray[binaryString.Length - i - 1] = binaryString[i] == '1';
}
return boolArray;
}
public static int ToInt(this bool[] boolArray)
{
int result = 0;
for (int i = 0; i < boolArray.Length; i++)
{
if (boolArray[i])
{
result |= (1 << i);
}
}
return result;
}
public static ushort[] ToUShortArray(this byte[] byteArray){
ushort[] ushortArray = new ushort[byteArray.Length / 2];
for (int i = 0, j = 0; i < byteArray.Length; i += 2, j++)
{
ushortArray[j] = (ushort)((byteArray[i] << 8) | byteArray[i + 1]);
}
return ushortArray;
}
public static byte[] ToByteArray(this float[] floatArray)
{
byte[] byteArray = new byte[floatArray.Length * 4];
for (int i = 0; i < floatArray.Length; i++)
{
byte[] tempArray = BitConverter.GetBytes(floatArray[i]);
if(!BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray); // 大端序需要反转字节数组以满足高字节在后
Array.Copy(tempArray, 0, byteArray, i * 4, 4);
}
return byteArray;
}
public static byte[] ToByteArray(this float value)
{
byte[] byteArray = new byte[4];
byte[] tempArray = BitConverter.GetBytes(value);
if(!BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray); // 大端序需要反转字节数组以满足高字节在后
Array.Copy(tempArray, 0, byteArray, 0, 4);
return byteArray;
}
public static byte[] ToByteArrayBigEndian(this float value)
{
byte[] byteArray = new byte[4];
byte[] tempArray = BitConverter.GetBytes(value);
if(BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray); // 大端序需要反转字节数组以满足高字节在后
Array.Copy(tempArray, 0, byteArray, 0, 4);
return byteArray;
}
public static float[] ToFloatArray(this byte[] byteArray)
{
float[] floatArray = new float[byteArray.Length / 4];
for (int i = 0; i < floatArray.Length; i++)
{
byte[] tempArray = new byte[4];
Array.Copy(byteArray, i * 4, tempArray, 0, 4);
if(!BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray);
floatArray[i] = BitConverter.ToSingle(tempArray, 0);
}
return floatArray;
}
public static float[] ToFloatArrayBigEndian(this byte[] byteArray)
{
float[] floatArray = new float[byteArray.Length / 4];
for (int i = 0; i < floatArray.Length; i++)
{
byte[] tempArray = new byte[4];
Array.Copy(byteArray, i * 4, tempArray, 0, 4);
if(BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray);
floatArray[i] = BitConverter.ToSingle(tempArray, 0);
}
return floatArray;
}
public static double[] ToDoubleArray(this byte[] byteArray)
{
double[] doubleArray = new double[byteArray.Length / 8];
for (int i = 0; i < doubleArray.Length; i++)
{
byte[] tempArray = new byte[8];
Array.Copy(byteArray, i * 8, tempArray, 0, 8);
if(!BitConverter.IsLittleEndian){
Array.Reverse(tempArray);
}
//Array.Reverse(tempArray);
doubleArray[i] = BitConverter.ToDouble(tempArray, 0);
}
return doubleArray;
}
public static byte[] ToByteArray(this int[] intArray)
{
byte[] byteArray = new byte[intArray.Length * 4];
for (int i = 0; i < intArray.Length; i++)
{
byte[] tempArray = BitConverter.GetBytes(intArray[i]);
//Array.Reverse(tempArray); // 大端序需要反转字节数组以满足高字节在后
Array.Copy(tempArray, 0, byteArray, i * 4, 4);
}
return byteArray;
}
public static byte[] Reverse(this byte[] bytes){
Array.Reverse(bytes);
return bytes;
}
public static byte[] ToSubByte(this byte[] bytes,int index,int length){
byte[] resultByte = new byte[length];
Array.Copy(bytes,index,resultByte,0,length);
return resultByte;
}
public static float[] ToSubFloat(this float[] floats,int index,int length){
float[] resultFloats = new float[length];
Array.Copy(floats,index,resultFloats,0,length);
return resultFloats;
}
public static float[] ToSubArrayByCount(this float[] originalArray, int targetLength)
{
float[] reducedArray = new float[targetLength];
float ratio = (float)(originalArray.Length - 1) / (targetLength - 1);
for (int i = 0; i < targetLength; i++)
{
int originalIndex = (int)Math.Round(ratio * i);
reducedArray[i] = originalArray[originalIndex];
}
return reducedArray;
}
}
}

154
EGFramework/Module/Extension/EGCrcExtension.cs

@ -0,0 +1,154 @@ @@ -0,0 +1,154 @@
using System;
using System.Security.Cryptography;
namespace EGFramework{
public static class EGCrcModbusExtension
{
/// CRC calculate is a common device verify algorithm
/// use
// hex = {0x80,0x05};
// Polynomial = x^16+x^15+x^2+1 = 1 80 05
public const ushort CRC_16_Modbus_Polynomial = 0x8005;
// hex = {0xFF,0xFF}
public const ushort CRC_16_Modbus_Start = 0xFFFF;
// hex = {0x00,0x00}
public const ushort CRC_16_Modbus_ResultXOR = 0x0000;
private static readonly ushort[] Crc_16_Table_Modbus ={
0x00,0xC0C1,0xC181,0x140,0xC301,0x3C0,0x280,0xC241,0xC601,0x6C0,0x780,0xC741,0x500,0xC5C1,0xC481,0x440,
0xCC01,0xCC0,0xD80,0xCD41,0xF00,0xCFC1,0xCE81,0xE40,0xA00,0xCAC1,0xCB81,0xB40,0xC901,0x9C0,0x880,0xC841,
0xD801,0x18C0,0x1980,0xD941,0x1B00,0xDBC1,0xDA81,0x1A40,0x1E00,0xDEC1,0xDF81,0x1F40,0xDD01,0x1DC0,0x1C80,0xDC41,
0x1400,0xD4C1,0xD581,0x1540,0xD701,0x17C0,0x1680,0xD641,0xD201,0x12C0,0x1380,0xD341,0x1100,0xD1C1,0xD081,0x1040,
0xF001,0x30C0,0x3180,0xF141,0x3300,0xF3C1,0xF281,0x3240,0x3600,0xF6C1,0xF781,0x3740,0xF501,0x35C0,0x3480,0xF441,
0x3C00,0xFCC1,0xFD81,0x3D40,0xFF01,0x3FC0,0x3E80,0xFE41,0xFA01,0x3AC0,0x3B80,0xFB41,0x3900,0xF9C1,0xF881,0x3840,
0x2800,0xE8C1,0xE981,0x2940,0xEB01,0x2BC0,0x2A80,0xEA41,0xEE01,0x2EC0,0x2F80,0xEF41,0x2D00,0xEDC1,0xEC81,0x2C40,
0xE401,0x24C0,0x2580,0xE541,0x2700,0xE7C1,0xE681,0x2640,0x2200,0xE2C1,0xE381,0x2340,0xE101,0x21C0,0x2080,0xE041,
0xA001,0x60C0,0x6180,0xA141,0x6300,0xA3C1,0xA281,0x6240,0x6600,0xA6C1,0xA781,0x6740,0xA501,0x65C0,0x6480,0xA441,
0x6C00,0xACC1,0xAD81,0x6D40,0xAF01,0x6FC0,0x6E80,0xAE41,0xAA01,0x6AC0,0x6B80,0xAB41,0x6900,0xA9C1,0xA881,0x6840,
0x7800,0xB8C1,0xB981,0x7940,0xBB01,0x7BC0,0x7A80,0xBA41,0xBE01,0x7EC0,0x7F80,0xBF41,0x7D00,0xBDC1,0xBC81,0x7C40,
0xB401,0x74C0,0x7580,0xB541,0x7700,0xB7C1,0xB681,0x7640,0x7200,0xB2C1,0xB381,0x7340,0xB101,0x71C0,0x7080,0xB041,
0x5000,0x90C1,0x9181,0x5140,0x9301,0x53C0,0x5280,0x9241,0x9601,0x56C0,0x5780,0x9741,0x5500,0x95C1,0x9481,0x5440,
0x9C01,0x5CC0,0x5D80,0x9D41,0x5F00,0x9FC1,0x9E81,0x5E40,0x5A00,0x9AC1,0x9B81,0x5B40,0x9901,0x59C0,0x5880,0x9841,
0x8801,0x48C0,0x4980,0x8941,0x4B00,0x8BC1,0x8A81,0x4A40,0x4E00,0x8EC1,0x8F81,0x4F40,0x8D01,0x4DC0,0x4C80,0x8C41,
0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040,
};
public static ushort CalculateCRC16Modbus(this byte[] bytes)
{
CRC16 provider = new CRC16(Crc_16_Table_Modbus);
byte[] hash = provider.ComputeHash(bytes);
ushort crc16 = BitConverter.ToUInt16(hash, 0);
ushort reversedResult = (ushort)((crc16 >> 8) | (crc16 << 8));
return reversedResult;
}
}
public static class EGCrcUtility
{
//Crc with table
public static uint CalculateCrc(byte[] data, uint initialValue, uint xorValue, bool inputReverse, bool outputReverse,uint[] CrcTable)
{
uint crc = initialValue;
for (int i = 0; i < data.Length; i++)
{
if (inputReverse)
data[i] = ReverseBits(data[i]);
crc ^= (uint)(data[i] << 24);
for (int j = 0; j < 8; j++)
{
crc = (crc << 8) ^ CrcTable[crc >> 24];
}
}
if (outputReverse)
crc = ReverseBits(crc);
return crc ^ xorValue;
}
//Crc without table
public static uint CalculateCrc(byte[] data, uint polynomial, uint initialValue, uint xorValue, bool inputReverse, bool outputReverse)
{
uint crc = initialValue;
for (int i = 0; i < data.Length; i++)
{
if (inputReverse)
data[i] = ReverseBits(data[i]);
crc ^= (uint)(data[i] << 24);
for (int j = 0; j < 8; j++)
{
if ((crc & 0x80000000) != 0)
{
crc = (crc << 1) ^ polynomial;
}
else
{
crc <<= 1;
}
}
}
if (outputReverse)
crc = ReverseBits(crc);
return crc ^ xorValue;
}
private static uint ReverseBits(uint value)
{
uint result = 0;
for (int i = 0; i < 8; i++)
{
result = (result << 1) | ((value >> i) & 1);
}
return result;
}
private static byte ReverseBits(byte value)
{
byte result = 0;
for (int i = 0; i < 8; i++)
{
result = (byte)((result << 1) | ((value >> i) & 1));
}
return result;
}
}
public class CRC16 : HashAlgorithm
{
private const ushort polynomial = 0x8005;
private ushort[] table = new ushort[256];
private ushort crc = 0xFFFF;
public CRC16(ushort[] table)
{
HashSizeValue = 16;
this.table = table;
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
for (int i = ibStart; i < ibStart + cbSize; i++)
{
byte index = (byte)(crc ^ array[i]);
crc = (ushort)((crc >> 8) ^ table[index]);
}
}
protected override byte[] HashFinal()
{
return BitConverter.GetBytes(crc);
}
public override void Initialize()
{
crc = ushort.MaxValue;
}
}
}

31
EGFramework/Module/Extension/EGDateTimeExtension.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
using System;
namespace EGFramework{
public static class EGDateTimeExtension
{
public static string GetFullDateMsg(this IEGFramework self)
{
return DateTime.Now.ToString("yyyy-MM-dd") + " " + DateTime.Now.ToString("HH:mm:ss");
}
public static string GetDayDateMsg(this IEGFramework self)
{
return DateTime.Now.ToString("HH:mm:ss");
}
public static long GetDateTime(this object self)
{
DateTime dt = DateTime.Now;
return dt.Ticks;
}
public static string GetFullDateMsg(this long ticks){
DateTime dateTime = new DateTime(ticks);
return dateTime.ToString("yyyy-MM-dd") + " " + dateTime.ToString("HH:mm:ss");
}
public static string GetDayDateMsg(this long ticks){
DateTime dateTime = new DateTime(ticks);
return dateTime.ToString("HH:mm:ss");
}
public static string GetDateMsg(this long ticks){
DateTime dateTime = new DateTime(ticks);
return dateTime.ToString("yyyy-MM-dd");
}
}
}

78
EGFramework/Module/Extension/EGEncodingExtension.cs

@ -0,0 +1,78 @@ @@ -0,0 +1,78 @@
using System.Text;
namespace EGFramework{
//use this extension,you should add System.Text.Encoding.CodePages package from Nuget
public static class EGEncodingExtension
{
public static bool IsInit{ set; get; }
/// <summary>
/// get encoding from encoding params(string).
/// </summary>
/// <param name="self"></param>
/// <param name="encodingTxt"></param>
/// <returns></returns>
public static Encoding GetEncoding(this IEGFramework self,string encodingTxt){
if(!IsInit){
IsInit = true;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
return Encoding.GetEncoding(encodingTxt);
}
/// <summary>
/// Make a string to bytes with encoding params(string).
/// </summary>
/// <param name="self"></param>
/// <param name="encodingTxt"></param>
/// <returns></returns>
public static byte[] ToBytesByEncoding(this string self,string encodingTxt){
if(!IsInit){
IsInit = true;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
return Encoding.GetEncoding(encodingTxt).GetBytes(self);
}
/// <summary>
/// Make a string to bytes with encoding.
/// </summary>
/// <param name="self"></param>
/// <param name="encoding"></param>
/// <returns></returns>
public static byte[] ToBytesByEncoding(this string self,Encoding encoding){
if(!IsInit){
IsInit = true;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
return encoding.GetBytes(self);
}
/// <summary>
/// Make a bytes to string with encoding params(string).
/// </summary>
/// <param name="self"></param>
/// <param name="encodingTxt"></param>
/// <returns></returns>
public static string ToStringByEncoding(this byte[] self,string encodingTxt){
if(!IsInit){
IsInit = true;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
return Encoding.GetEncoding(encodingTxt).GetString(self);
}
/// <summary>
/// Make a bytes to string with encoding.
/// </summary>
/// <param name="self"></param>
/// <param name="encodingTxt"></param>
/// <returns></returns>
public static string ToStringByEncoding(this byte[] self,Encoding encoding){
if(!IsInit){
IsInit = true;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
}
return encoding.GetString(self);
}
}
}

54
EGFramework/Module/Extension/EGIpExtension.cs

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
namespace EGFramework {
public static class EGIpExtension
{
/// <summary>
/// Get host from IP. Such as 192.168.0.1:5555 => get 192.168.0.1
/// </summary>
/// <param name="self"></param>
/// <returns></returns>
public static string GetHostByIp(this string ip)
{
int colonIndex = ip.IndexOf(":");
string host = "";
if (colonIndex != -1)
{
host = ip.Substring(0, colonIndex);
}
return host;
}
public static int GetPortByIp(this string ip)
{
int colonIndex = ip.IndexOf(":");
string portString = ip.Substring(colonIndex + 1);
int port;
if (int.TryParse(portString, out port))
{
//nothing to do
}
else
{
port = 0;
}
return port;
}
public static string GetStrFrontSymbol(this string str,char symbol){
int colonIndex = str.IndexOf(symbol);
string frontStr = "";
if (colonIndex != -1)
{
frontStr = str.Substring(0, colonIndex);
}
return frontStr;
}
public static string GetStrBehindSymbol(this string str,char symbol){
int colonIndex = str.IndexOf(symbol);
string behindStr = str.Substring(colonIndex + 1);
return behindStr;
}
}
}

146
EGFramework/Module/Extension/EGSqlExtension.cs

@ -0,0 +1,146 @@ @@ -0,0 +1,146 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace EGFramework
{
public static class EGSqlExtension
{
public static string ToCreateTableSQL(this PropertyInfo property)
{
string sqlCommand;
if (property.Name == "ID" || property.Name == "id" || property.Name == "Id")
{
return "";
}
if (property.PropertyType == typeof(int) || property.PropertyType.IsEnum)
{
sqlCommand = "`" + property.Name + "` INTEGER" + " NOT NULL,";
}
else if (property.PropertyType == typeof(double) || property.PropertyType == typeof(float))
{
sqlCommand = "`" + property.Name + "` REAL" + " NOT NULL,";
}
else if (property.PropertyType == typeof(bool))
{
sqlCommand = "`" + property.Name + "` REAL" + " NOT NULL,";
}
else if (property.PropertyType == typeof(long))
{
sqlCommand = "`" + property.Name + "` BIGINT(20)" + " NOT NULL,";
}
else if (property.PropertyType == typeof(string))
{
sqlCommand = "`" + property.Name + "` VARCHAR(255)" + " NOT NULL,";
}
else
{
sqlCommand = "`" + property.Name + "` VARCHAR(255)" + " NOT NULL,";
}
return sqlCommand;
}
public static string ToCreateTableSQL(this FieldInfo field)
{
string sqlCommand;
if (field.Name == "ID" || field.Name == "id" || field.Name == "Id")
{
return "";
}
if (field.FieldType == typeof(int) || field.FieldType.IsEnum)
{
sqlCommand = "`" + field.Name + "` INTEGER" + " NOT NULL,";
}
else if (field.FieldType == typeof(double) || field.FieldType == typeof(float))
{
sqlCommand = "`" + field.Name + "` REAL" + " NOT NULL,";
}
else if (field.FieldType == typeof(bool))
{
sqlCommand = "`" + field.Name + "` REAL" + " NOT NULL,";
}
else if (field.FieldType == typeof(long))
{
sqlCommand = "`" + field.Name + "` BIGINT(20)" + " NOT NULL,";
}
else if (field.FieldType == typeof(string))
{
sqlCommand = "`" + field.Name + "` VARCHAR(255)" + " NOT NULL,";
}
else
{
sqlCommand = "`" + field.Name + "` VARCHAR(255)" + " NOT NULL,";
}
return sqlCommand;
}
public static string ToCreateTableSQL(this KeyValuePair<string, Type> param)
{
string sqlCommand;
if (param.Key == "ID" || param.Key == "id" || param.Key == "Id")
{
return "";
}
if (param.Value == typeof(int) || param.Value.IsEnum)
{
sqlCommand = "`" + param.Key + "` INTEGER" + " NOT NULL,";
}
else if (param.Value == typeof(double) || param.Value == typeof(float))
{
sqlCommand = "`" + param.Key + "` REAL" + " NOT NULL,";
}
else if (param.Value == typeof(bool))
{
sqlCommand = "`" + param.Key + "` REAL" + " NOT NULL,";
}
else if (param.Value == typeof(long))
{
sqlCommand = "`" + param.Key + "` BIGINT(20)" + " NOT NULL,";
}
else if (param.Value == typeof(string))
{
sqlCommand = "`" + param.Key + "` VARCHAR(255)" + " NOT NULL,";
}
else
{
sqlCommand = "`" + param.Key + "` VARCHAR(255)" + " NOT NULL,";
}
return sqlCommand;
}
public static string ToCreateTableSQL(this Type type, string tableName)
{
var properties = type.GetProperties();
FieldInfo[] fields = type.GetFields();
string keySet = "";
foreach (PropertyInfo key in properties)
{
keySet += key.ToCreateTableSQL();
}
foreach (FieldInfo key in fields)
{
keySet += key.ToCreateTableSQL();
}
keySet = keySet.TrimEnd(',');
string createSql = @"CREATE TABLE " + tableName + " (" +
"`ID` INTEGER PRIMARY KEY AUTO_INCREMENT, " + keySet
+ ");";
return createSql;
}
public static string ToCreateTableSQL(this Dictionary<string,Type> tableParam,string tableName)
{
string keySet = "";
foreach(KeyValuePair<string,Type> key in tableParam){
keySet += key.ToCreateTableSQL();
}
keySet = keySet.TrimEnd(',');
string createSql = @"CREATE TABLE "+tableName+" ("+
"`ID` INTEGER PRIMARY KEY AUTOINCREMENT, "+keySet
+");";
return createSql;
}
}
}

16
EGFramework/Module/GenerateTools/EGGenerate.cs

@ -0,0 +1,16 @@ @@ -0,0 +1,16 @@
namespace EGFramework
{
public class EGGenerate : EGModule
{
public override void Init()
{
}
public T GenerateUI<T>(object data) where T : new()
{
T ui = new T();
return ui;
}
}
}

34
EGFramework/Module/GenerateTools/GenerateToolsInterface.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
namespace EGFramework
{
public interface IGenerateToolsInterface
{
public string GenerateCode<T>();
}
public interface IGodotTable
{
}
public interface IGodotRowData
{
}
public interface ITableData
{
/// <summary>
/// Get the data of the table.
/// </summary>
/// <returns></returns>
string[][] GetTableData();
/// <summary>
/// Get the header of the table.
/// </summary>
/// <returns></returns>
string[] GetTableHeader();
}
public interface ITableRowData
{
string[] GetRowData();
}
}

90
EGFramework/Module/GenerateTools/Templete/Code/EGSvgGenerator.cs

@ -0,0 +1,90 @@ @@ -0,0 +1,90 @@
namespace EGFramework.Code{
public class EGSvgGenerator : IGenerateToolsInterface
{
public string SvgHeader { get ; private set;}
public const string SvgFooter = "</svg>";
public int Width { get; set; }
public int Height { get; set; }
public EGSvgViewBox ViewBox { get; set; }
public EGSvgGenerator(int width, int height, EGSvgViewBox viewBox)
{
Width = width;
Height = height;
ViewBox = viewBox;
SvgHeader = $"<svg width=\"{width}\" height=\"{height}\" viewBox=\"{viewBox.X} {viewBox.Y} {viewBox.Width} {viewBox.Height}\" xmlns=\"http://www.w3.org/2000/svg\">";
}
public void DrawCircle(float x, float y, float radius, string color)
{
// Implementation for drawing a circle in SVG format
string svgCircle = $"<circle cx=\"{x}\" cy=\"{y}\" r=\"{radius}\" fill=\"{color}\" />";
}
public void DrawEllipse(float cx, float cy, float rx, float ry, string color)
{
// Implementation for drawing an ellipse in SVG format
string svgEllipse = $"<ellipse cx=\"{cx}\" cy=\"{cy}\" rx=\"{rx}\" ry=\"{ry}\" fill=\"{color}\" />";
}
public void DrawPolygon(float[] points, string color)
{
// Implementation for drawing a polygon in SVG format
string svgPolygon = "<polygon points=\"";
for (int i = 0; i < points.Length; i += 2)
{
svgPolygon += $"{points[i]},{points[i + 1]} ";
}
svgPolygon += $"\" fill=\"{color}\" />";
}
public void DrawPolyline(float[] points, string color)
{
// Implementation for drawing a polyline in SVG format
string svgPolyline = "<polyline points=\"";
for (int i = 0; i < points.Length; i += 2)
{
svgPolyline += $"{points[i]},{points[i + 1]} ";
}
svgPolyline += $"\" stroke=\"{color}\" fill=\"none\" />";
}
public void DrawPath(string d, string color)
{
// Implementation for drawing a path in SVG format
string svgPath = $"<path d=\"{d}\" fill=\"{color}\" />";
}
public void DrawRectangle(float x, float y, float width, float height, string color)
{
// Implementation for drawing a rectangle in SVG format
string svgRectangle = $"<rect x=\"{x}\" y=\"{y}\" width=\"{width}\" height=\"{height}\" fill=\"{color}\" />";
}
public void DrawLine(float x1, float y1, float x2, float y2, string color)
{
// Implementation for drawing a line in SVG format
string svgLine = $"<line x1=\"{x1}\" y1=\"{y1}\" x2=\"{x2}\" y2=\"{y2}\" stroke=\"{color}\" />";
}
public void DrawText(float x, float y, string text, string color)
{
// Implementation for drawing text in SVG format
string svgText = $"<text x=\"{x}\" y=\"{y}\" fill=\"{color}\">{text}</text>";
}
public string GenerateCode<T>()
{
return typeof(T).Name;
}
}
public struct EGSvgViewBox {
public float X { get; set; }
public float Y { get; set; }
public float Width { get; set; }
public float Height { get; set; }
public EGSvgViewBox(float x, float y, float width, float height)
{
X = x;
Y = y;
Width = width;
Height = height;
}
}
}

11
EGFramework/Module/GenerateTools/Templete/Code/EGSvgTempletes.cs

@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
namespace EGFramework
{
public static class EGSVG16PX
{
public const string Circle = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><circle cx=\"24\" cy=\"24\" r=\"20\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"3\"/></svg>";
public const string Rect = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M39 6H9C7.34315 6 6 7.34315 6 9V39C6 40.6569 7.34315 42 9 42H39C40.6569 42 42 40.6569 42 39V9C42 7.34315 40.6569 6 39 6Z\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"3\"/></svg>";
public const string Heart = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M15 8C8.92487 8 4 12.9249 4 19C4 30 17 40 24 42.3262C31 40 44 30 44 19C44 12.9249 39.0751 8 33 8C29.2797 8 25.9907 9.8469 24 12.6738C22.0093 9.8469 18.7203 8 15 8Z\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"miter\"/></svg>";
public const string Star = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><svg width=\"48\" height=\"48\" viewBox=\"0 0 48 48\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M23.9986 5L17.8856 17.4776L4 19.4911L14.0589 29.3251L11.6544 43L23.9986 36.4192L36.3454 43L33.9586 29.3251L44 19.4911L30.1913 17.4776L23.9986 5Z\" fill=\"none\" stroke=\"#ffffff\" stroke-width=\"3\" stroke-linejoin=\"miter\"/></svg>";
}
}

71
EGFramework/Module/GenerateTools/Templete/Variant/EGDataStruct.cs

@ -0,0 +1,71 @@ @@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
namespace EGFramework
{
public struct EGSelectParam
{
public int SelectID { set; get; }
public Dictionary<int, string> SelectList { set; get; }
public EGSelectParam(int selectID, Dictionary<int, string> selectList)
{
SelectID = selectID;
SelectList = selectList;
}
}
public struct EGRangeParam
{
public double Min { set; get; }
public double Max { set; get; }
public double Step { set; get; }
public double Value { set; get; }
public EGRangeParam(double min, double max, double step, double value)
{
Min = min;
Max = max;
Step = step;
Value = value;
}
}
public struct EGPathSelect
{
public string Path { set; get; }
public bool IsDir { set; get; }
public override string ToString()
{
return Path;
}
public EGPathSelect() { Path = ""; IsDir = false; }
public EGPathSelect(string path)
{
this.Path = path;
this.IsDir = false;
}
public EGPathSelect(string path, bool isDir)
{
this.Path = path;
this.IsDir = isDir;
}
}
public interface IEGReadOnlyString
{
public string GetString();
}
public struct EGReadOnlyString : IEGReadOnlyString
{
public string Value { get; private set; }
public EGReadOnlyString(string value)
{
Value = value;
}
public string GetString()
{
return Value;
}
}
}

127
EGFramework/Module/GenerateTools/Templete/Variant/EGTree.cs

@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
namespace EGFramework
{
public interface IEGTree
{
public string Name { set; get; }
public IEGTree GetParent();
public void SetParent(IEGTree tree);
public IEnumerable<IEGTree> GetChilds();
public void AppendTree(IEGTree tree);
}
public class EGTree : IEGTree
{
public string Name { set; get; }
public string StrValue { set; get; }
public long IntegerValue { set; get; }
public byte[] ByteValue { set; get; }
public float FloatValue { set; get; }
public bool BoolValue { set; get; }
public IEGTree Parent { set; get; }
public List<IEGTree> Childs { set; get; } = new List<IEGTree>();
public EGTree()
{
}
public EGTree(string name)
{
this.Name = name;
}
public void AppendTree(IEGTree tree)
{
tree.SetParent(this);
Childs.Add(tree);
}
public virtual IEnumerable<IEGTree> GetChilds()
{
return Childs;
}
public virtual IEGTree GetParent()
{
return Parent;
}
public void SetParent(IEGTree tree)
{
this.Parent = tree;
}
}
public static class EGTreeFactory
{
public static EGTree CreateTreeByJson(string json)
{
JsonTextReader reader = new JsonTextReader(new StringReader(json));
Stack<IEGTree> TreeStack = new Stack<IEGTree>();
EGTree resultTree = new EGTree();
EGTree lastTree = null;
while (reader.Read())
{
if (reader.TokenType == JsonToken.StartObject)
{
if (lastTree != null)
{
TreeStack.Push(lastTree);
}
}
if (reader.TokenType == JsonToken.EndObject)
{
if(TreeStack.Count>0)
TreeStack.Pop();
}
if (reader.TokenType == JsonToken.PropertyName)
{
EGTree newTree = new EGTree();
if (reader.Value != null)
{
newTree.Name = reader.Value.ToString();
}
if (TreeStack.Count > 0)
{
TreeStack.Peek().AppendTree(newTree);
}
else
{
resultTree.AppendTree(newTree);
}
lastTree = newTree;
}
if (lastTree != null && reader.TokenType == JsonToken.Integer)
{
lastTree.IntegerValue = (long)reader.Value;
}
if (lastTree != null && reader.TokenType == JsonToken.Boolean)
{
lastTree.BoolValue = (bool)reader.Value;
}
if (lastTree != null && reader.TokenType == JsonToken.String)
{
lastTree.StrValue = (string)reader.Value;
}
if (lastTree != null && reader.TokenType == JsonToken.Float)
{
lastTree.FloatValue = (float)reader.Value;
}
if (lastTree!=null && reader.TokenType == JsonToken.Bytes)
{
lastTree.ByteValue = (byte[])reader.Value;
}
}
return resultTree;
}
}
}

127
EGFramework/Module/GenerateTools/Templete/Variant/EGVariantGenerator.cs

@ -0,0 +1,127 @@ @@ -0,0 +1,127 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace EGFramework{
public static class EGenerateVariant
{
public static Dictionary<string, object> EGenerateDictiontaryByType(this Type self)
{
PropertyInfo[] propertyNames = self.GetProperties();
FieldInfo[] fieldNames = self.GetFields();
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (PropertyInfo pName in propertyNames)
{
result.Add(pName.Name, pName.Name);
}
foreach (FieldInfo fName in fieldNames)
{
result.Add(fName.Name, fName.Name);
}
return result;
}
public static Dictionary<string, object> EGenerateEmptyDictiontaryByType(this Type self)
{
PropertyInfo[] propertyNames = self.GetProperties();
FieldInfo[] fieldNames = self.GetFields();
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (PropertyInfo pName in propertyNames)
{
result.Add(pName.Name, "");
}
foreach (FieldInfo fName in fieldNames)
{
result.Add(fName.Name, "");
}
return result;
}
public static Dictionary<string, Type> EGenerateTypeDictiontaryByType(this Type self)
{
PropertyInfo[] propertyNames = self.GetProperties();
FieldInfo[] fieldNames = self.GetFields();
Dictionary<string, Type> result = new Dictionary<string, Type>();
foreach (PropertyInfo pName in propertyNames)
{
result.Add(pName.Name, pName.PropertyType);
}
foreach (FieldInfo fName in fieldNames)
{
result.Add(fName.Name, fName.FieldType);
}
return result;
}
public static Dictionary<string, object> EGenerateDictiontaryByObject<T>(this T self)
{
PropertyInfo[] propertyNames = typeof(T).GetProperties();
FieldInfo[] fieldNames = typeof(T).GetFields();
// object[] s = propertyNames.Select(p => p.GetValue(self)).ToArray();
// object[] a = fieldNames.Select(p => p.GetValue(self)).ToArray();
Dictionary<string, object> result = new Dictionary<string, object>();
foreach (PropertyInfo pName in propertyNames)
{
object p = pName.GetValue(self);
result.Add(pName.Name, p);
}
foreach (FieldInfo fName in fieldNames)
{
object p = fName.GetValue(self);
result.Add(fName.Name, p);
}
return result;
}
public static List<Dictionary<string, object>> EGenerateDictionaryByGroup<T>(this IEnumerable<T> self)
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
PropertyInfo[] propertyNames = typeof(T).GetProperties();
FieldInfo[] fieldNames = typeof(T).GetFields();
foreach (T member in self)
{
Dictionary<string, object> mResult = new Dictionary<string, object>();
foreach (PropertyInfo pName in propertyNames)
{
object p = pName.GetValue(member);
mResult.Add(pName.Name, p);
}
foreach (FieldInfo fName in fieldNames)
{
object p = fName.GetValue(member);
mResult.Add(fName.Name, p);
}
result.Add(mResult);
}
return result;
}
//Default primary key is id,Id,ID.
public static string EGetDefaultPrimaryKey(this Dictionary<string, object> self)
{
foreach (KeyValuePair<string, object> param in self)
{
if (param.Key == "ID" || param.Key == "Id" || param.Key == "id")
{
return param.Key;
}
}
return "";
}
public static List<Dictionary<string, object>> ESearchByKeyword(this List<Dictionary<string, object>> data, string fieldName, string keyWords)
{
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
foreach (Dictionary<string, object> tablerow in data)
{
if (tablerow.ContainsKey(fieldName))
{
if (tablerow[fieldName].ToString().Contains(keyWords))
{
result.Add(tablerow);
}
}
}
return result;
}
}
}

280
EGFramework/Module/OtherTools/EGModbus.cs

@ -0,0 +1,280 @@ @@ -0,0 +1,280 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace EGFramework{
/// <summary>
/// This class is not a simple protocol tools,only support sample functions to easy use.
/// </summary>
public class EGModbus : IEGFramework, IModule
{
public ConcurrentQueue<ModbusRTU_Response?> RTUCache = new ConcurrentQueue<ModbusRTU_Response?>();
public ConcurrentQueue<ModbusTCP_Response?> TCPCache = new ConcurrentQueue<ModbusTCP_Response?>();
public int Delay = 2000;
public ConcurrentQueue<int> WaitForSendRTU = new ConcurrentQueue<int>();
public int NextSendRTU = 0;
public int SendPointerRTU = 1;
public ConcurrentQueue<int> WaitForSendTCP = new ConcurrentQueue<int>();
public int NextSendTCP = 0;
public int SendPointerTCP = 1;
public EasyEvent OnReadTimeOut = new EasyEvent();
public void Init()
{
this.EGRegisterMessageEvent<ModbusRTU_Response>((e,sender,ProtocolType)=>{
if(ProtocolType == ProtocolType.SerialPort){
RTUCache.Enqueue(e);
}
});
this.EGRegisterMessageEvent<ModbusTCP_Response>((e,sender,ProtocolType)=>{
if(ProtocolType == ProtocolType.TCPClient){
TCPCache.Enqueue(e);
}
});
this.EGOnMessage<ModbusRTU_Response>();
this.EGOnMessage<ModbusTCP_Response>();
}
#region Modbus RTU Operations
private bool IsRequestRTU { set; get; }
public async Task<ModbusRTU_Response?> ReadRTUAsync(ModbusRegisterType registerType,string serialPort,byte deviceAddress,ushort start,ushort count){
if(IsRequestRTU){
SendPointerRTU++;
int messageId = SendPointerRTU;
WaitForSendRTU.Enqueue(messageId);
await Task.Run(async () =>
{
while (IsRequestRTU || NextSendRTU != messageId)
{
await Task.Delay(10);
//break;
}
});
EG.Print("-----Read"+messageId+" ----");
//return null;
}
RTUCache.Clear();
IsRequestRTU = true;
IRequest ReadRequest;
ModbusRTU_Response? res = null;
switch(registerType){
case ModbusRegisterType.Coil:
ReadRequest = new ModbusRTU_ReadCoils(deviceAddress,start,count);
this.EGSendMessage(ReadRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(6+count/8);
break;
case ModbusRegisterType.DiscreteInput:
ReadRequest = new ModbusRTU_ReadDiscreteInput(deviceAddress,start,count);
this.EGSendMessage(ReadRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(6+count/8);
break;
case ModbusRegisterType.HoldingRegister:
ReadRequest = new ModbusRTU_ReadHoldingRegisters(deviceAddress,start,count);
this.EGSendMessage(ReadRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(5+count*2);
break;
case ModbusRegisterType.InputRegisters:
ReadRequest = new ModbusRTU_ReadInputRegisters(deviceAddress,start,count);
this.EGSendMessage(ReadRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(5+count*2);
break;
}
await Task.Run(async ()=>{
int timeout = 0;
while(RTUCache.Count==0 && timeout < Delay){
await Task.Delay(10);
timeout+=10;
}
if(RTUCache.Count>0){
RTUCache.TryDequeue(out res);
}else{
//Print Error Timeout
OnReadTimeOut.Invoke();
}
});
this.EGSerialPort().ClearReceivedCache(serialPort);
IsRequestRTU = false;
if(this.WaitForSendRTU.Count>0){
this.WaitForSendRTU.TryDequeue(out NextSendRTU);
}
return res;
}
public async Task<ModbusRTU_Response?> WriteOnceRTUAsync(ModbusRegisterType registerType,string serialPort,byte deviceAddress,ushort registerAddress,object value){
if(IsRequestRTU){
SendPointerRTU++;
int messageId = SendPointerRTU;
WaitForSendRTU.Enqueue(messageId);
await Task.Run(async () =>
{
while (IsRequestRTU || NextSendRTU != messageId)
{
await Task.Delay(10);
//break;
}
});
EG.Print("-----Write"+messageId+" ----");
//return null;
}
RTUCache.Clear();
IsRequestRTU = true;
IRequest WriteRequest;
ModbusRTU_Response? res = null;
switch(registerType){
case ModbusRegisterType.Coil:
WriteRequest = new ModbusRTU_WriteSingleCoil(deviceAddress,registerAddress,(bool)value);
this.EGSendMessage(WriteRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(WriteRequest.ToProtocolByteData().Length);
break;
case ModbusRegisterType.HoldingRegister:
WriteRequest = new ModbusRTU_WriteSingleHoldingRegister(deviceAddress,registerAddress,(ushort)value);
this.EGSendMessage(WriteRequest,serialPort,ProtocolType.SerialPort);
this.EGSerialPort().SetExpectReceivedDataLength(WriteRequest.ToProtocolByteData().Length);
break;
}
await Task.Run(async ()=>{
int timeout = 0;
while(RTUCache.Count==0 && timeout < Delay){
await Task.Delay(10);
timeout+=10;
}
if(RTUCache.Count>0){
RTUCache.TryDequeue(out res);
}else{
//Print Error Timeout
OnReadTimeOut.Invoke();
}
});
this.EGSerialPort().ClearReceivedCache(serialPort);
IsRequestRTU = false;
if(this.WaitForSendRTU.Count>0){
this.WaitForSendRTU.TryDequeue(out NextSendRTU);
}
return res;
}
#endregion
#region Modbus TCP Operations
private bool IsRequestTCP { set; get; }
public async Task<ModbusTCP_Response?> ReadTCPAsync(ModbusRegisterType registerType,string ipPort,byte deviceAddress,ushort start,ushort count){
if(IsRequestTCP){
SendPointerTCP++;
int messageId = SendPointerTCP;
WaitForSendTCP.Enqueue(messageId);
await Task.Run(async () =>
{
while (IsRequestTCP || NextSendTCP != messageId)
{
await Task.Delay(10);
//break;
}
});
EG.Print("-----Read"+messageId+" ----");
//return null;
}
TCPCache.Clear();
IsRequestTCP = true;
IRequest ReadRequest;
ModbusTCP_Response? res = null;
switch(registerType){
case ModbusRegisterType.HoldingRegister:
ReadRequest = new ModbusTCP_ReadHoldingRegisters(deviceAddress,start,count);
// this.AppendMessage("【发送-"+DataModbusItem.SerialPort+"】 "+ReadRequest.ToProtocolByteData().ToStringByHex());
this.EGSendMessage(ReadRequest,ipPort,ProtocolType.TCPClient);
break;
}
await Task.Run(async ()=>{
int timeout = 0;
while(TCPCache.Count == 0 && timeout < Delay){
await Task.Delay(10);
timeout += 10;
}
if(TCPCache.Count>0){
TCPCache.TryDequeue(out res);
}else{
//Print Error Timeout
OnReadTimeOut.Invoke();
}
});
IsRequestTCP = false;
if(this.WaitForSendTCP.Count>0){
this.WaitForSendTCP.TryDequeue(out NextSendTCP);
}
return res;
}
public async Task<ModbusTCP_Response?> WriteOnceTCPAsync(ModbusRegisterType registerType,string ipPort,byte deviceAddress,ushort registerAddress,object value){
if(IsRequestTCP){
SendPointerTCP++;
int messageId = SendPointerTCP;
WaitForSendTCP.Enqueue(messageId);
await Task.Run(async () =>
{
while (IsRequestTCP || NextSendTCP != messageId)
{
await Task.Delay(10);
//break;
}
});
EG.Print("-----Write"+messageId+" ----");
//return null;
}
TCPCache.Clear();
IsRequestTCP = true;
IRequest WriteRequest;
ModbusTCP_Response? res = null;
switch(registerType){
case ModbusRegisterType.Coil:
WriteRequest = new ModbusTCP_WriteSingleCoil(deviceAddress,registerAddress,(bool)value);
this.EGSendMessage(WriteRequest,ipPort,ProtocolType.TCPClient);
break;
case ModbusRegisterType.HoldingRegister:
if(value.GetType() == typeof(float)){
ushort[] writeData = ((float)value).ToByteArrayBigEndian().ToUShortArray();
WriteRequest = new ModbusTCP_WriteMultiHoldingRegister(deviceAddress,registerAddress,writeData);
}else{
WriteRequest = new ModbusTCP_WriteSingleHoldingRegister(deviceAddress,registerAddress,(ushort)value);
}
this.EGSendMessage(WriteRequest,ipPort,ProtocolType.TCPClient);
break;
}
await Task.Run(async ()=>{
int timeout = 0;
while(TCPCache.Count==0 && timeout < Delay){
await Task.Delay(10);
timeout+=10;
}
if(TCPCache.Count>0){
TCPCache.TryDequeue(out res);
}else{
//Print Error Timeout
OnReadTimeOut.Invoke();
}
});
IsRequestTCP = false;
if(this.WaitForSendTCP.Count>0){
this.WaitForSendTCP.TryDequeue(out NextSendTCP);
}
if(this.WaitForSendTCP.Count>0){
this.WaitForSendTCP.TryDequeue(out NextSendTCP);
}
return res;
}
#endregion
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGModbusExtension{
public static EGModbus EGModbus(this IEGFramework self){
return self.GetModule<EGModbus>();
}
}
}

245
EGFramework/Module/OtherTools/EGSqlite.cs

@ -0,0 +1,245 @@ @@ -0,0 +1,245 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.Data.Sqlite;
using Newtonsoft.Json;
namespace EGFramework{
public class EGSqlite : EGModule
{
public string DBName = "Default";
private string DefaultDBFolder = "SaveData";
public SqliteConnection SqliteConn;
public string ExceptionMsg;
public override void Init()
{
if (!Directory.Exists(DefaultDBFolder))
{
Directory.CreateDirectory(DefaultDBFolder);
}
InitDatabase(DBName);
}
public void InitDatabase(string dataBaseName)
{
SqliteConn = new SqliteConnection("Data Source="+DefaultDBFolder+"/"+dataBaseName+".db;Mode=ReadWriteCreate;"); // Open the connection:
try
{
SqliteConn.Open();
}
catch (Exception ex)
{
ExceptionMsg = ex.ToString();
}
}
//Save data to default sqlite database;
public void SaveData<TData>(TData data) where TData : new()
{
// if table is not exist, create table and insert data to table,else insert into data to table
if(IsTableExist<TData>()){
InsertData(data);
}else{
CreateTable<TData>();
InsertData(data);
}
}
/// <summary>
/// Get data from table where named type of TData
/// </summary>
/// <typeparam name="TData">Table name</typeparam>
/// <returns></returns>
public List<TData> GetDataSet<TData>() where TData : new()
{
// query dataSet from table TData_List
List<TData> dataSet = new List<TData>();
if(IsTableExist<TData>()){
dataSet = SelectData<TData>();
}else{
ExceptionMsg = "No such table,ensure one data with type of TData has been saved at least!";
return null;
}
return dataSet;
}
#region SQL Operation
/// <summary>
/// Create table where table name is type of TData
/// </summary>
/// <typeparam name="TData"></typeparam>
/// <returns></returns>
public string CreateTable<TData>() where TData: new() {
string result = "Success:";
try
{
string sqlCommand = "CREATE TABLE " + typeof(TData).Name;
sqlCommand += "(\"ID\" INTEGER NOT NULL UNIQUE,";
var properties = typeof(TData).GetProperties();
EG.Print(properties.Count() + " Readed ");
foreach(var property in properties){
if(property.PropertyType == typeof(int) || property.PropertyType == typeof(bool) || property.PropertyType.IsEnum){
sqlCommand += "\"" + property.Name + "\" INTEGER" + " NOT NULL,";
}else if(property.PropertyType == typeof(double) || property.PropertyType == typeof(float)){
sqlCommand += "\"" + property.Name + "\" REAL" + " NOT NULL,";
}
else{
sqlCommand += "\"" + property.Name + "\" TEXT" + " NOT NULL,";
}
}
sqlCommand += "PRIMARY KEY(\"ID\" AUTOINCREMENT))";
EG.Print(sqlCommand);
SqliteCommand createCommand = new SqliteCommand(sqlCommand,SqliteConn);
result = result + createCommand.ExecuteNonQuery().ToString();
}
catch (System.Exception e)
{
return "Error:"+e;
}
return result;
}
/// <summary>
/// Drop table where table name is type of TData
/// </summary>
/// <typeparam name="TData"></typeparam>
/// <returns></returns>
public string DropTable<TData>() where TData: new(){
string result = "Success:";
try
{
string sqlCommand = "DROP TABLE " + typeof(TData).Name;
SqliteCommand createCommand = new SqliteCommand(sqlCommand,SqliteConn);
result = result + createCommand.ExecuteNonQuery().ToString();
}
catch (System.Exception e)
{
return "Error:"+e;
}
return result;
}
/// <summary>
/// Insert data to table where table name is type of TData
/// </summary>
/// <param name="data"></param>
/// <typeparam name="TData"></typeparam>
/// <returns>success or error</returns>
public string InsertData<TData>(TData data) where TData: new(){
string result = "Success:";
try
{
string sqlCommand = "INSERT INTO " + typeof(TData).Name;
var properties = typeof(TData).GetProperties();
Dictionary<string,object> dataParams = new Dictionary<string, object>();
foreach(var property in properties){
dataParams.Add(property.Name,property.GetValue(data));
if(property.PropertyType==typeof(bool) || property.PropertyType.IsEnum){
// If property is bool type , save data to data base should be 0 or 1 instead of false or true;
// If property is Enum type , then transform data to int;
dataParams[property.Name] = System.Convert.ToInt32(dataParams[property.Name]);
}else if(property.PropertyType.IsClass || property.PropertyType.IsValueType && !property.PropertyType.IsPrimitive && property.PropertyType != typeof(string)){
dataParams[property.Name] = JsonConvert.SerializeObject(dataParams[property.Name]);
}
}
sqlCommand += "(";
string keySet = "";
foreach(string key in dataParams.Keys){
keySet += key + ",";
}
keySet = keySet.TrimEnd(',');
sqlCommand += keySet;
sqlCommand += ") VALUES (";
string valueSet = "";
foreach(var value in dataParams.Values){
if(value.GetType() == typeof(int) || value.GetType() == typeof(float) || value.GetType() == typeof(double)){
valueSet += value + ",";
}else{
valueSet += "'" + value + "',";
}
}
valueSet = valueSet.TrimEnd(',');
sqlCommand += valueSet;
sqlCommand += ")";
SqliteCommand createCommand = new SqliteCommand(sqlCommand,SqliteConn);
result = result + createCommand.ExecuteNonQuery().ToString();
}
catch (System.Exception e)
{
ExceptionMsg = e.ToString();
return "Error:"+ExceptionMsg;
}
return result;
}
/// <summary>
/// Query Data and return object list with TData type,Support Data Type:ClassObject,Enum,int,string.float,struct.Not support double,if double then auto convert to float
/// </summary>
/// <returns>List of TData or null ,if null then you can print ExceptionMsg to check your error</returns>
public List<TData> SelectData<TData>() where TData: new(){
List<TData> resultList = new List<TData>();
try
{
string sqlCommand = "SELECT * FROM " + typeof(TData).Name;
SqliteCommand selectCommand = new SqliteCommand(sqlCommand,SqliteConn);
SqliteDataReader reader = selectCommand.ExecuteReader();
var properties = typeof(TData).GetProperties();
while (reader.Read())
{
TData dataRow = new TData();
foreach(var property in properties){
if(property.PropertyType == reader[property.Name].GetType()){
property.SetValue(dataRow,reader[property.Name]);
}else if(property.PropertyType.IsEnum){
object propertyEnum = Enum.Parse(property.PropertyType,reader[property.Name].ToString());
property.SetValue(dataRow,propertyEnum);
}
else if(property.PropertyType.IsPrimitive) {
object propertyObject = System.Convert.ChangeType(reader[property.Name],property.PropertyType);
property.SetValue(dataRow,propertyObject);
}else{
object classObject = JsonConvert.DeserializeObject(reader[property.Name].ToString(),property.PropertyType);
property.SetValue(dataRow,classObject);
}
}
resultList.Add(dataRow);
}
}
catch (System.Exception e)
{
ExceptionMsg = e.ToString();
return null;
}
return resultList;
}
public bool IsTableExist<TData>() where TData:new(){
try
{
string sqlCommand = "SELECT name FROM sqlite_sequence";
SqliteCommand selectCommand = new SqliteCommand(sqlCommand,SqliteConn);
SqliteDataReader reader = selectCommand.ExecuteReader();
while (reader.Read()){
if(reader["name"].ToString()==typeof(TData).Name){
return true;
}
}
}
catch (System.Exception e)
{
ExceptionMsg = e.ToString();
return false;
}
return false;
}
#endregion
}
public static class CanGetEGSqliteExtension{
public static EGSqlite EGSqlite(this IEGFramework self){
return EGArchitectureImplement.Interface.GetModule<EGSqlite>();
}
}
}

241
EGFramework/Module/OtherTools/EGWebDav.cs

@ -0,0 +1,241 @@ @@ -0,0 +1,241 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using WebDav;
namespace EGFramework{
public class EGWebDav : IModule
{
public string ServerUrl { set; get; } = "";
private string UserName { set; get; } = "";
private string Password { set; get; } = "";
public bool IsInit { set; get; }
private WebDavClient WebDavClient { set; get; }
private string CurrentPath { set; get; } = "/";
public List<WebDavFileMsg> CurrentFileList { set; get; } = new List<WebDavFileMsg>();
public void Init()
{
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
public void InitClient(string serverUrl, string userName,string password){
this.ServerUrl = serverUrl;
this.UserName = userName;
this.Password = password;
Dictionary<string,string> headersAdd = new Dictionary<string, string>
{
{ "Connection", "keep-alive" },
{ "Authorization", "Basic "+ EGWebDavExtension.EncodeCredentials(userName,password) }
};
WebDavClient = new WebDavClient(new WebDavClientParams
{
BaseAddress = new Uri(ServerUrl),
Credentials = new NetworkCredential(userName, password),
DefaultRequestHeaders = headersAdd
});
Console.WriteLine("Client has been init");
}
//---------download or upload from WebDav server---------//
/// <summary>
/// Download a file from dav path
/// </summary>
/// <param name="downloadUri">Such as /dav/Picture/Picture1.jpg</param>
/// <param name="localPath">download destination,such as C:\Users\W35\Pictures</param>
/// <param name="fileName">you can define file by this name,or by uri</param>
/// <returns></returns>
public async Task<bool> DownloadFile(string downloadUri,string localPath,string fileName = ""){
if (fileName.Equals("")){
fileName = Path.GetFileName(downloadUri);
}
using (var response = await WebDavClient.GetRawFile(downloadUri))
{
if(response.IsSuccessful == true){
// use response.Stream
using (FileStream DestinationStream = File.Create(localPath + "/" + fileName))
{
await response.Stream.CopyToAsync(DestinationStream);
//Print("【WebDav】" + fileName + "下载成功!");
}
return true;
}else{
return false;
}
}
}
public async Task<bool> DownloadFilProcessed(string downloadUri,string localPath,string fileName = ""){
if (fileName.Equals("")){
fileName = Path.GetFileName(downloadUri);
}
using (var response = await WebDavClient.GetProcessedFile(downloadUri))
{
if(response.IsSuccessful == true){
// use response.Stream
using (FileStream DestinationStream = File.Create(localPath + "/" + fileName))
{
await response.Stream.CopyToAsync(DestinationStream);
//Print("【WebDav】" + fileName + "下载成功!");
}
return true;
}else{
return false;
}
}
}
/// <summary>
/// Upload a file by localUrl
/// </summary>
/// <param name="localUrl">Such as C:\Users\W35\Pictures\Picture1.jpg</param>
/// <param name="uploadPath">upload destination,such as /dav/Picture</param>
/// <param name="fileName">you can define file by this name,or by local url</param>
/// <returns></returns>
public async Task<bool> UploadFile(string localUrl,string uploadPath,string fileName = ""){
if (fileName.Equals("")){
fileName = Path.GetFileName(localUrl);
}
// use response.Stream
var result = await WebDavClient.PutFile(uploadPath+"/"+fileName, File.OpenRead(localUrl));
if(result.IsSuccessful){
return true;
}else{
return false;
}
}
//-----------operate disk-----------//
/// <summary>
/// Default root path is "/",any path should be start with "/"
/// </summary>
/// <param name="currentPath"></param>
/// <returns></returns>
public async Task<List<WebDavFileMsg>> GetList(string currentPath){
PropfindResponse result = await WebDavClient.Propfind(ServerUrl+currentPath);
List<WebDavFileMsg> ResultFileList = new List<WebDavFileMsg>();
if (result.IsSuccessful)
{
foreach (WebDavResource res in result.Resources)
{
ResultFileList.Add(new WebDavFileMsg{
FileName = res.DisplayName ,
IsCollection = res.IsCollection ,
Size = res.ContentLength ,
Uri = res.Uri ,
LastUpdateTime = res.LastModifiedDate
});
}
}
return ResultFileList;
}
/// <summary>
/// simple CD command, prop find all file message to CurrentFileList.
/// </summary>
/// <param name="destinationPath"></param>
/// <returns></returns>
public async Task ChangeDictionary(string destinationPath){
CurrentPath = destinationPath;
PropfindResponse result = await WebDavClient.Propfind(ServerUrl+CurrentPath);
CurrentFileList.Clear();
if (result.IsSuccessful)
{
foreach (WebDavResource res in result.Resources)
{
CurrentFileList.Add(new WebDavFileMsg{
FileName = res.DisplayName ,
IsCollection = res.IsCollection ,
Size = res.ContentLength ,
Uri = res.Uri ,
LastUpdateTime = res.LastModifiedDate
});
}
}
}
/// <summary>
/// create a directory
/// </summary>
/// <param name="dictionaryName"></param>
/// <returns></returns>
public async Task MakeDictionary(string dictionaryName){
await WebDavClient.Mkcol(dictionaryName);
}
/// <summary>
/// simple cp command, copy a file with differentName.
/// </summary>
/// <param name="sourceFile"></param>
/// <param name="copyFile"></param>
/// <returns></returns>
public async Task Copy(string sourceFile,string copyFile){
await WebDavClient.Copy(sourceFile,copyFile);
}
/// <summary>
/// simple mv command, move a file with change fileName or different path.
/// </summary>
/// <param name="sourceFile"></param>
/// <param name="moveFile"></param>
/// <returns></returns>
public async Task Move(string sourceFile,string moveFile){
await WebDavClient.Move(sourceFile,moveFile);
}
/// <summary>
/// simple rm command,delete a file.
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public async Task Remove(string fileName){
await WebDavClient.Delete(fileName);
}
}
public struct WebDavFileMsg : IEGFileMsg{
public string FileName { set; get; }
public bool IsCollection { set; get; }
/// <summary>
/// unit is kb
/// </summary>
public long? Size { set; get; }
public string Uri { set; get; }
public DateTime? LastUpdateTime { set; get; }
public DateTime? LastModify { set; get; }
public void Init(string fileName, bool isCollection, string uri, long? size = null, DateTime? lastModify = null)
{
this.FileName = fileName;
this.IsCollection = isCollection;
this.Uri = uri;
this.Size = size;
this.LastModify = lastModify;
}
}
public static class EGWebDavExtension{
public static EGWebDav EGWebDav(this IEGFramework self)
{
return EGArchitectureImplement.Interface.GetModule<EGWebDav>();
}
public static string EncodeCredentials(string username, string password)
{
string credentials = $"{username}:{password}";
byte[] credentialsBytes = System.Text.Encoding.UTF8.GetBytes(credentials);
string encodedCredentials = Convert.ToBase64String(credentialsBytes);
return encodedCredentials;
}
}
}

335
EGFramework/Module/ProtocolTools/EGMessage.cs

@ -0,0 +1,335 @@ @@ -0,0 +1,335 @@
using System;
using System.Collections.Concurrent;
using System.Timers;
namespace EGFramework
{
//before use this module,you should install NewtonSoft.Json Nuget Package
//in vscode,you can install this package by install vscode extension NuGet Package Manager GUI
//search 'Newton' and choose Newtonsoft.Json
//EGMessage, Every Message tools will be based in this class
public class EGMessage : EGModule
{
public EasyEvent<ResponseMsg> OnDataReceived { set; get; } = new EasyEvent<ResponseMsg>();
public EasyEvent<ResponseMsgEvent> OnResponse { set; get; } = new EasyEvent<ResponseMsgEvent>();
public EasyEvent<RequestMsgEvent> OnRequest { set; get; } = new EasyEvent<RequestMsgEvent>();
/// <summary>
/// Send delay in millisecond,if you don't need a Timer to delay send message,you can set it to 0. ( this delay options is prevent for sticky package )
/// </summary>
/// <value></value>
public int SendDelay { set; get; } = 100;
public ConcurrentDictionary<string,ConcurrentQueue<RequestMsgEvent>> RequestCache { set; get; } = new ConcurrentDictionary<string,ConcurrentQueue<RequestMsgEvent>>();
private System.Timers.Timer RequestTimer { set; get; }
public override void Init()
{
if(SendDelay>0){
RequestTimer = new System.Timers.Timer(SendDelay);
RequestTimer.Elapsed += ExecuteRequest;
RequestTimer.AutoReset = true;
RequestTimer.Enabled = true;
}
}
#region ReceiveFunctions
private void ReceiveResponse<T>(ResponseMsg msg) where T :IResponse, new()
{
this.ExecuteResponse(new T(),msg.stringData,msg.byteData,msg.sender,msg.protocolType);
}
/// <summary>
/// Start to receive type of T data
/// </summary>
/// <typeparam name="T">Data class of message</typeparam>
public void OnReceive<T>() where T : IResponse, new()
{
OnDataReceived.Register(ReceiveResponse<T>);
}
/// <summary>
/// Stop to receive type of T data
/// </summary>
/// <typeparam name="T">Data class of message</typeparam>
public void OffReceive<T>() where T : IResponse, new()
{
OnDataReceived.UnRegister(ReceiveResponse<T>);
}
#endregion
#region request & response
public void SendRequest<TRequest>(TRequest request,string sender,ProtocolType protocolType) where TRequest:IRequest
{
if(SendDelay>0){
if(!RequestCache.ContainsKey(sender)){
RequestCache[sender] = new ConcurrentQueue<RequestMsgEvent>();
}
RequestCache[sender].Enqueue(new RequestMsgEvent(request,sender,protocolType));
}else{
OnRequest.Invoke(new RequestMsgEvent(request,sender,protocolType));
}
//ExecuteRequest();
//OnRequest.Invoke(requestCache.Dequeue());
}
private void ExecuteRequest(object source, ElapsedEventArgs e){
foreach(ConcurrentQueue<RequestMsgEvent> singleCache in RequestCache.Values){
if(singleCache.Count>0){
singleCache.TryDequeue(out RequestMsgEvent msg);
OnRequest.Invoke(msg);
}
}
}
private void ExecuteResponse<TResponse>(TResponse response,string protocolString,byte[] protocolBytes,string sender,ProtocolType protocolType) where TResponse:IResponse
{
bool isSet = response.TrySetData(protocolString,protocolBytes);
if (isSet)
{
//this.SendEvent(new ResponseMsgEvent(response, sender));
OnResponse.Invoke(new ResponseMsgEvent(response,sender,protocolType));
}
}
#endregion
public void SetDelay(int millisecond){
this.SendDelay = millisecond;
if(millisecond != 0){
RequestTimer.Interval = millisecond;
}
}
}
#region interface
public interface IResponse
{
/// <summary>
/// Attempt to fill in the data. If it does not comply with the relevant protocol rules, it is recommended to return false. If false is returned here, the data response will be ignored.
/// </summary>
/// <param name="protocolData">original received</param>
/// <returns></returns>
bool TrySetData(string protocolData,byte[] protocolBytes);
}
public interface IRequest
{
/// <summary>
/// define you message info in this function,and this return will be send to server&client by request.
/// </summary>
/// <returns>request info</returns>
string ToProtocolData();
byte[] ToProtocolByteData();
}
#endregion
#region AbstractClass
public class BaseJsonResponse : IResponse
{
private string ExceptionMsg;
public virtual string ToProtocolData()
{
return "";
}
public virtual bool TrySetData(string json,byte[] bytes)
{
try
{
return true;
}
catch (Exception e)
{
ExceptionMsg = e.ToString();
//PrintErr(ExceptionMsg);
return false;
}
}
}
public class StringRequest : IRequest
{
private string RequestStr;
public StringRequest() {
RequestStr = "No message";
}
public StringRequest(string str) {
RequestStr = str;
}
public byte[] ToProtocolByteData()
{
return null;
}
public string ToProtocolData()
{
return RequestStr;
}
}
#endregion
#region Extension
public static class CanRegisterMessageExtension {
/// <summary>
/// To register event until message received,if you only need message,please use:
/// this.RegisterMessageEvent<BaseJsonResponse>(e=>{ //To execute your message})
/// if you want to get sender,you also can to:
/// this.RegisterMessageEvent<BaseJsonResponse>((res,sender))=>{ //To execute your message
/// Print(res.toProtocolData());
/// Print(sender);
/// })
/// </summary>
/// <param name="self"></param>
/// <param name="onEvent"></param>
/// <typeparam name="TResponse"></typeparam>
/// <returns></returns>
public static IUnRegister EGRegisterMessageEvent<TResponse>(this IEGFramework self, Action<TResponse> onEvent)where TResponse : IResponse
{
return EGArchitectureImplement.Interface.GetModule<EGMessage>().OnResponse.Register(e=> {
if (e.res.GetType() == typeof(TResponse)) {
onEvent.Invoke((TResponse)e.res);
}
});
}
/// <summary>
/// To register event until message received,if you only need message,please use:
/// this.RegisterMessageEvent<BaseJsonResponse>(e=>{ //To execute your message})
/// if you want to get sender,you also can to:
/// this.RegisterMessageEvent<BaseJsonResponse>((res,sender))=>{ //To execute your message
/// Print(res.toProtocolData());
/// Print(sender);
/// })
/// </summary>
/// <param name="self"></param>
/// <param name="onEvent"></param>
/// <typeparam name="TResponse"></typeparam>
/// <returns></returns>
public static IUnRegister EGRegisterMessageEvent<TResponse>(this IEGFramework self, Action<TResponse,string> onEvent)where TResponse : IResponse
{
return EGArchitectureImplement.Interface.GetModule<EGMessage>().OnResponse.Register(e=> {
if (e.res.GetType() == typeof(TResponse)) {
onEvent.Invoke((TResponse)e.res,e.sender);
}
});
}
public static IUnRegister EGRegisterMessageEvent<TResponse>(this IEGFramework self, Action<TResponse,string,ProtocolType> onEvent)where TResponse : IResponse
{
return EGArchitectureImplement.Interface.GetModule<EGMessage>().OnResponse.Register(e=> {
if (e.res.GetType() == typeof(TResponse)) {
onEvent.Invoke((TResponse)e.res,e.sender,e.protocolType);
}
});
}
/// <summary>
/// Start to receive type of TResponse data
/// </summary>
/// <param name="self"></param>
/// <typeparam name="TResponse"></typeparam>
public static void EGOnMessage<TResponse>(this IEGFramework self) where TResponse : IResponse,new()
{
EGArchitectureImplement.Interface.GetModule<EGMessage>().OnReceive<TResponse>();
}
/// <summary>
/// Stop to receive type of TResponse data
/// </summary>
/// <param name="self"></param>
/// <typeparam name="TResponse"></typeparam>
public static void EGOffMessage<TResponse>(this IEGFramework self) where TResponse : IResponse,new()
{
EGArchitectureImplement.Interface.GetModule<EGMessage>().OffReceive<TResponse>();
}
}
public static class CanSendMessageExtension {
/// <summary>
/// to send message by request and define sender
/// </summary>
/// <param name="self"></param>
/// <param name="request"></param>
/// <param name="sender"></param>
/// <typeparam name="TRequest"></typeparam>
public static void EGSendMessage<TRequest>(this IEGFramework self, TRequest request,string sender,ProtocolType protocolType)where TRequest : IRequest
{
EGArchitectureImplement.Interface.GetModule<EGMessage>().SendRequest(request,sender,protocolType);
}
}
/// <summary>
/// this extension to link with protocol tools,such as tcp,udp,serial port,etc...
/// </summary>
public static class EGMessageEventExtension{
public static void EGOnReceivedData(this IModule self, ResponseMsg receivedData)
{
EGArchitectureImplement.Interface.GetModule<EGMessage>().OnDataReceived.Invoke(receivedData);
}
public static void EGRegisterSendAction(this IModule self, Action<RequestMsgEvent> sendAction){
EGArchitectureImplement.Interface.GetModule<EGMessage>().OnRequest.Register(sendAction);
}
}
#endregion
#region event
public struct ResponseMsg
{
public string sender;
public string stringData;
public byte[] byteData;
public ProtocolType protocolType;
public ResponseMsg(string stringData_,byte[] byteData_,string sender_,ProtocolType protocolType_)
{
stringData = stringData_;
byteData = byteData_;
sender = sender_;
protocolType = protocolType_;
}
}
public struct ResponseMsgEvent
{
public IResponse res;
public string sender;
public ProtocolType protocolType;
public ResponseMsgEvent(IResponse res_,string sender_,ProtocolType protocolType_)
{
res = res_;
sender = sender_;
protocolType = protocolType_;
}
}
public struct RequestMsgEvent
{
public IRequest req;
public string sender;
public ProtocolType protocolType;
public RequestMsgEvent(IRequest req_ ,string sender_,ProtocolType protocolType_)
{
req = req_;
sender = sender_;
protocolType = protocolType_;
}
}
#endregion
public enum ProtocolType{
TCPClient = 0x00,
TCPServer = 0x01,
UDP = 0x02,
SerialPort = 0x03,
WebSocketClient = 0x10,
WebSocketServer = 0x11,
HttpServer = 0x20,
HttpGet = 0x21,
HttpPost = 0x22,
HttpPut = 0x23,
HttpPatch = 0x24,
HttpDelete = 0x25,
DTLSClient = 0x30,
DTLSServer = 0x31,
SSLClient = 0x40,
SSLServer = 0x41,
FileStream = 0x50,
MemoryStream = 0x60,
MQTTClient = 0x70,
Bacnet = 0x80,
SSHClient = 0x90,
Process = 0xA0,
//MQTT,SSH,etc...
}
}

58
EGFramework/Module/ProtocolTools/EGProtocolSchedule.cs

@ -0,0 +1,58 @@ @@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
namespace EGFramework{
public class EGProtocolSchedule : IEGFramework,IModule
{
public Dictionary<Type,IProtocolReceived> ProtocolTools = new Dictionary<Type, IProtocolReceived>();
public void Init()
{
}
public void CheckedProcess()
{
foreach (IProtocolReceived tool in ProtocolTools.Values)
{
if (tool.GetReceivedMsg().Count > 0)
{
bool isDequeue = tool.GetReceivedMsg().TryDequeue(out ResponseMsg msg);
if (isDequeue)
{
this.GetModule<EGMessage>().OnDataReceived.Invoke(msg);
}
}
}
}
public void EnabledAllTools(){
this.EnabledTool<EGTCPClient>();
this.EnabledTool<EGTCPServer>();
this.EnabledTool<EGUDP>();
this.EnabledTool<EGSerialPort>();
this.EnabledTool<EGFileStream>();
}
public void EnabledTool<TProtocolReceived>() where TProtocolReceived : class, IModule,IProtocolReceived,new(){
if(!ProtocolTools.ContainsKey(typeof(TProtocolReceived))){
ProtocolTools.Add(typeof(TProtocolReceived),this.GetModule<TProtocolReceived>());
}
}
public void DisabledAllTools(){
ProtocolTools.Clear();
}
public void DisabledTool<TProtocolReceived>() where TProtocolReceived : class, IModule,IProtocolReceived,new(){
if(ProtocolTools.ContainsKey(typeof(TProtocolReceived))){
ProtocolTools.Remove(typeof(TProtocolReceived));
}
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
}

573
EGFramework/Module/ProtocolTools/Internet/EGBacnet.cs

@ -0,0 +1,573 @@ @@ -0,0 +1,573 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO.BACnet;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace EGFramework{
public class EGBacnet : IEGFramework, IModule,IProtocolSend,IProtocolReceived
{
public BacnetClient BacnetClient;
// All the present Bacnet Device List
public Dictionary<uint,BacnetAddress> DevicesList = new Dictionary<uint,BacnetAddress>();
public Encoding StringEncoding { set; get; } = Encoding.ASCII;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.Bacnet){
if(request.req.ToProtocolData() != "" && request.req.ToProtocolData() != null){
this.SendStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData().Length > 0 && request.req.ToProtocolByteData() != null){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
StartIPV4();
}
public void StartIPV4(int port = 0xBAC0)
{
// Bacnet on UDP/IP/Ethernet
BacnetClient = new BacnetClient(new BacnetIpUdpProtocolTransport(port, false));
BacnetClient.Start(); // go
BacnetClient.OnIam += new BacnetClient.IamHandler(OnIam);
BacnetClient.WhoIs();
// Or Bacnet Ethernet
// bacnet_client = new BacnetClient(new BacnetEthernetProtocolTransport("Connexion au réseau local"));
// Send WhoIs in order to get back all the Iam responses :
/* Optional Remote Registration as A Foreign Device on a BBMD at @192.168.1.1 on the default 0xBAC0 port
bacnet_client.RegisterAsForeignDevice("192.168.1.1", 60);
Thread.Sleep(20);
bacnet_client.RemoteWhoIs("192.168.1.1");
*/
}
public void StartIPV6(int port = 0xBAC0){
//Bacnet on IPV6
BacnetClient = new BacnetClient(new BacnetIpV6UdpProtocolTransport(port));
BacnetClient.Start(); // go
BacnetClient.OnIam += new BacnetClient.IamHandler(OnIam);
BacnetClient.WhoIs();
}
public void StartMSTP(string serialPort = "COM4",int baudRate = 38400){
// Bacnet Mstp on COM4 à 38400 bps, own master id 8
BacnetClient = new BacnetClient(new BacnetMstpProtocolTransport(serialPort, baudRate, 8));
BacnetClient.Start(); // go
BacnetClient.OnIam += new BacnetClient.IamHandler(OnIam);
BacnetClient.WhoIs();
}
public void OnIam(BacnetClient sender, BacnetAddress adr, uint device_id, uint max_apdu, BacnetSegmentations segmentation, ushort vendor_id)
{
lock (DevicesList)
{
// Not already in the list
if(DevicesList.ContainsKey(device_id)){
DevicesList[device_id]=adr;
}else{
DevicesList.Add(device_id,adr); // add it
}
if(!IsWaitForIam){
WaitForIamResponse();
}
}
}
public bool IsWaitForIam { set; get; } = false;
public async void WaitForIamResponse(){
IsWaitForIam = true;
await Task.Delay(2000);
EG.Print("-----Get device----");
string serializeData = JsonConvert.SerializeObject(new EGBacnetWhoIsResponse(DevicesList.Keys.ToList()));
this.ResponseMsgs.Enqueue(new ResponseMsg(serializeData,StringEncoding.GetBytes(serializeData),"Who Is",ProtocolType.Bacnet));
IsWaitForIam = false;
}
public bool ReadProperty(BacnetAddress bacnetAddress, EGBacnetRequest bacnetData, out IList<BacnetValue> Value)
{
IList<BacnetValue> NoScalarValue;
Value = new List<BacnetValue>();
// Property Read
if (BacnetClient.ReadPropertyRequest(bacnetAddress, new BacnetObjectId(bacnetData.ObjectTypes, bacnetData.RegisterAddress), bacnetData.PropertyIds, out NoScalarValue)==false)
return false;
Value = NoScalarValue;
return true;
}
public bool WriteProperty(BacnetAddress bacnetAddress,EGBacnetRequest bacnetData)
{
// Property Write
BacnetValue[] NoScalarValue = { new BacnetValue(bacnetData.Value) };
//GD.Print("ValueType is " + bacnetData.ValueType+"|" +bacnetData.Value.GetType());
if (BacnetClient.WritePropertyRequest(bacnetAddress, new BacnetObjectId(bacnetData.ObjectTypes, bacnetData.RegisterAddress), bacnetData.PropertyIds, NoScalarValue) == false)
return false;
return true;
}
public bool ExecuteBacnetData(EGBacnetRequest bacnetRequest){
bool executeResult = false;
EG.Print("Execute bacnet request");
if(bacnetRequest.OperateCode == EGBacnetOperateCode.WhoIsRequest){
EG.Print("Request for Who Is");
BacnetClient.WhoIs();
return true;
}
if(!DevicesList.ContainsKey(bacnetRequest.DeviceId)){
return false;
}
BacnetAddress address = DevicesList[bacnetRequest.DeviceId];
IList<BacnetValue> bacnetValueQuery = null;
switch(bacnetRequest.OperateCode){
case EGBacnetOperateCode.ReadPropertyRequest:
executeResult = ReadProperty(address,bacnetRequest,out bacnetValueQuery);
break;
case EGBacnetOperateCode.WritePropertyRequest:
executeResult = WriteProperty(address,bacnetRequest);
break;
}
EGBacnetResponse response = new EGBacnetResponse(bacnetRequest,bacnetValueQuery);
response.IsSuccess = executeResult;
string serializeData = JsonConvert.SerializeObject(response);
this.ResponseMsgs.Enqueue(new ResponseMsg(serializeData,StringEncoding.GetBytes(serializeData),bacnetRequest.DeviceId.ToString(),ProtocolType.Bacnet));
return executeResult;
}
public EGBacnetWhoIsResponse WhoIs(){
return new EGBacnetWhoIsResponse(DevicesList.Keys.ToList());
}
public EGBacnetResponse ReadRegisterProperty(EGBacnetRequest bacnetRequest){
bool executeResult = false;
try
{
BacnetAddress address = DevicesList[bacnetRequest.DeviceId];
IList<BacnetValue> bacnetValueQuery = null;
switch(bacnetRequest.OperateCode){
case EGBacnetOperateCode.ReadPropertyRequest:
executeResult = ReadProperty(address,bacnetRequest,out bacnetValueQuery);
break;
}
EG.Print(bacnetValueQuery[0].Value.GetType());
EGBacnetResponse response = new EGBacnetResponse(bacnetRequest,bacnetValueQuery);
response.IsSuccess = executeResult;
return response;
}
catch (System.Exception e)
{
EGBacnetResponse response = new EGBacnetResponse(bacnetRequest);
response.IsSuccess = executeResult;
response.FailedReason = e.ToString();
return response;
}
}
public EGBacnetResponse WriteRegisterProperty(EGBacnetRequest bacnetRequest){
bool executeResult = false;
try
{
if(bacnetRequest.ValueType != BacnetApplicationTags.BACNET_APPLICATION_TAG_NULL){
bacnetRequest.Value = bacnetRequest.Value.ConvertBacnetValueType(bacnetRequest.ValueType);
}
EG.Print(bacnetRequest.Value.GetType());
BacnetAddress address = DevicesList[bacnetRequest.DeviceId];
switch(bacnetRequest.OperateCode){
case EGBacnetOperateCode.WritePropertyRequest:
executeResult = WriteProperty(address,bacnetRequest);
break;
}
EGBacnetResponse response = new EGBacnetResponse(bacnetRequest);
response.IsSuccess = executeResult;
return response;
}
catch (System.Exception e)
{
EGBacnetResponse response = new EGBacnetResponse(bacnetRequest);
response.IsSuccess = executeResult;
response.FailedReason = e.ToString();
return response;
}
}
public EGBacnetResponseReadMulti ReadRegisterMulti(EGBacnetRequestReadMulti bacnetRequest){
bool executeResult = false;
try
{
if(!DevicesList.ContainsKey(bacnetRequest.DeviceId)){
return new EGBacnetResponseReadMulti(){
FailedReason = "Device " + bacnetRequest.DeviceId + " is offline!"
};
}
BacnetAddress address = DevicesList[bacnetRequest.DeviceId];
List<EGBacnetRegisterValueInfo> resultSet = new List<EGBacnetRegisterValueInfo>();
switch(bacnetRequest.OperateCode){
case EGBacnetOperateCode.ReadMultiRequest:
foreach(EGBacnetRegisterInfo info in bacnetRequest.RegisterInfos){
EGBacnetRegisterValueInfo result = ReadRegisterOne(address,info);
resultSet.Add(result);
}
executeResult = true;
break;
}
EGBacnetResponseReadMulti response = new EGBacnetResponseReadMulti(resultSet);
response.IsSuccess = executeResult;
return response;
}
catch (System.Exception e)
{
return new EGBacnetResponseReadMulti(){
FailedReason = e.ToString()
};
}
}
public EGBacnetRegisterValueInfo ReadRegisterOne(BacnetAddress bacnetAddress, EGBacnetRegisterInfo registerInfo){
EGBacnetRegisterValueInfo value = new EGBacnetRegisterValueInfo(){
ObjectTypes = registerInfo.ObjectTypes,
RegisterAddress = registerInfo.RegisterAddress,
PropertyIds = registerInfo.PropertyIds
};
IList<BacnetValue> NoScalarValue;
try
{
bool IsSuccess = BacnetClient.ReadPropertyRequest(bacnetAddress, new BacnetObjectId(registerInfo.ObjectTypes, registerInfo.RegisterAddress), registerInfo.PropertyIds, out NoScalarValue);
if(IsSuccess){
value.IsSuccess = true;
value.Value = NoScalarValue[0];
}
}
catch (System.Exception e)
{
EG.Print(e);
throw;
}
return value;
}
public void SendByteData(string destination, byte[] data)
{
try
{
string DataJson = StringEncoding.GetString(data);
SendStringData(destination,DataJson);
}
catch (System.Exception)
{
throw;
}
}
public void SendStringData(string destination, string data)
{
try
{
EGBacnetRequest bacnetData = JsonConvert.DeserializeObject<EGBacnetRequest>(data);
ExecuteBacnetData(bacnetData);
}
catch (System.Exception e)
{
EG.Print("Error:"+e);
throw;
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return this.ResponseMsgs;
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
#region Who Is
public class EGBacnetWhoIsResponse : IResponse,IRequest
{
public string FunctionCode { set; get; } = "WhoIsResponse";
public List<uint> DevicesList = new List<uint>();
public EGBacnetWhoIsResponse(){
}
public EGBacnetWhoIsResponse(List<uint> devicesList){
this.DevicesList = devicesList;
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
EGBacnetWhoIsResponse response = JsonConvert.DeserializeObject<EGBacnetWhoIsResponse>(protocolData);
if(response.FunctionCode != FunctionCode){
return false;
}
this.DevicesList = response.DevicesList;
//throw new System.NotImplementedException();
return true;
}
catch (System.Exception e)
{
EG.Print("Who is error:"+ e);
return false;
}
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this,Formatting.Indented);
}
public byte[] ToProtocolByteData()
{
return null;
}
}
#endregion
#region Read&Write One Register
public class EGBacnetRequest : IRequest,IResponse{
public string FunctionCode { set; get; } = "OperateRequest";
public EGBacnetOperateCode OperateCode { set; get; }
public uint DeviceId { set; get; }
public BacnetObjectTypes ObjectTypes { set; get; }
public uint RegisterAddress { set; get; }
public BacnetPropertyIds PropertyIds { set; get; }
public object Value { set; get; }
public BacnetApplicationTags ValueType { set; get; }
public byte[] ToProtocolByteData()
{
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this,Formatting.Indented);
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
//GD.Print("Init Request");
EGBacnetRequest request = JsonConvert.DeserializeObject<EGBacnetRequest>(protocolData);
if(request.FunctionCode != FunctionCode){
return false;
}
//GD.Print("OperateCode is " + request.OperateCode);
this.OperateCode = request.OperateCode;
this.DeviceId = request.DeviceId;
this.ObjectTypes = request.ObjectTypes;
this.RegisterAddress = request.RegisterAddress;
this.PropertyIds = request.PropertyIds;
this.Value = request.Value;
this.ValueType = request.ValueType;
return true;
}
catch (System.Exception e)
{
EG.Print("Error:"+e);
return false;
}
}
}
public class EGBacnetResponse : IResponse,IRequest
{
public string FunctionCode { set; get; } = "OperateResponse";
public bool IsSuccess { set; get; } = false;
public EGBacnetRequest Request { set; get; }
public IList<BacnetValue> ValueQuery { set; get; }
public string FailedReason { set; get; }
public EGBacnetResponse(){
}
public EGBacnetResponse(EGBacnetRequest request){
this.Request = request;
}
public EGBacnetResponse(EGBacnetRequest request,IList<BacnetValue> values){
this.Request = request;
this.ValueQuery = values;
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
EGBacnetResponse response = JsonConvert.DeserializeObject<EGBacnetResponse>(protocolData);
if(response.FunctionCode != FunctionCode){
return false;
}
this.IsSuccess = response.IsSuccess;
this.Request = response.Request;
this.ValueQuery = response.ValueQuery;
return true;
}
catch (System.Exception)
{
return false;
}
//throw new System.NotImplementedException();
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this,Formatting.Indented);
}
public byte[] ToProtocolByteData()
{
return null;
}
}
#endregion
#region Multi Operate
public class EGBacnetRequestReadMulti : IRequest,IResponse{
public string FunctionCode { set; get; } = "ReadMultiRequest";
public EGBacnetOperateCode OperateCode { set; get; }
public uint DeviceId { set; get; }
public List<EGBacnetRegisterInfo> RegisterInfos { set; get; } = new List<EGBacnetRegisterInfo>();
public byte[] ToProtocolByteData()
{
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this,Formatting.Indented);
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
//GD.Print("Init Request");
EGBacnetRequestReadMulti request = JsonConvert.DeserializeObject<EGBacnetRequestReadMulti>(protocolData);
if(request.FunctionCode != FunctionCode){
return false;
}
//GD.Print("OperateCode is " + request.OperateCode);
this.OperateCode = request.OperateCode;
this.DeviceId = request.DeviceId;
this.RegisterInfos = request.RegisterInfos;
return true;
}
catch (System.Exception e)
{
EG.Print("Error:"+e);
return false;
}
}
}
public class EGBacnetResponseReadMulti : IResponse,IRequest
{
public string FunctionCode { set; get; } = "ReadMultiResponse";
public bool IsSuccess { set; get; } = false;
public List<EGBacnetRegisterValueInfo> RegisterInfos { set; get; } = new List<EGBacnetRegisterValueInfo>();
public string FailedReason { set; get; }
public EGBacnetResponseReadMulti(){}
public EGBacnetResponseReadMulti(List<EGBacnetRegisterValueInfo> valueSet){
this.RegisterInfos = valueSet;
}
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
EGBacnetResponseReadMulti response = JsonConvert.DeserializeObject<EGBacnetResponseReadMulti>(protocolData);
if(response.FunctionCode != FunctionCode){
FailedReason = "[Error] FunctionCode is error!";
return false;
}
this.IsSuccess = response.IsSuccess;
this.RegisterInfos = response.RegisterInfos;
this.FailedReason = response.FailedReason;
return true;
}
catch (System.Exception e)
{
EG.Print("Error:"+e);
return false;
}
//throw new System.NotImplementedException();
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this,Formatting.Indented);
}
public byte[] ToProtocolByteData()
{
return null;
}
}
public struct EGBacnetRegisterInfo{
public BacnetObjectTypes ObjectTypes { set; get; }
public uint RegisterAddress { set; get; }
public BacnetPropertyIds PropertyIds { set; get; }
}
public struct EGBacnetRegisterValueInfo{
public BacnetObjectTypes ObjectTypes { set; get; }
public uint RegisterAddress { set; get; }
public BacnetPropertyIds PropertyIds { set; get; }
public bool IsSuccess { set; get; }
public BacnetValue Value{ set; get; }
}
#endregion
public enum EGBacnetOperateCode{
ReadPropertyRequest = 0,
WritePropertyRequest = 1,
WhoIsRequest = 2,
ReadMultiRequest = 3,
}
public static class CanGetEGBacnetExtension{
public static EGBacnet EGBacnet(this IEGFramework self){
return self.GetModule<EGBacnet>();
}
public static object ConvertBacnetValueType(this object value,BacnetApplicationTags valueType){
object resultValue = value;
switch(valueType){
case BacnetApplicationTags.BACNET_APPLICATION_TAG_BOOLEAN:
resultValue = Convert.ToBoolean(value);
break;
case BacnetApplicationTags.BACNET_APPLICATION_TAG_UNSIGNED_INT:
resultValue = Convert.ToUInt32(value);
break;
case BacnetApplicationTags.BACNET_APPLICATION_TAG_SIGNED_INT:
resultValue = Convert.ToInt32(value);
break;
case BacnetApplicationTags.BACNET_APPLICATION_TAG_REAL:
resultValue = Convert.ToSingle(value);
break;
case BacnetApplicationTags.BACNET_APPLICATION_TAG_DOUBLE:
resultValue = Convert.ToDouble(value);
break;
}
return resultValue;
}
}
}

96
EGFramework/Module/ProtocolTools/Internet/EGHttpClient.cs

@ -0,0 +1,96 @@ @@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Drawing.Printing;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace EGFramework{
public class EGHttpClient : IEGFramework, IModule
{
public HttpClient HTTPClient { set; get; } = new HttpClient();
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public void Init()
{
}
public async Task<TResponse> HttpRequest<TResponse>(string hostUrl,IRequest request,ProtocolType protocolType = ProtocolType.HttpGet,EGFormData formData = null) where TResponse : IResponse,new(){
// Call asynchronous network methods in a try/catch block to handle exceptions.
try
{
HttpContent httpContent = new StringContent("",Encoding.UTF8,"application/json");
if(formData != null){
MultipartFormDataContent formContent = new MultipartFormDataContent();
foreach(KeyValuePair<string,string> pair in formData.FormStrings){
formContent.Add(new StringContent(pair.Value,Encoding.UTF8),pair.Key);
}
foreach(KeyValuePair<string,byte[]> pair in formData.FormBytes){
formContent.Add(new ByteArrayContent(pair.Value),pair.Key,pair.Key+"."+formData.Suffix);
}
foreach(KeyValuePair<string,Stream> pair in formData.FormStreams){
formContent.Add(new StreamContent(pair.Value),pair.Key,pair.Key+"."+formData.Suffix);
}
httpContent = formContent;
}
else if(request.ToProtocolData() != null && request.ToProtocolData() != ""){
httpContent = new StringContent(request.ToProtocolData(),Encoding.UTF8,"application/json");
}else if (request.ToProtocolByteData() != null){
httpContent = new ByteArrayContent(request.ToProtocolByteData());
}
HttpResponseMessage httpResponse;
switch(protocolType){
case ProtocolType.HttpGet:
httpResponse = await HTTPClient.GetAsync(hostUrl);
break;
case ProtocolType.HttpPost:
httpResponse = await HTTPClient.PostAsync(hostUrl,httpContent);
break;
case ProtocolType.HttpPut:
httpResponse = await HTTPClient.PutAsync(hostUrl,httpContent);
break;
case ProtocolType.HttpPatch:
httpResponse = await HTTPClient.PatchAsync(hostUrl,httpContent);
break;
case ProtocolType.HttpDelete:
httpResponse = await HTTPClient.DeleteAsync(hostUrl);
break;
default:
httpResponse = await HTTPClient.GetAsync(hostUrl);
break;
}
httpResponse.EnsureSuccessStatusCode();
byte[] responseBytes = await httpResponse.Content.ReadAsByteArrayAsync();
string responseBody = await httpResponse.Content.ReadAsStringAsync();
TResponse response = new TResponse();
response.TrySetData(responseBody,responseBytes);
return response;
}
catch (HttpRequestException e)
{
EG.Print("Exception Message : "+e.Message);
return default;
}
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public class EGFormData{
public string Suffix = "";
public Dictionary<string,string> FormStrings = new Dictionary<string, string>();
public Dictionary<string,byte[]> FormBytes = new Dictionary<string, byte[]>();
public Dictionary<string,System.IO.Stream> FormStreams = new Dictionary<string, System.IO.Stream>();
}
public static class CanGetEGHttpClientExtension{
public static EGHttpClient EGHttpClient(this IEGFramework self){
return self.GetModule<EGHttpClient>();
}
}
}

148
EGFramework/Module/ProtocolTools/Internet/EGHttpServer.cs

@ -0,0 +1,148 @@ @@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace EGFramework{
public class EGHttpServer : IEGFramework, IModule
{
public HttpListener HttpServer { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public Dictionary<string,HttpListenerResponse> ResponsePools { set; get; } = new Dictionary<string, HttpListenerResponse>();
public Dictionary<string,Func<ResponseMsg,IRequest>> ExecuteDelegates { set; get; } = new Dictionary<string, Func<ResponseMsg, IRequest>>();
public void Init()
{
}
/// <summary>
/// if you are in Win7 or newest system, you should add prefix in urlacl by cmd for example: netsh http add urlacl url=http://+:6555/index/ user=Everyone
/// </summary>
/// <param name="prefix"></param>
/// <returns></returns>
public async void Listen(string prefix,Func<ResponseMsg,IRequest> responseFunc){
ExecuteDelegates.Add(prefix,responseFunc);
if(!HttpListener.IsSupported){
return;
}
if(HttpServer == null){
HttpServer = new HttpListener();
}
HttpServer.Prefixes.Add(prefix);
if(!HttpServer.IsListening){
HttpServer.Start();
//GD.Print("Http listened in :" + prefix);
while(true){
HttpListenerContext context = await HttpServer.GetContextAsync();
HttpListenerRequest request = context.Request;
string responseKey = "";
ResponseMsg receivedMsgs = new ResponseMsg();
try
{
switch (request.HttpMethod)
{
case "POST":
{
Stream stream = context.Request.InputStream;
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
// byte[] postBuffer = new byte[stream.Length];
// stream.Read(postBuffer,0,postBuffer.Length);
string postString = reader.ReadToEnd();
receivedMsgs = new ResponseMsg(postString,new byte[1],"POST", ProtocolType.HttpServer);
}
break;
case "GET":
{
NameValueCollection data = request.QueryString;
Dictionary<string,string> getDic = data.AllKeys.ToDictionary(k=>k,k=>data[k]);
string getData = JsonConvert.SerializeObject(getDic);
byte[] getBuffer = StringEncoding.GetBytes(getData);
responseKey = "GET:"+this.GetDateTime().ToString();
receivedMsgs = new ResponseMsg(getData,getBuffer,responseKey, ProtocolType.HttpServer);
//GD.Print("Received from "+receivedMsgs.sender+": "+receivedMsgs.stringData);
}
break;
case "PUT":
{
Stream stream = context.Request.InputStream;
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
byte[] postBuffer = new byte[stream.Length];
stream.Read(postBuffer,0,postBuffer.Length);
string postData = reader.ReadToEnd();
receivedMsgs = new ResponseMsg(postData,postBuffer,"PUT", ProtocolType.HttpServer);
}
break;
case "PATCH":
{
Stream stream = context.Request.InputStream;
StreamReader reader = new StreamReader(stream, Encoding.UTF8);
byte[] postBuffer = new byte[stream.Length];
stream.Read(postBuffer,0,postBuffer.Length);
string postData = reader.ReadToEnd();
receivedMsgs = new ResponseMsg(postData,postBuffer,"PATCH", ProtocolType.HttpServer);
}
break;
case "DELETE":
{
NameValueCollection data = request.QueryString;
Dictionary<string,string> getDic = data.AllKeys.ToDictionary(k=>k,k=>data[k]);
string getData = JsonConvert.SerializeObject(getDic);
byte[] getBuffer = StringEncoding.GetBytes(getData);
receivedMsgs = new ResponseMsg(getData,getBuffer,"DELETE", ProtocolType.HttpServer);
}
break;
}
}
catch (System.Exception e)
{
receivedMsgs.stringData = "Exception:"+e;
throw;
}
HttpListenerResponse response = context.Response;
response.AppendHeader("Access-Control-Allow-Origin", "*");
response.AppendHeader("Access-Control-Allow-Credentials", "true");
response.AppendHeader("Server", "MyIIS");
response.StatusCode = 200;
byte[] buffer = StringEncoding.GetBytes("API not found!");
if(ExecuteDelegates.ContainsKey(request.Url.ToString()+"/")){
IRequest result = ExecuteDelegates[request.Url.ToString()+"/"].Invoke(receivedMsgs);
buffer = StringEncoding.GetBytes(result.ToProtocolData());
}
System.IO.Stream output = response.OutputStream;
await output.WriteAsync(buffer, 0, buffer.Length);
output.Close();
// if(!ResponsePools.ContainsKey("")){
// ResponsePools.Add("",response);
// }
// Response("","Hello world");
}
}
EG.Print("Server Overed");
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGHttpServerExtension{
public static EGHttpServer EGHttpServer(this IEGFramework self){
return self.GetModule<EGHttpServer>();
}
public static void EGHttpServerListen(this IEGFramework self ,string prefix,Func<ResponseMsg,IRequest> responseFunc){
self.GetModule<EGHttpServer>().Listen(prefix,responseFunc);
}
}
}

163
EGFramework/Module/ProtocolTools/Internet/EGMQTT.cs

@ -0,0 +1,163 @@ @@ -0,0 +1,163 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MQTTnet;
using MQTTnet.Client;
//Important:
//This EGModule implement by the nuget package MQTTnet:
//the project url is: https://github.com/dotnet/MQTTnet
//license is : https://github.com/dotnet/MQTTnet/blob/master/LICENSE by MIT license
namespace EGFramework{
public class EGMqtt : IEGFramework, IModule, IProtocolSend, IProtocolReceived
{
public MqttFactory MqttFactory = new MqttFactory();
public Dictionary<string,IMqttClient> MqttDevices { set; get; } = new Dictionary<string, IMqttClient>();
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public EasyEvent<string> OnMqttConnect { set; get; } = new EasyEvent<string>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.MQTTClient){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender.GetStrFrontSymbol('|'),request.sender.GetStrBehindSymbol('|'),request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender.GetStrFrontSymbol('|'),request.sender.GetStrBehindSymbol('|'),request.req.ToProtocolByteData());
}
}
});
}
public async void ConnectMQTTServer(string serverURL){
if(!MqttDevices.ContainsKey(serverURL)){
IMqttClient mqttClient = MqttFactory.CreateMqttClient();
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(serverURL).Build();
mqttClient.ApplicationMessageReceivedAsync += e =>
{
byte[] receivedBytes = e.ApplicationMessage.PayloadSegment.ToArray();
ResponseMsgs.Enqueue(new ResponseMsg(StringEncoding.GetString(receivedBytes),receivedBytes,serverURL + "|" + e.ApplicationMessage.Topic,ProtocolType.MQTTClient));
//GD.Print(e.ApplicationMessage.Topic+":"+e.ApplicationMessage.PayloadSegment.ToArray().ToStringByHex());
return Task.CompletedTask;
};
await mqttClient.ConnectAsync(mqttClientOptions,CancellationToken.None);
MqttDevices.Add(serverURL,mqttClient);
EG.Print("Success Connect!"+MqttDevices[serverURL].IsConnected);
OnMqttConnect.Invoke(serverURL);
}else{
if(!MqttDevices[serverURL].IsConnected){
var mqttClientOptions = new MqttClientOptionsBuilder().WithTcpServer(serverURL).Build();
await MqttDevices[serverURL].ConnectAsync(mqttClientOptions,CancellationToken.None);
EG.Print("Success Connect!"+MqttDevices[serverURL].IsConnected);
OnMqttConnect.Invoke(serverURL);
}else{
EG.Print("Server has been Connected"+MqttDevices[serverURL].IsConnected);
OnMqttConnect.Invoke(serverURL);
}
}
}
public async void DisconnectMQTTServer(string serverURL){
if(MqttDevices.ContainsKey(serverURL) && MqttDevices[serverURL].IsConnected){
await MqttDevices[serverURL].DisconnectAsync(new MqttClientDisconnectOptionsBuilder().WithReason(MqttClientDisconnectOptionsReason.NormalDisconnection).Build());
}else{
EG.Print("Not connect");
}
}
public async void SubScribeTheme(string serverURL,string Theme){
MqttClientSubscribeOptions mqttSubscribeOptions = MqttFactory.CreateSubscribeOptionsBuilder()
.WithTopicFilter(
f =>
{
f.WithTopic(Theme);
})
.Build();
if(MqttDevices.ContainsKey(serverURL) && MqttDevices[serverURL].IsConnected){
await MqttDevices[serverURL].SubscribeAsync(mqttSubscribeOptions,CancellationToken.None);
EG.Print("Subscribe "+Theme+" success!");
}else{
EG.Print("Not connect");
}
}
public async void UnSubScribeTheme(string serverURL,string Theme){
MqttClientUnsubscribeOptions mqttUnSubscribeOptions = MqttFactory.CreateUnsubscribeOptionsBuilder()
.WithTopicFilter(Theme)
.Build();
if(MqttDevices.ContainsKey(serverURL) && MqttDevices[serverURL].IsConnected){
await MqttDevices[serverURL].UnsubscribeAsync(mqttUnSubscribeOptions,CancellationToken.None);
}
}
public async void PublishTheme(string serverURL,string Theme,string Data){
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic(Theme)
.WithPayload(Data)
.Build();
if(MqttDevices.ContainsKey(serverURL) && MqttDevices[serverURL].IsConnected){
await MqttDevices[serverURL].PublishAsync(applicationMessage, CancellationToken.None);
}
}
public async void PublishTheme(string serverURL,string Theme,byte[] Data){
var applicationMessage = new MqttApplicationMessageBuilder()
.WithTopic(Theme)
.WithPayload(Data)
.Build();
if(MqttDevices.ContainsKey(serverURL) && MqttDevices[serverURL].IsConnected){
await MqttDevices[serverURL].PublishAsync(applicationMessage, CancellationToken.None);
EG.Print("publish success!");
}
}
public void SendByteData(string serverURL,string theme, byte[] data)
{
this.PublishTheme(serverURL,theme,data);
}
public void SendByteData(string destination, byte[] data)
{
this.SendByteData(destination.GetStrFrontSymbol('|'),destination.GetStrBehindSymbol('|'),data);
}
public void SendStringData(string serverURL,string theme, string data)
{
this.PublishTheme(serverURL,theme,data);
}
public void SendStringData(string destination, string data)
{
this.SendStringData(destination.GetStrFrontSymbol('|'),destination.GetStrBehindSymbol('|'),data);
}
public void SetEncoding(Encoding textEncoding)
{
StringEncoding = textEncoding;
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGMqttExtension{
public static EGMqtt EGMqtt(this IEGFramework self){
return self.GetModule<EGMqtt>();
}
}
}

179
EGFramework/Module/ProtocolTools/Internet/EGSsh.cs

@ -0,0 +1,179 @@ @@ -0,0 +1,179 @@
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Renci.SshNet;
namespace EGFramework{
public class EGSsh : IModule, IProtocolSend, IProtocolReceived
{
public Dictionary<string,SshClient> SshClientDevices { set; get; } = new Dictionary<string, SshClient>();
public string ErrorLogs { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public int TimeOutDelay = 5000;
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.SSHClient){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender,request.req.ToProtocolData());
}else if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
/// <summary>
/// Connect Ssh Server by using username and passwd
/// </summary>
public async Task<bool> ConnectSsh(string host,string username,string password){
try{
//Reconnect
if(SshClientDevices.ContainsKey(host)){
if(SshClientDevices[host].IsConnected){
return true;
}else{
CancellationTokenSource sourceReconnect = new CancellationTokenSource();
CancellationToken tokenReconnect = sourceReconnect.Token;
tokenReconnect.Register(() => EG.Print("Ssh connect timeout!"));
await SshClientDevices[host].ConnectAsync(tokenReconnect);
if(!SshClientDevices[host].IsConnected){
return false;
}else{
return true;
}
}
}
//First Connect
SshClient client = new SshClient(host, username, password);
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
token.Register(() => EG.Print("Ssh connect timeout!"));
source.CancelAfter(TimeOutDelay);
await client.ConnectAsync(token);
if(!client.IsConnected){
return false;
}else{
SshClientDevices.Add(host,client);
}
return true;
}
catch(Exception e){
ErrorLogs = "[ssh connect error]" + e.ToString();
return false;
}
}
/// <summary>
/// Connect Ssh Server by using private key file
/// </summary>
public async Task<bool> ConnectSsh(string host,string username,PrivateKeyFile keyFile){
try{
//Reconnect
if(SshClientDevices.ContainsKey(host)){
if(SshClientDevices[host].IsConnected){
return true;
}else{
CancellationTokenSource sourceReconnect = new CancellationTokenSource();
CancellationToken tokenReconnect = sourceReconnect.Token;
tokenReconnect.Register(() => EG.Print("Ssh connect timeout!"));
await SshClientDevices[host].ConnectAsync(tokenReconnect);
if(!SshClientDevices[host].IsConnected){
return false;
}else{
return true;
}
}
}
//First Connect
SshClient client = new SshClient(host, username, keyFile);
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
token.Register(() => EG.Print("Ssh connect timeout!"));
source.CancelAfter(TimeOutDelay);
await client.ConnectAsync(token);
if(!client.IsConnected){
return false;
}else{
SshClientDevices.Add(host,client);
}
return true;
}
catch(Exception e){
ErrorLogs = "[ssh connect error]" + e.ToString();
return false;
}
}
public void DisconnectSsh(string host){
if(SshClientDevices.ContainsKey(host)){
if (SshClientDevices[host].IsConnected)
{
SshClientDevices[host].Disconnect();
SshClientDevices[host].Dispose();
SshClientDevices.Remove(host);
}
}
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
public void SendByteData(string destination, byte[] data)
{
if(SshClientDevices.ContainsKey(destination)){
if (SshClientDevices[destination].IsConnected)
{
SshCommand cmd = SshClientDevices[destination].RunCommand(StringEncoding.GetString(data));
ResponseMsg receivedMsgs = new ResponseMsg(cmd.Result,StringEncoding.GetBytes(cmd.Result),destination, ProtocolType.SSHClient);
ResponseMsgs.Enqueue(receivedMsgs);
}
}
}
public void SendStringData(string destination, string data)
{
if(SshClientDevices.ContainsKey(destination)){
if (SshClientDevices[destination].IsConnected)
{
SshCommand cmd = SshClientDevices[destination].RunCommand(data);
ResponseMsg receivedMsgs = new ResponseMsg(cmd.Result,StringEncoding.GetBytes(cmd.Result),destination, ProtocolType.SSHClient);
ResponseMsgs.Enqueue(receivedMsgs);
}
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
//throw new System.NotImplementedException();
}
}
public static class CanGetEGSShClientExtension{
public static EGSsh EGSsh(this IEGFramework self){
return self.GetModule<EGSsh>();
}
public static SshClient EGGetSshClient(this IEGFramework self,string host){
return self.GetModule<EGSsh>().SshClientDevices[host];
}
}
}

182
EGFramework/Module/ProtocolTools/Internet/EGTCPClient.cs

@ -0,0 +1,182 @@ @@ -0,0 +1,182 @@
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Net;
namespace EGFramework{
public class EGTCPClient : IModule, IEGFramework, IProtocolSend, IProtocolReceived
{
public Dictionary<string,TcpClient> TCPClientDevices { set; get; } = new Dictionary<string, TcpClient>();
public string ErrorLogs { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.TCPClient){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender.GetHostByIp(),request.sender.GetPortByIp(),request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender.GetHostByIp(),request.sender.GetPortByIp(),request.req.ToProtocolByteData());
}
}
});
}
/// <summary>
/// Connect Tcp client to server with check if target server is listened.
/// </summary>
public async Task<bool> ConnectTCP(string host,int port){
try{
if(!TCPClientDevices.ContainsKey(host + ":" + port)){
TcpClient tcpClient = new TcpClient();
await tcpClient.ConnectAsync(host,port);
//Print("Connect Tcp success in "+tcpClient.Client.RemoteEndPoint.ToString());
TCPClientDevices.Add(host + ":" + port,tcpClient);
_ = HandleClientAsync(tcpClient,host,port);
}else{
if(!TCPClientDevices[host + ":" + port].Connected){
await TCPClientDevices[host + ":" + port].ConnectAsync(host,port);
_ = HandleClientAsync(TCPClientDevices[host + ":" + port],host,port);
}
}
return true;
}
catch(Exception e){
ErrorLogs = "[open port error]" + e.ToString();
return false;
}
}
/// <summary>
/// Disconnect Tcp client to server.
/// </summary>
public void DisconnectTCP(string host,int port){
if(TCPClientDevices.ContainsKey(host + ":" + port)){
if (TCPClientDevices[host + ":" + port].Connected)
{
TCPClientDevices[host + ":" + port].Close();
TCPClientDevices.Remove(host + ":" + port);
}
}else{
//Not found in TCPClientDevices,need add?
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public async void SendByteData(string host,int port,byte[] data){
// if serial port not open,open first
try{
bool result = await ConnectTCP(host,port);
if(result){
await TCPClientDevices[host + ":" + port].GetStream().WriteAsync(data,0,data.Length);
}
}catch(Exception e){
ErrorLogs = "[write error]" + e.ToString();
}
}
public void SendByteData(string destination,byte[] data){
SendByteData(destination.GetHostByIp(),destination.GetPortByIp(),data);
}
public void SendByteDataOnce(string host,int port,byte[] data){
SendByteData(host,port,data);
DisconnectTCP(host,port);
}
public void SendStringData(string host,int port,string str){
SendByteData(host,port,StringEncoding.GetBytes(str));
}
public void SendStringData(string destination,string data){
SendStringData(destination.GetHostByIp(),destination.GetPortByIp(),data);
}
public void SendStringDataOnce(string host,int port,string str){
SendStringData(host,port,str);
DisconnectTCP(host,port);
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
/// <summary>
/// UpdateStatus
/// </summary>
public async void CheckAndRelink(){
foreach(TcpClient tcpClient in TCPClientDevices.Values){
if(!tcpClient.Connected){
await tcpClient.ConnectAsync((IPEndPoint)tcpClient.Client.RemoteEndPoint);
}
}
}
public async Task HandleClientAsync(TcpClient client,string host,int port)
{
try
{
NetworkStream stream = client.GetStream();
string ClientName = host+":"+port;
while (true)
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
break;
}
string data = StringEncoding.GetString(buffer, 0, bytesRead);
byte[] receivedByte = new byte[bytesRead];
Array.Copy(buffer, 0, receivedByte, 0, bytesRead);
ResponseMsg receivedMsgs = new ResponseMsg(data,receivedByte,ClientName, ProtocolType.TCPClient);
ResponseMsgs.Enqueue(receivedMsgs);
//this.EGOnReceivedData(receivedMsgs);
}
DeleteClient(client,host,port);
}
catch (Exception)
{
}
}
public void DeleteClient(TcpClient client,string host,int port)
{
client.Close();
string clientName = host+":"+port;
if (TCPClientDevices.ContainsKey(clientName)) {
TCPClientDevices.Remove(clientName);
}
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGTCPClientExtension{
public static EGTCPClient EGTCPClient(this IEGFramework self){
return self.GetModule<EGTCPClient>();
}
public static TcpClient EGGetTCPClient(this IEGFramework self,string host,int port){
return self.GetModule<EGTCPClient>().TCPClientDevices[host + ":" + port];
}
}
}

167
EGFramework/Module/ProtocolTools/Internet/EGTCPServer.cs

@ -0,0 +1,167 @@ @@ -0,0 +1,167 @@
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace EGFramework{
public class EGTCPServer : IModule, IEGFramework,IProtocolReceived
{
public Dictionary<int,TcpListener> TcpServerDevices { set; get; } = new Dictionary<int, TcpListener>();
public Dictionary<int,bool> IsListening { set; get; } = new Dictionary<int, bool>();
public Dictionary<string, TcpClient> LinkedClients { set; get; } = new Dictionary<string, TcpClient>();
public Dictionary<int, List<string>> LinkedIPs { set; get; } = new Dictionary<int, List<string>>();
public Dictionary<string, int> ClientMappings { set; get; } = new Dictionary<string, int>();
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public EasyEvent<string> OnClientConnect { set; get; } = new EasyEvent<string>();
public EasyEvent<string> OnClientDisconnect { set; get; } = new EasyEvent<string>();
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public string ErrorLogs { set; get; }
public void Init()
{
this.EGRegisterSendAction(request => {
if(request.protocolType == ProtocolType.TCPServer){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
ResponseStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
ResponseByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
public async void StartServer(int port)
{
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port);
TcpListener tcpServer = new TcpListener(ipEndPoint);
if(TcpServerDevices.ContainsKey(port)){
return;
}else{
TcpServerDevices.Add(port,tcpServer);
IsListening.Add(port,true);
}
TcpServerDevices[port].Start();
try
{
while (IsListening[port])
{
TcpClient client = await TcpServerDevices[port].AcceptTcpClientAsync();
LinkedClients.Add(client.Client.RemoteEndPoint.ToString(), client);
OnClientConnect.Invoke(client.Client.RemoteEndPoint.ToString());
if (!LinkedIPs.Keys.Contains(port))
{
LinkedIPs.Add(port, new List<string>());
LinkedIPs[port].Add(client.Client.RemoteEndPoint.ToString());
}
else
{
LinkedIPs[port].Add(client.Client.RemoteEndPoint.ToString());
}
if (!ClientMappings.ContainsKey(client.Client.RemoteEndPoint.ToString()))
{
ClientMappings.Add(client.Client.RemoteEndPoint.ToString(), port);
}
_ = HandleClientAsync(client);
EG.Print("[EGTCPServer]"+port+" Client connected: " + client.Client.RemoteEndPoint.ToString());
}
TcpServerDevices[port].Stop();
}
catch (Exception e)
{
EG.Print("[EGTCPServer]"+port+" Error: " + e.ToString());
}
}
public void EndServer(int port){
IsListening[port] = false;
}
public async Task HandleClientAsync(TcpClient client)
{
try
{
NetworkStream stream = client.GetStream();
string ClientName = client.Client.RemoteEndPoint.ToString();
while (client.Connected)
{
byte[] buffer = new byte[1024];
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
if (bytesRead == 0)
{
break;
}
string data = StringEncoding.GetString(buffer, 0, bytesRead);
ResponseMsg receivedMsgs = new ResponseMsg(data,buffer,ClientName, ProtocolType.TCPServer);
//await Task.Run(() => OnDataReceived(receivedMsgs)).ConfigureAwait(false);
//this.EGOnReceivedData(receivedMsgs);
ResponseMsgs.Enqueue(receivedMsgs);
}
//await Task.Run(() => DeleteClient(client)).ConfigureAwait(false);
EG.Print("[EGTCPServer] Client Disconnected: " + client.Client.LocalEndPoint.ToString() + "--" + client.Client.RemoteEndPoint.ToString());
int port = ClientMappings[client.Client.RemoteEndPoint.ToString()];
ClientMappings.Remove(client.Client.RemoteEndPoint.ToString());
LinkedIPs[port].Remove(client.Client.RemoteEndPoint.ToString());
DeleteClient(client);
client.Close();
}
catch (Exception)
{
}
}
public async void ResponseByteData(string clientName,byte[] data){
// if serial port not open,open first
try{
await this.LinkedClients[clientName]?.GetStream().WriteAsync(data, 0, data.Length);
}catch(Exception e){
ErrorLogs = "[write error]" + e.ToString();
}
}
public void ResponseStringData(string clientName,string str){
byte[] buffer = StringEncoding.GetBytes(str);
ResponseByteData(clientName,buffer);
}
public void DeleteClient(TcpClient client)
{
string clientName = client.Client.RemoteEndPoint.ToString();
if (LinkedClients.ContainsKey(clientName)) {
LinkedClients.Remove(clientName);
}
OnClientDisconnect.Invoke(clientName);
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGTCPServerExtension{
public static EGTCPServer EGTCPServer(this IEGFramework self){
return self.GetModule<EGTCPServer>();
}
public static void EGTCPServerListen(this IEGFramework self ,int port){
self.GetModule<EGTCPServer>().StartServer(port);
}
public static void EGTCPServerEndListen(this IEGFramework self ,int port){
self.GetModule<EGTCPServer>().EndServer(port);
}
}
}

137
EGFramework/Module/ProtocolTools/Internet/EGUDP.cs

@ -0,0 +1,137 @@ @@ -0,0 +1,137 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
namespace EGFramework{
public class EGUDP : IEGFramework, IModule, IProtocolSend, IProtocolReceived
{
public Dictionary<int,UdpClient> UDPDevices { set; get; } = new Dictionary<int, UdpClient>();
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request => {
if(request.protocolType == ProtocolType.UDP){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender.GetHostByIp(),request.sender.GetPortByIp(),request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender.GetHostByIp(),request.sender.GetPortByIp(),request.req.ToProtocolByteData());
}
}
});
}
public void ListenUDP(int localPort){
if (!UDPDevices.ContainsKey(localPort)) {
try
{
UdpClient udpDevice = new UdpClient(localPort);
UDPDevices.Add(localPort,udpDevice);
//udpDevice.EnableBroadcast = true;
HandleUDPListenAsync(udpDevice);
//StartListening(localPort);
}
catch (Exception e){
EG.Print("Error" + e);
}
}
}
public void EndListenUDP(int localPort){
if (UDPDevices.ContainsKey(localPort)) {
UDPDevices[localPort].Close();
UDPDevices.Remove(localPort);
}
}
public async void HandleUDPListenAsync(UdpClient client)
{
try
{
//EG.Print("UDP listened in "+((IPEndPoint)client.Client.LocalEndPoint).Port);
while (true)
{
UdpReceiveResult data = await client.ReceiveAsync();
string dataStr = StringEncoding.GetString(data.Buffer);
ResponseMsg receivedMsgs = new ResponseMsg(dataStr,data.Buffer,data.RemoteEndPoint.ToString(), ProtocolType.UDP);
//this.EGOnReceivedData(receivedMsgs);
ResponseMsgs.Enqueue(receivedMsgs);
}
}
catch (Exception e)
{
EG.Print("Listen false by:"+e);
}
}
public void SendByteData(string host,int port,byte[] data){
UdpClient udpClient;
if(UDPDevices.Count>0){
udpClient = UDPDevices.First().Value;
}else{
udpClient = new UdpClient();
}
try{
EG.Print(udpClient.EnableBroadcast);
udpClient.Send(data, data.Length, host, port);
}
catch ( Exception e ){
EG.Print(e.ToString());
}
if(UDPDevices.Count<=0){
udpClient.Close();
udpClient.Dispose();
}
}
public void SendByteData(string destination,byte[] data){
SendByteData(destination.GetHostByIp(),destination.GetPortByIp(),data);
}
public void SendStringData(string host,int port,string data){
byte[] buffer = StringEncoding.GetBytes(data);
this.SendByteData(host,port,buffer);
}
public void SendStringData(string destination,string data){
SendStringData(destination.GetHostByIp(),destination.GetPortByIp(),data);
}
public void SetEncoding(Encoding textEncoding){
StringEncoding = textEncoding;
}
public void BroadCastUDPMessage(string host,int port,byte[] message){
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return ResponseMsgs;
}
}
public static class CanGetEGUDPExtension{
public static EGUDP EGUDP(this IEGFramework self){
return self.GetModule<EGUDP>();
}
public static void EGUDPListen(this IEGFramework self ,int port){
self.GetModule<EGUDP>().ListenUDP(port);
}
public static void EGUDPEndListen(this IEGFramework self ,int port){
self.GetModule<EGUDP>().EndListenUDP(port);
}
}
}

139
EGFramework/Module/ProtocolTools/Internet/EGWebSocketClient.cs

@ -0,0 +1,139 @@ @@ -0,0 +1,139 @@
using System;
using System.Collections.Concurrent;
using System.Text;
using System.Net.Sockets;
using System.Collections.Generic;
using System.Net.WebSockets;
using System.Threading.Tasks;
namespace EGFramework{
public class EGWebSocketClient : IEGFramework, IModule, IProtocolSend, IProtocolReceived
{
public Dictionary<string,ClientWebSocket> WebSocketClientDevices { set; get; } = new Dictionary<string, ClientWebSocket>();
public string ErrorLogs { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.TCPClient){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
/// <summary>
/// Connect Websocket client to server with check if target server is listened.
/// </summary>
public async Task<bool> ConnectWebSocket(string address){
try{
Uri uri = new Uri(address);
if(!WebSocketClientDevices.ContainsKey(address)){
ClientWebSocket ws = new ClientWebSocket();
await ws.ConnectAsync(uri,default);
//Print("Connect Tcp success in "+tcpClient.Client.RemoteEndPoint.ToString());
WebSocketClientDevices.Add(address,ws);
_ = HandleClientAsync(ws,address);
}else{
if(WebSocketClientDevices[address].State != WebSocketState.Open){
await WebSocketClientDevices[address].ConnectAsync(uri,default);
_ = HandleClientAsync(WebSocketClientDevices[address],address);
}
}
return true;
}
catch(Exception e){
ErrorLogs = "[open port error]" + e.ToString();
return false;
}
}
/// <summary>
/// Disconnect Websocket client to server.
/// </summary>
public void DisconnectWebsocket(string address){
if(WebSocketClientDevices.ContainsKey(address)){
if (WebSocketClientDevices[address].State == WebSocketState.Open)
{
WebSocketClientDevices[address].CloseAsync(WebSocketCloseStatus.NormalClosure,"Client closed",default);
WebSocketClientDevices[address].Dispose();
WebSocketClientDevices.Remove(address);
}
}else{
//Not found in Websocket client,need add?
}
}
public async Task HandleClientAsync(ClientWebSocket client,string address)
{
try
{
string ClientName = address;
while (true)
{
byte[] buffer = new byte[1024];
WebSocketReceiveResult result = await client.ReceiveAsync(buffer, default);
if (result.Count == 0)
{
break;
}
string data = StringEncoding.GetString(buffer, 0, result.Count);
byte[] receivedByte = new byte[result.Count];
Array.Copy(buffer, 0, receivedByte, 0, result.Count);
ResponseMsg receivedMsgs = new ResponseMsg(data,receivedByte,ClientName, ProtocolType.WebSocketClient);
ResponseMsgs.Enqueue(receivedMsgs);
//this.EGOnReceivedData(receivedMsgs);
}
DisconnectWebsocket(address);
}
catch (Exception)
{
}
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return this.ResponseMsgs;
}
public async void SendByteDataAsync(string address,byte[] data){
// if serial port not open,open first
try{
bool result = await ConnectWebSocket(address);
if(result){
await WebSocketClientDevices[address].SendAsync(data,WebSocketMessageType.Binary,true,default);
}
}catch(Exception e){
ErrorLogs = "[write error]" + e.ToString();
}
}
public void SendByteData(string destination, byte[] data)
{
SendByteDataAsync(destination, data);
}
public void SendStringData(string destination, string data)
{
SendByteData(destination,StringEncoding.GetBytes(data));
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
}

101
EGFramework/Module/ProtocolTools/Other/EGFileStream.cs

@ -0,0 +1,101 @@ @@ -0,0 +1,101 @@
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections.Concurrent;
namespace EGFramework{
public class EGFileStream : IEGFramework, IModule,IProtocolSend,IProtocolReceived
{
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.FileStream){
if(request.req.ToProtocolData() != "" && request.req.ToProtocolData() != null){
this.SendStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData().Length > 0 && request.req.ToProtocolByteData() != null){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
public async void SendByteData(string destination, byte[] data)
{
string path = destination;
try
{
if (File.Exists(path))
{
File.Delete(path);
}
FileStream fileStream = File.Create(path);
await fileStream.WriteAsync(data,0,data.Length);
fileStream.Close();
await fileStream.DisposeAsync();
}
catch (System.Exception)
{
throw;
}
//throw new System.NotImplementedException();
}
public void SendStringData(string destination, string data)
{
SendByteData(destination,StringEncoding.GetBytes(data));
//throw new System.NotImplementedException();
}
/// <summary>
/// Read file by FileStream and return received a byte data or string data from file
/// </summary>
/// <param name="path">File Path</param>
public async void ReadFromFile(string path){
try
{
FileStream fileStream = new FileStream(path,FileMode.Open);
byte[] buffer = new byte[fileStream.Length];
await fileStream.ReadAsync(buffer, 0, (int)fileStream.Length);
fileStream.Close();
await fileStream.DisposeAsync();
string data = StringEncoding.GetString(buffer);
ResponseMsg receivedMsgs = new ResponseMsg(data,buffer,path, ProtocolType.FileStream);
ResponseMsgs.Enqueue(receivedMsgs);
}
catch (System.Exception e)
{
EG.Print("e:" + e);
throw;
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return this.ResponseMsgs;
}
}
public static class CanGetEGFileStreamExtension{
public static EGFileStream EGFileStream(this IEGFramework self){
return self.GetModule<EGFileStream>();
}
public static void EGReadFromFile(this IEGFramework self,string path){
self.GetModule<EGFileStream>().ReadFromFile(path);
}
}
}

124
EGFramework/Module/ProtocolTools/Other/EGProcess.cs

@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Threading.Tasks;
namespace EGFramework{
public class EGProcess : IEGFramework, IModule, IProtocolSend, IProtocolReceived
{
public Dictionary<string,Process> Processes { set; get; } = new Dictionary<string, Process>();
public string ErrorLogs { set; get; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.Process){
if(request.req.ToProtocolData() != null && request.req.ToProtocolData() != ""){
this.SendStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData() != null && request.req.ToProtocolByteData().Length > 0){
this.SendByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
/// <summary>
/// Connect process program with check if target program is exist.
/// </summary>
public void InitProcess(string processName){
try{
if(!Processes.ContainsKey(processName)){
Process process = new Process();
if(processName.GetStrFrontSymbol(' ') == ""){
process.StartInfo.FileName = processName.GetStrBehindSymbol(' ');
}else{
process.StartInfo.FileName = processName.GetStrFrontSymbol(' ');
process.StartInfo.Arguments = processName.GetStrBehindSymbol(' ');; // Add any arguments if needed
}
EG.Print("[open process]"+process.StartInfo.FileName+" "+process.StartInfo.Arguments);
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.CreateNoWindow = true;
process.EnableRaisingEvents = true;
process.OutputDataReceived += (sender, e) => {
if (!string.IsNullOrEmpty(e.Data)) {
try
{
ResponseMsgs.Enqueue(new ResponseMsg { sender = processName, stringData = e.Data });
}
catch (Exception err)
{
ErrorLogs = "[process output error]" + err.ToString();
EG.Print(ErrorLogs);
}
}
};
process.Exited += (sender, e) => {
Processes.Remove(processName);
};
Processes.Add(processName,process);
process.Start();
process.BeginOutputReadLine();
}
}
catch(Exception e){
ErrorLogs = "[open process error]" + e.ToString();
EG.Print(ErrorLogs);
}
}
public void CloseProcess(string processName){
if(Processes.ContainsKey(processName)){
Processes[processName].Kill();
Processes.Remove(processName);
EG.Print("[close process]"+processName);
}
}
public void SetEncoding(Encoding textEncoding)
{
this.StringEncoding = textEncoding;
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return this.ResponseMsgs;
}
public void SendByteData(string destination, byte[] data)
{
Processes[destination].StandardInput.WriteLine(data);
}
public void SendStringData(string destination, string data)
{
Processes[destination].StandardInput.WriteLine(data);
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGProcessExtension{
public static EGProcess EGProcess(this IEGFramework self){
return self.GetModule<EGProcess>();
}
public static Process EGGetSshClient(this IEGFramework self,string processName){
return self.GetModule<EGProcess>().Processes[processName];
}
}
}

299
EGFramework/Module/ProtocolTools/ProtocolExtension/EGDnsExtension.cs

@ -0,0 +1,299 @@ @@ -0,0 +1,299 @@
using System;
using System.Collections.Generic;
namespace EGFramework{
/// <summary>
/// Support a class for analysis the .local(mdns) or other www.com(dns) protocol to get the message,
/// mdns protocol format type reference from https://github.com/richardschneider/net-mdns
/// nuget package is Makaretu.Dns.Multicast
/// mdns reference from https://www.rfc-editor.org/rfc/rfc6763.html
/// </summary>
public static class EGDnsExtension
{
public const string DefaultDnsServer = "1.1.1.1";
public const int DefaultDnsPort = 53;
public const string DefaultMDnsServerIpv4 = "224.0.0.251";
public const string DefaultMDnsServerIpv6 = "FF02::FB";
public const int DefaultMDnsPort = 5353;
public const string DNS_SRV_RR = "_services._dns-sd._udp.local";
}
/// <summary>
/// Dns's OpCode
/// </summary>
public enum DnsOpCode : ushort{
/// <summary>
/// Standard query.
/// </summary>
Query = 0x0000,
/// <summary>
/// Inverse query (obsolete), see https://tools.ietf.org/html/rfc3425.
/// </summary>
InverseQuery = 0x0800,
/// <summary>
/// A server status request.
/// </summary>
Status = 0x1000,
/// <summary>
/// Zone change, see https://tools.ietf.org/html/rfc1996.
/// </summary>
Notify = 0x2000,
/// <summary>
/// Update message, see https://tools.ietf.org/html/rfc2136.
/// </summary>
Update = 0x2800
}
/// <summary>
/// A resource record or query type.
/// </summary>
public enum DnsType{
/// <summary>
/// A host address.
/// </summary>
A = 1,
/// <summary>
/// An authoritative name server.
/// </summary>
NS = 2,
/// <summary>
/// The canonical name for an alias.
/// </summary>
CNAME = 5,
/// <summary>
/// Marks the start of a zone of authority.
/// </summary>
SOA = 6,
/// <summary>
/// A mailbox domain name (EXPERIMENTAL).
/// </summary>
MB = 7,
/// <summary>
/// A mail group member (EXPERIMENTAL).
/// </summary>
MG = 8,
/// <summary>
/// A mailbox rename domain name (EXPERIMENTAL).
/// </summary>
MR = 9,
/// <summary>
/// A Null resource record (EXPERIMENTAL).
/// </summary>
NULL = 10,
/// <summary>
/// A well known service description.
/// </summary>
WKS = 11,
/// <summary>
/// A domain name pointer.
/// </summary>
PTR = 12,
/// <summary>
/// Host information.
/// </summary>
HINFO = 13,
/// <summary>
/// Mailbox or mail list information.
/// </summary>
MINFO = 14,
/// <summary>
/// Mail exchange.
/// </summary>
MX = 15,
/// <summary>
/// Text resources.
/// </summary>
TXT = 16,
/// <summary>
/// Responsible Person.
/// </summary>
RP = 17,
/// <summary>
/// AFS Data Base location.
/// </summary>
AFSDB = 18,
/// <summary>
/// An IPv6 host address.
/// </summary>
AAAA = 28,
/// <summary>
/// A resource record which specifies the location of the server(s) for a specific protocol and domain.
/// </summary>
SRV = 33,
/// <summary>
/// Maps an entire domain name.
/// </summary>
DNAME = 39,
/// <summary>
/// Option record.
/// </summary>
OPT = 41,
/// <summary>
/// Delegation Signer.
/// </summary>
DS = 43,
/// <summary>
/// Signature for a RRSET with a particular name, class, and type.
/// </summary>
RRSIG = 46,
/// <summary>
/// Next secure owener.
/// </summary>
NSEC = 47,
/// <summary>
/// Public key cryptography to sign and authenticate resource records.
/// </summary>
DNSKEY = 48,
/// <summary>
/// Authenticated next secure owner.
/// </summary>
NSEC3 = 50,
/// <summary>
/// Parameters needed by authoritative servers to calculate hashed owner names.
/// </summary>
NSEC3PARAM = 51,
/// <summary>
/// Shared secret key.
/// </summary>
TKEY = 249,
/// <summary>
/// Transactional Signature.
/// </summary>
TSIG = 250,
/// <summary>
/// A request for a transfer of an entire zone.
/// </summary>
AXFR = 252,
/// <summary>
/// A request for mailbox-related records (MB, MG or MR).
/// </summary>
MAILB = 253,
/// <summary>
/// A request for any record(s).
/// </summary>
ANY = 255,
/// <summary>
/// A Uniform Resource Identifier (URI) resource record.
/// </summary>
URI = 256,
/// <summary>
/// A certification authority authorization.
/// </summary>
CAA = 257
}
/// <summary>
/// The values are maintained by IANA at https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml#dns-parameters-2.
/// </summary>
public enum DnsClass : ushort
{
/// <summary>
/// The Internet.
/// </summary>
IN = 1,
/// <summary>
/// The CSNET class (Obsolete - used only for examples insome obsolete RFCs).
/// </summary>
CS = 2,
/// <summary>
/// The CHAOS class.
/// </summary>
CH = 3,
/// <summary>
/// Hesiod[Dyer 87].
/// </summary>
HS = 4,
/// <summary>
/// Used in UPDATE message to signify no class.
/// </summary>
None = 254,
/// <summary>
/// Only used in QCLASS.
/// </summary>
ANY = 255
}
public struct DnsHead{
}
/// <summary>
/// MDns Head
/// | TransactionID (2 bytes) | OpCode (2 bytes) | Dns Sign (2 byte)
/// </summary>
public struct MDnsHead {
/// <summary>
///
/// </summary>
/// <value></value>
public ushort TransactionID { set; get; }
/// <summary>
/// The requested operation.
/// </summary>
/// <value></value>
public DnsOpCode OpCode { set; get; }
#region Sign Code
/// <summary>
/// A one bit field that specifies whether this message is a query(0), or a response(1).
/// </summary>
/// <value></value>
public bool QR { set; get; }
public bool AA { set; get; }
public bool TC { set; get; }
public bool RD { set; get; }
public bool RA { set; get; }
public byte OpCode4Bit { set; get; }
/// <summary>
/// Reserved for future use.
/// </summary>
/// <value>Must be zero in all queries and responses.</value>
public byte Z { set; get; }
/// <summary>
/// Authentic data.
/// </summary>
/// <value> true if the response data is authentic; otherwise, false.</value>
public bool AD { get; set; }
/// <summary>
/// Checking disabled.
/// </summary>
/// <value>true if the query does not require authenticated data; otherwise, false.</value>
public bool CD { get; set; }
#endregion
}
public struct DnsQuestionRequest : IRequest
{
public byte ReplyCode { set; get; }
public ushort QuestionsCount { set; get; }
public ushort AnswerRRs { set; get; }
public ushort AuthorityRRs { set; get; }
public ushort Additional { set; get; }
public List<byte[]> Data { set; get; }
public byte QuestionType { set; get; }
public byte QuestionClass { set; get; }
public byte[] ToProtocolByteData()
{
throw new NotImplementedException();
}
public string ToProtocolData()
{
throw new NotImplementedException();
}
}
}

899
EGFramework/Module/ProtocolTools/ProtocolExtension/EGModbusExtension.cs

@ -0,0 +1,899 @@ @@ -0,0 +1,899 @@
using System;
using System.Linq;
namespace EGFramework{
/// <summary>
/// some extensions function about Modbus-TCP and Modbus-RTU (Physic layer used RS-485)
/// not include Modbus-ASCII,because LRC verify not developed
/// </summary>
public static class EGModbusExtension
{
//Send Protocol
//---------Modbus-TCP's Prefix---------
//[00 00 00 00 00 06] 01 03 00 00 00 08
//00 00 ----- info head (check for reply Any things can be defined)
//xx xx 00 00 00 06 info length ( Max length 65535 )
public static byte[] MakeModbusTCPPrefix(this object self,ushort messageId,uint length){
return messageId.ToBytes().Concat(length.ToBytes()).ToArray();
}
public static byte[] MakeModbusTCPPrefix(this object self,ushort messageId,byte[] sendData){
return messageId.ToBytes().Concat(((uint)sendData.Length).ToBytes()).ToArray();
}
}
/// <summary>
/// Modbus FunctionCode
/// 0x01 => Read Coils ---- OK
/// 0x02 => Read Discrete input ---- OK
/// 0x03 => Read Holding registers ---- OK
/// 0x04 => Read Input registers ---- OK
/// 0x05 => Write Single Coils ---- OK
/// 0x06 => Write Single Holding registers ---- OK
/// 0x0F => Write Multi Coils ---- OK
/// 0x10 => Write Multi Holding registers ---- OK
/// </summary>
#region Modbus TCP Request and Response
public class ModbusTCP_ReadCoils : IRequest
{
public const byte FunctionCode = 0x01;
public const ushort MessageId = 0xFF01;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusTCP_ReadCoils(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>2000){
ReadCount = 2000;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_ReadDiscreteInput : IRequest
{
public const byte FunctionCode = 0x02;
public const ushort MessageId = 0xFF02;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusTCP_ReadDiscreteInput(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>2000){
ReadCount = 2000;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_ReadHoldingRegisters : IRequest
{
public const byte FunctionCode = 0x03;
public const ushort MessageId = 0xFF03;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 125</param>
public ModbusTCP_ReadHoldingRegisters(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>125){
ReadCount = 125;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_ReadInputRegisters : IRequest
{
public const byte FunctionCode = 0x04;
public const ushort MessageId = 0xFF04;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 125</param>
public ModbusTCP_ReadInputRegisters(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>125){
ReadCount = 125;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_WriteSingleCoil : IRequest
{
public const byte FunctionCode = 0x05;
public const ushort MessageId = 0xFF05;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public bool Value { set; get; }
public ModbusTCP_WriteSingleCoil(byte deviceAddress,ushort registerAddress,bool value){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
Value = value;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
byte[] registerValues = {0x00,0x00};
if(Value){
registerValues[0]=0xFF;
}
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_WriteSingleHoldingRegister : IRequest
{
public const byte FunctionCode = 0x06;
public const ushort MessageId = 0xFF06;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort Value { set; get; }
public ModbusTCP_WriteSingleHoldingRegister(byte deviceAddress,ushort registerAddress,ushort value){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
Value = value;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = this.MakeModbusTCPPrefix(MessageId,6);
protocolRequest = protocolRequest.Append(DeviceAddress).ToArray();
protocolRequest = protocolRequest.Append(FunctionCode).ToArray();
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
byte[] registerValues = Value.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_WriteMultiCoil : IRequest{
public const byte FunctionCode = 0x0F;
public const ushort MessageId = 0xFF0F;
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public bool[] Values { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress">usual use 0x01 for device address</param>
/// <param name="registerStartAddress"></param>
/// <param name="values">Values length should be less than 2000</param>
public ModbusTCP_WriteMultiCoil(byte deviceAddress,ushort registerStartAddress,bool[] values){
DeviceAddress = deviceAddress;
RegisterStartAddress = registerStartAddress;
Values = values;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = {DeviceAddress,FunctionCode};
protocolRequest = protocolRequest.Concat(RegisterStartAddress.ToBytes()).ToArray();
protocolRequest = protocolRequest.Concat(((ushort)Values.Length).ToBytes()).ToArray();
//Length range should be 1-2000 0x0001-0x07D0,otherwise delete the data after 2000
if(Values.Length>2000){
bool[] SourceValues = Values;
Values = new bool[2000];
Array.Copy(Values,0,SourceValues,0,2000);
}
//bool array 2000 => byte array 250
byte[] valueGroup = Values.ToByteArray();
byte valueLength = (byte)valueGroup.Length;
protocolRequest = protocolRequest.Append(valueLength).ToArray();
protocolRequest = protocolRequest.Concat(valueGroup).ToArray();
byte[] protocolPrefix = this.MakeModbusTCPPrefix(MessageId,protocolRequest);
protocolRequest = protocolPrefix.Concat(protocolRequest).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
/// <summary>
/// Start write at Register start address,such as 0x03,write order by order like 0x03,0x04,0x05...,write count is the value array length
/// </summary>
public class ModbusTCP_WriteMultiHoldingRegister : IRequest
{
public const byte FunctionCode = 0x10;
public const ushort MessageId = 0xFF10;
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public ushort[] Values { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress">usual use 0x01 for device address</param>
/// <param name="registerStartAddress"></param>
/// <param name="values">Values length should be less than 125</param>
public ModbusTCP_WriteMultiHoldingRegister(byte deviceAddress,ushort registerStartAddress,ushort[] values){
DeviceAddress = deviceAddress;
RegisterStartAddress = registerStartAddress;
Values = values;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = {DeviceAddress,FunctionCode};
protocolRequest = protocolRequest.Concat(RegisterStartAddress.ToBytes()).ToArray();
protocolRequest = protocolRequest.Concat(((ushort)Values.Length).ToBytes()).ToArray();
//Length range should be 1-125 0x0001-0x07D,otherwise delete the data after 125
if(Values.Length>125){
ushort[] SourceValues = Values;
Values = new ushort[125];
Array.Copy(Values,0,SourceValues,0,125);
}
//ushort array 125 => byte array 250
byte[] valueGroup = {};
foreach(ushort value in Values){
byte[] registerValues = value.ToBytes();
valueGroup = valueGroup.Concat(registerValues).ToArray();
}
byte valueLength = (byte)valueGroup.Length;
protocolRequest = protocolRequest.Append(valueLength).ToArray();
protocolRequest = protocolRequest.Concat(valueGroup).ToArray();
byte[] protocolPrefix = this.MakeModbusTCPPrefix(MessageId,protocolRequest);
protocolRequest = protocolPrefix.Concat(protocolRequest).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusTCP_Response : IResponse
{
public bool[] Coil { set; get; }
public bool[] DiscreteInput { set; get; }
public ushort[] HoldingRegister { set; get; }
public ushort[] InputRegister { set; get; }
public byte FunctionCode { set; get; }
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public uint DataLength { set; get; }
public byte[] SourceData { set; get; }
public byte[] SourceValueData { set; get; }
public ModbusFunctionType FunctionType { set; get; }
public ModbusErrorCode ErrorCode { set; get; }
public bool IsError { set; get; }
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
if(protocolBytes==null && protocolBytes.Length < 8){
return false;
}
SourceData = protocolBytes;
DeviceAddress = protocolBytes[6];
FunctionType = (ModbusFunctionType)protocolBytes[7];
if(FunctionCode == 0x83){
ErrorCode = (ModbusErrorCode)protocolBytes[2];
IsError = true;
return true;
}
byte[] dataLength = new byte[4];
Array.Copy(protocolBytes,2,dataLength,0,4);
DataLength = dataLength.ToUINT();
if(protocolBytes.Length != DataLength+6){
return false;
}
//every response's start should be 0xff,because the request's start is 0xff
if(protocolBytes[0]==0xff){
switch(FunctionType){
case ModbusFunctionType.ReadCoil:
byte readCoilLength = protocolBytes[8];
byte[] CoilBytes = new byte[readCoilLength];
Array.Copy(protocolBytes,9,CoilBytes,0,readCoilLength);
SourceValueData = CoilBytes;
Coil = CoilBytes.ToBoolArray();
return true;
case ModbusFunctionType.ReadDiscreteInput:
byte readDiscreteInputLength = protocolBytes[8];
byte[] DiscreteInputBytes = new byte[readDiscreteInputLength];
Array.Copy(protocolBytes,9,DiscreteInputBytes,0,readDiscreteInputLength);
SourceValueData = DiscreteInputBytes;
DiscreteInput = DiscreteInputBytes.ToBoolArray();
return true;
case ModbusFunctionType.ReadHoldingRegisters:
byte readHoldingRegistersLength = protocolBytes[8];
byte[] HoldingRegistersBytes = new byte[readHoldingRegistersLength];
Array.Copy(protocolBytes,9,HoldingRegistersBytes,0,readHoldingRegistersLength);
SourceValueData = HoldingRegistersBytes;
HoldingRegister = HoldingRegistersBytes.ToUShortArray();
return true;
case ModbusFunctionType.ReadInputRegisters:
byte readInputRegistersLength = protocolBytes[8];
byte[] InputRegistersBytes = new byte[readInputRegistersLength];
Array.Copy(protocolBytes,9,InputRegistersBytes,0,readInputRegistersLength);
SourceValueData = InputRegistersBytes;
InputRegister = InputRegistersBytes.ToUShortArray();
return true;
case ModbusFunctionType.WriteSingleCoil:
return true;
case ModbusFunctionType.WriteSingleHoldingRegister:
return true;
case ModbusFunctionType.WriteMultiCoil:
return true;
case ModbusFunctionType.WriteMultiHoldingRegister:
return true;
default:
return false;
}
}
}
catch (Exception)
{
return false;
}
return false;
}
}
#endregion
#region Modbus RTU Request and Response,Used RS-485 for Physic layer
public class ModbusRTU_ReadCoils : IRequest{
public const byte FunctionCode = 0x01;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusRTU_ReadCoils(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>2000){
ReadCount = 2000;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_ReadDiscreteInput : IRequest{
public const byte FunctionCode = 0x02;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusRTU_ReadDiscreteInput(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>2000){
ReadCount = 2000;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_ReadHoldingRegisters : IRequest{
public const byte FunctionCode = 0x03;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
public ModbusRTU_ReadHoldingRegisters()
{
}
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusRTU_ReadHoldingRegisters(byte deviceAddress, ushort registerAddress, ushort readCount)
{
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>125){
ReadCount = 125;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_ReadInputRegisters : IRequest{
public const byte FunctionCode = 0x04;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort ReadCount { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress"></param>
/// <param name="registerAddress"></param>
/// <param name="readCount">Read count should be less than 2000</param>
public ModbusRTU_ReadInputRegisters(byte deviceAddress,ushort registerAddress,ushort readCount){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
ReadCount = readCount;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
if(ReadCount>125){
ReadCount = 125;
}
byte[] registerValues = ReadCount.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_WriteSingleCoil : IRequest{
public const byte FunctionCode = 0x05;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public bool Value { set; get; }
public ModbusRTU_WriteSingleCoil(byte deviceAddress,ushort registerAddress,bool value){
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
Value = value;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
byte[] registerValues = {0x00,0x00};
if(Value){
registerValues[0]=0xFF;
}
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_WriteSingleHoldingRegister : IRequest{
public const byte FunctionCode = 0x06;
public byte DeviceAddress { set; get; }
public ushort RegisterAddress { set; get; }
public ushort Value { set; get; }
public ModbusRTU_WriteSingleHoldingRegister()
{
}
public ModbusRTU_WriteSingleHoldingRegister(byte deviceAddress, ushort registerAddress, ushort value)
{
DeviceAddress = deviceAddress;
RegisterAddress = registerAddress;
Value = value;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = { DeviceAddress , FunctionCode };
protocolRequest = protocolRequest.Concat(RegisterAddress.ToBytes()).ToArray();
byte[] registerValues = Value.ToBytes();
protocolRequest = protocolRequest.Concat(registerValues).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_WriteMultiCoil : IRequest{
public const byte FunctionCode = 0x0F;
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public bool[] Values { set; get; }
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress">usual use 0x01 for device address</param>
/// <param name="registerStartAddress"></param>
/// <param name="values">Values length should be less than 2000</param>
public ModbusRTU_WriteMultiCoil(byte deviceAddress,ushort registerStartAddress,bool[] values){
DeviceAddress = deviceAddress;
RegisterStartAddress = registerStartAddress;
Values = values;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = {DeviceAddress,FunctionCode};
protocolRequest = protocolRequest.Concat(RegisterStartAddress.ToBytes()).ToArray();
protocolRequest = protocolRequest.Concat(((ushort)Values.Length).ToBytes()).ToArray();
//Length range should be 1-2000 0x0001-0x07D0,otherwise delete the data after 2000
if(Values.Length>2000){
bool[] SourceValues = Values;
Values = new bool[2000];
Array.Copy(Values,0,SourceValues,0,2000);
}
//bool array 2000 => byte array 250
byte[] valueGroup = Values.ToByteArray();
byte valueLength = (byte)valueGroup.Length;
protocolRequest = protocolRequest.Append(valueLength).ToArray();
protocolRequest = protocolRequest.Concat(valueGroup).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
/// <summary>
/// Start write at Register start address,such as 0x03,write order by order like 0x03,0x04,0x05...,write count is the value array length
/// </summary>
public class ModbusRTU_WriteMultiHoldingRegister : IRequest
{
public const byte FunctionCode = 0x10;
public const ushort MessageId = 0xFF10;
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public ushort[] Values { set; get; }
public ModbusRTU_WriteMultiHoldingRegister()
{
}
/// <summary>
/// Construct the protocol
/// </summary>
/// <param name="deviceAddress">usual use 0x01 for device address</param>
/// <param name="registerStartAddress"></param>
/// <param name="values">Values length should be less than 125</param>
public ModbusRTU_WriteMultiHoldingRegister(byte deviceAddress, ushort registerStartAddress, ushort[] values)
{
DeviceAddress = deviceAddress;
RegisterStartAddress = registerStartAddress;
Values = values;
}
public byte[] ToProtocolByteData()
{
byte[] protocolRequest = {DeviceAddress,FunctionCode};
protocolRequest = protocolRequest.Concat(RegisterStartAddress.ToBytes()).ToArray();
protocolRequest = protocolRequest.Concat(((ushort)Values.Length).ToBytes()).ToArray();
//Length range should be 1-125 0x0001-0x07D,otherwise delete the data after 125
if(Values.Length>125){
ushort[] SourceValues = Values;
Values = new ushort[125];
Array.Copy(Values,0,SourceValues,0,125);
}
//ushort array 125 => byte array 250
byte[] valueGroup = {};
foreach(ushort value in Values){
byte[] registerValues = value.ToBytes();
valueGroup = valueGroup.Concat(registerValues).ToArray();
}
byte valueLength = (byte)valueGroup.Length;
protocolRequest = protocolRequest.Append(valueLength).ToArray();
protocolRequest = protocolRequest.Concat(valueGroup).ToArray();
protocolRequest = protocolRequest.Concat(protocolRequest.CalculateCRC16Modbus().ToBytes()).ToArray();
return protocolRequest;
}
public string ToProtocolData()
{
return "";
}
}
public class ModbusRTU_Response : IResponse
{
public bool[] Coil { set; get; }
public bool[] DiscreteInput { set; get; }
public ushort[] HoldingRegister { set; get; }
public ushort[] InputRegister { set; get; }
public byte FunctionCode { set; get; }
public byte DeviceAddress { set; get; }
public ushort RegisterStartAddress { set; get; }
public byte[] SourceData { set; get; }
public byte[] SourceValueData { set; get; }
public ModbusFunctionType FunctionType { set; get; }
public ModbusErrorCode ErrorCode { set; get; }
public bool IsError { set; get; }
public virtual bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
if(protocolBytes==null && protocolBytes.Length < 4){
return false;
}
SourceData = protocolBytes;
DeviceAddress = protocolBytes[0];
FunctionCode = protocolBytes[1];
FunctionType = (ModbusFunctionType)protocolBytes[1];
if(FunctionCode >= 0x80){
ErrorCode = (ModbusErrorCode)protocolBytes[2];
IsError = true;
return true;
}
//check crc verify is success
byte[] resultArray = new byte[protocolBytes.Length - 2];
Array.Copy(protocolBytes, 0, resultArray, 0, protocolBytes.Length - 2);
byte[] crcArray = new byte[2];
Array.Copy(protocolBytes, protocolBytes.Length - 2, crcArray, 0, 2);
if(resultArray.CalculateCRC16Modbus()!=crcArray.ToUShort()){
return false;
}
//every response's start should be 0xff,because the request's start is 0xff
switch(FunctionType){
case ModbusFunctionType.ReadCoil:
byte readCoilLength = protocolBytes[2];
byte[] CoilBytes = new byte[readCoilLength];
Array.Copy(protocolBytes,3,CoilBytes,0,readCoilLength);
SourceValueData = CoilBytes;
Coil = CoilBytes.ToBoolArray();
return true;
case ModbusFunctionType.ReadDiscreteInput:
byte readDiscreteInputLength = protocolBytes[2];
byte[] DiscreteInputBytes = new byte[readDiscreteInputLength];
Array.Copy(protocolBytes,3,DiscreteInputBytes,0,readDiscreteInputLength);
SourceValueData = DiscreteInputBytes;
DiscreteInput = DiscreteInputBytes.ToBoolArray();
return true;
case ModbusFunctionType.ReadHoldingRegisters:
byte readHoldingRegistersLength = protocolBytes[2];
byte[] HoldingRegistersBytes = new byte[readHoldingRegistersLength];
Array.Copy(protocolBytes,3,HoldingRegistersBytes,0,readHoldingRegistersLength);
SourceValueData = HoldingRegistersBytes;
HoldingRegister = HoldingRegistersBytes.ToUShortArray();
return true;
case ModbusFunctionType.ReadInputRegisters:
byte readInputRegistersLength = protocolBytes[2];
byte[] InputRegistersBytes = new byte[readInputRegistersLength];
Array.Copy(protocolBytes,3,InputRegistersBytes,0,readInputRegistersLength);
SourceValueData = InputRegistersBytes;
InputRegister = InputRegistersBytes.ToUShortArray();
return true;
case ModbusFunctionType.WriteSingleCoil:
return true;
case ModbusFunctionType.WriteSingleHoldingRegister:
return true;
case ModbusFunctionType.WriteMultiCoil:
return true;
case ModbusFunctionType.WriteMultiHoldingRegister:
return true;
default:
return false;
}
}
catch (Exception)
{
return false;
}
}
}
#endregion
public enum ModbusFunctionType{
None = 0x00,
ReadCoil = 0x01,
ReadDiscreteInput = 0x02,
ReadHoldingRegisters = 0x03,
ReadInputRegisters = 0x04,
WriteSingleCoil = 0x05,
WriteSingleHoldingRegister = 0x06,
WriteMultiCoil = 0x0f,
WriteMultiHoldingRegister = 0x10
}
public enum ModbusRegisterType{
None = 0x00,
Coil = 0x01,
DiscreteInput = 0x02,
HoldingRegister = 0x03,
InputRegisters = 0x04
}
public enum ModbusErrorCode{
NoError = 0x00,
IllegalFunction = 0x01,
IllegalDataAddress = 0x02,
IllegalDataValue = 0x03,
SlaveDeviceFailure = 0x04,
Acknowledge = 0x05,
SlaveDeviceBusy = 0x06,
MemoryParityError = 0x08,
GatewayPathUnavailable = 0x0A,
GatewayTargetDeviceFailedToRespond = 0x0B
}
}

19
EGFramework/Module/ProtocolTools/ProtocolToolsInterface.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using System.Collections.Concurrent;
using System.Text;
namespace EGFramework{
public interface IProtocolSend{
public void SendByteData(string destination,byte[] data);
public void SendStringData(string destination,string data);
public void SetEncoding(Encoding textEncoding);
}
public interface IProtocolReceived{
public ConcurrentQueue<ResponseMsg> GetReceivedMsg();
}
public interface IProtocolListener{
public bool IsEnabled(string ServiceName);
}
}

240
EGFramework/Module/ProtocolTools/SerialPort/EGSerialPort.cs

@ -0,0 +1,240 @@ @@ -0,0 +1,240 @@
using System.IO.Ports;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Concurrent;
namespace EGFramework{
public class EGSerialPort : IModule,IEGFramework,IProtocolSend,IProtocolReceived
{
public Dictionary<string,SerialPort> SerialPortDevices { set; get; } = new Dictionary<string, SerialPort>();
public Dictionary<string,int> SerialPortMapping { set; get; } = new Dictionary<string, int>();
public int DefaultBaudRate { set; get; } = 115200;
// If data pack break,you can set this param to control the data pack completed at least.
private int MinDataPackLength { set; get; } = 0;
public string ErrorLogs { set; get; }
public string ReceivedStr { set; get; } = "";
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
public ConcurrentQueue<ResponseMsg> ResponseMsgs { set; get; } = new ConcurrentQueue<ResponseMsg>();
public Dictionary<string,byte[]> ReceivedCache { set; get; } = new Dictionary<string,byte[]>();
public void Init()
{
this.EGRegisterSendAction(request=>{
if(request.protocolType == ProtocolType.SerialPort){
if(request.req.ToProtocolData() != "" && request.req.ToProtocolData() != null){
this.SendSerialStringData(request.sender,request.req.ToProtocolData());
}
if(request.req.ToProtocolByteData().Length > 0 && request.req.ToProtocolByteData() != null){
this.SendSerialByteData(request.sender,request.req.ToProtocolByteData());
}
}
});
}
public ConcurrentQueue<ResponseMsg> GetReceivedMsg()
{
return this.ResponseMsgs;
}
public void SetEncoding(Encoding encoding){
this.StringEncoding = encoding;
}
public Encoding GetEncoding(){
return StringEncoding;
}
public List<string> RefreshSerialPort(){
string[] portNames = SerialPort.GetPortNames();
SerialPortMapping.Clear();
int index = 0;
foreach (string portName in portNames)
{
SerialPortMapping.Add(portName,index);
index++;
}
return SerialPortMapping.Keys.ToList();
}
public void SetBaudRate(int baudRate){
this.DefaultBaudRate = baudRate;
}
public bool Open(string serialPort)
{
return Open(serialPort, DefaultBaudRate);
}
/// <summary>
/// Open serial port with check if target serial port isOpen.
/// </summary>
/// <param name="serialPort"></param>
public bool Open(string serialPort, int baudRate)
{
try
{
if (!SerialPortDevices.ContainsKey(serialPort))
{
SerialPort newPort = new SerialPort(serialPort, baudRate, Parity.None, 8, StopBits.One);
SerialPortDevices.Add(serialPort, newPort);
ReceivedCache.Add(serialPort, new byte[0]);
if (!SerialPortDevices[serialPort].IsOpen)
{
SerialPortDevices[serialPort].Open();
SerialPortDevices[serialPort].DataReceived += SerialPort_DataReceived;
// EG.Print("OpenPort " + serialPort + " in " + baudRate);
}
}
else
{
if (!SerialPortDevices[serialPort].IsOpen)
{
SerialPortDevices[serialPort].Open();
SerialPortDevices[serialPort].BaudRate = baudRate;
}
}
return true;
}
catch (Exception e)
{
ErrorLogs = "[open port error]" + e.ToString();
EG.Print("Error:"+e);
return false;
}
}
/// <summary>
/// Close serial port with check if target serial port isOpen.
/// </summary>
/// <param name="serialPort"></param>
public void Close(string serialPort)
{
if (SerialPortDevices.ContainsKey(serialPort))
{
if (SerialPortDevices[serialPort].IsOpen)
{
SerialPortDevices[serialPort].DataReceived -= SerialPort_DataReceived;
SerialPortDevices[serialPort].Close();
SerialPortDevices.Remove(serialPort);
ReceivedCache.Remove(serialPort);
}
}
else
{
//Not found in SerialPortDevices,need add?
}
}
public bool SendSerialByteData(string serialPort,byte[] data){
// if serial port not open,open first
try{
bool isSuccessPort = Open(serialPort);
if(isSuccessPort){
SerialPortDevices[serialPort].Write(data, 0, data.Length);
return true;
}else{
return false;
}
}catch(Exception e){
ErrorLogs = "[write error]" + e.ToString();
return false;
}
}
public void SendByteData(string destination,byte[] data){
SendSerialByteData(destination,data);
}
public bool SendByteDataOnce(string serialPort,byte[] data){
bool isSuccessSend = SendSerialByteData(serialPort,data);
if(isSuccessSend){
SerialPortDevices[serialPort].Close();
SerialPortDevices.Remove(serialPort);
}
return isSuccessSend;
}
public bool SendSerialStringData(string serialPort,string data){
// if serial port not open,open first
try{
bool isSuccessPort = Open(serialPort);
if(isSuccessPort){
byte[] encodingData = StringEncoding.GetBytes(data);
SerialPortDevices[serialPort].Write(encodingData, 0, encodingData.Length);
return true;
}else{
return false;
}
}catch(Exception e){
ErrorLogs = "[write error]" + e.ToString();
return false;
}
}
public void SendStringData(string destination,string data){
SendSerialStringData(destination,data);
}
public bool SendStringDataOnce(string serialPort,string data){
bool isSuccessSend = SendSerialStringData(serialPort,data);
if(isSuccessSend){
SerialPortDevices[serialPort].Close();
SerialPortDevices.Remove(serialPort);
}
return isSuccessSend;
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//await Task.Run(() => {}).ConfigureAwait(false);
SerialPort serialPort = (SerialPort)sender;
if(serialPort.BytesToRead >= 0){
int bufferSize = serialPort.BytesToRead;
byte[] buffer = new byte[bufferSize];
serialPort.Read(buffer,0,serialPort.BytesToRead);
ReceivedCache[serialPort.PortName] = ReceivedCache[serialPort.PortName].Concat(buffer).ToArray();
}
if(ReceivedCache[serialPort.PortName].Length >= MinDataPackLength){
string str = StringEncoding.GetString(ReceivedCache[serialPort.PortName]);
EG.Print("[Receive]"+ReceivedCache[serialPort.PortName].ToStringByHex());
ResponseMsgs.Enqueue(new ResponseMsg(str,ReceivedCache[serialPort.PortName],serialPort.PortName,ProtocolType.SerialPort));
ReceivedCache[serialPort.PortName] = new byte[0];
MinDataPackLength = 0;
//this.EGOnReceivedData(new ResponseMsg(str,buffer,serialPort.PortName,ProtocolType.SerialPort));
}else{
EG.Print("[Data Get]" + ReceivedCache[serialPort.PortName].Length);
string str = StringEncoding.GetString(ReceivedCache[serialPort.PortName]);
ResponseMsgs.Enqueue(new ResponseMsg(str,ReceivedCache[serialPort.PortName],serialPort.PortName,ProtocolType.SerialPort));
}
}
public void SetExpectReceivedDataLength(int leastLength){
this.MinDataPackLength = leastLength;
}
public void ClearReceivedCache(string serialPort){
ReceivedCache[serialPort] = new byte[0];
}
public IArchitecture GetArchitecture()
{
return EGArchitectureImplement.Interface;
}
}
public static class CanGetEGSerialPortExtension{
public static EGSerialPort EGSerialPort(this IEGFramework self){
return self.GetModule<EGSerialPort>();
}
public static SerialPort EGGetSerialPort(this IEGFramework self,string serial){
return self.GetModule<EGSerialPort>().SerialPortDevices[serial];
}
}
}

499
EGFramework/Module/SaveTools/Data/EGCsvSave.cs

@ -0,0 +1,499 @@ @@ -0,0 +1,499 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Reflection;
using System.Configuration;
namespace EGFramework
{
/// <summary>
/// CSV Save tools, support read and write CSV file.The dataKey param is not use.please use "" or any string.
/// </summary>
public class EGCsvSave : IEGSaveData, IEGSave, IEGSaveReadOnly
{
public bool IsReadOnly { get; set; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
private string DefaultPath { set; get; }
private List<string[]> CsvDataBlock { get; set; }
private Dictionary<string,int> CsvDataHeader = new Dictionary<string,int>();
public IOCContainer TypeDataContainer = new IOCContainer();
private string ReadText { set; get; }
public void InitSave(string path)
{
ReadDataBlock(path);
}
public void InitReadOnly(string data)
{
ReadText = data;
if(ReadText != null || ReadText != ""){
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader);
}
}
public void InitReadOnly(byte[] data)
{
ReadText = StringEncoding.GetString(data);
if(ReadText != null || ReadText != ""){
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader);
}
}
public void ReadDataBlock(string path){
DefaultPath = path;
try
{
if (!File.Exists(path))
{
FileStream newCsvFile = File.Create(path);
CsvDataBlock = new List<string[]>();
newCsvFile.Close();
newCsvFile.Dispose();
return;
}
FileStream fileStream = new FileStream(path,FileMode.Open);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
fileStream.Close();
fileStream.Dispose();
ReadText = StringEncoding.GetString(buffer);
}
catch (System.Exception e)
{
EG.Print("e:" + e);
throw;
}
if(ReadText != null || ReadText != ""){
CsvDataBlock = GetCSVDataBlockFromText(ReadText,out CsvDataHeader);
}
}
public void WriteDataBlock(string path){
try
{
FileStream fileStream = File.Create(path);
string writeText = "";
string headerText = "";
foreach(string headStr in CsvDataHeader.Keys){
headerText+=headStr + ",";
}
headerText = headerText.Remove(headerText.Length-1,1);
writeText = headerText + "\n";
foreach(string[] lineData in CsvDataBlock){
string lineText = "";
foreach(string singleData in lineData){
lineText += singleData + ",";
}
lineText = lineText.Remove(lineText.Length-1,1);
writeText += lineText + "\n";
}
writeText = writeText.Remove(writeText.Length-1,1);
byte[] data = StringEncoding.GetBytes(writeText);
fileStream.Write(data,0,data.Length);
fileStream.Close();
fileStream.Dispose();
}
catch (System.Exception e)
{
EG.Print("e:" + e);
throw;
}
}
public List<string[]> GetCSVDataBlockFromText(string text,out Dictionary<string,int> header){
List<string[]> csvBlock = new List<string[]>();
string[] lineData = text.Split('\n');
string[] headerStr = lineData[0].Split(',');
header = new Dictionary<string,int>();
for (int i = 0; i < headerStr.Length; i++)
{
header.Add(headerStr[i],i);
}
for (int lineID = 0; lineID < lineData.Length; lineID++)
{
if (lineID!=0){
csvBlock.Add(lineData[lineID].Split(','));
}
}
return csvBlock;
}
public string[] ReadLine(int id){
if(CsvDataBlock.Count()>0){
return CsvDataBlock[id];
}else{
return null;
}
}
public void WriteLine(string[] lineData){
CsvDataBlock.Add(lineData);
this.WriteDataBlock(DefaultPath);
}
public void SetData<TData>(string dataKey, TData data, object id)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any data to file.");
}
bool IsAdd = false;
int dataID = 0;
if(id.GetType()==typeof(int)){
dataID = (int)id;
}else if(int.TryParse(id.ToString() ,out dataID)){
throw new Exception("Id cannot be convert to int!");
}
if(dataID>=CsvDataBlock.Count() || dataID < 0){
IsAdd = true;
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach(PropertyInfo property in data.GetType().GetProperties()){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString();
}
}
if(IsAdd){
CsvDataBlock.Add(csvSet);
}else{
CsvDataBlock[dataID] = csvSet;
}
this.WriteDataBlock(DefaultPath);
}
public TData GetData<TData>(string dataKey, object id) where TData : new()
{
TData data = new TData();
int dataID = 0;
if(id.GetType()==typeof(int)){
dataID = (int)id;
}else if(int.TryParse(id.ToString() ,out dataID)){
throw new Exception("Id cannot be convert to int!");
}
if(dataID>=CsvDataBlock.Count()){
throw new IndexOutOfRangeException("Parameter index is out of range.");
}
foreach(PropertyInfo property in data.GetType().GetProperties()){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]];
if(property.PropertyType==typeof(string)){
property.SetValue(data,valueStr);
}else{
property.SetValue(data,Convert.ChangeType(valueStr,property.PropertyType));
}
}
}
return data;
}
public IEnumerable<TData> GetAll<TData>(string dataKey) where TData : new()
{
// throw new NotImplementedException();
List<TData> DataList = new List<TData>();
PropertyInfo[] properties = typeof(TData).GetProperties();
for (int dataID = 0; dataID < CsvDataBlock.Count(); dataID++){
TData data = new TData();
foreach(PropertyInfo property in properties){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]];
if(property.PropertyType==typeof(string)){
property.SetValue(data,valueStr);
}else{
property.SetValue(data,Convert.ChangeType(valueStr,property.PropertyType));
}
}
}
DataList.Add(data);
}
TypeDataContainer.Register(DataList);
return DataList;
}
public IEnumerable<TData> GetPage<TData>(string dataKey, int pageIndex, int pageSize) where TData : new()
{
if(pageIndex <= 0){
pageIndex = 1;
}
int startPointer = (pageIndex - 1) * pageSize;
List<TData> DataList = new List<TData>();
PropertyInfo[] properties = typeof(TData).GetProperties();
for (int dataID = startPointer; dataID < startPointer+pageSize; dataID++){
TData data = new TData();
foreach(PropertyInfo property in properties){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]];
if(property.PropertyType==typeof(string)){
property.SetValue(data,valueStr);
}else{
property.SetValue(data,Convert.ChangeType(valueStr,property.PropertyType));
}
}
}
DataList.Add(data);
}
TypeDataContainer.Register(DataList);
return DataList;
}
public IEnumerable<TData> FindData<TData>(string dataKey, Expression<Func<TData, bool>> expression) where TData : new()
{
List<TData> sourceList;
if(TypeDataContainer.self.ContainsKey(typeof(List<TData>))){
sourceList = TypeDataContainer.Get<List<TData>>();
}else{
sourceList = (List<TData>)GetAll<TData>(dataKey);
}
return sourceList.Where(expression.Compile());
}
public IEnumerable<TData> FindData<TData>(string dataKey, string columnName, string keyWords) where TData : new()
{
// throw new NotImplementedException();
List<TData> DataList = new List<TData>();
PropertyInfo[] properties = typeof(TData).GetProperties();
if (!CsvDataHeader.ContainsKey(columnName))
{
EG.Print("Column not found!");
return null;
}
for (int dataID = 0; dataID < CsvDataBlock.Count(); dataID++)
{
TData data = new TData();
string compareStr = CsvDataBlock[dataID][CsvDataHeader[columnName]];
if (!compareStr.Contains(keyWords))
{
continue;
}
foreach (PropertyInfo property in properties)
{
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if (csvParam != null && CsvDataHeader.ContainsKey(csvParam._name))
{
string valueStr = CsvDataBlock[dataID][CsvDataHeader[csvParam._name]];
if (property.PropertyType == typeof(string))
{
property.SetValue(data, valueStr);
}
else
{
property.SetValue(data, Convert.ChangeType(valueStr, property.PropertyType));
}
}
}
DataList.Add(data);
}
return DataList;
}
public void AddData<TData>(string dataKey, TData data)
{
if (IsReadOnly)
{
throw new Exception("This file is readonly! can't set any data to file.");
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach (PropertyInfo property in data.GetType().GetProperties())
{
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if (csvParam != null && CsvDataHeader.ContainsKey(csvParam._name))
{
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString();
}
}
CsvDataBlock.Add(csvSet);
this.WriteDataBlock(DefaultPath);
}
public void AddData<TData>(string dataKey, IEnumerable<TData> dataSet)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any data to file.");
}
foreach(TData data in dataSet){
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach(PropertyInfo property in data.GetType().GetProperties()){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString();
}
}
CsvDataBlock.Add(csvSet);
}
this.WriteDataBlock(DefaultPath);
}
public void AddData(string datakey, Dictionary<string, object> data)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any data to file.");
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach(KeyValuePair<string,object> param in data){
if(CsvDataHeader.ContainsKey(param.Key)){
csvSet[CsvDataHeader[param.Key]] = param.Value.ToString();
}
}
CsvDataBlock.Add(csvSet);
this.WriteDataBlock(DefaultPath);
}
public void AddGroup(string datakey, List<Dictionary<string, object>> dataGroup)
{
if (IsReadOnly)
{
throw new Exception("This file is readonly! can't set any data to file.");
}
foreach (Dictionary<string, object> data in dataGroup)
{
if (CsvDataHeader.Count == 0)
{
int id = 0;
foreach (string key in data.Keys)
{
CsvDataHeader.Add(key, id);
id++;
}
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach (KeyValuePair<string, object> param in data)
{
if (CsvDataHeader.ContainsKey(param.Key))
{
csvSet[CsvDataHeader[param.Key]] = param.Value.ToString();
}
}
CsvDataBlock.Add(csvSet);
}
this.WriteDataBlock(DefaultPath);
}
public int RemoveData(string dataKey, object id)
{
if (IsReadOnly)
{
throw new Exception("This file is readonly! can't set any data to file.");
}
bool IsAdd = false;
int dataID = 0;
if (id.GetType() == typeof(int))
{
dataID = (int)id;
}
else if (int.TryParse(id.ToString(), out dataID))
{
throw new Exception("Id cannot be convert to int!");
}
if (dataID >= CsvDataBlock.Count() || dataID < 0)
{
IsAdd = true;
}
if (IsAdd)
{
return 0;
}
else
{
CsvDataBlock.RemoveAt(dataID);
}
this.WriteDataBlock(DefaultPath);
return 1;
}
public void UpdateData<TData>(string dataKey, TData data, object id)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any data to file.");
}
bool IsAdd = false;
int dataID = 0;
if(id.GetType()==typeof(int)){
dataID = (int)id;
}else if(int.TryParse(id.ToString() ,out dataID)){
throw new Exception("Id cannot be convert to int!");
}
if(dataID>=CsvDataBlock.Count() || dataID < 0){
IsAdd = true;
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach(PropertyInfo property in data.GetType().GetProperties()){
CsvParamAttribute csvParam = property.GetCustomAttribute<CsvParamAttribute>();
if(csvParam != null && CsvDataHeader.ContainsKey(csvParam._name)){
csvSet[CsvDataHeader[csvParam._name]] = property.GetValue(data).ToString();
}
}
if(!IsAdd){
CsvDataBlock[dataID] = csvSet;
}else{
throw new Exception("Data not found!");
}
this.WriteDataBlock(DefaultPath);
}
public void UpdateData(string dataKey, Dictionary<string, object> data, object id)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any data to file.");
}
bool IsAdd = false;
int dataID = 0;
if(id.GetType()==typeof(int)){
dataID = (int)id;
}else if(int.TryParse(id.ToString() ,out dataID)){
throw new Exception("Id cannot be convert to int!");
}
if(dataID>=CsvDataBlock.Count() || dataID < 0){
IsAdd = true;
}
string[] csvSet = new string[CsvDataHeader.Keys.Count()];
foreach(KeyValuePair<string,object> param in data){
if(CsvDataHeader.ContainsKey(param.Key)){
csvSet[CsvDataHeader[param.Key]] = param.Value.ToString();
}
}
if(!IsAdd){
CsvDataBlock[dataID] = csvSet;
}else{
throw new Exception("Data not found!");
}
this.WriteDataBlock(DefaultPath);
}
public IEnumerable<string> GetKeys()
{
return CsvDataHeader.Keys;
}
public bool ContainsKey(string dataKey)
{
return CsvDataHeader.ContainsKey(dataKey);
}
public bool ContainsData(string dataKey, object id)
{
return CsvDataBlock.Count() > 0 && id.GetType() == typeof(int) && (int)id < CsvDataBlock.Count();
}
public int GetDataCount(string dataKey)
{
return CsvDataBlock.Count();
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class CsvParamAttribute: Attribute{
public string _name { set; get; }
public CsvParamAttribute(string name){
this._name = name;
}
}
}

336
EGFramework/Module/SaveTools/Data/EGDapper.cs

@ -0,0 +1,336 @@ @@ -0,0 +1,336 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Dapper;
//ORM Save tools. First support SQLite and MySQL,In future we will support other Database who implement DBConnection.
namespace EGFramework
{
public abstract class EGDapper : IEGSave, IEGSaveData, IEGDataBase
{
public DbConnection Connection { get; set; }
public string ExceptionMsg;
public abstract void InitSave(string conn);
public IEnumerable<TData> GetAll<TData>(string dataKey) where TData : new()
{
IEnumerable<TData> result = Connection.Query<TData>("select * from " + dataKey);
return result;
}
public IEnumerable<TData> GetPage<TData>(string dataKey, int pageIndex, int pageSize) where TData : new()
{
if (pageIndex <= 0)
{
pageIndex = 1;
}
int startPointer = (pageIndex - 1) * pageSize;
IEnumerable<TData> result = Connection.Query<TData>("select * from " + dataKey + " limit " + startPointer + "," + pageSize);
return result;
}
public TData GetData<TData>(string dataKey, object id) where TData : new()
{
TData result = Connection.QuerySingle<TData>("select * from " + dataKey + " where ID = @ID", new { ID = id });
return result;
}
public IEnumerable<TData> FindData<TData>(string dataKey, Expression<Func<TData, bool>> expression) where TData : new()
{
IEnumerable<TData> sourceList = Connection.Query<TData>("select * from " + dataKey);
return sourceList.Where(expression.Compile());
}
public IEnumerable<TData> FindData<TData>(string dataKey, string columnName, string keyWords) where TData : new()
{
IEnumerable<TData> sourceList = Connection.Query<TData>("select * from " + dataKey + " where " + columnName + " like " + "'%"+keyWords+"%'");
return sourceList;
}
public void SetData<TData>(string dataKey, TData data, object id)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
else
{
if (this.ContainsData(dataKey, id))
{
UpdateData(dataKey, data, id);
}
else
{
AddData(dataKey, data);
}
//EG.Print("data:" + data);
}
}
public void AddData<TData>(string dataKey, TData data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
// throw new System.NotImplementedException();
Type DataType = typeof(TData);
var properties = DataType.GetProperties();
var fields = DataType.GetFields();
string keySet = "";
string keySetParam = "";
foreach (PropertyInfo key in properties)
{
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
if (DataType.IsPrimitive)
{
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
else
{
keySet += key.Name + ",";
keySetParam += "'" + key.GetValue(data).ToString() + "',";
}
}
foreach (FieldInfo key in fields)
{
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
if (DataType.IsPrimitive)
{
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
else
{
keySet += key.Name + ",";
keySetParam += "'" + key.GetValue(data).ToString() + "',";
}
}
keySet = keySet.TrimEnd(',');
keySetParam = keySetParam.TrimEnd(',');
int count = Connection.Execute(@"insert " + dataKey + "(" + keySet + ") values(" + keySetParam + ")", data);
//EG.Print("count:" + count);
}
/// <summary>
/// TData Must be all member to type of properties. such as 'public string Name { set; get; }'. Properties cannot be except string, primitive
/// </summary>
/// <param name="dataKey"></param>
/// <param name="data"></param>
/// <typeparam name="TData"></typeparam>
public void AddData<TData>(string dataKey, IEnumerable<TData> data)
{
Type DataType = typeof(TData);
var properties = DataType.GetProperties();
string keySet = "";
string keySetParam = "";
foreach (PropertyInfo key in properties)
{
if (key.Name == "ID" || key.Name == "Id" || key.Name == "id")
{
continue;
}
keySet += key.Name + ",";
keySetParam += "@" + key.Name + ",";
}
keySet = keySet.TrimEnd(',');
keySetParam = keySetParam.TrimEnd(',');
string sql = @"insert " + dataKey + "(" + keySet + ") values(" + keySetParam + ")";
EG.Print("sql:" + sql);
int count = Connection.Execute(sql, data);
//EG.Print("count:" + count);
}
public void AddData(string dataKey, Dictionary<string, object> data)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
string keySet = "";
string keySetParam = "";
foreach (KeyValuePair<string, object> param in data)
{
if (param.Key == "ID" || param.Key == "Id" || param.Key == "id")
{
continue;
}
keySet += param.Key + ",";
if (param.Value is string)
{
keySetParam += "'" + param.Value + "',";
}
else
{
keySetParam += param.Value + ",";
}
}
keySet = keySet.TrimEnd(',');
keySetParam = keySetParam.TrimEnd(',');
EG.Print("insert into " + dataKey + "(" + keySet + ") values(" + keySetParam + ")");
int count = Connection.Execute("insert into " + dataKey + "(" + keySet + ") values(" + keySetParam + ")");
}
public void AddGroup(string datakey, List<Dictionary<string, object>> dataGroup)
{
foreach (Dictionary<string, object> data in dataGroup)
{
this.AddData(datakey, data);
}
}
public int RemoveData(string dataKey, object id)
{
int count = Connection.Execute(@"delete from " + dataKey + " where id = @ID", new { ID = id });
return count;
//EG.Print("count:" + count);
}
public void UpdateData<TData>(string dataKey, TData data, object id)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
Type DataType = typeof(TData);
var properties = DataType.GetProperties();
string keyMap = "";
foreach (PropertyInfo key in properties)
{
if (key.Name == "ID" || key.Name == "id" || key.Name == "Id")
{
continue;
}
keyMap += key.Name + " = @" + key.Name + ",";
}
keyMap = keyMap.TrimEnd(',');
string sql = @"update " + dataKey + " set " + keyMap + " where ID = " + id;
EG.Print(sql);
int count = Connection.Execute(sql, data);
//EG.Print("count:" + count);
}
public void UpdateData(string dataKey, Dictionary<string, object> data, object id)
{
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
string keyMap = "";
foreach (KeyValuePair<string, object> param in data)
{
if (param.Key == "ID" || param.Key == "Id" || param.Key == "id")
{
continue;
}
if (param.Value is string)
{
keyMap += param.Key + " = '" + param.Value + "',";
}
else
{
keyMap += param.Key + " = " + param.Value + ",";
}
}
keyMap = keyMap.TrimEnd(',');
if (id is string)
{
id = "'" + id + "'";
}
string sql = @"update " + dataKey + " set " + keyMap + " where ID = " + id;
EG.Print(sql);
int count = Connection.Execute(sql, data);
}
public virtual IEnumerable<string> GetKeys()
{
IEnumerable<string> result = Connection.Query<string>("show tables");
return result;
}
public bool ContainsKey(string dataKey)
{
return GetKeys().Contains(dataKey);
}
public bool ContainsData(string dataKey, object id)
{
try
{
var result = Connection.QuerySingle("select * from " + dataKey + " where ID = @ID", new { ID = id });
if (result == null)
{
return false;
}
else
{
return true;
}
}
catch (System.Exception)
{
return false;
}
}
public int GetDataCount(string dataKey)
{
int count = Connection.QuerySingle<int>("select COUNT(*) from " + dataKey);
return count;
}
public DbConnection GetConnection()
{
return Connection;
}
public void CreateTable<TData>(string dataKey)
{
// throw new System.NotImplementedException();
if (this.ContainsKey(dataKey))
{
EG.Print("Table " + dataKey + " has been created!");
return;
}
string createSql = typeof(TData).ToCreateTableSQL(dataKey);
int count = Connection.Execute(createSql);
}
public void CreateTable(string dataKey, Dictionary<string, object> tableParam)
{
if (this.ContainsKey(dataKey))
{
EG.Print("Table " + dataKey + " has been created!");
return;
}
Dictionary<string, Type> tableType = new Dictionary<string, Type>();
foreach (KeyValuePair<string, object> pair in tableParam)
{
tableType.Add(pair.Key, pair.Value.GetType());
}
string createSql = tableType.ToCreateTableSQL(dataKey);
int count = Connection.Execute(createSql);
}
public void DropTable(string dataKey)
{
if (this.ContainsKey(dataKey))
{
Connection.Execute(@"DROP TABLE IF EXISTS "+dataKey+"");
}
}
}
}

162
EGFramework/Module/SaveTools/Data/EGLiteDBSave.cs

@ -0,0 +1,162 @@ @@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using LiteDB;
namespace EGFramework
{
public class EGLiteDBSave : IEGSave,IEGSaveData
{
private string DefaultPath { set; get; }
private LiteDatabase _Database { set; get; }
private LiteDatabase Database{
get {
if(_Database == null){
InitSave(DefaultPath);
}
return _Database;
}
}
public void InitSave(string path)
{
DefaultPath = path;
if (!Directory.Exists(Path.GetDirectoryName(DefaultPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(DefaultPath));
}
// Default is "SaveData/DefaultLiteDBData.db"
_Database = new LiteDatabase(path);
}
public TData GetData<TData>(string dataKey, object id) where TData : new()
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
TData result = collection.FindById((BsonValue)id);
return result;
}
public void SetData<TData>(string dataKey, TData data, object id)
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
if(collection.FindById((BsonValue)id)==null){
collection.Insert((BsonValue)id, data);
}
collection.Update(data);
}
public IEnumerable<TData> GetAll<TData>(string dataKey) where TData : new()
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
return collection.FindAll();
}
public IEnumerable<TData> GetPage<TData>(string dataKey, int pageIndex, int pageSize) where TData : new()
{
if(pageIndex <= 0){
pageIndex = 1;
}
int startPointer = (pageIndex - 1) * pageSize;
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
IEnumerable<TData> result = collection.FindAll().Skip(startPointer).Take(pageSize);
return result;
}
public IEnumerable<TData> FindData<TData>(string dataKey, Expression<Func<TData, bool>> expression) where TData : new()
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
return collection.Find(expression);
}
public IEnumerable<TData> FindData<TData>(string dataKey, string columnName, string keyWords) where TData : new()
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
return collection.Find(Query.EQ(columnName,new BsonValue(keyWords)));
}
public void AddData<TData>(string dataKey, TData data)
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
collection.Insert(data);
}
public void AddData<TData>(string dataKey, IEnumerable<TData> data)
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
collection.Insert(data);
}
public void AddData(string dataKey, Dictionary<string, object> data)
{
ILiteCollection<BsonDocument> collection = Database.GetCollection(dataKey);
BsonDocument keyValuePairs = new BsonDocument();
foreach (var param in data) {
keyValuePairs.Add(param.Key, new BsonValue(param.Value));
}
collection.Insert(keyValuePairs);
}
public void AddGroup(string datakey, List<Dictionary<string, object>> dataGroup)
{
foreach (Dictionary<string, object> data in dataGroup)
{
this.AddData(datakey, data);
}
}
public int RemoveData(string dataKey, object id)
{
ILiteCollection<BsonDocument> collection = Database.GetCollection(dataKey);
if (collection.FindById((BsonValue)id) != null)
{
collection.Delete((BsonValue)id);
return 1;
}
else
{
return 0;
}
}
public void UpdateData<TData>(string dataKey, TData data, object id)
{
LiteCollection<TData> collection = (LiteCollection<TData>)Database.GetCollection<TData>(dataKey);
collection.Update((BsonValue)id,data);
}
public void UpdateData(string dataKey, Dictionary<string, object> data, object id)
{
ILiteCollection<BsonDocument> collection = Database.GetCollection(dataKey);
BsonDocument keyValuePairs = new BsonDocument();
foreach (var param in data) {
keyValuePairs.Add(param.Key, new BsonValue(param.Value));
}
collection.Update((BsonValue)id,keyValuePairs);
}
public IEnumerable<string> GetKeys()
{
return Database.GetCollectionNames();
}
public bool ContainsKey(string dataKey)
{
return GetKeys().Contains(dataKey);
}
public bool ContainsData(string dataKey, object id)
{
return Database.GetCollection(dataKey).Exists((BsonValue)id);
}
public int GetDataCount(string dataKey)
{
return Database.GetCollection(dataKey).Count();
}
}
}

29
EGFramework/Module/SaveTools/Data/EGMysqlSave.cs

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
using MySql.Data.MySqlClient;
namespace EGFramework{
/// <summary>
/// This Class used Dapper for operate MySQL database.
/// </summary>
public class EGMysqlSave : EGDapper
{
public string Conn { set; get; }
public bool IsInit { set; get; }
/// <summary>
/// "server="+Address+";port="+Port+";uid="+UserName+";pwd="+Password+";database="+DataBase+";"
/// </summary>
/// <param name="conn">files conn Str or address ip port,username and passwd</param>
public override void InitSave(string conn)
{
try
{
Connection = new MySqlConnection(conn);
IsInit = true;
this.Conn = conn;
}
catch (System.Exception e)
{
EG.Print("e:" + e);
}
}
}
}

50
EGFramework/Module/SaveTools/Data/EGSqliteSave.cs

@ -0,0 +1,50 @@ @@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.IO;
using Dapper;
using Microsoft.Data.Sqlite;
namespace EGFramework{
public class EGSqliteSave : EGDapper
{
public string Conn { set; get; }
public bool IsInit { set; get; }
/// <summary>
/// If path not exist, create it.
/// </summary>
/// <param name="path">please add *.db suffix or your db file suffix</param>
public override void InitSave(string path)
{
if (!File.Exists(path))
{
Directory.CreateDirectory(path);
}
InitDatabase(path);
}
/// <summary>
/// Init database with path.
/// </summary>
/// <param name="dataBaseName">name is the file path.such as SaveData.db</param>
public void InitDatabase(string dataBaseName)
{
Connection = new SqliteConnection("Data Source=" + dataBaseName + ";Mode=ReadWriteCreate;"); // Open the connection:
try
{
// Connection.Open();
this.Conn = dataBaseName;
IsInit = true;
}
catch (Exception ex)
{
ExceptionMsg = ex.ToString();
}
}
public override IEnumerable<string> GetKeys()
{
IEnumerable<string> result = Connection.Query<string>("SELECT name FROM sqlite_schema WHERE type='table' AND name NOT LIKE 'sqlite_%'");
return result;
}
}
}

79
EGFramework/Module/SaveTools/EGSave.cs

@ -0,0 +1,79 @@ @@ -0,0 +1,79 @@
using System;
using System.IO;
using System.Collections.Generic;
using Dapper;
using System.Linq;
namespace EGFramework
{
public class EGSave : EGModule
{
#region About Godot File's PATH
// Godot's Path has res:// and user://
// UserPath is used for every platform such as android.
// You can use ProjectSettings.GlobalizePath("") to convert a "local" path like res://path/to/file.txt to an absolute OS path.
#endregion
public HashSet<string> KeySet = new HashSet<string>();
public Dictionary<string, object> SaveMapping = new Dictionary<string, object>();
public EGJsonSave DefaultJsonSave { set; get; }
public EGSave() { }
public override void Init()
{
DefaultJsonSave = Load<EGJsonSave>(Directory.GetCurrentDirectory()+"/SaveData/DefaultJsonSave.json");
}
#region Load Data or Object and Unload
public TSaveData Load<TSaveData>(string path) where TSaveData : IEGSave, new()
{
KeySet.Add(path);
TSaveData saveData = new TSaveData();
saveData.InitSave(path);
SaveMapping.Add(path, saveData);
return saveData;
}
public TReadOnlyData Read<TReadOnlyData>(string key, string data) where TReadOnlyData : IEGSaveReadOnly, new()
{
KeySet.Add(key);
TReadOnlyData readOnlyData = new TReadOnlyData();
readOnlyData.InitReadOnly(data);
SaveMapping.Add(key, readOnlyData);
return readOnlyData;
}
public TReadOnlyData Read<TReadOnlyData>(string key, byte[] data) where TReadOnlyData : IEGSaveReadOnly, new()
{
KeySet.Add(key);
TReadOnlyData readOnlyData = new TReadOnlyData();
readOnlyData.InitReadOnly(data);
SaveMapping.Add(key, readOnlyData);
return readOnlyData;
}
#endregion
#region Default Json Operation
public void SetObjectToJson<TObject>(TObject obj)
{
DefaultJsonSave.SetObject(typeof(TObject).ToString(), obj);
}
public TObject GetObjectFromJson<TObject>() where TObject : new(){
return DefaultJsonSave.GetObject<TObject>(typeof(TObject).ToString());
}
#endregion
}
public static class CanGetEGSaveExtension{
public static EGSave EGSave(this IEGFramework self){
return self.GetModule<EGSave>();
}
public static string GetDirectoryName(this string path){
return Path.GetDirectoryName(path);
}
}
}

116
EGFramework/Module/SaveTools/File/EGFtpSave.cs

@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
using System.Collections.Generic;
using System.IO;
using FluentFTP;
namespace EGFramework{
public class EGFtpSave : IEGSave, IEGSaveFile
{
public FtpClient FTPClient { set; get; }
public void InitSave(string host)
{
this.FTPClient = new FtpClient(host);
}
public void InitUser(string user, string password)
{
this.FTPClient.Credentials = new System.Net.NetworkCredential(user, password);
}
public void CopyFile(string sourcePath, string copyPath)
{
FTPClient.Connect();
Stream fileStream = FTPClient.OpenRead(sourcePath);
FTPClient.UploadStream(fileStream, copyPath, FtpRemoteExists.Overwrite, true);
fileStream.Close();
FTPClient.Disconnect();
}
public void DownloadFile(string remotePath, string localPath)
{
FTPClient.Connect();
FTPClient.DownloadFile(localPath, remotePath, FtpLocalExists.Overwrite);
FTPClient.Disconnect();
}
public Stream DownloadFile(string remotePath)
{
FTPClient.Connect();
Stream fileStream = FTPClient.OpenRead(remotePath);
FTPClient.Disconnect();
return fileStream;
}
public bool IsRemoteDirectoryExist(string remotePath)
{
FTPClient.Connect();
bool isExist = FTPClient.DirectoryExists(remotePath);
FTPClient.Disconnect();
return isExist;
}
public bool IsRemoteFileExist(string remotePath)
{
FTPClient.Connect();
bool isExist = FTPClient.FileExists(remotePath);
FTPClient.Disconnect();
return isExist;
}
public IEnumerable<IEGFileMsg> ListRemoteFilePath(string remotePath)
{
FTPClient.Connect();
FtpListItem[] nameList = FTPClient.GetListing(remotePath);
List<IEGFileMsg> fileList = new List<IEGFileMsg>();
foreach (var item in nameList)
{
IEGFileMsg fileMsg = new EGFileMsg();
fileMsg.Init(item.Name, item.Type == FtpObjectType.Directory, item.FullName, item.Size/1024, item.Modified);
fileList.Add(fileMsg);
}
FTPClient.Disconnect();
return fileList;
}
public void MakeDirectory(string remotePath)
{
FTPClient.Connect();
FTPClient.CreateDirectory(remotePath, true);
FTPClient.Disconnect();
}
public void MoveFile(string sourcePath, string movePath)
{
FTPClient.Connect();
FTPClient.MoveFile(sourcePath, movePath ,FtpRemoteExists.Overwrite);
FTPClient.Disconnect();
}
public void RemoveFile(string remotePath)
{
FTPClient.Connect();
FTPClient.DeleteFile(remotePath);
FTPClient.Disconnect();
}
public void SyncFile(string remotePath, string localPath)
{
FTPClient.Connect();
FTPClient.DownloadFile(localPath, remotePath, FtpLocalExists.Overwrite);
FTPClient.Disconnect();
}
public void UploadFile(FileStream localFileStream, string remotePath)
{
FTPClient.Connect();
FTPClient.UploadStream(localFileStream, remotePath, FtpRemoteExists.Overwrite, true);
FTPClient.Disconnect();
}
public void UploadFile(string localPath, string remotePath)
{
FTPClient.Connect();
FTPClient.UploadFile(localPath, remotePath, FtpRemoteExists.Overwrite, true, FtpVerify.Retry);
FTPClient.Disconnect();
}
}
}

173
EGFramework/Module/SaveTools/File/EGLocalFileSave.cs

@ -0,0 +1,173 @@ @@ -0,0 +1,173 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
namespace EGFramework{
/// <summary>
/// This class is used to save files locally. such as u disk or other local path. used for backup or other purpose.
/// </summary>
public class EGLocalFileSave : IEGSave, IEGSaveFile
{
public string RootPath { get; set; }
public void InitSave(string path)
{
this.RootPath = path;
}
public void CopyFile(string sourcePath, string copyPath)
{
if(IsRemoteFileExist(sourcePath)){
string sourceCombinedPath = Path.Combine(RootPath, sourcePath);
string copyCombinedPath = Path.Combine(RootPath, copyPath);
File.Copy(sourceCombinedPath,copyCombinedPath,true);
}else{
throw new FileNotFoundException("File not exist!");
}
}
public void DownloadFile(string remotePath, string localPath)
{
if(IsRemoteFileExist(remotePath)){
string combinedPath = Path.Combine(RootPath, remotePath);
File.Copy(combinedPath,localPath,true);
}else{
throw new FileNotFoundException("File not exist!");
}
}
public Stream DownloadFile(string remotePath)
{
if(IsRemoteFileExist(remotePath)){
string combinedPath = Path.Combine(RootPath, remotePath);
FileStream fileStream = new FileStream(combinedPath,FileMode.Open,FileAccess.Read);
return fileStream;
}else{
throw new FileNotFoundException("File not exist!");
}
}
public bool IsRemoteDirectoryExist(string remotePath)
{
string combinedPath = Path.Combine(RootPath, remotePath);
return Directory.Exists(combinedPath);
}
public bool IsRemoteFileExist(string remotePath)
{
string combinedPath = Path.Combine(RootPath, remotePath);
return File.Exists(combinedPath);
}
public IEnumerable<IEGFileMsg> ListLocalFilePath(string localPath)
{
string [] filePaths = Directory.GetFiles(localPath);
string [] directoryPaths = Directory.GetDirectories(localPath);
List<IEGFileMsg> fileMsgs = new List<IEGFileMsg>();
foreach(string filePath in filePaths){
FileInfo fileInfo = new FileInfo(filePath);
EGFileMsg msg = new EGFileMsg();
msg.Init(fileInfo.Name,false,filePath,fileInfo.Length,fileInfo.LastWriteTime);
fileMsgs.Add(msg);
}
foreach(string directoryPath in directoryPaths){
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
EGFileMsg msg = new EGFileMsg();
msg.Init(directoryInfo.Name,true,directoryPath,null,directoryInfo.LastWriteTime);
fileMsgs.Add(msg);
}
return fileMsgs;
}
public IEnumerable<IEGFileMsg> ListRemoteFilePath(string remotePath)
{
string combinedPath = Path.Combine(RootPath, remotePath);
string [] filePaths = Directory.GetFiles(combinedPath);
string [] directoryPaths = Directory.GetDirectories(combinedPath);
List<IEGFileMsg> fileMsgs = new List<IEGFileMsg>();
foreach(string filePath in filePaths){
FileInfo fileInfo = new FileInfo(filePath);
EGFileMsg msg = new EGFileMsg();
msg.Init(fileInfo.Name,false,filePath,fileInfo.Length,fileInfo.LastWriteTime);
fileMsgs.Add(msg);
}
foreach(string directoryPath in directoryPaths){
DirectoryInfo directoryInfo = new DirectoryInfo(directoryPath);
EGFileMsg msg = new EGFileMsg();
msg.Init(directoryInfo.Name,true,directoryPath,null,directoryInfo.LastWriteTime);
fileMsgs.Add(msg);
}
return fileMsgs;
}
public void MakeDirectory(string remotePath)
{
string combinedPath = Path.Combine(RootPath, remotePath);
if(Directory.Exists(combinedPath) == false){
Directory.CreateDirectory(combinedPath);
}
}
public void MoveFile(string sourcePath, string movePath)
{
if(IsRemoteFileExist(sourcePath)){
string sourceCombinedPath = Path.Combine(RootPath, sourcePath);
string moveCombinedPath = Path.Combine(RootPath, movePath);
File.Move(sourceCombinedPath,moveCombinedPath);
}else{
throw new FileNotFoundException("File not exist!");
}
}
public void RemoveFile(string remotePath)
{
if(IsRemoteFileExist(remotePath)){
string combinedPath = Path.Combine(RootPath, remotePath);
File.Delete(combinedPath);
}else{
throw new FileNotFoundException("File not exist!");
}
}
public void SyncFile(string remotePath, string localPath)
{
FileInfo fileInfo = new FileInfo(localPath);
if(fileInfo.Exists == false){
throw new FileNotFoundException("Local File not exist!");
}
FileInfo remoteFileInfo = new FileInfo(remotePath);
if(remoteFileInfo.Exists == false){
throw new FileNotFoundException("Remote File not exist!");
}
if(fileInfo.LastWriteTime > remoteFileInfo.LastWriteTime){
string combinedPath = Path.Combine(RootPath, remotePath);
File.Copy(localPath,combinedPath,true);
}else if(fileInfo.LastWriteTime < remoteFileInfo.LastWriteTime){
string combinedPath = Path.Combine(RootPath, remotePath);
File.Copy(combinedPath,localPath,true);
}else{
EG.Print("File is same, no need to sync!");
}
}
public void UploadFile(FileStream localFileStream, string remotePath)
{
string combinedPath = Path.Combine(RootPath, remotePath);
FileStream fileStream = new FileStream(combinedPath,FileMode.Create,FileAccess.Write);
localFileStream.CopyTo(fileStream);
fileStream.Close();
localFileStream.Close();
fileStream.Dispose();
}
public void UploadFile(string localPath, string remotePath)
{
if(File.Exists(localPath)){
string combinedPath = Path.Combine(RootPath, remotePath);
File.Copy(localPath,combinedPath,true);
}else{
throw new FileNotFoundException("File not exist!");
}
}
}
}

98
EGFramework/Module/SaveTools/File/EGSftpSave.cs

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
using System.Collections.Generic;
using System.IO;
using Newtonsoft.Json;
using Renci.SshNet;
namespace EGFramework{
public struct EGSftpHost
{
public string Host { set; get; }
public string User { set; get; }
public string Password { set; get; }
public int Port { set; get; }
}
public class EGSftpSave : IEGSave,IEGSaveFile
{
public SftpClient Sftp { set; get; }
/// <summary>
/// Host is a json string, such as {"Host":"","User":"","Password":"","Port":22}
/// </summary>
/// <param name="hostJson"></param>
public void InitSave(string hostJson)
{
EGSftpHost host = JsonConvert.DeserializeObject<EGSftpHost>(hostJson);
if(host.Port == 0){
host.Port = 22;
}
this.Sftp = new SftpClient(host.Host, host.Port, host.User, host.Password);
// this.Sftp = new SftpClient(path);
}
public void CopyFile(string sourcePath, string copyPath)
{
throw new System.NotImplementedException();
}
public void DownloadFile(string remotePath, string localPath)
{
throw new System.NotImplementedException();
}
public Stream DownloadFile(string remotePath)
{
throw new System.NotImplementedException();
}
public bool IsRemoteDirectoryExist(string remotePath)
{
throw new System.NotImplementedException();
}
public bool IsRemoteFileExist(string remotePath)
{
throw new System.NotImplementedException();
}
public IEnumerable<IEGFileMsg> ListLocalFilePath(string localPath)
{
throw new System.NotImplementedException();
}
public IEnumerable<IEGFileMsg> ListRemoteFilePath(string remotePath)
{
throw new System.NotImplementedException();
}
public void MakeDirectory(string remotePath)
{
throw new System.NotImplementedException();
}
public void MoveFile(string sourcePath, string movePath)
{
throw new System.NotImplementedException();
}
public void RemoveFile(string remotePath)
{
throw new System.NotImplementedException();
}
public void SyncFile(string remotePath, string localPath)
{
throw new System.NotImplementedException();
}
public void UploadFile(FileStream localFileStream, string remotePath)
{
throw new System.NotImplementedException();
}
public void UploadFile(string localPath, string remotePath)
{
throw new System.NotImplementedException();
}
}
}

77
EGFramework/Module/SaveTools/File/EGWebDavSave.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
using System.Collections.Generic;
using System.IO;
namespace EGFramework{
public class EGWebDavSave : IEGSave, IEGSaveFile
{
public void InitSave(string path)
{
throw new System.NotImplementedException();
}
public void CopyFile(string sourcePath, string copyPath)
{
throw new System.NotImplementedException();
}
public void DownloadFile(string remotePath, string localPath)
{
throw new System.NotImplementedException();
}
public Stream DownloadFile(string remotePath)
{
throw new System.NotImplementedException();
}
public bool IsRemoteDirectoryExist(string remotePath)
{
throw new System.NotImplementedException();
}
public bool IsRemoteFileExist(string remotePath)
{
throw new System.NotImplementedException();
}
public IEnumerable<IEGFileMsg> ListLocalFilePath(string localPath)
{
throw new System.NotImplementedException();
}
public IEnumerable<IEGFileMsg> ListRemoteFilePath(string remotePath)
{
throw new System.NotImplementedException();
}
public void MakeDirectory(string remotePath)
{
throw new System.NotImplementedException();
}
public void MoveFile(string sourcePath, string movePath)
{
throw new System.NotImplementedException();
}
public void RemoveFile(string remotePath)
{
throw new System.NotImplementedException();
}
public void SyncFile(string remotePath, string localPath)
{
throw new System.NotImplementedException();
}
public void UploadFile(FileStream localFileStream, string remotePath)
{
throw new System.NotImplementedException();
}
public void UploadFile(string localPath, string remotePath)
{
throw new System.NotImplementedException();
}
}
}

131
EGFramework/Module/SaveTools/Object/EGByteSave.cs

@ -0,0 +1,131 @@ @@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace EGFramework
{
/// Pointer max length is 4294967295.
/// Data protocol:
/// [XX XX XX XX](Pointer length) [XX XX XX XX]...[XX XX XX XX](Pointers) [DataBlock 1]...[DataBlock N](Data)
/// 1. The first (four byte) is the length of the data pointers (uint type).
/// 2. The pointer List is the position to the data block.
/// 3. The data block is the data you want to save.
public interface IEGByteObject{
byte[] GetBytes();
void SetBytes(byte[] byteData);
}
[Obsolete("This class is not comlpete, please not use it!")]
public class EGByteObjectSave : IEGSave, IEGSaveObject
{
public Encoding StringEncoding { set; get; } = Encoding.ASCII;
private string DefaultPath { set; get; }
private uint PointerLength { get; set; }
private uint[] Pointer { get; set; }
private Dictionary<uint, byte[]> Data { get; set; }
private byte[] _Data;
public void ReadDataBlock(string path)
{
DefaultPath = path;
try
{
FileStream fileStream = new FileStream(path, FileMode.OpenOrCreate);
byte[] buffer = new byte[fileStream.Length];
fileStream.Read(buffer, 0, (int)fileStream.Length);
fileStream.Close();
fileStream.Dispose();
_Data = buffer;
}
catch (System.Exception e)
{
EG.Print("e:" + e);
throw;
}
}
public void WriteDataBlock(string path)
{
try
{
FileStream fileStream = File.Create(path);
fileStream.Write(_Data, 0, _Data.Length);
fileStream.Close();
fileStream.Dispose();
}
catch (System.Exception e)
{
EG.Print("e:" + e);
throw;
}
}
public void InitSave(string path)
{
ReadDataBlock(path);
}
/// <summary>
/// Set object to the file,the pointer
/// </summary>
/// <param name="objectKey"></param>
/// <param name="obj"></param>
/// <typeparam name="TObject"></typeparam>
public void SetObject<TObject>(string objectKey, TObject obj)
{
if (typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject)))
{
_Data = ((IEGByteObject)obj).GetBytes();
}
else
{
throw new Exception("This byte class cannot be serialized! you should implement IRequest first!");
}
WriteDataBlock(DefaultPath);
}
public void RemoveObject<TObject>(string objectKey)
{
throw new NotImplementedException();
}
public void AddObject<TObject>(string objectKey, TObject obj)
{
throw new NotImplementedException();
}
public void UpdateObject<TObject>(string objectKey, TObject obj)
{
throw new NotImplementedException();
}
public IEnumerable<string> GetKeys()
{
throw new NotImplementedException();
}
public bool ContainsKey(string objectKey)
{
throw new NotImplementedException();
}
public TObject GetObject<TObject>(string objectKey)
{
throw new NotImplementedException();
// if(typeof(TObject).GetInterfaces().Contains(typeof(IEGByteObject))){
// TObject result = new TObject();
// ((IEGByteObject)result).SetBytes(_Data);
// return result;
// }else{
// throw new Exception("This byte class cannot be serialized! you should implement IRequest first!");
// }
}
}
public interface IEGByteInit{
void Init(byte[] data);
}
}

136
EGFramework/Module/SaveTools/Object/EGJsonSave.cs

@ -0,0 +1,136 @@ @@ -0,0 +1,136 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace EGFramework
{
public class EGJsonSave : IEGSave,IEGSaveReadOnly,IEGSaveObject
{
public bool IsReadOnly { get; set; }
public Encoding StringEncoding { set; get; } = Encoding.UTF8;
private string DefaultPath { set; get; }
private JObject _SaveObject;
private JObject SaveObject{
get {
if(_SaveObject == null){
InitSave(DefaultPath);
}
return _SaveObject;
}
}
/// <summary>
/// Init a new save data file or load an other file with json suffix, if you want to load other save data, please use this function to reload;
/// </summary>
public void InitSave(string path)
{
DefaultPath = path;
if(!File.Exists(path)){
if (!Directory.Exists(Path.GetDirectoryName(DefaultPath)))
{
Directory.CreateDirectory(Path.GetDirectoryName(DefaultPath));
File.WriteAllText(DefaultPath,"{}");
}else if(!File.Exists(DefaultPath)){
File.WriteAllText(DefaultPath,"{}");
}
}
using (StreamReader reader = File.OpenText(path))
{
_SaveObject = (JObject)JToken.ReadFrom(new JsonTextReader(reader));
}
}
public void InitReadOnly(string data)
{
_SaveObject = JObject.Parse(data);
IsReadOnly = true;
}
public void InitReadOnly(byte[] data)
{
_SaveObject = JObject.Parse(StringEncoding.GetString(data));
IsReadOnly = true;
}
public void SetObject<TObject>(string objectKey,TObject obj)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any object to file.");
}
if(SaveObject.ContainsKey(objectKey)){
SaveObject[objectKey] = JToken.FromObject(obj);
}else{
SaveObject.Add(objectKey,JToken.FromObject(obj));
}
File.WriteAllText(DefaultPath,JsonConvert.SerializeObject(SaveObject,Formatting.Indented));
}
/// <summary>
/// Get data from file, if your data is not in file, then throw an exception.
/// </summary>
public TObject GetObject<TObject>(string objectKey)
{
if(!SaveObject.ContainsKey(objectKey)){
throw new Exception("Key not found!");
}
TObject data = SaveObject[objectKey].ToObject<TObject>();
return data;
}
public void RemoveObject<TObject>(string objectKey)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any object to file.");
}
if(SaveObject.ContainsKey(objectKey)){
SaveObject.Remove(objectKey);
}
File.WriteAllText(DefaultPath,JsonConvert.SerializeObject(SaveObject,Formatting.Indented));
}
public void AddObject<TObject>(string objectKey, TObject obj)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any object to file.");
}
if(!SaveObject.ContainsKey(objectKey)){
SaveObject.Add(objectKey,JToken.FromObject(obj));
}else{
throw new Exception("Key already exists!");
}
File.WriteAllText(DefaultPath,JsonConvert.SerializeObject(SaveObject,Formatting.Indented));
}
public void UpdateObject<TObject>(string objectKey, TObject obj)
{
if(IsReadOnly){
throw new Exception("This file is readonly! can't set any object to file.");
}
if(SaveObject.ContainsKey(objectKey)){
SaveObject[objectKey] = JToken.FromObject(obj);
}else{
throw new Exception("Key not found!");
}
File.WriteAllText(DefaultPath,JsonConvert.SerializeObject(SaveObject,Formatting.Indented));
}
public IEnumerable<string> GetKeys()
{
List<string> keys = new List<string>();
foreach(string key in SaveObject.Properties())
{
keys.Add(key);
}
return keys;
}
public bool ContainsKey(string objectKey)
{
return SaveObject.ContainsKey(objectKey);
}
}
}

88
EGFramework/Module/SaveTools/Object/EGRedisSave.cs

@ -0,0 +1,88 @@ @@ -0,0 +1,88 @@
using System.Collections.Generic;
using Newtonsoft.Json;
using StackExchange.Redis;
namespace EGFramework{
public class EGRedisSave : IEGSave, IEGSaveObject
{
public string Conn { set; get; }
public bool IsInit { set; get; }
public ConnectionMultiplexer Redis { set; get; }
public IDatabase Database { set; get; }
public ISubscriber Subscriber { set; get; }
/// <summary>
/// connect to redis server
/// </summary>
/// <param name="conn"> such as server1:6379,server2:6379 </param>
public void InitSave(string conn)
{
try
{
Redis = ConnectionMultiplexer.Connect(conn);
IsInit = true;
this.Conn = conn;
Redis = ConnectionMultiplexer.Connect(conn);
Database = Redis.GetDatabase();
Subscriber = Redis.GetSubscriber();
}
catch (System.Exception)
{
//EG.Print("e:" + e);
}
}
public void AddObject<TObject>(string objectKey, TObject obj)
{
if(!Database.KeyExists(objectKey)){
Database.SetAdd(objectKey, JsonConvert.SerializeObject(obj));
}else{
throw new System.Exception("Key already exists in redis database.");
}
}
public void UpdateObject<TObject>(string objectKey, TObject obj)
{
if(Database.KeyExists(objectKey)){
Database.SetAdd(objectKey, JsonConvert.SerializeObject(obj));
}else{
throw new System.Exception("Key not exists in redis database.");
}
}
public void RemoveObject<TObject>(string objectKey)
{
Database.KeyDelete(objectKey);
}
public void SetObject<TObject>(string objectKey, TObject obj)
{
Database.SetAdd(objectKey, JsonConvert.SerializeObject(obj));
}
public TObject GetObject<TObject>(string objectKey)
{
try
{
string result = Database.StringGet(objectKey);
TObject resultObj = JsonConvert.DeserializeObject<TObject>(result);
return resultObj;
}
catch (System.Exception)
{
throw;
}
}
public bool ContainsKey(string objectKey)
{
return Database.KeyExists(objectKey);
}
public IEnumerable<string> GetKeys()
{
throw new System.NotImplementedException();
}
}
}

151
EGFramework/Module/SaveTools/SaveToolsInterface.cs

@ -0,0 +1,151 @@ @@ -0,0 +1,151 @@
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace EGFramework
{
#region SaveInit
public interface IEGSave
{
void InitSave(string path);
}
public interface IEGSaveReadOnly {
void InitReadOnly(string data);
void InitReadOnly(byte[] data);
}
public interface IEGSaveAsync {
Task InitSaveFileAsync(string path);
}
public interface IEGSaveReadOnlyAsync {
Task InitReadOnlyAsync(string data);
Task InitReadOnlyAsync(byte[] data);
}
#endregion
#region DBConnection
public interface IEGCanGetDBConnection
{
DbConnection GetConnection();
}
public interface IEGDataBase : IEGCanGetDBConnection
{
void CreateTable<TData>(string dataKey);
void CreateTable(string dataKey, Dictionary<string, object> tableParam);
void DropTable(string dataKey);
}
#endregion
#region Object
public interface IEGSaveObjectReadOnly
{
TObject GetObject<TObject>(string objectKey);
IEnumerable<string> GetKeys();
bool ContainsKey(string objectKey);
}
public interface IEGSaveObject : IEGSaveObjectReadOnly{
/// <summary>
/// SetObject will add a object if it not exisits, replace the object if it already exists.
/// </summary>
/// <param name="objectKey"></param>
/// <param name="obj"></param>
/// <typeparam name="TObject"></typeparam>
void SetObject<TObject>(string objectKey,TObject obj);
void RemoveObject<TObject>(string objectKey);
void AddObject<TObject>(string objectKey,TObject obj);
void UpdateObject<TObject>(string objectKey,TObject obj);
}
public interface IEGSaveObjectReadOnlyAsync{
Task<TObject> GetObjectAsync<TObject>(string objectKey) where TObject : new();
}
public interface IEGSaveObjectAsync : IEGSaveObjectReadOnlyAsync{
Task SetObjectAsync<TObject>(string objectKey,TObject obj);
}
#endregion
#region Data
public interface IEGSaveDataReadOnly{
TData GetData<TData>(string dataKey,object id) where TData : new();
IEnumerable<TData> GetAll<TData>(string dataKey) where TData : new();
IEnumerable<TData> GetPage<TData>(string dataKey,int pageIndex,int pageSize) where TData : new();
IEnumerable<TData> FindData<TData>(string dataKey,Expression<Func<TData, bool>> expression) where TData : new();
IEnumerable<TData> FindData<TData>(string dataKey, string columnName, string keyWords) where TData : new();
IEnumerable<string> GetKeys();
bool ContainsKey(string dataKey);
bool ContainsData(string dataKey,object id);
int GetDataCount(string dataKey);
}
public interface IEGSaveData : IEGSaveDataReadOnly{
void SetData<TData>(string dataKey,TData data,object id);
void AddData<TData>(string dataKey,TData data);
void AddData<TData>(string dataKey,IEnumerable<TData> data);
void AddData(string datakey, Dictionary<string, object> data);
void AddGroup(string datakey, List<Dictionary<string, object>> dataGroup);
int RemoveData(string dataKey,object id);
void UpdateData(string dataKey, Dictionary<string, object> data, object id);
void UpdateData<TData>(string dataKey,TData data,object id);
}
public interface IEGSaveDataReadOnlyAsync{
Task<TData> GetDataAsync<TData>(string dataKey,object id) where TData : new();
Task<IEnumerable<TData>> GetAllAsync<TData>(string dataKey) where TData : new();
Task<IEnumerable<TData>> FindDataAsync<TData>(string dataKey,Expression<Func<TData, bool>> expression) where TData : new();
}
public interface IEGSaveDataAsync : IEGSaveDataReadOnlyAsync{
Task SetDataAsync<TData>(string dataKey,TData data,object id);
}
#endregion
#region File
public interface IEGFileMsg{
public string FileName { get; }
public bool IsCollection { get; }
/// <summary>
/// unit is kb
/// </summary>
public long? Size { get; }
public string Uri { get; }
public DateTime? LastModify { get; }
public void Init(string fileName,bool isCollection,string uri,long? size,DateTime? lastmodify);
}
public struct EGFileMsg : IEGFileMsg{
public string FileName { get; set; }
public bool IsCollection { get; set; }
public long? Size { get; set; }
public string Uri { get; set; }
public DateTime? LastModify { get; set; }
public void Init(string fileName,bool isCollection,string uri,long? size,DateTime? lastmodify){
this.FileName = fileName;
this.IsCollection = isCollection;
this.Uri = uri;
this.Size = size;
this.LastModify = lastmodify;
}
}
public interface IEGSaveFileReadOnly{
IEnumerable<IEGFileMsg> ListRemoteFilePath(string remotePath);
bool IsRemoteFileExist(string remotePath);
bool IsRemoteDirectoryExist(string remotePath);
void DownloadFile(string remotePath,string localPath);
Stream DownloadFile(string remotePath);
void SyncFile(string remotePath,string localPath);
}
public interface IEGSaveFile:IEGSaveFileReadOnly{
void UploadFile(FileStream localFileStream,string remotePath);
void UploadFile(string localPath,string remotePath);
void CopyFile(string sourcePath,string copyPath);
void MoveFile(string sourcePath,string movePath);
void RemoveFile(string remotePath);
void MakeDirectory(string remotePath);
}
#endregion
}

158
InstallManual.md

@ -0,0 +1,158 @@ @@ -0,0 +1,158 @@
# 靶机程序安装手册
Version`V0.1`试行版
修订记录
| 日期 | 版本 | 说明 | 作者 |
| ------------- | ---- | -------- | ------ |
| 2025年12月4日 | V0.1 | 首次编写 | 朱冠臣 |
| | | | |
| | | | |
| | | | |
## 1. 概述
> 本文档为安装手册,用于任何形式的轨道靶机,不限于地轨,空轨,竖轨等等。
>
> 靶机运行环境为如下
>
> - 架构为AMD64
> - 需要预装.net8 运行时
> - 设备具备ch341或ch340驱动
>
> 靶机需提前配置好串口编号并测试串口信息输出
## 2. 安装系统环境
1. Ubuntu20.04
2. openssh-server
3. net-tools
4. git
5. dotnet8
6. 串口授权
默认安装环境已完成
### 2.1 安装openssh-server(镜像可能自带)
```shell
sudo apt-get install openssh-server
```
### 2.2 安装net-tools(镜像可能自带)
```shell
sudo apt-get install net-tools
```
### 2.3 安装git
```shell
sudo apt-get install git
```
### 2.4 安装dotnet8
参考链接-微软安装手册 https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-ubuntu-decision#register-the-microsoft-package-repository
```shell
# Get OS version info which adds the $ID and $VERSION_ID variables
source /etc/os-release
# Download Microsoft signing key and repository
wget https://packages.microsoft.com/config/$ID/$VERSION_ID/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
# Install Microsoft signing key and repository
sudo dpkg -i packages-microsoft-prod.deb
# Clean up
rm packages-microsoft-prod.deb
# Update packages
sudo apt update
```
安装dotnet
```shell
sudo apt-get install dotnet-sdk-8.0
```
### 2.5 串口授权(如果用户名为其它则修改为u)
```shell
sudo usermod -aG dialout u
```
### 2.6 关闭防火墙&允许访问端口
检查防火墙状态
```shell
sudo ufw status
```
如果关闭
Status: inactive
如果开启,关闭防火墙
```shell
sudo ufw disable
```
或者开启对应端口
```shell
sudo ufw allow <port/service>
```
## 3. 编译安装软件
1. 克隆项目(项目地址以实际地址为准)
2. 打release包
3. 注册程序为Systemctl 服务
### 3.1 克隆项目
```shell
git clone http://byserver:3000/TargetMachine/TrackTargetService
```
### 3.2 发布release包
```shell
dotnet publish --configuration Release
```
### 3.3 注册程序为Systemctl 服务
```shell
# 切换到工程对应路径SystemCtl下
cd SystemCtl
# 启动install.sh脚本
sudo chmod 777 install.sh
./install.sh
```
### 3.4 开启或关闭服务
```shell
# 开启服务
sudo systemctl start TrackTarget.service
# 关闭服务
sudo systemctl stop TrackTarget.service
# 重启服务
sudo systemctl restart TrackTarget.service
# 查看运行状态
sudo systemctl status TrackTarget.service
```

23
Program.cs

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
using TargetService.Components;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
}
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();

29
Properties/launchSettings.json

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:16619",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "http://localhost:5257",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

41
Script/Architecture/EGBlazorController.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
using System.Timers;
namespace EGFramework
{
public class EGBlazorController : IEGBehavior, IEGFramework
{
private EGProtocolSchedule? ProtocolSchedule { set; get; }
private System.Timers.Timer ProcessTimer { set; get; } = new System.Timers.Timer(20);
public void Init()
{
ProtocolSchedule = this.GetModule<EGProtocolSchedule>();
this.GetModule<EGMessage>().SetDelay(100);
ProcessTimer.Elapsed += this.Process;
ProcessTimer.AutoReset = true;
ProcessTimer.Enabled = true;
}
public void Start()
{
ProtocolSchedule?.EnabledTool<EGTCPServer>();
// ProtocolSchedule?.EnabledTool<EGTCPClient>();
ProtocolSchedule?.EnabledTool<EGSerialPort>();
ProtocolSchedule?.EnabledTool<EGUDP>();
this.GetModule<ModelSerialServer>();
this.GetModule<ModelSerialTest>();
this.GetModule<ModelControlServer>();
}
public void Process(object? source, ElapsedEventArgs e)
{
ProtocolSchedule?.CheckedProcess();
}
public void Exit()
{
}
}
}

14
Script/Data/DataActionStatus.cs

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
public class DataActionStatus
{
/// <summary>
/// 0-200
/// </summary>
/// <value></value>
public int Position { set; get; }
/// <summary>
/// 0-90
/// </summary>
/// <value></value>
public int Rotate { set; get; }
}

19
Script/Data/DataSetting.cs

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
using System.Numerics;
public class DataSetting
{
public int DeviceID { set; get; }
public int MoveSpeed { set; get; }
public int MoveLowSpeed { set; get; }
public int RotateSpeed { set; get; }
public int TimeoutStop { set; get; }
public float ColorOffset { set; get; }
public Dictionary<int, Vector3> ColorMapping { set; get; } = new Dictionary<int, Vector3>();
}
public class DataSerialPortSetting
{
public string MotorDevicePort { set; get; }
public string ColorSensorDevicePort { set; get; }
}

98
Script/Extension/ColorConvertExtension.cs

@ -0,0 +1,98 @@ @@ -0,0 +1,98 @@
using System;
using System.Numerics;
public static class ColorConvertExtension
{
/// <summary>
/// 将RGB颜色转换为HSV颜色空间
/// </summary>
/// <param name="rgb">RGB颜色向量,X=R, Y=G, Z=B,取值范围0-1</param>
/// <returns>HSV颜色向量,X=H(0-360), Y=S(0-1), Z=V(0-1)</returns>
public static Vector3 RGBToHSV(this Vector3 rgb)
{
float r = rgb.X;
float g = rgb.Y;
float b = rgb.Z;
float max = Math.Max(r, Math.Max(g, b));
float min = Math.Min(r, Math.Min(g, b));
float delta = max - min;
float h = 0f;
float s = 0f;
float v = max;
// 计算色相 (H)
if (delta > 0f)
{
if (max == r)
{
h = (g - b) / delta;
if (h < 0f) h += 6f;
}
else if (max == g)
{
h = 2f + (b - r) / delta;
}
else // max == b
{
h = 4f + (r - g) / delta;
}
h *= 60f; // 转换为度数
}
// 计算饱和度 (S)
if (max > 0f)
{
s = delta / max;
}
return new Vector3(h, s, v);
}
/// <summary>
/// 将HSV颜色转换为RGB颜色空间
/// </summary>
/// <param name="hsv">HSV颜色向量,X=H(0-360), Y=S(0-1), Z=V(0-1)</param>
/// <returns>RGB颜色向量,X=R, Y=G, Z=B,取值范围0-1</returns>
public static Vector3 HSVToRGB(this Vector3 hsv)
{
float h = hsv.X;
float s = hsv.Y;
float v = hsv.Z;
// 处理色相超出范围的情况
h = h % 360f;
if (h < 0f) h += 360f;
// 限制饱和度和明度在0-1范围内
s = Math.Clamp(s, 0f, 1f);
v = Math.Clamp(v, 0f, 1f);
// 如果饱和度为0,直接返回灰度值
if (s <= 0f)
{
return new Vector3(v, v, v);
}
// 将色相转换为0-6的范围
float hNormalized = h / 60f;
int sector = (int)hNormalized;
float fractional = hNormalized - sector;
float p = v * (1f - s);
float q = v * (1f - s * fractional);
float t = v * (1f - s * (1f - fractional));
return sector switch
{
0 => new Vector3(v, t, p),
1 => new Vector3(q, v, p),
2 => new Vector3(p, v, t),
3 => new Vector3(p, q, v),
4 => new Vector3(t, p, v),
_ => new Vector3(v, p, q) // 5 或 其他情况
};
}
}

12
Script/Interface/IEGBehavior.cs

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
using System.Timers;
namespace EGFramework
{
public interface IEGBehavior
{
public void Init();
public void Start();
public void Process(object source, ElapsedEventArgs e);
public void Exit();
}
}

41
Script/Model/ModelActionStatus.cs

@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
using System.Data;
using EGFramework;
public class ModelActionStatus : EGModule, IEGFramework
{
public DataActionStatus Status { set; get; }
public override void Init()
{
if (!this.EGSave().DefaultJsonSave.ContainsKey("DataActionStatus"))
{
DataActionStatus newStatus = new DataActionStatus();
this.EGSave().DefaultJsonSave.SetObject("DataActionStatus", newStatus);
Status = newStatus;
// this.EGRegisterObject<DataSetting>(newSetting);
}
else
{
DataActionStatus settings = this.EGSave().DefaultJsonSave.GetObject<DataActionStatus>("DataActionStatus");
this.EGRegisterObject<DataActionStatus>(settings);
Status = settings;
}
}
public void Save(DataActionStatus status)
{
this.EGSave().DefaultJsonSave.SetObject("DataActionStatus", status);
}
public void SetPosition(int position)
{
this.Status.Position = position;
this.Save(Status);
}
public void SetRotation(int rotation)
{
this.Status.Rotate = rotation;
this.Save(Status);
}
}

51
Script/Model/ModelControlServer.cs

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
using EGFramework;
public class ModelControlServer : EGModule, IEGFramework
{
public const int TCPListenPort = 6557;
public const int UDPListenPort = 6558;
public override void Init()
{
this.EGTCPServerListen(TCPListenPort);
this.EGUDPListen(UDPListenPort);
this.EGOnMessage<ResponseControl>();
this.EGRegisterMessageEvent<ResponseControl>(OnResponseControl);
// throw new NotImplementedException();
}
public void OnResponseControl(ResponseControl data, string sender, ProtocolType type)
{
if (type == ProtocolType.TCPServer || type == ProtocolType.UDP)
{
switch (data.FunctionCode)
{
case (int)TypeControlFunction.StartShooting:
this.GetModule<ModelTrackControl>().StartTarget();
break;
case (int)TypeControlFunction.StopShooting:
this.GetModule<ModelTrackControl>().RevertTarget();
break;
case (int)TypeControlFunction.Status:
this.EGSendMessage(new RequestControlStatus()
{
TargetID = this.GetModule<ModelParamSetting>().Setting.DeviceID,
FunctionCode = data.FunctionCode,
IsStart = this.GetModule<ModelTrackControl>().CurrentRotation > 0,
Position = this.GetModule<ModelTrackControl>().CurrentPosition
}, sender, type);
return;
case (int)TypeControlFunction.TrackMove:
this.GetModule<ModelTrackControl>().MoveToPosition(data.Position);
break;
}
}
this.EGSendMessage(new RequestControl()
{
TargetID = this.GetModule<ModelParamSetting>().Setting.DeviceID,
FunctionCode = data.FunctionCode,
ExecuteSuccess = true,
ErrorCode = 0
}, sender, type);
}
}

77
Script/Model/ModelParamSetting.cs

@ -0,0 +1,77 @@ @@ -0,0 +1,77 @@
using System.Numerics;
using EGFramework;
public class ModelParamSetting : EGModule, IEGFramework
{
public DataSetting Setting { set; get; }
public DataSerialPortSetting SerialPortSetting { set; get; }
public override void Init()
{
if (!this.EGSave().DefaultJsonSave.ContainsKey("DataSetting"))
{
DataSetting newSetting = CreateDefault();
this.EGSave().DefaultJsonSave.SetObject("DataSetting", newSetting);
Setting = newSetting;
// this.EGRegisterObject<DataSetting>(newSetting);
}
else
{
DataSetting settings = this.EGSave().DefaultJsonSave.GetObject<DataSetting>("DataSetting");
this.EGRegisterObject<DataSetting>(settings);
Setting = settings;
}
if (!this.EGSave().DefaultJsonSave.ContainsKey("DataSerialPortSetting"))
{
DataSerialPortSetting newPortSetting = CreateSerialPortSetting();
this.EGSave().DefaultJsonSave.SetObject("DataSerialPortSetting", newPortSetting);
SerialPortSetting = newPortSetting;
// this.EGRegisterObject<DataSetting>(newSetting);
}
else
{
DataSerialPortSetting portSettings = this.EGSave().DefaultJsonSave.GetObject<DataSerialPortSetting>("DataSerialPortSetting");
this.EGRegisterObject<DataSerialPortSetting>(portSettings);
SerialPortSetting = portSettings;
}
}
public DataSetting CreateDefault()
{
DataSetting newSetting = new DataSetting()
{
DeviceID = 0,
MoveSpeed = 200,
MoveLowSpeed = 100,
RotateSpeed = 2000,
TimeoutStop = 5000,
ColorOffset = 5,
ColorMapping = new Dictionary<int, System.Numerics.Vector3>()
};
newSetting.ColorMapping.Add(0, new Vector3(107, 100, 100));
newSetting.ColorMapping.Add(7, new Vector3(83, 100, 100));
newSetting.ColorMapping.Add(10, new Vector3(194, 100, 100));
newSetting.ColorMapping.Add(15, new Vector3(334, 100, 100));
newSetting.ColorMapping.Add(25, new Vector3(349, 100, 100));
return newSetting;
}
public DataSerialPortSetting CreateSerialPortSetting()
{
return new DataSerialPortSetting();
}
public void Save(DataSetting editSetting)
{
this.EGSave().DefaultJsonSave.SetObject("DataSetting", editSetting);
this.Setting = editSetting;
}
public void Save(DataSetting editSetting, DataSerialPortSetting portSetting)
{
this.EGSave().DefaultJsonSave.SetObject("DataSetting", editSetting);
this.EGSave().DefaultJsonSave.SetObject("DataSerialPortSetting", portSetting);
this.Setting = editSetting;
this.SerialPortSetting = portSetting;
}
}

56
Script/Model/ModelSerialServer.cs

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
using EGFramework;
public class ModelSerialServer : EGModule,IEGFramework
{
public int SerialServerPort { set; get; } = 6550;
public int SerialServerPortBackUp { set; get; } = 6551;
public List<string> SerialNames { set; get; } = new List<string>();
public override void Init()
{
this.EGTCPServerListen(SerialServerPort);
this.EGOnMessage<ResponseSerialPort>();
this.EGOnMessage<ResponseSerialServer>();
this.EGRegisterMessageEvent<ResponseSerialServer>(OnReceivedFromTCP);
this.EGRegisterMessageEvent<ResponseSerialPort>(OnReceivedFromSerialPort);
EG.Print("串口转TCP服务已开启!");
// throw new NotImplementedException();
}
public void SendToSerial(ResponseSerialServer res)
{
if (!SerialNames.Contains(res.SerialPort) && res.BaudRate != 0)
{
this.EGSerialPort().Open(res.SerialPort, res.BaudRate);
SerialNames.Add(res.SerialPort);
}
EG.Print("Send Serial : " + res.StringData);
this.EGSendMessage<RequestSerialPort>(new RequestSerialPort(res), res.SerialPort, ProtocolType.SerialPort);
}
public void SendToClient(byte[] data,string serialPortName)
{
if (this.EGTCPServer().LinkedIPs.ContainsKey(6550))
{
EG.Print("Send Client : " + data.ToStringByHex());
foreach (string sender in this.EGTCPServer().LinkedIPs[6550])
{
this.EGSendMessage<RequestSerialRevert>(new RequestSerialRevert(data,serialPortName), sender, ProtocolType.TCPServer);
}
}
}
public void OnReceivedFromTCP(ResponseSerialServer tcpData,string sender,ProtocolType protocol)
{
if(protocol == ProtocolType.TCPServer && this.EGTCPServer().LinkedIPs[6550].Contains(sender))
{
SendToSerial(tcpData);
}
}
public void OnReceivedFromSerialPort(ResponseSerialPort serialData,string sender,ProtocolType protocol)
{
if(protocol == ProtocolType.SerialPort)
{
SendToClient(serialData.Data,sender);
}
}
}

108
Script/Model/ModelSerialTest.cs

@ -0,0 +1,108 @@ @@ -0,0 +1,108 @@
using EGFramework;
/// <summary>
/// 检测串口对应的空轨驱动器,或是颜色传感器,检测后记录到串口列表中
/// </summary>
public class ModelSerialTest : EGModule,IEGFramework
{
public const int BAUD_RATE_ENGINE = 9600;
public const int BAUD_RATE_COLOR = 38400;
public const string PORT_LINUX_0 = "/dev/ttyUSB0";
public const string PORT_LINUX_1 = "/dev/ttyUSB1";
public const string PORT_WIN_0 = "COM2";
public const string PORT_WIN_1 = "COM5";
public bool IsLinux = true;
public string TestPort0 { set; get; } = PORT_LINUX_0;
public string TestPort1 { set; get; } = PORT_LINUX_1;
public string ColorSerialPort { set; get; } = "";
public string EngineSerialPort { set; get; } = "";
public IUnRegister ColorSensorInitEvent { set; get; }
public IUnRegister EngineInitEvent{ set; get; }
public override void Init()
{
ColorSensorInitEvent = this.EGRegisterMessageEvent<ResponseColorSensor>(OnColorSensorInit);
this.EGOnMessage<ResponseColorSensor>();
this.EGOnMessage<ResponseTrack>();
if (!IsLinux)
{
TestPort0 = PORT_WIN_0;
TestPort1 = PORT_WIN_1;
}
InitSerialPort();
// throw new NotImplementedException();
}
public async void InitSerialPort()
{
this.EGSerialPort().Open(TestPort0, 38400);
this.EGSendMessage(new RequestColorSingleRead(), TestPort0, ProtocolType.SerialPort);
await Task.Delay(2000);
if(ColorSerialPort == "")
{
this.EGSerialPort().Close(TestPort0);
this.EGSerialPort().Open(TestPort1, 38400);
this.EGSendMessage(new RequestColorSingleRead(), TestPort1, ProtocolType.SerialPort);
await Task.Delay(2000);
if(ColorSerialPort == "")
{
this.EGSerialPort().Close(TestPort1);
EG.Print("Color sensor init failed,Time out.");
}
else
{
EG.Print("_"+this.EGSerialPort().SerialPortDevices.ContainsKey(TestPort0));
this.EGSerialPort().Open(TestPort0, 9600);
this.EGSendMessage(new RequestTrackReadEnabled(), TestPort0, ProtocolType.SerialPort);
EngineInitEvent = this.EGRegisterMessageEvent<ResponseTrack>(OnEngineInit);
await Task.Delay(2000);
if(EngineSerialPort == "")
{
this.EGSerialPort().Close(TestPort0);
EG.Print("Engine init failed USB0,Time out.");
}
}
}
else
{
this.EGSerialPort().Open(TestPort1, 9600);
this.EGSendMessage(new RequestTrackReadEnabled(), TestPort1, ProtocolType.SerialPort);
EngineInitEvent = this.EGRegisterMessageEvent<ResponseTrack>(OnEngineInit);
await Task.Delay(2000);
if(EngineSerialPort == "")
{
this.EGSerialPort().Close(TestPort1);
EG.Print("Engine init failed USB1,Time out.");
}
}
}
public void OnColorSensorInit(ResponseColorSensor res, string sender, ProtocolType type)
{
if (type == ProtocolType.SerialPort)
{
ColorSensorInitEvent.UnRegister();
this.ColorSerialPort = sender;
EG.Print("Color sensor init success!");
}
}
public void OnEngineInit(ResponseTrack res,string sender,ProtocolType type)
{
if (type == ProtocolType.SerialPort)
{
EngineInitEvent.UnRegister();
this.EngineSerialPort = sender;
EG.Print("Engine sensor init success!");
this.GetModule<ModelTrackControl>().ResetTrack();
}
}
}

317
Script/Model/ModelTrackControl.cs

@ -0,0 +1,317 @@ @@ -0,0 +1,317 @@
using System.Numerics;
using EGFramework;
using Tmds.Linux;
public class ModelTrackControl : EGModule, IEGFramework
{
public const int SlaveID = 3;
public bool IsInitTrack { set; get; } = false;
public bool IsScanning { set; get; } = false;
public string PortName { set; get; } = "";
public Vector3 CurrentColorRGB { set; get; } = new Vector3();
public Vector3 CurrentColorHSV { set; get; } = new Vector3();
private IUnRegister ColorSensorEvent { set; get; }
public int CurrentPosition { set; get; } = 0;
public int TargetPosition { set; get; } = 0;
public StatusTrack MoveStatus { set; get; } = StatusTrack.Stop;
private ushort LowSpeed { set; get; }
private ushort Speed { set; get; }
public int CurrentRotation { set; get; } = 0;
public override void Init()
{
// List<string> portList = this.EGSerialPort().RefreshSerialPort();
CurrentPosition = this.GetModule<ModelActionStatus>().Status.Position;
CurrentRotation = this.GetModule<ModelActionStatus>().Status.Rotate;
LowSpeed = (ushort)this.GetModule<ModelParamSetting>().Setting.MoveLowSpeed;
Speed = (ushort)this.GetModule<ModelParamSetting>().Setting.MoveSpeed;
ResetTarget();
}
public void EnableTrack()
{
this.EGSendMessage(new RequestTrackEnabled(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
IsInitTrack = true;
}
public void StartTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackSpeed(Speed), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackMove(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void StartSlowTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackSpeed(LowSpeed), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackMove(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void BackTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackSpeed(Speed), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackBack(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void BackSlowTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackSpeed(LowSpeed), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackBack(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void StopTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackSpeed(0), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackStop(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void BreakTrack()
{
if (!IsInitTrack)
{
EnableTrack();
}
this.EGSendMessage(new RequestTrackBreak(), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
this.EGSendMessage(new RequestTrackSpeed(0), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
}
public void MoveToPosition(int position)
{
if (this.CurrentPosition == position)
{
EG.Print("Position is same.Nothing need to move!");
return;
}
if (this.MoveStatus != StatusTrack.Stop)
{
EG.Print("Machine should be stop first!");
return;
}
if (!this.GetModule<ModelParamSetting>().Setting.ColorMapping.ContainsKey(position))
{
EG.Print("Position invalid!Please add color first!");
return;
}
TargetPosition = position;
if (this.CurrentPosition > position)
{
this.StartScanColor();
this.StartTrack();
this.MoveStatus = StatusTrack.Start;
}
if (this.CurrentPosition < position)
{
this.StartScanColor();
this.BackTrack();
this.MoveStatus = StatusTrack.Back;
}
}
public void StartTarget()
{
if (CurrentRotation != 90)
{
this.EGSendMessage(new RequestTargetControl(2000,500,false), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
CurrentRotation = 90;
this.GetModule<ModelActionStatus>().SetRotation(CurrentRotation);
}
}
public void RevertTarget()
{
if (CurrentRotation != 0)
{
this.EGSendMessage(new RequestTargetControl(2000, 0, false), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
CurrentRotation = 0;
this.GetModule<ModelActionStatus>().SetRotation(CurrentRotation);
}
}
public void ResetTarget()
{
if (CurrentRotation != 0)
{
this.EGSendMessage(new RequestTargetControl(2000, 500, true), this.GetModule<ModelSerialTest>().EngineSerialPort, ProtocolType.SerialPort);
CurrentRotation = 0;
this.GetModule<ModelActionStatus>().SetRotation(CurrentRotation);
}
}
public void StartScanColor()
{
this.EGSendMessage(new RequestColorStartScan(), this.GetModule<ModelSerialTest>().ColorSerialPort, ProtocolType.SerialPort);
ColorSensorEvent = this.EGRegisterMessageEvent<ResponseColorSensor>(OnColorScanned);
IsScanning = true;
}
public void StopScanColor()
{
this.EGSendMessage(new RequestColorStopScan(), this.GetModule<ModelSerialTest>().ColorSerialPort, ProtocolType.SerialPort);
//null exception
ColorSensorEvent.UnRegister();
IsScanning = false;
}
public void ResetTrack()
{
this.CurrentPosition = 0;
this.StartScanColor();
this.StartTrack();
this.MoveStatus = StatusTrack.Reset;
}
private float HueCache { set; get; }
public void OnColorScanned(ResponseColorSensor color, string sender, ProtocolType type)
{
if (type == ProtocolType.SerialPort)
{
this.CurrentColorHSV = color.ColorHSV;
this.CurrentColorRGB = color.ColorRGB;
if (this.MoveStatus == StatusTrack.Start)
{
float currentHue = CurrentColorHSV.X;
if (MathF.Abs(HueCache - currentHue) > this.GetModule<ModelParamSetting>().Setting.ColorOffset)
{
HueCache = currentHue;
return;
}
float targetHue = this.GetModule<ModelParamSetting>().Setting.ColorMapping[TargetPosition].X;
bool compareResult = this.CompareHue(currentHue, targetHue);
if (compareResult)
{
this.StartSlowTrack();
this.MoveStatus = StatusTrack.StartSlow;
BroadCastMoveStatus();
}
}
if (this.MoveStatus == StatusTrack.Back)
{
float currentHue = CurrentColorHSV.X;
if (MathF.Abs(HueCache - currentHue) > this.GetModule<ModelParamSetting>().Setting.ColorOffset)
{
HueCache = currentHue;
return;
}
float targetHue = this.GetModule<ModelParamSetting>().Setting.ColorMapping[TargetPosition].X;
bool compareResult = this.CompareHue(currentHue, targetHue);
if (compareResult)
{
this.BackSlowTrack();
this.MoveStatus = StatusTrack.BackSlow;
BroadCastMoveStatus();
}
}
if (this.MoveStatus == StatusTrack.BackSlow || this.MoveStatus == StatusTrack.StartSlow)
{
float currentHue = CurrentColorHSV.X;
float targetHue = 4.0f;
bool compareResult = this.CompareHue(currentHue, targetHue);
if (compareResult)
{
this.BreakTrack();
this.MoveStatus = StatusTrack.Stop;
this.StopScanColor();
this.CurrentPosition = this.TargetPosition;
BroadCastMoveStatus();
}
}
if(this.MoveStatus == StatusTrack.Reset)
{
float currentHue = CurrentColorHSV.X;
float targetHue = this.GetModule<ModelParamSetting>().Setting.ColorMapping[0].X;
bool compareResult = this.CompareHue(currentHue, targetHue);
if (compareResult)
{
this.BreakTrack();
this.MoveStatus = StatusTrack.Stop;
this.StopScanColor();
this.CurrentPosition = 0;
BroadCastMoveStatus();
}
}
HueCache = CurrentColorHSV.X;
}
}
public bool CompareHue(float hue1,float hue2)
{
if (hue1 > hue2 - this.GetModule<ModelParamSetting>().Setting.ColorOffset &&
hue1 < hue2 + this.GetModule<ModelParamSetting>().Setting.ColorOffset)
{
return true;
}
else
{
return false;
}
}
public Vector3 GetColor()
{
return CurrentColorRGB;
}
public Vector3 GetColorHSV()
{
return CurrentColorHSV;
}
public void BroadCastMoveStatus()
{
if (this.EGTCPServer().LinkedIPs.ContainsKey(6557))
{
foreach (string sender in this.EGTCPServer().LinkedIPs[6557])
{
this.EGSendMessage<RequestControlMoveStatus>(new RequestControlMoveStatus()
{
TargetID = this.GetModule<ModelParamSetting>().Setting.DeviceID,
FunctionCode = 301,
Position = this.GetModule<ModelTrackControl>().CurrentPosition,
Status = MoveStatus
}, sender, ProtocolType.TCPServer);
}
}
}
}
public enum StatusTrack
{
Stop = 0x00,
Start = 0x01,
StartSlow = 0x02,
Back = 0x03,
BackSlow = 0x04,
Reset = 0x05
}

113
Script/Protocol/RequestSerialServer.cs

@ -0,0 +1,113 @@ @@ -0,0 +1,113 @@
using EGFramework;
using Newtonsoft.Json;
public class RequestSerialPort : IRequest
{
public string SerialPort { set; get; }
public string StringData { set; get; }
public byte[] Data { set; get; }
public RequestSerialPort(byte[] data)
{
this.Data = data;
}
public RequestSerialPort(ResponseSerialServer data)
{
this.Data = data.GetBytes();
}
public string ToProtocolData()
{
return null;
}
public byte[] ToProtocolByteData()
{
return Data;
}
}
public class ResponseSerialPort : IResponse
{
public byte[] Data { set; get; }
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
this.Data = protocolBytes;
if(Data == null)
{
return false;
}
return true;
}
catch (System.Exception)
{
return false;
// throw;
}
}
}
public class RequestSerialRevert : IRequest, IEGFramework
{
public string SerialPort { set; get; }
public bool IsByte { set; get; }
public string StringData { set; get; }
public RequestSerialRevert(byte[] data,string serialPort)
{
this.StringData = data.ToStringByHex();
this.IsByte = true;
this.SerialPort = serialPort;
}
public byte[] ToProtocolByteData()
{
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this);
}
}
public class ResponseSerialServer : IResponse, IEGFramework
{
public string SerialPort { set; get; }
public bool IsByte { set; get; }
public string StringData { set; get; }
public int BaudRate { set; get; }
private byte[] Data { set; get; }
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
if (!protocolData.StartsWith('{') && !protocolData.StartsWith('['))
{
return false;
}
ResponseSerialServer data = JsonConvert.DeserializeObject<ResponseSerialServer>(protocolData);
if (data != null && data.SerialPort != null && data.SerialPort != "")
{
this.SerialPort = data.SerialPort;
this.IsByte = data.IsByte;
this.StringData = data.StringData;
this.BaudRate = data.BaudRate;
this.Data = data.StringData.ToHexByString();
return true;
}
else
{
return false;
}
}
catch (System.Exception)
{
return false;
}
}
public byte[] GetBytes()
{
return Data;
}
}

31
Script/Protocol/RequestTargetEngine.cs

@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
using EGFramework;
public class RequestTargetControl : ModbusRTU_WriteMultiHoldingRegister, IEGFramework
{
public bool IsBack { set; get; } = false;
public ushort Speed { set; get; } = 2000;
public ushort Position { set; get; } = 0;
public RequestTargetControl(ushort speed,ushort position,bool isBack)
{
this.DeviceAddress = 0x01;
this.RegisterStartAddress = 68;
this.Speed = speed;
this.Position = position;
this.IsBack = isBack;
this.Values = GetValues();
EG.Print("[TargetSend]" + this.ToProtocolByteData().ToStringByHex());
}
public ushort[] GetValues()
{
ushort[] resultValues = { Speed,0x00,0x00,Position};
if (IsBack)
{
ushort max = 65535;
resultValues[2] = max;
resultValues[3] = (ushort)(max - Position);
}
return resultValues;
}
}

103
Script/Protocol/RequestTrackEngine.cs

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
using EGFramework;
public class RequestTrackEnabled : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackEnabled()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0xB6;
this.Value = 0x01;
}
}
public class RequestTrackDisabled : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackDisabled()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0xB6;
this.Value = 0x02;
}
}
public class RequestTrackSpeed: ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackSpeed(ushort speed)
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0x56;
this.Value = speed;
}
}
public class RequestTrackStop : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackStop()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0x66;
this.Value = 0x00;
}
}
public class RequestTrackMove : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackMove()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0x66;
this.Value = 0x01;
}
}
public class RequestTrackBack : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackBack()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0x66;
this.Value = 0x02;
}
}
public class RequestTrackBreak : ModbusRTU_WriteSingleHoldingRegister, IEGFramework
{
public RequestTrackBreak()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0x66;
this.Value = 0x03;
}
}
public class RequestTrackReadEnabled: ModbusRTU_ReadHoldingRegisters, IEGFramework
{
public RequestTrackReadEnabled()
{
this.DeviceAddress = 0x03;
this.RegisterAddress = 0xB6;
this.ReadCount = 0x01;
}
}
public class ResponseTrack : ModbusRTU_Response, IEGFramework
{
public uint ResValue { set; get; }
public override bool TrySetData(string protocolData, byte[] protocolBytes)
{
bool result = base.TrySetData(protocolData, protocolBytes);
if (!result)
{
return false;
}
if (this.HoldingRegister != null && this.HoldingRegister.Length >= 1)
{
ResValue = HoldingRegister[0];
}
else
{
return false;
}
return result;
}
}

59
Script/Protocol/ResponseColorSensor.cs

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
using System.Numerics;
using EGFramework;
public class RequestColorStartScan : ModbusRTU_WriteSingleHoldingRegister
{
public RequestColorStartScan()
{
this.DeviceAddress = 0x01;
this.RegisterAddress = 0x3007;
this.Value = 0x02;
}
}
public class RequestColorStopScan : ModbusRTU_WriteSingleHoldingRegister
{
public RequestColorStopScan()
{
this.DeviceAddress = 0x01;
this.RegisterAddress = 0x3007;
this.Value = 0x01;
}
}
public class RequestColorSingleRead : ModbusRTU_ReadHoldingRegisters
{
public RequestColorSingleRead()
{
this.DeviceAddress = 0x01;
this.RegisterAddress = 0x00;
this.ReadCount = 3;
}
}
public class ResponseColorSensor : ModbusRTU_Response
{
public Vector3 ColorRGB { set; get; }
public Vector3 ColorHSV { set; get; }
public override bool TrySetData(string protocolData, byte[] protocolBytes)
{
bool result = base.TrySetData(protocolData, protocolBytes);
if (!result)
{
return false;
}
if (this.HoldingRegister != null && this.HoldingRegister.Length >= 3)
{
ColorRGB = new Vector3(HoldingRegister[0] / 1000f, HoldingRegister[1] / 1000f, HoldingRegister[2] / 1000f);
ColorHSV = ColorRGB.RGBToHSV();
}
else
{
return false;
}
return result;
}
}

105
Script/Protocol/ResponseControl.cs

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
using EGFramework;
using Newtonsoft.Json;
//通讯协议类定义
public class ResponseControl : IResponse
{
public int FunctionCode { set; get; }
public int Position { set; get; }
public bool TrySetData(string protocolData, byte[] protocolBytes)
{
try
{
if (!protocolData.StartsWith('{') && !protocolData.StartsWith('['))
{
return false;
}
ResponseControl data = JsonConvert.DeserializeObject<ResponseControl>(protocolData);
if (data != null && data.FunctionCode != 0)
{
this.FunctionCode = data.FunctionCode;
this.Position = data.Position;
return true;
}
else
{
return false;
}
}
catch (System.Exception)
{
return false;
// throw;
}
}
}
//数据返回
public class RequestControl : IRequest
{
public int TargetID { set; get; }
public int FunctionCode { set; get; }
public bool ExecuteSuccess { set; get; }
public int ErrorCode { set; get; }
public byte[] ToProtocolByteData()
{
// throw new NotImplementedException();
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this);
}
}
//状态查询
public class RequestControlStatus : IRequest
{
public int TargetID { set; get; }
public int FunctionCode { set; get; }
public bool IsStart { set; get; }
public int Position { set; get; }
public byte[] ToProtocolByteData()
{
// throw new NotImplementedException();
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this);
}
}
//移动状态反馈
public class RequestControlMoveStatus : IRequest
{
public int TargetID { set; get; }
public int FunctionCode { set; get; }
public int Position { set; get; }
public StatusTrack Status { set; get; }
public byte[] ToProtocolByteData()
{
return null;
}
public string ToProtocolData()
{
return JsonConvert.SerializeObject(this);
}
}
public enum TypeControlFunction
{
StartShooting = 201,
StopShooting = 200,
Status = 100,
TargetMessage = 300,
TrackMessage = 301,
OtherMessage = 302,
TrackMove = 401,
TrackStop = 400,
TrackError = 404
}

14
SystemCtl/TrackTarget.service

@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
[Unit]
Description=TrackTargetService
After=network.target
[Service]
ExecStart=/home/u/TrackTargetService/bin/Release/net8.0/publish/TrackTargetService
WorkingDirectory=/home/u/TrackTargetService
User=u
Group=dialout
Restart=always
Type=simple
[Install]
WantedBy=multi-user.target

51
SystemCtl/install.sh

@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
#!/bin/bash
# 服务文件名
SERVICE_FILE="TrackTarget.service"
# 检查当前目录下是否存在服务文件
if [ ! -f "$SERVICE_FILE" ]; then
echo "错误: 在当前目录下未找到 $SERVICE_FILE 文件"
exit 1
fi
# 检查systemctl是否可用
if ! command -v systemctl &> /dev/null; then
echo "错误: systemctl 命令未找到,请确保系统使用systemd"
exit 1
fi
# 复制服务文件到系统目录
echo "正在复制 $SERVICE_FILE 到 /etc/systemd/system/"
sudo cp "$SERVICE_FILE" /etc/systemd/system/
# 检查复制是否成功
if [ $? -ne 0 ]; then
echo "错误: 复制服务文件失败"
exit 1
fi
# 重新加载systemd配置
echo "重新加载systemd配置"
sudo systemctl daemon-reload
# 启用服务开机启动
echo "启用服务开机启动"
sudo systemctl enable "$SERVICE_FILE"
# 检查启用是否成功
if [ $? -ne 0 ]; then
echo "错误: 启用开机启动失败"
exit 1
fi
# 显示服务状态
echo "服务状态:"
sudo systemctl status "$SERVICE_FILE"
echo "操作完成!$SERVICE_FILE 已安装并设置为开机启动"
echo "你可以使用以下命令管理服务:"
echo "启动服务: sudo systemctl start $SERVICE_FILE"
echo "停止服务: sudo systemctl stop $SERVICE_FILE"
echo "重启服务: sudo systemctl restart $SERVICE_FILE"
echo "查看状态: sudo systemctl status $SERVICE_FILE"

26
TargetService.csproj

@ -0,0 +1,26 @@ @@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="System.IO.Ports" Version="8.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="8.0.1" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="8.0.0" />
<PackageReference Include="WebDav.Client" Version="2.8.0" />
<PackageReference Include="MQTTnet" Version="4.3.3.952" />
<PackageReference Include="Makaretu.Dns.Multicast" Version="0.27.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.Ini" Version="8.0.0" />
<PackageReference Include="LiteDB" Version="5.0.21" />
<PackageReference Include="BACnet" Version="2.0.4" />
<PackageReference Include="MySql.Data" Version="9.1.0" />
<PackageReference Include="Dapper" Version="2.1.35" />
<PackageReference Include="SSH.NET" Version="2024.2.0" />
<PackageReference Include="StackExchange.Redis" Version="2.8.31" />
<PackageReference Include="FluentFTP" Version="52.1.0" />
</ItemGroup>
</Project>

24
TargetService.sln

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.2.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TargetService", "TargetService.csproj", "{78C10421-FFB8-A719-CD69-10EB6D9087BF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{78C10421-FFB8-A719-CD69-10EB6D9087BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{78C10421-FFB8-A719-CD69-10EB6D9087BF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78C10421-FFB8-A719-CD69-10EB6D9087BF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78C10421-FFB8-A719-CD69-10EB6D9087BF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4C675282-8DA8-4A2B-BCFE-1C2914B1E8F5}
EndGlobalSection
EndGlobal

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save