Z
5 months ago
commit
5c3e1143b9
71 changed files with 8417 additions and 0 deletions
@ -0,0 +1,2 @@
@@ -0,0 +1,2 @@
|
||||
# Normalize EOL for all files that Git considers text files. |
||||
* text=auto eol=lf |
@ -0,0 +1,21 @@
@@ -0,0 +1,21 @@
|
||||
# Godot 4+ specific ignores |
||||
.godot/ |
||||
|
||||
# Godot-specific ignores |
||||
.import/ |
||||
export.cfg |
||||
export_presets.cfg |
||||
|
||||
# Imported translations (automatically generated from CSV files) |
||||
*.translation |
||||
|
||||
# Mono-specific ignores |
||||
.mono/ |
||||
data_*/ |
||||
mono_crash.*.json |
||||
|
||||
# VScode-Specific ignores |
||||
.vscode/ |
||||
|
||||
#EGSave-Specific ignores |
||||
SaveData/ |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Godot.NET.Sdk/4.2.1"> |
||||
<PropertyGroup> |
||||
<TargetFramework>net6.0</TargetFramework> |
||||
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'android' ">net7.0</TargetFramework> |
||||
<TargetFramework Condition=" '$(GodotTargetPlatform)' == 'ios' ">net8.0</TargetFramework> |
||||
<EnableDynamicLoading>true</EnableDynamicLoading> |
||||
</PropertyGroup> |
||||
<ItemGroup> |
||||
<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="BACnet" Version="2.0.4" /> |
||||
</ItemGroup> |
||||
</Project> |
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00 |
||||
# Visual Studio 2012 |
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EGFramework", "EGFramework.csproj", "{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}" |
||||
EndProject |
||||
Global |
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution |
||||
Debug|Any CPU = Debug|Any CPU |
||||
ExportDebug|Any CPU = ExportDebug|Any CPU |
||||
ExportRelease|Any CPU = ExportRelease|Any CPU |
||||
EndGlobalSection |
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.Debug|Any CPU.Build.0 = Debug|Any CPU |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.ExportDebug|Any CPU.ActiveCfg = ExportDebug|Any CPU |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.ExportDebug|Any CPU.Build.0 = ExportDebug|Any CPU |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.ExportRelease|Any CPU.ActiveCfg = ExportRelease|Any CPU |
||||
{C87FD7C2-9AA4-44E6-9B4C-8EEADF9D3E09}.ExportRelease|Any CPU.Build.0 = ExportRelease|Any CPU |
||||
EndGlobalSection |
||||
EndGlobal |
@ -0,0 +1,79 @@
@@ -0,0 +1,79 @@
|
||||
[gd_scene load_steps=6 format=3 uid="uid://hp4ae14r3hpm"] |
||||
|
||||
[ext_resource type="Script" path="res://Example/Gateway/Script/View/ViewGateway.cs" id="1_tas7d"] |
||||
[ext_resource type="Script" path="res://Example/Gateway/Script/View/ViewTcpGateway.cs" id="2_ct4oh"] |
||||
[ext_resource type="Script" path="res://Example/Gateway/Script/View/ViewBacNetGateway.cs" id="3_ip8nj"] |
||||
[ext_resource type="Script" path="res://Example/Gateway/Script/View/ViewBacnetHttpServer.cs" id="4_plubp"] |
||||
[ext_resource type="FontFile" uid="uid://b1atsgy4xkk7d" path="res://Font/SourceHanSansCN-Regular.otf" id="5_q4lsg"] |
||||
|
||||
[node name="Gateway" type="Control"] |
||||
layout_mode = 3 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("1_tas7d") |
||||
|
||||
[node name="TcpGateway" type="Control" parent="."] |
||||
visible = false |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("2_ct4oh") |
||||
|
||||
[node name="BacNetGateway" type="Control" parent="."] |
||||
visible = false |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("3_ip8nj") |
||||
|
||||
[node name="BacnetHttpServer" type="Control" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("4_plubp") |
||||
|
||||
[node name="Setting" type="Control" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
|
||||
[node name="GatewaySetting" type="Label" parent="Setting"] |
||||
layout_mode = 1 |
||||
anchors_preset = 5 |
||||
anchor_left = 0.5 |
||||
anchor_right = 0.5 |
||||
offset_left = -181.5 |
||||
offset_right = 181.5 |
||||
offset_bottom = 70.0 |
||||
grow_horizontal = 2 |
||||
theme_override_colors/font_shadow_color = Color(0, 0, 0, 1) |
||||
theme_override_constants/shadow_offset_x = 4 |
||||
theme_override_constants/shadow_offset_y = 4 |
||||
theme_override_fonts/font = ExtResource("5_q4lsg") |
||||
theme_override_font_sizes/font_size = 48 |
||||
text = "Gateway Setting" |
||||
|
||||
[node name="MessageContainer" type="TextEdit" parent="Setting"] |
||||
layout_mode = 1 |
||||
anchors_preset = -1 |
||||
anchor_top = 0.56 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
editable = false |
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://c8vhi8ojdtjnb"] |
||||
|
||||
[ext_resource type="Script" path="res://Example/Gateway/Script/View/ViewModbusGateway.cs" id="1_34uaa"] |
||||
|
||||
[node name="ModbusGateway" type="Control"] |
||||
layout_mode = 3 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("1_34uaa") |
@ -0,0 +1,13 @@
@@ -0,0 +1,13 @@
|
||||
using System.Collections.Generic; |
||||
using System.IO.BACnet; |
||||
|
||||
namespace EGFramework.Examples.Gateway |
||||
{ |
||||
public class DataBacnetGatewaySetting { |
||||
public string MqttHost { set; get; } |
||||
public string HttpServerPrefix { set; get; } |
||||
public string RequestTheme { set; get; } |
||||
public string ResponseTheme { set; get; } |
||||
} |
||||
|
||||
} |
@ -0,0 +1,31 @@
@@ -0,0 +1,31 @@
|
||||
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework.Examples.Gateway{ |
||||
public class DataModbusGatewaySetting{ |
||||
public float Delay { set; get; } |
||||
public List<DataModbus485Device> Devices485 = new List<DataModbus485Device>(); |
||||
public List<DataModbusTCPDevice> DevicesTCP = new List<DataModbusTCPDevice>(); |
||||
} |
||||
public class DataModbus485Device{ |
||||
public string SerialPort { set; get; } |
||||
public byte Address { set; get; } |
||||
public int BaudRate { set; get; } |
||||
public Dictionary<string,DataModbusRegister> Registers = new Dictionary<string, DataModbusRegister>(); |
||||
} |
||||
|
||||
public class DataModbusTCPDevice{ |
||||
public string Host { set; get; } |
||||
public int Port { set; get; } |
||||
public byte Address { set; get; } |
||||
public Dictionary<string,DataModbusRegister> Registers = new Dictionary<string, DataModbusRegister>(); |
||||
} |
||||
public class DataModbusRegister{ |
||||
public short Address { set; get; } |
||||
public ModbusRegisterType RegisterType { set; get; } = ModbusRegisterType.HoldingRegister; |
||||
public string Info { set; get; } |
||||
public string Unit { set; get; } |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,16 @@
@@ -0,0 +1,16 @@
|
||||
|
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework.Examples.Gateway{ |
||||
public class DataTcpGatewaySetting{ |
||||
public List<DataTcpGatewayDevice> DataTcpGatewayDevices = new List<DataTcpGatewayDevice>(); |
||||
|
||||
} |
||||
public class DataTcpGatewayDevice{ |
||||
public string Host { set; get; } |
||||
public int Port { set; get; } |
||||
public string MqttHost { set; get; } |
||||
public string RequestTheme { set; get; } |
||||
public string ResponseTheme { set; get; } |
||||
} |
||||
} |
@ -0,0 +1,6 @@
@@ -0,0 +1,6 @@
|
||||
namespace EGFramework.Examples.Gateway |
||||
{ |
||||
public interface IGateway{ |
||||
public void InitGateway(); |
||||
} |
||||
} |
@ -0,0 +1,73 @@
@@ -0,0 +1,73 @@
|
||||
using Godot; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO.BACnet; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace EGFramework.Examples.Gateway{ |
||||
public partial class ViewBacNetGateway : Control,IGateway,IEGFramework |
||||
{ |
||||
public DataBacnetGatewaySetting DataBacnetGatewaySetting { set; get; } |
||||
|
||||
// Called when the node enters the scene tree for the first time. |
||||
public override void _Ready() |
||||
{ |
||||
if(this.Visible){ |
||||
InitGateway(); |
||||
} |
||||
} |
||||
|
||||
public void InitGateway() |
||||
{ |
||||
if(this.EGSave().GetDataByFile<DataBacnetGatewaySetting>() == null){ |
||||
DataBacnetGatewaySetting = new DataBacnetGatewaySetting(){ |
||||
MqttHost = "192.168.1.220", |
||||
HttpServerPrefix = "http://127.0.0.1:5000/", |
||||
ResponseTheme = "/LocalBacnetResponse", |
||||
RequestTheme = "/LocalBacnetRequest" |
||||
}; |
||||
this.EGSave().SetDataToFile(DataBacnetGatewaySetting); |
||||
}else{ |
||||
DataBacnetGatewaySetting = this.EGSave().GetDataByFile<DataBacnetGatewaySetting>(); |
||||
} |
||||
this.EGEnabledProtocolTool<EGBacnet>(); |
||||
this.EGEnabledProtocolTool<EGMqtt>(); |
||||
InitMqttClient(DataBacnetGatewaySetting); |
||||
this.EGOnMessage<EGBacnetRequest>(); |
||||
this.EGOnMessage<EGBacnetResponse>(); |
||||
this.EGOnMessage<EGBacnetWhoIsResponse>(); |
||||
} |
||||
public void InitMqttClient(DataBacnetGatewaySetting settings){ |
||||
this.EGMqtt().OnMqttConnect.Register(e=>{ |
||||
if(e == settings.MqttHost){ |
||||
this.EGMqtt().SubScribeTheme(settings.MqttHost,settings.RequestTheme); |
||||
// byte[] testData = {0x3A,0x55}; |
||||
// this.EGMqtt().PublishTheme("192.168.1.220","test",testData); |
||||
} |
||||
}); |
||||
this.EGRegisterMessageEvent<EGBacnetRequest>((e,sender,protocol)=>{ |
||||
GD.Print("Sender:"+sender); |
||||
if(protocol == ProtocolType.MQTTClient && sender == settings.MqttHost+"|"+settings.RequestTheme){ |
||||
GD.Print("MQTT Received->BACnet:"+e.ToProtocolData()); |
||||
this.EGSendMessage(e,e.DeviceId.ToString(),ProtocolType.Bacnet); |
||||
} |
||||
}); |
||||
this.EGRegisterMessageEvent<EGBacnetResponse>((e,sender,protocol)=>{ |
||||
if(protocol == ProtocolType.Bacnet){ |
||||
GD.Print("BACnet Received->MQTT:"+e.ToProtocolData()); |
||||
this.EGSendMessage(e,settings.MqttHost+"|"+settings.ResponseTheme,ProtocolType.MQTTClient); |
||||
} |
||||
}); |
||||
this.EGRegisterMessageEvent<EGBacnetWhoIsResponse>((e,sender,protocol)=>{; |
||||
if(protocol == ProtocolType.Bacnet){ |
||||
GD.Print("BACnet Who Is Received->MQTT:"+e.ToProtocolData()); |
||||
this.EGSendMessage(e,settings.MqttHost+"|"+settings.ResponseTheme,ProtocolType.MQTTClient); |
||||
} |
||||
}); |
||||
this.EGMqtt().ConnectMQTTServer(settings.MqttHost); |
||||
GD.Print("Init Over"); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,57 @@
@@ -0,0 +1,57 @@
|
||||
using EGFramework; |
||||
using Godot; |
||||
using System; |
||||
namespace EGFramework.Examples.Gateway{ |
||||
public partial class ViewBacnetHttpServer : Control,IGateway,IEGFramework |
||||
{ |
||||
public DataBacnetGatewaySetting DataBacnetGatewaySetting { set; get; } |
||||
// Called when the node enters the scene tree for the first time. |
||||
public override void _Ready() |
||||
{ |
||||
if(this.Visible){ |
||||
InitGateway(); |
||||
} |
||||
} |
||||
public void InitGateway(){ |
||||
if(this.EGSave().GetDataByFile<DataBacnetGatewaySetting>() == null){ |
||||
DataBacnetGatewaySetting = new DataBacnetGatewaySetting(){ |
||||
MqttHost = "192.168.1.220", |
||||
HttpServerPrefix = "http://127.0.0.1:5000/", |
||||
ResponseTheme = "/LocalBacnetResponse", |
||||
RequestTheme = "/LocalBacnetRequest" |
||||
}; |
||||
this.EGSave().SetDataToFile(DataBacnetGatewaySetting); |
||||
}else{ |
||||
DataBacnetGatewaySetting = this.EGSave().GetDataByFile<DataBacnetGatewaySetting>(); |
||||
} |
||||
this.EGEnabledProtocolTool<EGBacnet>(); |
||||
this.EGHttpServerListen(DataBacnetGatewaySetting.HttpServerPrefix+"WhoIs/",requestMsg=>{ |
||||
GD.Print("---WhoIsRequest---"); |
||||
return this.EGBacnet().WhoIs(); |
||||
}); |
||||
this.EGHttpServerListen(DataBacnetGatewaySetting.HttpServerPrefix+"ReadRegisterProperty/",requestMsg=>{ |
||||
GD.Print("---ReadRegisterPropertyRequest---"); |
||||
EGBacnetRequest bacnetRequest = new EGBacnetRequest(); |
||||
bacnetRequest.TrySetData(requestMsg.stringData,null); |
||||
EGBacnetResponse response = this.EGBacnet().ReadRegisterProperty(bacnetRequest); |
||||
return response; |
||||
}); |
||||
this.EGHttpServerListen(DataBacnetGatewaySetting.HttpServerPrefix+"ReadMultiRegister/",requestMsg=>{ |
||||
GD.Print("---ReadMultiRequest---"); |
||||
EGBacnetRequestReadMulti bacnetRequest = new EGBacnetRequestReadMulti(); |
||||
bacnetRequest.TrySetData(requestMsg.stringData,null); |
||||
GD.Print("Get "+bacnetRequest.RegisterInfos.Count+" Values Request"); |
||||
EGBacnetResponseReadMulti response = this.EGBacnet().ReadRegisterMulti(bacnetRequest); |
||||
return response; |
||||
}); |
||||
|
||||
this.EGHttpServerListen(DataBacnetGatewaySetting.HttpServerPrefix+"WriteRegisterProperty/",requestMsg=>{ |
||||
GD.Print("---WriteRegisterPropertyRequest---"); |
||||
EGBacnetRequest bacnetRequest = new EGBacnetRequest(); |
||||
bacnetRequest.TrySetData(requestMsg.stringData,null); |
||||
EGBacnetResponse response = this.EGBacnet().WriteRegisterProperty(bacnetRequest); |
||||
return response; |
||||
}); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,23 @@
@@ -0,0 +1,23 @@
|
||||
using Godot; |
||||
using EGFramework; |
||||
using System; |
||||
using System.Threading.Tasks; |
||||
namespace EGFramework.Examples.Gateway{ |
||||
public partial class ViewGateway : Control,IEGFramework |
||||
{ |
||||
// Called when the node enters the scene tree for the first time. |
||||
public override void _Ready() |
||||
{ |
||||
|
||||
} |
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame. |
||||
public override void _Process(double delta) |
||||
{ |
||||
} |
||||
public override void _ExitTree() |
||||
{ |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,69 @@
@@ -0,0 +1,69 @@
|
||||
using EGFramework; |
||||
using EGFramework.Examples.Gateway; |
||||
using Godot; |
||||
using System; |
||||
namespace EGFramework.Examples.Gateway{ |
||||
public partial class ViewModbusGateway : Control,IEGFramework,IGateway |
||||
{ |
||||
public DataModbusGatewaySetting Setting { set; get; } |
||||
|
||||
// Called when the node enters the scene tree for the first time. |
||||
public override void _Ready() |
||||
{ |
||||
this.EGEnabledProtocolTool<EGSerialPort>(); |
||||
this.EGEnabledProtocolTool<EGTCPClient>(); |
||||
this.EGSerialPort().SetBaudRate(9600); |
||||
ReadTest(); |
||||
ReadTest2(); |
||||
ReadTest3(); |
||||
ReadTest3(); |
||||
ReadTest2(); |
||||
ReadTest(); |
||||
} |
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame. |
||||
public override void _Process(double delta) |
||||
{ |
||||
} |
||||
|
||||
public void InitGateway() |
||||
{ |
||||
if(this.EGSave().GetDataByFile<DataModbusGatewaySetting>() == null){ |
||||
Setting = new DataModbusGatewaySetting(); |
||||
this.EGSave().SetDataToFile(Setting); |
||||
}else{ |
||||
Setting = this.EGSave().GetDataByFile<DataModbusGatewaySetting>(); |
||||
} |
||||
this.EGEnabledProtocolTool<EGTCPClient>(); |
||||
this.EGEnabledProtocolTool<EGSerialPort>(); |
||||
//this.EGOnMessage<GateWayMessage>(); |
||||
} |
||||
|
||||
public async void ReadTest(){ |
||||
ModbusRTU_Response? result = await this.EGModbus().ReadRTUAsync(ModbusRegisterType.HoldingRegister,"COM4",0x01,0x00,0x01); |
||||
if(result != null){ |
||||
GD.Print("Register[0]"+((ModbusRTU_Response)result).HoldingRegister[0]); |
||||
}else{ |
||||
GD.Print("Timeout!"); |
||||
} |
||||
} |
||||
|
||||
public async void ReadTest2(){ |
||||
ModbusRTU_Response? result2 = await this.EGModbus().ReadRTUAsync(ModbusRegisterType.HoldingRegister,"COM4",0x01,0x01,0x01); |
||||
if(result2 != null){ |
||||
GD.Print("Register[1]"+((ModbusRTU_Response)result2).HoldingRegister[0]); |
||||
}else{ |
||||
GD.Print("Timeout!"); |
||||
} |
||||
} |
||||
public async void ReadTest3(){ |
||||
ModbusRTU_Response? result3 = await this.EGModbus().ReadRTUAsync(ModbusRegisterType.HoldingRegister,"COM4",0x01,0x10,0x01); |
||||
if(result3 != null){ |
||||
GD.Print("Register[2]"+((ModbusRTU_Response)result3).HoldingRegister[0]); |
||||
}else{ |
||||
GD.Print("Timeout!"); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,109 @@
@@ -0,0 +1,109 @@
|
||||
using Godot; |
||||
using System; |
||||
using System.Net.Sockets; |
||||
|
||||
namespace EGFramework.Examples.Gateway{ |
||||
public partial class ViewTcpGateway : Control,IEGFramework,IGateway |
||||
{ |
||||
public DataTcpGatewaySetting DataTcpGatewaySetting { set; get; } |
||||
public override void _Ready() |
||||
{ |
||||
if(this.Visible){ |
||||
InitGateway(); |
||||
} |
||||
} |
||||
|
||||
public void InitGateway(){ |
||||
if(this.EGSave().GetDataByFile<DataTcpGatewaySetting>() == null){ |
||||
DataTcpGatewaySetting = new DataTcpGatewaySetting(); |
||||
DataTcpGatewaySetting.DataTcpGatewayDevices.Add(new DataTcpGatewayDevice(){ |
||||
Host = "127.0.0.1", |
||||
Port = 8234, |
||||
MqttHost = "192.168.1.220", |
||||
ResponseTheme = "/LocalTCPResponse", |
||||
RequestTheme = "/LocalTCPRequest" |
||||
}); |
||||
this.EGSave().SetDataToFile(DataTcpGatewaySetting); |
||||
}else{ |
||||
DataTcpGatewaySetting = this.EGSave().GetDataByFile<DataTcpGatewaySetting>(); |
||||
} |
||||
this.EGEnabledProtocolTool<EGTCPClient>(); |
||||
this.EGEnabledProtocolTool<EGMqtt>(); |
||||
InitMqttClient(DataTcpGatewaySetting); |
||||
this.EGOnMessage<GateWayMessage>(); |
||||
} |
||||
|
||||
public void InitMqttClient(DataTcpGatewaySetting settings){ |
||||
foreach(DataTcpGatewayDevice deviceSetting in settings.DataTcpGatewayDevices){ |
||||
InitOneMqttClient(deviceSetting); |
||||
} |
||||
} |
||||
|
||||
public async void InitOneMqttClient(DataTcpGatewayDevice deviceSetting){ |
||||
this.EGMqtt().OnMqttConnect.Register(e=>{ |
||||
if(e == deviceSetting.MqttHost){ |
||||
this.EGMqtt().SubScribeTheme(deviceSetting.MqttHost,deviceSetting.RequestTheme); |
||||
// byte[] testData = {0x3A,0x55}; |
||||
// this.EGMqtt().PublishTheme("192.168.1.220","test",testData); |
||||
} |
||||
}); |
||||
this.EGRegisterMessageEvent<GateWayMessage>((e,sender,protocol)=>{ |
||||
GD.Print("Sender:"+sender); |
||||
if(protocol == ProtocolType.MQTTClient && sender == deviceSetting.MqttHost+"|"+deviceSetting.RequestTheme){ |
||||
GD.Print("MQTT Received->TCP:"+e.DataBytes.ToStringByHex()); |
||||
this.EGSendMessage(new GateWayMessage(e.DataBytes),deviceSetting.Host+":"+deviceSetting.Port,ProtocolType.TCPClient); |
||||
} |
||||
}); |
||||
this.EGRegisterMessageEvent<GateWayMessage>((e,sender,protocol)=>{ |
||||
if(protocol == ProtocolType.TCPClient && sender == deviceSetting.Host+":"+deviceSetting.Port){ |
||||
GD.Print("TCP Received->MQTT:"+e.DataBytes.ToStringByHex()); |
||||
this.EGSendMessage(new GateWayMessage(e.DataBytes),deviceSetting.MqttHost+"|"+deviceSetting.ResponseTheme,ProtocolType.MQTTClient); |
||||
} |
||||
}); |
||||
this.EGMqtt().ConnectMQTTServer(deviceSetting.MqttHost); |
||||
await this.EGTCPClient().ConnectTCP(deviceSetting.Host,deviceSetting.Port); |
||||
GD.Print("Init Over"); |
||||
} |
||||
|
||||
public override void _Process(double delta) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public class GateWayMessage : IRequest, IResponse |
||||
{ |
||||
public byte[] DataBytes; |
||||
public string DataString; |
||||
public GateWayMessage(){ |
||||
} |
||||
public GateWayMessage(byte[] bytes){ |
||||
this.DataBytes = bytes; |
||||
} |
||||
public byte[] ToProtocolByteData() |
||||
{ |
||||
return DataBytes; |
||||
} |
||||
|
||||
public string ToProtocolData() |
||||
{ |
||||
return DataString; |
||||
} |
||||
|
||||
|
||||
public bool TrySetData(string protocolData, byte[] protocolBytes) |
||||
{ |
||||
try |
||||
{ |
||||
this.DataBytes = protocolBytes; |
||||
this.DataString = protocolData; |
||||
return true; |
||||
} |
||||
catch (System.Exception e) |
||||
{ |
||||
GD.PrintErr(e); |
||||
return false; |
||||
throw; |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,154 @@
@@ -0,0 +1,154 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://c8kk7iegicmdr"] |
||||
|
||||
[ext_resource type="Script" path="res://Example/ModbusDebugTool/Script/ViewModbusItem.cs" id="1_ih8g3"] |
||||
[ext_resource type="FontFile" uid="uid://b1atsgy4xkk7d" path="res://Font/SourceHanSansCN-Regular.otf" id="1_upshn"] |
||||
|
||||
[node name="ModbusItem" type="Control"] |
||||
custom_minimum_size = Vector2(200, 200) |
||||
layout_mode = 3 |
||||
anchors_preset = 0 |
||||
script = ExtResource("1_ih8g3") |
||||
|
||||
[node name="BackGround" type="ColorRect" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0, 0, 0, 0.196078) |
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."] |
||||
custom_minimum_size = Vector2(200, 37) |
||||
layout_mode = 1 |
||||
anchors_preset = 5 |
||||
anchor_left = 0.5 |
||||
anchor_right = 0.5 |
||||
offset_left = -100.0 |
||||
offset_right = 100.0 |
||||
offset_bottom = 37.0 |
||||
grow_horizontal = 2 |
||||
color = Color(0, 0, 0, 1) |
||||
|
||||
[node name="Title" type="Label" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 10 |
||||
anchor_right = 1.0 |
||||
offset_bottom = 37.0 |
||||
grow_horizontal = 2 |
||||
theme_override_fonts/font = ExtResource("1_upshn") |
||||
theme_override_font_sizes/font_size = 25 |
||||
text = "保持寄存器65535" |
||||
horizontal_alignment = 1 |
||||
|
||||
[node name="Value" type="Label" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 4 |
||||
anchor_top = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = 93.0 |
||||
offset_top = -50.0 |
||||
offset_right = 149.0 |
||||
offset_bottom = -20.0 |
||||
grow_vertical = 2 |
||||
theme_override_fonts/font = ExtResource("1_upshn") |
||||
theme_override_font_sizes/font_size = 20 |
||||
text = "65535" |
||||
horizontal_alignment = 1 |
||||
|
||||
[node name="ID" type="Label" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 4 |
||||
anchor_top = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = 9.0 |
||||
offset_top = -50.0 |
||||
offset_right = 88.0 |
||||
offset_bottom = -20.0 |
||||
grow_vertical = 2 |
||||
theme_override_fonts/font = ExtResource("1_upshn") |
||||
theme_override_font_sizes/font_size = 20 |
||||
text = "1-1" |
||||
horizontal_alignment = 1 |
||||
|
||||
[node name="WriteEdit" type="LineEdit" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 4 |
||||
anchor_top = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = 8.0 |
||||
offset_right = 120.0 |
||||
offset_bottom = 38.0 |
||||
grow_vertical = 2 |
||||
theme_override_fonts/font = ExtResource("1_upshn") |
||||
theme_override_font_sizes/font_size = 20 |
||||
placeholder_text = "输入写入值" |
||||
|
||||
[node name="Get" type="Button" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 6 |
||||
anchor_left = 1.0 |
||||
anchor_top = 0.5 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -46.0 |
||||
offset_top = -50.0 |
||||
offset_right = -6.0 |
||||
offset_bottom = -19.0 |
||||
grow_horizontal = 0 |
||||
grow_vertical = 2 |
||||
focus_mode = 0 |
||||
text = "获取" |
||||
|
||||
[node name="WriteBtn" type="Button" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 6 |
||||
anchor_left = 1.0 |
||||
anchor_top = 0.5 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -74.0 |
||||
offset_right = -6.0 |
||||
offset_bottom = 38.0 |
||||
grow_horizontal = 0 |
||||
grow_vertical = 2 |
||||
focus_mode = 0 |
||||
theme_override_fonts/font = ExtResource("1_upshn") |
||||
theme_override_font_sizes/font_size = 20 |
||||
text = "写入" |
||||
|
||||
[node name="ModifyBtn" type="Button" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 2 |
||||
anchor_top = 1.0 |
||||
anchor_bottom = 1.0 |
||||
offset_left = 13.0 |
||||
offset_top = -51.0 |
||||
offset_right = 81.0 |
||||
offset_bottom = -13.0 |
||||
grow_vertical = 0 |
||||
focus_mode = 0 |
||||
theme_override_font_sizes/font_size = 20 |
||||
text = "修改" |
||||
|
||||
[node name="DeleteBtn" type="Button" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 3 |
||||
anchor_left = 1.0 |
||||
anchor_top = 1.0 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
offset_left = -81.0 |
||||
offset_top = -51.0 |
||||
offset_right = -13.0 |
||||
offset_bottom = -13.0 |
||||
grow_horizontal = 0 |
||||
grow_vertical = 0 |
||||
focus_mode = 0 |
||||
theme_override_font_sizes/font_size = 20 |
||||
text = "删除" |
||||
|
||||
[connection signal="pressed" from="Get" to="." method="GetValue"] |
||||
[connection signal="pressed" from="WriteBtn" to="." method="WriteValue"] |
||||
[connection signal="pressed" from="ModifyBtn" to="." method="OnModifyItem"] |
||||
[connection signal="pressed" from="DeleteBtn" to="." method="OnDeleteItem"] |
@ -0,0 +1,32 @@
@@ -0,0 +1,32 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public class DataModbus{ |
||||
/// <summary> |
||||
/// Key is the ModbusRTU Type + "-" + DeviceAddress + "-" + RegisterAddress + "-" + Port |
||||
/// </summary> |
||||
/// <typeparam name="string">Key is the ModbusRTU DeviceAddress + "-" + Type + "-" + RegisterAddress + "-" + Port</typeparam> |
||||
/// <typeparam name="DataModbusItem"></typeparam> |
||||
/// <returns></returns> |
||||
public Dictionary<string,DataModbusItem> Items { set; get; } = new Dictionary<string,DataModbusItem>(); |
||||
} |
||||
public class DataModbusItem |
||||
{ |
||||
public ModbusRegisterType Type { set; get; } = ModbusRegisterType.HoldingRegister; |
||||
|
||||
public byte DeviceAddress { set; get; } |
||||
|
||||
public ushort RegisterAddress { set; get; } |
||||
|
||||
public string SerialPort { set; get; } |
||||
|
||||
public string GetKey(){ |
||||
return Type + "-" + DeviceAddress + "-" + RegisterAddress + "-" + SerialPort; |
||||
} |
||||
} |
||||
|
||||
public class DataModbusSettings{ |
||||
public int BaudRate{ set; get; } = 115200; |
||||
} |
||||
} |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
using Godot; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO.Ports; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public partial class ViewEdit : Control,IEGFramework |
||||
{ |
||||
public DataModbusItem DataModbusItem { set; get; } |
||||
public ModbusRegisterType ModbusRegisterType { set; get; } |
||||
|
||||
public Label Title { set; get; } |
||||
public LineEdit EditDeviceAddress { set; get; } |
||||
public LineEdit EditRegisterAddress { set; get; } |
||||
public OptionButton SerialPortSelect { set; get; } |
||||
public ViewMenu ViewMenu { set; get; } |
||||
|
||||
public Dictionary<string,int> SerialPortMapping { set; get; } = new Dictionary<string, int>(); |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
Title = this.GetNode<Label>("Title"); |
||||
SerialPortSelect = this.GetNode<OptionButton>("List/SerialPortSelect"); |
||||
EditDeviceAddress = this.GetNode<LineEdit>("List/Device"); |
||||
EditRegisterAddress = this.GetNode<LineEdit>("List/Register"); |
||||
ViewMenu = this.GetNode<ViewMenu>("/root/Menu"); |
||||
ModbusRegisterType = ModbusRegisterType.HoldingRegister; |
||||
RefreshSerialPort(); |
||||
} |
||||
|
||||
public void RefreshSerialPort(){ |
||||
string[] portNames = SerialPort.GetPortNames(); |
||||
SerialPortMapping.Clear(); |
||||
int index = 0; |
||||
SerialPortSelect.Clear(); |
||||
foreach (string portName in portNames) |
||||
{ |
||||
SerialPortMapping.Add(portName,index); |
||||
SerialPortSelect.AddItem(portName,index); |
||||
index++; |
||||
} |
||||
} |
||||
|
||||
public void Modify(DataModbusItem modbusItem){ |
||||
DataModbusItem = modbusItem; |
||||
ModbusRegisterType = modbusItem.Type; |
||||
Title.Text = ModbusRegisterType.ToString(); |
||||
EditDeviceAddress.Text = modbusItem.DeviceAddress.ToString(); |
||||
EditRegisterAddress.Text = modbusItem.RegisterAddress.ToString(); |
||||
if(SerialPortMapping.ContainsKey(modbusItem.SerialPort)){ |
||||
SerialPortSelect.Selected = SerialPortMapping[modbusItem.SerialPort]; |
||||
} |
||||
} |
||||
|
||||
public void New(ModbusRegisterType type){ |
||||
DataModbusItem = null; |
||||
ModbusRegisterType = type; |
||||
Title.Text = ModbusRegisterType.ToString(); |
||||
} |
||||
|
||||
public void OnClose(){ |
||||
this.Visible = false; |
||||
} |
||||
|
||||
public void Save(){ |
||||
try |
||||
{ |
||||
DataModbusItem modbusItem = new DataModbusItem(){ |
||||
DeviceAddress = (byte)int.Parse(EditDeviceAddress.Text), |
||||
RegisterAddress = (ushort)int.Parse(EditRegisterAddress.Text), |
||||
SerialPort = SerialPortSelect.GetItemText(SerialPortSelect.GetSelectedId()), |
||||
Type = ModbusRegisterType |
||||
}; |
||||
if(DataModbusItem != null){ |
||||
this.EGGetObject<DataModbus>().Items.Remove(DataModbusItem.GetKey()); |
||||
} |
||||
this.EGGetObject<DataModbus>().Items.Add(modbusItem.GetKey(),modbusItem); |
||||
this.EGSave().SetDataToFile(this.EGGetObject<DataModbus>()); |
||||
this.Visible = false; |
||||
this.ViewMenu.RefreshSaveData(); |
||||
|
||||
} |
||||
catch (System.Exception ex) |
||||
{ |
||||
GD.Print("Save Exception" + ex); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
public static class ViewEditExtension{ |
||||
public static void OnModifyEdit(this Node self,DataModbusItem dataModbusItem){ |
||||
self.GetTree().CurrentScene.GetNode<ViewEdit>("Edit").Visible = true; |
||||
self.GetTree().CurrentScene.GetNode<ViewEdit>("Edit").Modify(dataModbusItem); |
||||
} |
||||
public static void OnNewEdit(this Node self,ModbusRegisterType type){ |
||||
self.GetTree().CurrentScene.GetNode<ViewEdit>("Edit").Visible = true; |
||||
self.GetTree().CurrentScene.GetNode<ViewEdit>("Edit").New(type); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,78 @@
@@ -0,0 +1,78 @@
|
||||
using Godot; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public partial class ViewMenu : Node,IEGFramework |
||||
{ |
||||
[Export] public PackedScene StorageItem = GD.Load<PackedScene>("res://Example/ModbusDebugTool/Component/modbus_item.tscn"); |
||||
public PopupMenu MenuAdd; |
||||
public PopupMenu MenuSettings; |
||||
public GridContainer ModbusItemContainer; |
||||
public ViewEdit Edit; |
||||
|
||||
public EasyEvent<ModbusRTU_Response> OnModbusRTUGet { set; get; } = new EasyEvent<ModbusRTU_Response>(); |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
MenuAdd = this.GetNode<PopupMenu>("MenuBar/添加"); |
||||
MenuSettings = this.GetNode<PopupMenu>("MenuBar/设置"); |
||||
ModbusItemContainer = this.GetNode<GridContainer>("Scroll/ModbusList"); |
||||
Edit = this.GetNode<ViewEdit>("Edit"); |
||||
Edit.Visible = false; |
||||
this.EGEnabledProtocolTools(); |
||||
DataModbus dataModbus = this.EGSave().GetDataByFile<DataModbus>(); |
||||
if (dataModbus == null) |
||||
{ |
||||
dataModbus = new DataModbus(); |
||||
} |
||||
this.EGRegisterObject(dataModbus); |
||||
RefreshSaveData(); |
||||
this.EGRegisterMessageEvent<ModbusRTU_Response>((e,sender,ProtocolType)=>{ |
||||
if(ProtocolType == ProtocolType.SerialPort){ |
||||
this.AppendMessage("【接收-"+sender+"】 "+e.SourceData.ToStringByHex()); |
||||
OnModbusRTUGet.Invoke(e); |
||||
} |
||||
}); |
||||
this.EGOnMessage<ModbusRTU_Response>(); |
||||
} |
||||
|
||||
public void OpenEdit(int AddMenuId){ |
||||
GD.Print(MenuAdd.GetItemText(AddMenuId)); |
||||
switch(MenuAdd.GetItemText(AddMenuId)){ |
||||
case "保持寄存器": |
||||
this.OnNewEdit(ModbusRegisterType.HoldingRegister); |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
public void OpenSettings(int OtherId){ |
||||
switch(MenuSettings.GetItemText(OtherId)){ |
||||
case "查看报文": |
||||
this.ViewMessage().Visible = true; |
||||
break; |
||||
case "设置": |
||||
this.ViewSettings().Visible = true; |
||||
break; |
||||
default: |
||||
break; |
||||
} |
||||
} |
||||
|
||||
public void ReadAll(int ReadMenuId){ |
||||
GD.Print(MenuAdd.GetItemText(ReadMenuId)); |
||||
} |
||||
|
||||
public void RefreshSaveData(){ |
||||
ModbusItemContainer.ClearChildren(); |
||||
if(this.EGGetObject<DataModbus>() != null){ |
||||
foreach(DataModbusItem item in this.EGGetObject<DataModbus>().Items.Values){ |
||||
ViewModbusItem viewItem = StorageItem.Instantiate<ViewModbusItem>(); |
||||
ModbusItemContainer.AddChild(viewItem); |
||||
viewItem.LoadData(item); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
using Godot; |
||||
using System; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public partial class ViewMessage : Control |
||||
{ |
||||
public TextEdit MessageContainer { set; get; } |
||||
public override void _Ready() |
||||
{ |
||||
this.Visible = false; |
||||
MessageContainer = this.GetNode<TextEdit>("MessageContainer"); |
||||
} |
||||
public void OnClose(){ |
||||
this.Visible = false; |
||||
} |
||||
public void Clear(){ |
||||
MessageContainer.Text = ""; |
||||
} |
||||
public void AppendMessage(string msg){ |
||||
MessageContainer.Text += msg + "\n"; |
||||
} |
||||
} |
||||
|
||||
public static class ViewMessageExtension{ |
||||
public static ViewMessage ViewMessage(this Node self){ |
||||
return self.GetTree().CurrentScene.GetNode<ViewMessage>("Message"); |
||||
} |
||||
public static void AppendMessage(this Node self,string msg){ |
||||
self.GetTree().CurrentScene.GetNode<ViewMessage>("Message").AppendMessage(msg); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,99 @@
@@ -0,0 +1,99 @@
|
||||
using Godot; |
||||
using System; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public partial class ViewModbusItem : Node,IEGFramework |
||||
{ |
||||
public DataModbusItem DataModbusItem { set; get; } |
||||
|
||||
public Label ID { set; get; } |
||||
|
||||
public Label Title { set; get; } |
||||
|
||||
public Label Value { set; get; } |
||||
|
||||
public LineEdit InputData { set; get; } |
||||
|
||||
private bool IsLoadUI { set; get; } |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public void LoadUI(){ |
||||
if(!IsLoadUI){ |
||||
Title = this.GetNode<Label>("Title"); |
||||
Value = this.GetNode<Label>("Value"); |
||||
ID = this.GetNode<Label>("ID"); |
||||
InputData = this.GetNode<LineEdit>("WriteEdit"); |
||||
InputData.Text = "0"; |
||||
IsLoadUI = true; |
||||
} |
||||
} |
||||
|
||||
public void LoadData(DataModbusItem data){ |
||||
LoadUI(); |
||||
this.DataModbusItem = data; |
||||
Title.Text = data.Type.ToString(); |
||||
ID.Text = data.DeviceAddress+"-"+data.RegisterAddress; |
||||
Value.Text = ""; |
||||
} |
||||
public void OnModifyItem(){ |
||||
this.OnModifyEdit(DataModbusItem); |
||||
} |
||||
|
||||
public void WriteValue(){ |
||||
try |
||||
{ |
||||
IRequest WriteRequest; |
||||
switch(DataModbusItem.Type){ |
||||
case ModbusRegisterType.HoldingRegister: |
||||
WriteRequest = new ModbusRTU_WriteSingleHoldingRegister |
||||
(DataModbusItem.DeviceAddress,DataModbusItem.RegisterAddress,ushort.Parse(InputData.Text)); |
||||
this.AppendMessage("【发送-"+DataModbusItem.SerialPort+"】 "+WriteRequest.ToProtocolByteData().ToStringByHex()); |
||||
this.EGSendMessage(WriteRequest,DataModbusItem.SerialPort,ProtocolType.SerialPort); |
||||
break; |
||||
} |
||||
} |
||||
catch (System.Exception ex) |
||||
{ |
||||
GD.PrintErr(ex); |
||||
} |
||||
} |
||||
|
||||
public void OnDeleteItem(){ |
||||
if(this.EGGetObject<DataModbus>().Items.ContainsKey(DataModbusItem.GetKey())){ |
||||
this.EGGetObject<DataModbus>().Items.Remove(DataModbusItem.GetKey()); |
||||
} |
||||
this.EGSave().SetDataToFile(this.EGGetObject<DataModbus>()); |
||||
this.GetNode<ViewMenu>("/root/Menu").RefreshSaveData(); |
||||
} |
||||
|
||||
public void GetValue(){ |
||||
IRequest ReadRequest; |
||||
switch(DataModbusItem.Type){ |
||||
case ModbusRegisterType.HoldingRegister: |
||||
ReadRequest = new ModbusRTU_ReadHoldingRegisters |
||||
(DataModbusItem.DeviceAddress,DataModbusItem.RegisterAddress,1); |
||||
this.AppendMessage("【发送-"+DataModbusItem.SerialPort+"】 "+ReadRequest.ToProtocolByteData().ToStringByHex()); |
||||
this.EGSendMessage(ReadRequest,DataModbusItem.SerialPort,ProtocolType.SerialPort); |
||||
this.EGSerialPort().SetExpectReceivedDataLength(6); |
||||
break; |
||||
} |
||||
this.GetNode<ViewMenu>("/root/Menu").OnModbusRTUGet.Register(OnValueGet); |
||||
} |
||||
|
||||
public void OnValueGet(ModbusRTU_Response e){ |
||||
if((int)e.FunctionType == (int)DataModbusItem.Type && DataModbusItem.DeviceAddress == e.DeviceAddress){ |
||||
switch(DataModbusItem.Type){ |
||||
case ModbusRegisterType.HoldingRegister: |
||||
this.Value.Text = e.HoldingRegister[0].ToString(); |
||||
break; |
||||
} |
||||
} |
||||
this.GetNode<ViewMenu>("/root/Menu").OnModbusRTUGet.UnRegister(OnValueGet); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,55 @@
@@ -0,0 +1,55 @@
|
||||
using Godot; |
||||
using System; |
||||
|
||||
namespace EGFramework.Examples.ModbusDebugTool{ |
||||
public partial class ViewSettings : Control,IEGFramework |
||||
{ |
||||
public LineEdit EditBaudRate { set; get; } |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
EditBaudRate = this.GetNode<LineEdit>("List/Device"); |
||||
this.Visible = false; |
||||
LoadSettings(); |
||||
} |
||||
|
||||
public void LoadSettings(){ |
||||
DataModbusSettings settings = this.EGSave().GetDataByFile<DataModbusSettings>(); |
||||
this.EGRegisterObject(settings); |
||||
UpdateSettings(settings); |
||||
EditBaudRate.Text = settings.BaudRate.ToString(); |
||||
} |
||||
|
||||
public void OnClose(){ |
||||
this.Visible = false; |
||||
} |
||||
|
||||
public void UpdateSettings(DataModbusSettings settings){ |
||||
this.EGSerialPort().SetBaudRate(settings.BaudRate); |
||||
} |
||||
|
||||
public void Save(){ |
||||
try |
||||
{ |
||||
DataModbusSettings settings = new DataModbusSettings(){ |
||||
BaudRate = int.Parse(EditBaudRate.Text) |
||||
}; |
||||
UpdateSettings(settings); |
||||
this.EGRegisterObject(settings); |
||||
this.EGSave().SetDataToFile(this.EGGetObject<DataModbusSettings>()); |
||||
this.Visible = false; |
||||
} |
||||
catch (System.Exception ex) |
||||
{ |
||||
GD.Print("Save Exception" + ex); |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class ViewSettingsExtension{ |
||||
public static ViewSettings ViewSettings(this Node self){ |
||||
return self.GetTree().CurrentScene.GetNode<ViewSettings>("Settings"); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,417 @@
@@ -0,0 +1,417 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://qo2w16ececmu"] |
||||
|
||||
[ext_resource type="Script" path="res://Example/ModbusDebugTool/Script/ViewMenu.cs" id="1_7ubyu"] |
||||
[ext_resource type="FontFile" uid="uid://b1atsgy4xkk7d" path="res://Font/SourceHanSansCN-Regular.otf" id="1_tw1qu"] |
||||
[ext_resource type="PackedScene" uid="uid://c8kk7iegicmdr" path="res://Example/ModbusDebugTool/Component/modbus_item.tscn" id="3_c8jeq"] |
||||
[ext_resource type="Script" path="res://Example/ModbusDebugTool/Script/ViewEdit.cs" id="4_smsvf"] |
||||
[ext_resource type="Script" path="res://Example/ModbusDebugTool/Script/ViewMessage.cs" id="5_8s6lk"] |
||||
[ext_resource type="Script" path="res://Example/ModbusDebugTool/Script/ViewSettings.cs" id="6_38tri"] |
||||
|
||||
[node name="Menu" type="Control"] |
||||
layout_mode = 3 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("1_7ubyu") |
||||
|
||||
[node name="ColorRect" type="ColorRect" parent="."] |
||||
visible = false |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0, 0, 0, 1) |
||||
|
||||
[node name="Title" type="Label" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 5 |
||||
anchor_left = 0.5 |
||||
anchor_right = 0.5 |
||||
offset_left = -253.0 |
||||
offset_top = 52.0 |
||||
offset_right = 251.0 |
||||
offset_bottom = 128.0 |
||||
grow_horizontal = 2 |
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||
theme_override_constants/outline_size = 10 |
||||
theme_override_fonts/font = ExtResource("1_tw1qu") |
||||
theme_override_font_sizes/font_size = 52 |
||||
text = "Modbus调试工具V1.0" |
||||
|
||||
[node name="Scroll" type="ScrollContainer" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = -1 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
offset_left = 10.0 |
||||
offset_top = 140.0 |
||||
offset_right = -9.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 0 |
||||
|
||||
[node name="ModbusList" type="GridContainer" parent="Scroll"] |
||||
layout_mode = 2 |
||||
theme_override_constants/h_separation = 30 |
||||
theme_override_constants/v_separation = 30 |
||||
columns = 5 |
||||
|
||||
[node name="ModbusItem" parent="Scroll/ModbusList" instance=ExtResource("3_c8jeq")] |
||||
layout_mode = 2 |
||||
|
||||
[node name="MenuBar" type="MenuBar" parent="."] |
||||
layout_mode = 1 |
||||
anchors_preset = 10 |
||||
anchor_right = 1.0 |
||||
offset_bottom = 45.0 |
||||
grow_horizontal = 2 |
||||
theme_override_fonts/font = ExtResource("1_tw1qu") |
||||
theme_override_font_sizes/font_size = 25 |
||||
|
||||
[node name="添加" type="PopupMenu" parent="MenuBar"] |
||||
size = Vector2i(108, 116) |
||||
item_count = 4 |
||||
item_0/text = "线圈" |
||||
item_0/id = 0 |
||||
item_1/text = "离散输入" |
||||
item_1/id = 1 |
||||
item_2/text = "保持寄存器" |
||||
item_2/id = 2 |
||||
item_3/text = "输入寄存器" |
||||
item_3/id = 3 |
||||
|
||||
[node name="读取" type="PopupMenu" parent="MenuBar"] |
||||
size = Vector2i(108, 116) |
||||
item_count = 4 |
||||
item_0/text = "线圈" |
||||
item_0/id = 0 |
||||
item_1/text = "离散输入" |
||||
item_1/id = 1 |
||||
item_2/text = "保持寄存器" |
||||
item_2/id = 2 |
||||
item_3/text = "输入寄存器" |
||||
item_3/id = 3 |
||||
|
||||
[node name="帮助" type="PopupMenu" parent="MenuBar"] |
||||
item_count = 3 |
||||
item_0/text = "关于jkpete" |
||||
item_0/id = 0 |
||||
item_1/text = "关于EGFramework" |
||||
item_1/id = 1 |
||||
item_2/text = "使用手册" |
||||
item_2/id = 2 |
||||
|
||||
[node name="设置" type="PopupMenu" parent="MenuBar"] |
||||
item_count = 2 |
||||
item_0/text = "查看报文" |
||||
item_0/id = 0 |
||||
item_1/text = "设置" |
||||
item_1/id = 1 |
||||
|
||||
[node name="Message" type="Control" parent="."] |
||||
layout_mode = 1 |
||||
anchor_top = 0.558642 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("5_8s6lk") |
||||
metadata/_edit_use_anchors_ = true |
||||
|
||||
[node name="MessageContainer" type="TextEdit" parent="Message"] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
editable = false |
||||
|
||||
[node name="Close" type="Button" parent="Message"] |
||||
layout_mode = 1 |
||||
anchors_preset = 1 |
||||
anchor_left = 1.0 |
||||
anchor_right = 1.0 |
||||
offset_left = -40.0 |
||||
offset_bottom = 31.0 |
||||
grow_horizontal = 0 |
||||
text = "关闭" |
||||
|
||||
[node name="Clear" type="Button" parent="Message"] |
||||
layout_mode = 1 |
||||
anchors_preset = 1 |
||||
anchor_left = 1.0 |
||||
anchor_right = 1.0 |
||||
offset_left = -82.0 |
||||
offset_right = -42.0 |
||||
offset_bottom = 31.0 |
||||
grow_horizontal = 0 |
||||
text = "清空" |
||||
|
||||
[node name="Edit" type="Control" parent="."] |
||||
visible = false |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("4_smsvf") |
||||
|
||||
[node name="Back" type="ColorRect" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0, 0, 0, 0.392157) |
||||
|
||||
[node name="Back2" type="ColorRect" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -300.0 |
||||
offset_top = -300.0 |
||||
offset_right = 300.0 |
||||
offset_bottom = 300.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0.0588235, 0.231373, 0.270588, 1) |
||||
|
||||
[node name="Close" type="Button" parent="Edit/Back2"] |
||||
layout_mode = 1 |
||||
anchors_preset = 1 |
||||
anchor_left = 1.0 |
||||
anchor_right = 1.0 |
||||
offset_left = -50.0 |
||||
offset_bottom = 50.0 |
||||
grow_horizontal = 0 |
||||
text = "X" |
||||
|
||||
[node name="Title" type="Label" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 5 |
||||
anchor_left = 0.5 |
||||
anchor_right = 0.5 |
||||
offset_left = -168.0 |
||||
offset_top = 54.0 |
||||
offset_right = 168.0 |
||||
offset_bottom = 124.0 |
||||
grow_horizontal = 2 |
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||
theme_override_constants/outline_size = 10 |
||||
theme_override_fonts/font = ExtResource("1_tw1qu") |
||||
theme_override_font_sizes/font_size = 48 |
||||
text = "保持寄存器" |
||||
horizontal_alignment = 1 |
||||
|
||||
[node name="List" type="VBoxContainer" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -264.0 |
||||
offset_top = -174.0 |
||||
offset_right = 265.0 |
||||
offset_bottom = 117.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
theme_override_constants/separation = 24 |
||||
alignment = 1 |
||||
|
||||
[node name="Device" type="LineEdit" parent="Edit/List"] |
||||
custom_minimum_size = Vector2(529, 64) |
||||
layout_mode = 2 |
||||
theme_override_font_sizes/font_size = 24 |
||||
placeholder_text = "请输入设备地址" |
||||
virtual_keyboard_type = 2 |
||||
|
||||
[node name="Register" type="LineEdit" parent="Edit/List"] |
||||
custom_minimum_size = Vector2(529, 64) |
||||
layout_mode = 2 |
||||
theme_override_font_sizes/font_size = 24 |
||||
placeholder_text = "请输入寄存器地址" |
||||
virtual_keyboard_type = 2 |
||||
|
||||
[node name="SerialPortSelect" type="OptionButton" parent="Edit/List"] |
||||
custom_minimum_size = Vector2(0, 64) |
||||
layout_mode = 2 |
||||
theme_override_font_sizes/font_size = 24 |
||||
item_count = 1 |
||||
popup/item_0/text = "COM1" |
||||
popup/item_0/id = 0 |
||||
|
||||
[node name="Save" type="Button" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 7 |
||||
anchor_left = 0.5 |
||||
anchor_top = 1.0 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 1.0 |
||||
offset_left = -80.0 |
||||
offset_top = -109.0 |
||||
offset_right = 80.0 |
||||
offset_bottom = -45.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 0 |
||||
theme_override_font_sizes/font_size = 36 |
||||
text = "保存" |
||||
|
||||
[node name="RefreshPort" type="Button" parent="Edit"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = 211.0 |
||||
offset_top = 109.0 |
||||
offset_right = 264.0 |
||||
offset_bottom = 141.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
text = "刷新" |
||||
|
||||
[node name="Settings" type="Control" parent="."] |
||||
visible = false |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("6_38tri") |
||||
|
||||
[node name="Back" type="ColorRect" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0, 0, 0, 0.392157) |
||||
|
||||
[node name="Back2" type="ColorRect" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -300.0 |
||||
offset_top = -300.0 |
||||
offset_right = 300.0 |
||||
offset_bottom = 300.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
color = Color(0.0588235, 0.231373, 0.270588, 1) |
||||
|
||||
[node name="Close" type="Button" parent="Settings/Back2"] |
||||
layout_mode = 1 |
||||
anchors_preset = 1 |
||||
anchor_left = 1.0 |
||||
anchor_right = 1.0 |
||||
offset_left = -50.0 |
||||
offset_bottom = 50.0 |
||||
grow_horizontal = 0 |
||||
text = "X" |
||||
|
||||
[node name="Title" type="Label" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 5 |
||||
anchor_left = 0.5 |
||||
anchor_right = 0.5 |
||||
offset_left = -168.0 |
||||
offset_top = 54.0 |
||||
offset_right = 168.0 |
||||
offset_bottom = 124.0 |
||||
grow_horizontal = 2 |
||||
theme_override_colors/font_outline_color = Color(0, 0, 0, 1) |
||||
theme_override_constants/outline_size = 10 |
||||
theme_override_fonts/font = ExtResource("1_tw1qu") |
||||
theme_override_font_sizes/font_size = 48 |
||||
text = "设置" |
||||
horizontal_alignment = 1 |
||||
|
||||
[node name="List" type="VBoxContainer" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -84.0 |
||||
offset_top = -174.0 |
||||
offset_right = 266.0 |
||||
offset_bottom = 117.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
theme_override_constants/separation = 24 |
||||
alignment = 1 |
||||
|
||||
[node name="Device" type="LineEdit" parent="Settings/List"] |
||||
custom_minimum_size = Vector2(250, 64) |
||||
layout_mode = 2 |
||||
theme_override_font_sizes/font_size = 24 |
||||
text = "115200" |
||||
placeholder_text = "请输入波特率" |
||||
virtual_keyboard_type = 2 |
||||
|
||||
[node name="OptionText" type="VBoxContainer" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 8 |
||||
anchor_left = 0.5 |
||||
anchor_top = 0.5 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 0.5 |
||||
offset_left = -214.0 |
||||
offset_top = -174.0 |
||||
offset_right = -114.0 |
||||
offset_bottom = 117.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
theme_override_constants/separation = 24 |
||||
alignment = 1 |
||||
|
||||
[node name="Label" type="Label" parent="Settings/OptionText"] |
||||
custom_minimum_size = Vector2(100, 64) |
||||
layout_mode = 2 |
||||
theme_override_font_sizes/font_size = 24 |
||||
text = "波特率" |
||||
horizontal_alignment = 2 |
||||
vertical_alignment = 1 |
||||
|
||||
[node name="Save" type="Button" parent="Settings"] |
||||
layout_mode = 1 |
||||
anchors_preset = 7 |
||||
anchor_left = 0.5 |
||||
anchor_top = 1.0 |
||||
anchor_right = 0.5 |
||||
anchor_bottom = 1.0 |
||||
offset_left = -80.0 |
||||
offset_top = -109.0 |
||||
offset_right = 80.0 |
||||
offset_bottom = -45.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 0 |
||||
theme_override_font_sizes/font_size = 36 |
||||
text = "保存" |
||||
|
||||
[connection signal="index_pressed" from="MenuBar/添加" to="." method="OpenEdit"] |
||||
[connection signal="index_pressed" from="MenuBar/设置" to="." method="OpenSettings"] |
||||
[connection signal="pressed" from="Message/Close" to="Message" method="OnClose"] |
||||
[connection signal="pressed" from="Message/Clear" to="Message" method="Clear"] |
||||
[connection signal="pressed" from="Edit/Back2/Close" to="Edit" method="OnClose"] |
||||
[connection signal="pressed" from="Edit/Save" to="Edit" method="Save"] |
||||
[connection signal="pressed" from="Edit/RefreshPort" to="Edit" method="RefreshSerialPort"] |
||||
[connection signal="pressed" from="Settings/Back2/Close" to="Settings" method="OnClose"] |
||||
[connection signal="pressed" from="Settings/Save" to="Settings" method="Save"] |
@ -0,0 +1,3 @@
@@ -0,0 +1,3 @@
|
||||
[gd_resource type="Theme" format=3 uid="uid://cbf2s7b2p1p2j"] |
||||
|
||||
[resource] |
@ -0,0 +1,27 @@
@@ -0,0 +1,27 @@
|
||||
[gd_scene load_steps=2 format=3 uid="uid://dfa86yq8m28rk"] |
||||
|
||||
[ext_resource type="Script" path="res://Example/UsingTest/Script/EGTest.cs" id="1_s8hm3"] |
||||
|
||||
[node name="TestEgFramework" type="Control"] |
||||
layout_mode = 3 |
||||
anchors_preset = 15 |
||||
anchor_right = 1.0 |
||||
anchor_bottom = 1.0 |
||||
grow_horizontal = 2 |
||||
grow_vertical = 2 |
||||
script = ExtResource("1_s8hm3") |
||||
|
||||
[node name="Timer" type="Timer" parent="."] |
||||
autostart = true |
||||
|
||||
[node name="Label" type="Label" parent="."] |
||||
layout_mode = 0 |
||||
offset_right = 361.0 |
||||
offset_bottom = 164.0 |
||||
|
||||
[node name="Button1" type="Button" parent="."] |
||||
layout_mode = 0 |
||||
offset_right = 50.0 |
||||
offset_bottom = 50.0 |
||||
|
||||
[connection signal="pressed" from="Button1" to="." method="OnButton1Click"] |
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
using Godot; |
||||
using System; |
||||
using EGFramework; |
||||
using WebDav; |
||||
using System.Threading.Tasks; |
||||
using System.Net; |
||||
|
||||
public partial class EGMDnsTest : Node, IEGFramework |
||||
{ |
||||
private string serverUrl = "http://192.168.1.170:5212/dav"; |
||||
private string username = "ZK@zk.com"; |
||||
private string password = "uQTl7lzLSMZQ1QBd7sZZMlG2Gya65XKM"; |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
//TestDav(); |
||||
} |
||||
|
||||
public async void TestDav(){ |
||||
this.EGWebDav().InitClient(serverUrl,username,password); |
||||
await InitClient(); |
||||
} |
||||
public async Task<bool> InitClient() |
||||
{ |
||||
string result = EncodeCredentials(username,password); |
||||
GD.Print(result); |
||||
//ScanWebDavAndDownload(); |
||||
//await this.EGWebDav().DownloadFile("/dav/Picture/风景1.jpg",ProjectSettings.GlobalizePath("user://"),"风景1.jpg"); |
||||
//Print("download success!"); |
||||
//await this.EGWebDav().UploadFile(ProjectSettings.GlobalizePath("user://4.mp4"),"/dav/Picture","4.mp4"); |
||||
await this.EGWebDav().UploadFile(ProjectSettings.GlobalizePath("user://PPT_Test.jpg"),"/dav/Picture","PPT_Test.jpg"); |
||||
GD.Print("upload success!"); |
||||
//var result = await this.EGWebDav().GetList("/Video"); |
||||
//Print(JsonConvert.SerializeObject(result)); |
||||
return true; |
||||
} |
||||
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; |
||||
} |
||||
|
||||
} |
@ -0,0 +1,313 @@
@@ -0,0 +1,313 @@
|
||||
using Godot; |
||||
using static Godot.GD; |
||||
using System.Collections.Generic; |
||||
using EGFramework; |
||||
using Newtonsoft.Json; |
||||
using System; |
||||
using System.Net; |
||||
|
||||
public partial class EGTest : Node,IEGFramework |
||||
{ |
||||
public Label label { set; get; } |
||||
|
||||
public override void _Ready() |
||||
{ |
||||
this.EGEnabledProtocolTools(); |
||||
|
||||
this.EGMqtt().ConnectMQTTServer("192.168.1.220"); |
||||
|
||||
//this.EGUDP().UDPDevices[5555].Connect(IPAddress.Parse("224.0.0.251"),5353); |
||||
//byte[] sendData = { 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x5F, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x07, 0x5F, 0x64, 0x6E, 0x73, 0x2D, 0x73, 0x64, 0x04, 0x5F, 0x75, 0x64, 0x70, 0x05, 0x6C, 0x6F, 0x63, 0x61, 0x6C, 0x00, 0x00, 0x0C, 0x00, 0x01 }; |
||||
//this.EGUDP().UDPDevices[5555].Send(sendData); |
||||
// this.EGRegisterMessageEvent<PrintResponse>((e,sender,protocol)=>{ |
||||
// Print(sender); |
||||
// }); |
||||
// this.EGOnMessage<PrintResponse>(); |
||||
// this.EGReadFromFile("SaveData/MySeg2.seg2"); |
||||
//TestTCPClient(); |
||||
//TestSerialPort(); |
||||
//TestTCPServer(); |
||||
//this.EGUDP(); |
||||
//this.EGUDPListen(11000); |
||||
//this.EGSendMessage(new MessageStruct(1,"xxx"),"192.168.1.192:9002",ProtocolType.UDP); |
||||
//this.EGHttpClient(); |
||||
//this.EGHttpServer().Listen("http://+:6555/index/"); |
||||
} |
||||
public override void _Process(double delta) |
||||
{ |
||||
//Print(this.EGMqtt().MqttDevices["192.168.1.220"].IsConnected); |
||||
} |
||||
public override void _ExitTree() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public void OnButton1Click(){ |
||||
this.EGMqtt().SubScribeTheme("192.168.1.220","test"); |
||||
byte[] testData = {0x3A,0x55}; |
||||
this.EGMqtt().PublishTheme("192.168.1.220","test",testData); |
||||
} |
||||
|
||||
public void RefreshMsg(bool coil){ |
||||
label.Text += coil+" "; |
||||
} |
||||
public void OnTimer(){ |
||||
//this.EGSendMessage(new MessageStruct(1,"山东博裕1"),"COM4",ProtocolType.SerialPort); |
||||
//this.EGSendMessage(new MessageStruct(1,"山东博裕1"),"192.168.1.244:6060",ProtocolType.TCPClient); |
||||
//this.EGSendMessage(new ModbusTCP_WriteMultiCoil(1,0,sendData),"192.168.1.200:3000",ProtocolType.TCPClient); |
||||
//TestSingleCoil(); |
||||
//TestMultiCoil(); |
||||
//TestSingleHoldingRegister(); |
||||
//TestMultiHoldingRegister(); |
||||
} |
||||
public void TestModbus(){ |
||||
label = this.GetNode<Label>("Label"); |
||||
label.Text = "[Modbus]"; |
||||
this.EGRegisterMessageEvent<MessageResponse>((e,sender,type)=>{ |
||||
Print("[Got Response]"+"[sender = "+sender+"]"+"["+type+"]"+ e.MessageId+"||"+e.Author); |
||||
}); |
||||
this.EGOnMessage<MessageResponse>(); |
||||
this.EGRegisterMessageEvent<ModbusTCP_Response>((e,sender,type)=>{ |
||||
if(type == ProtocolType.TCPClient && e.FunctionType == ModbusFunctionType.ReadCoil){ |
||||
int registerId = 0; |
||||
foreach(bool coil in e.Coil){ |
||||
Print(registerId + "Status:" + coil); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.TCPClient && e.FunctionType == ModbusFunctionType.ReadDiscreteInput){ |
||||
int registerId = 0; |
||||
foreach(bool discreteInput in e.DiscreteInput){ |
||||
Print(registerId + "Status:" + discreteInput); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.TCPClient && e.FunctionType == ModbusFunctionType.ReadHoldingRegisters){ |
||||
int registerId = 0; |
||||
foreach(ushort holdingRegister in e.HoldingRegister){ |
||||
Print(registerId + "Status:" + holdingRegister); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.TCPClient && e.FunctionType == ModbusFunctionType.ReadInputRegisters){ |
||||
int registerId = 0; |
||||
foreach(ushort inputRegister in e.InputRegister){ |
||||
Print(registerId + "Status:" + inputRegister); |
||||
label.Text+=registerId + "Status:" + inputRegister; |
||||
registerId++; |
||||
} |
||||
} |
||||
//this.EGOffMessage<ModbusTCP_Response>(); |
||||
}); |
||||
|
||||
this.EGRegisterMessageEvent<ModbusRTU_Response>((e,sender,type)=>{ |
||||
if(type == ProtocolType.SerialPort && e.FunctionType == ModbusFunctionType.ReadCoil){ |
||||
int registerId = 0; |
||||
foreach(bool coil in e.Coil){ |
||||
Print(registerId + "Status:" + coil); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.SerialPort && e.FunctionType == ModbusFunctionType.ReadDiscreteInput){ |
||||
int registerId = 0; |
||||
foreach(bool discreteInput in e.DiscreteInput){ |
||||
Print(registerId + "Status:" + discreteInput); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.SerialPort && e.FunctionType == ModbusFunctionType.ReadHoldingRegisters){ |
||||
int registerId = 0; |
||||
foreach(ushort holdingRegister in e.HoldingRegister){ |
||||
Print(registerId + "Status:" + holdingRegister); |
||||
registerId++; |
||||
} |
||||
} |
||||
if(type == ProtocolType.SerialPort && e.FunctionType == ModbusFunctionType.ReadInputRegisters){ |
||||
int registerId = 0; |
||||
foreach(ushort inputRegister in e.InputRegister){ |
||||
Print(registerId + "Status:" + inputRegister); |
||||
label.Text+=registerId + "Status:" + inputRegister; |
||||
registerId++; |
||||
} |
||||
} |
||||
//this.EGOffMessage<ModbusRTU_Response>(); |
||||
}); |
||||
|
||||
} |
||||
|
||||
public void TestTCPServer(){ |
||||
this.EGTCPServer().OnClientConnect.Register(e=>{ |
||||
Print(e +" is connected"); |
||||
this.EGSendMessage(new MessageStruct(1,"Hello"),e,ProtocolType.TCPServer); |
||||
}); |
||||
this.EGTCPServer().OnClientDisconnect.Register(e=>{ |
||||
Print(e +" is disconnect"); |
||||
}); |
||||
this.EGTCPServerListen(9999); |
||||
} |
||||
|
||||
public void TestSqlite(){ |
||||
this.EGSqlite().SaveData(new TestBoxMessage()); |
||||
List<TestBoxMessage> result = this.EGSqlite().GetDataSet<TestBoxMessage>(); |
||||
if(result == null){ |
||||
PrintErr(this.EGSqlite().ExceptionMsg); |
||||
} |
||||
Print("Result = " + result[0].TestDouble + result[0].TestFloat); |
||||
} |
||||
public void TestSerialPort(){ |
||||
this.EGSerialPort().SetBaudRate(9600); |
||||
this.EGSendMessage(new ModbusRTU_ReadInputRegisters(1,0,2),"COM4",ProtocolType.SerialPort); |
||||
this.EGSendMessage(new ModbusRTU_ReadCoils(1,0,8),"COM4",ProtocolType.SerialPort); |
||||
this.EGOnMessage<ModbusRTU_Response>(); |
||||
} |
||||
|
||||
public void TestTCPClient(){ |
||||
this.EGTCPClient(); |
||||
this.EGSendMessage(new ModbusTCP_ReadDiscreteInput(1,0,8),"192.168.1.196:6000",ProtocolType.TCPClient); |
||||
this.EGSendMessage(new ModbusTCP_ReadInputRegisters(1,0,2),"192.168.1.196:6000",ProtocolType.TCPClient); |
||||
this.EGOnMessage<ModbusTCP_Response>(); |
||||
} |
||||
|
||||
private bool IsOpen = false; |
||||
public void TestSingleCoil(){ |
||||
if(IsOpen){ |
||||
//this.EGSendMessage(new ModbusRTU_WriteSingleCoil(1,0,false),"COM4",ProtocolType.SerialPort); |
||||
this.EGSendMessage(new ModbusTCP_WriteSingleCoil(1,0,false),"192.168.1.196:6000",ProtocolType.TCPClient); |
||||
IsOpen = false; |
||||
}else{ |
||||
//this.EGSendMessage(new ModbusRTU_WriteSingleCoil(1,0,true),"COM4",ProtocolType.SerialPort); |
||||
this.EGSendMessage(new ModbusTCP_WriteSingleCoil(1,0,true),"192.168.1.196:6000",ProtocolType.TCPClient); |
||||
IsOpen = true; |
||||
} |
||||
} |
||||
public void TestMultiCoil(){ |
||||
byte[] OpenCode = {0xFF}; |
||||
byte[] CloseCode = {0x00}; |
||||
if(IsOpen){ |
||||
this.EGSendMessage(new ModbusRTU_WriteMultiCoil(1,0,CloseCode.ToBoolArray()),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = false; |
||||
}else{ |
||||
this.EGSendMessage(new ModbusRTU_WriteMultiCoil(1,0,OpenCode.ToBoolArray()),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = true; |
||||
} |
||||
} |
||||
public void TestSingleHoldingRegister(){ |
||||
if(IsOpen){ |
||||
this.EGSendMessage(new ModbusRTU_WriteSingleHoldingRegister(1,0,0x00),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = false; |
||||
}else{ |
||||
this.EGSendMessage(new ModbusRTU_WriteSingleHoldingRegister(1,0,0x01),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = true; |
||||
} |
||||
} |
||||
public void TestMultiHoldingRegister(){ |
||||
ushort[] OpenCode = {1,1,1,1,1,1,1,1}; |
||||
ushort[] CloseCode = {0,0,0,0,0,0,0,0}; |
||||
if(IsOpen){ |
||||
this.EGSendMessage(new ModbusRTU_WriteMultiHoldingRegister(1,0,CloseCode),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = false; |
||||
}else{ |
||||
this.EGSendMessage(new ModbusRTU_WriteMultiHoldingRegister(1,0,OpenCode),"COM4",ProtocolType.SerialPort); |
||||
IsOpen = true; |
||||
} |
||||
} |
||||
|
||||
} |
||||
public class TestBoxMessage { |
||||
public int Code = 0; |
||||
public float TestFloat = 0.1f; |
||||
public double TestDouble; |
||||
public bool IsHaveMessage; |
||||
public string MessageInfo; |
||||
public MessageType MsgType; |
||||
public MessageStruct MsgStruct; |
||||
public MessagePair MsgPair; |
||||
public TestBoxMessage(){ |
||||
this.Code = 1; |
||||
this.TestFloat = 1.2f; |
||||
this.TestDouble = 2.52; |
||||
this.IsHaveMessage = true; |
||||
this.MessageInfo = "DefaultInfo"; |
||||
MsgType = MessageType.TypeInt; |
||||
MsgPair = new MessagePair(); |
||||
MsgStruct = new MessageStruct(5,"Ad"); |
||||
} |
||||
public string ToProtocolData() |
||||
{ |
||||
return JsonConvert.SerializeObject(this); |
||||
} |
||||
} |
||||
public class MessagePair{ |
||||
public int MessageId; |
||||
public string Author; |
||||
public string MessageInfo; |
||||
public int TimeStamp; |
||||
public MessagePair(){ |
||||
this.MessageId = 10001; |
||||
this.Author = "Admin"; |
||||
this.MessageInfo = "Hello every one!"; |
||||
this.TimeStamp = 1690188342; |
||||
} |
||||
} |
||||
public struct MessageStruct : IRequest,IEGFramework{ |
||||
public string FunctionCode; |
||||
public int MessageId; |
||||
public string Author; |
||||
public MessageStruct(int messageId,string author){ |
||||
FunctionCode = "Message"; |
||||
MessageId = messageId; |
||||
Author = author; |
||||
} |
||||
public byte[] ToProtocolByteData() |
||||
{ |
||||
return JsonConvert.SerializeObject(this).ToBytesByEncoding("GBK"); |
||||
} |
||||
public string ToProtocolData() |
||||
{ |
||||
return ""; |
||||
//return JsonConvert.SerializeObject(this); |
||||
} |
||||
} |
||||
public struct MessageResponse : IResponse |
||||
{ |
||||
public string FunctionCode { set; get; } |
||||
public int MessageId; |
||||
public string Author; |
||||
public bool TrySetData(string protocolData, byte[] protocolBytes) |
||||
{ |
||||
try |
||||
{ |
||||
//GD.Print(protocolData); |
||||
MessageResponse res = JsonConvert.DeserializeObject<MessageResponse>(protocolData); |
||||
if(res.FunctionCode == "Message"){ |
||||
this.FunctionCode = res.FunctionCode; |
||||
this.MessageId = res.MessageId; |
||||
this.Author = res.Author; |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
catch (Exception) |
||||
{ |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public struct PrintResponse : IResponse |
||||
{ |
||||
public bool TrySetData(string protocolData, byte[] protocolBytes) |
||||
{ |
||||
//Print("Received String is " + protocolData); |
||||
Print("Received bytes is " + protocolBytes.ToStringByHex()); |
||||
return true; |
||||
} |
||||
|
||||
} |
||||
|
||||
public enum MessageType{ |
||||
TypeString = 1, |
||||
TypeInt = 2, |
||||
TypeObject = 3, |
||||
TypeArray = 4 |
||||
} |
Binary file not shown.
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
[remap] |
||||
|
||||
importer="font_data_dynamic" |
||||
type="FontFile" |
||||
uid="uid://b1atsgy4xkk7d" |
||||
path="res://.godot/imported/SourceHanSansCN-Regular.otf-a74baadd242fcbfb420558b64440f859.fontdata" |
||||
|
||||
[deps] |
||||
|
||||
source_file="res://Font/SourceHanSansCN-Regular.otf" |
||||
dest_files=["res://.godot/imported/SourceHanSansCN-Regular.otf-a74baadd242fcbfb420558b64440f859.fontdata"] |
||||
|
||||
[params] |
||||
|
||||
Rendering=null |
||||
antialiasing=1 |
||||
generate_mipmaps=false |
||||
multichannel_signed_distance_field=false |
||||
msdf_pixel_range=8 |
||||
msdf_size=48 |
||||
allow_system_fallback=true |
||||
force_autohinter=false |
||||
hinting=1 |
||||
subpixel_positioning=1 |
||||
oversampling=0.0 |
||||
Fallbacks=null |
||||
fallbacks=[] |
||||
Compress=null |
||||
compress=true |
||||
preload=[] |
||||
language_support={} |
||||
script_support={} |
||||
opentype_features={} |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
MIT License |
||||
|
||||
Copyright (c) 2024 petejk |
||||
|
||||
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. |
@ -0,0 +1,211 @@
@@ -0,0 +1,211 @@
|
||||
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> |
||||
/// 委托对象 |
||||
/// </summary> |
||||
private Action OnUnRegister { get; set; } |
||||
/// <summary> |
||||
/// 带参构造函数 |
||||
/// </summary> |
||||
/// <param name="onDispose"></param> |
||||
public CustomUnRegister(Action onUnRegister) |
||||
{ |
||||
OnUnRegister = onUnRegister; |
||||
} |
||||
/// <summary> |
||||
/// 资源释放 |
||||
/// </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 |
||||
} |
@ -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. |
@ -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. |
@ -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. |
@ -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. |
@ -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. |
@ -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. |
@ -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 |
||||
} |
@ -0,0 +1,107 @@
@@ -0,0 +1,107 @@
|
||||
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; |
||||
} |
||||
} |
||||
|
||||
|
||||
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); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,324 @@
@@ -0,0 +1,324 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
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. |
||||
/// </summary> |
||||
/// <value></value> |
||||
public int SendDelay { set; get; } = 100; |
||||
public Queue<RequestMsgEvent> RequestCache { set; get; } = new Queue<RequestMsgEvent>(); |
||||
private Timer RequestTimer { set; get; } |
||||
|
||||
public override void Init() |
||||
{ |
||||
if(SendDelay>0){ |
||||
RequestTimer = new 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){ |
||||
RequestCache.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){ |
||||
if(RequestCache.Count>0){ |
||||
OnRequest.Invoke(RequestCache.Dequeue()); |
||||
} |
||||
} |
||||
|
||||
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; |
||||
} |
||||
} |
||||
|
||||
#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, |
||||
DLTSClient = 0x30, |
||||
DLTSServer = 0x31, |
||||
SSLClient = 0x40, |
||||
SSLServer = 0x41, |
||||
FileStream = 0x50, |
||||
MemoryStream = 0x60, |
||||
MQTTClient = 0x70, |
||||
Bacnet = 0x80 |
||||
//MQTT,SSH,etc... |
||||
} |
||||
} |
@ -0,0 +1,65 @@
@@ -0,0 +1,65 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework |
||||
{ |
||||
public interface IEGObject |
||||
{ |
||||
void RegisterObject<T>(T object_); |
||||
T GetObject<T>() where T : class,new(); |
||||
|
||||
} |
||||
public class EGObject : EGModule,IEGObject |
||||
{ |
||||
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<EGObject>().GetObject<T>(); |
||||
} |
||||
} |
||||
public static class CanRegisterObjectExtension |
||||
{ |
||||
public static void EGRegisterObject<T>(this IArchitecture self,T object_) where T : class,new() |
||||
{ |
||||
self.GetModule<EGObject>().RegisterObject(object_); |
||||
} |
||||
public static void EGRegisterObject<T>(this IEGFramework self,T object_) where T : class,new() |
||||
{ |
||||
EGArchitectureImplement.Interface.GetModule<EGObject>().RegisterObject(object_); |
||||
} |
||||
} |
||||
|
||||
public static class CanContainsObjectExtension{ |
||||
public static bool EGContainsObject<T>(this IEGFramework self) |
||||
{ |
||||
return EGArchitectureImplement.Interface.GetModule<EGObject>().ContainsObject<T>(); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,218 @@
@@ -0,0 +1,218 @@
|
||||
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 byte[] ToBytes(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); |
||||
} |
||||
|
||||
/// <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 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; |
||||
} |
||||
|
||||
} |
||||
} |
@ -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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,20 @@
@@ -0,0 +1,20 @@
|
||||
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 GetTimeStamp(this IEGFramework self) |
||||
{ |
||||
TimeSpan ts = DateTime.Now - new DateTime(1970, 1, 1, 8, 0, 0, 0); |
||||
return System.Convert.ToInt64(ts.TotalSeconds); |
||||
} |
||||
} |
||||
} |
||||
|
@ -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); |
||||
} |
||||
} |
||||
} |
||||
|
@ -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; |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
using Godot; |
||||
using static Godot.GD; |
||||
|
||||
namespace EGFramework{ |
||||
|
||||
public class EGSingletonNode : IEGFramework, IModule |
||||
{ |
||||
public IOCContainer NodeContainer = new IOCContainer(); |
||||
public void Init() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public IArchitecture GetArchitecture() |
||||
{ |
||||
return EGArchitectureImplement.Interface; |
||||
} |
||||
|
||||
} |
||||
|
||||
public static class EGCanCreateNodeExtension |
||||
{ |
||||
public static TNode CreateNode<TNode>(this Node self) where TNode : Node,new(){ |
||||
TNode nodeData = new TNode(); |
||||
nodeData.Name = typeof(TNode).Name; |
||||
self.AddChild(nodeData); |
||||
return nodeData; |
||||
} |
||||
|
||||
public static TNode CreateNode<TNode>(this Node self,string name) where TNode : Node,new(){ |
||||
TNode nodeData = new TNode(); |
||||
nodeData.Name = name; |
||||
self.AddChild(nodeData); |
||||
return nodeData; |
||||
} |
||||
|
||||
public static TNode SingletonNode<TNode>(this Node self) where TNode : Node,new(){ |
||||
TNode nodeData = new TNode(); |
||||
nodeData.Name = typeof(TNode).Name; |
||||
self.AddChild(nodeData); |
||||
return nodeData; |
||||
} |
||||
|
||||
public static void Alert(this Node self,string alertMsg){ |
||||
|
||||
} |
||||
} |
||||
} |
@ -0,0 +1,29 @@
@@ -0,0 +1,29 @@
|
||||
using Godot; |
||||
using static Godot.GD; |
||||
using System; |
||||
namespace EGFramework{ |
||||
public static class EGNodeExtension |
||||
{ |
||||
public static TModule NodeModule<TModule>(this Node self) where TModule : Node,IModule,new(){ |
||||
if(EGArchitectureImplement.Interface.IsInitModule<TModule>()){ |
||||
TModule module = new TModule(); |
||||
module.Name = typeof(TModule).ToString(); |
||||
Print(module.Name); |
||||
self.AddChild(module); |
||||
EGArchitectureImplement.Interface.RegisterModule(module); |
||||
return module; |
||||
}else{ |
||||
return EGArchitectureImplement.Interface.GetModule<TModule>(); |
||||
} |
||||
} |
||||
|
||||
public static void ClearChildren(this Node itemContainer) |
||||
{ |
||||
foreach (Node child in itemContainer.GetChildren()) |
||||
{ |
||||
child.QueueFree(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
} |
@ -0,0 +1,9 @@
@@ -0,0 +1,9 @@
|
||||
using Godot; |
||||
using static Godot.GD; |
||||
|
||||
namespace EGFramework{ |
||||
public static class EGTween |
||||
{ |
||||
|
||||
} |
||||
} |
@ -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(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,871 @@
@@ -0,0 +1,871 @@
|
||||
using System; |
||||
using System.Linq; |
||||
using log4net.Core; |
||||
|
||||
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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 struct 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 ModbusFunctionType FunctionType { set; get; } |
||||
public ModbusErrorCode ErrorCode { 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]; |
||||
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); |
||||
Coil = CoilBytes.ToBoolArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadDiscreteInput: |
||||
byte readDiscreteInputLength = protocolBytes[8]; |
||||
byte[] DiscreteInputBytes = new byte[readDiscreteInputLength]; |
||||
Array.Copy(protocolBytes,9,DiscreteInputBytes,0,readDiscreteInputLength); |
||||
DiscreteInput = DiscreteInputBytes.ToBoolArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadHoldingRegisters: |
||||
byte readHoldingRegistersLength = protocolBytes[8]; |
||||
byte[] HoldingRegistersBytes = new byte[readHoldingRegistersLength]; |
||||
Array.Copy(protocolBytes,9,HoldingRegistersBytes,0,readHoldingRegistersLength); |
||||
HoldingRegister = HoldingRegistersBytes.ToUShortArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadInputRegisters: |
||||
byte readInputRegistersLength = protocolBytes[8]; |
||||
byte[] InputRegistersBytes = new byte[readInputRegistersLength]; |
||||
Array.Copy(protocolBytes,9,InputRegistersBytes,0,readInputRegistersLength); |
||||
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 struct 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 struct 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 struct ModbusRTU_ReadHoldingRegisters : IRequest{ |
||||
public const byte FunctionCode = 0x03; |
||||
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_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 struct 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 struct 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 struct 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(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 struct 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 struct 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; } |
||||
|
||||
/// <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 struct 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 ModbusFunctionType FunctionType { set; get; } |
||||
public ModbusErrorCode ErrorCode { set; get; } |
||||
|
||||
public 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 == 0x83){ |
||||
ErrorCode = (ModbusErrorCode)protocolBytes[2]; |
||||
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); |
||||
Coil = CoilBytes.ToBoolArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadDiscreteInput: |
||||
byte readDiscreteInputLength = protocolBytes[2]; |
||||
byte[] DiscreteInputBytes = new byte[readDiscreteInputLength]; |
||||
Array.Copy(protocolBytes,3,DiscreteInputBytes,0,readDiscreteInputLength); |
||||
DiscreteInput = DiscreteInputBytes.ToBoolArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadHoldingRegisters: |
||||
byte readHoldingRegistersLength = protocolBytes[2]; |
||||
byte[] HoldingRegistersBytes = new byte[readHoldingRegistersLength]; |
||||
Array.Copy(protocolBytes,3,HoldingRegistersBytes,0,readHoldingRegistersLength); |
||||
HoldingRegister = HoldingRegistersBytes.ToUShortArray(); |
||||
return true; |
||||
case ModbusFunctionType.ReadInputRegisters: |
||||
byte readInputRegistersLength = protocolBytes[2]; |
||||
byte[] InputRegistersBytes = new byte[readInputRegistersLength]; |
||||
Array.Copy(protocolBytes,3,InputRegistersBytes,0,readInputRegistersLength); |
||||
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 |
||||
} |
||||
} |
@ -0,0 +1,573 @@
@@ -0,0 +1,573 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO.BACnet; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
using Godot; |
||||
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 Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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); |
||||
GD.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; |
||||
GD.Print("Execute bacnet request"); |
||||
if(bacnetRequest.OperateCode == EGBacnetOperateCode.WhoIsRequest){ |
||||
GD.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; |
||||
|
||||
} |
||||
GD.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); |
||||
} |
||||
GD.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) |
||||
{ |
||||
GD.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) |
||||
{ |
||||
GD.PrintErr(e); |
||||
throw; |
||||
} |
||||
} |
||||
|
||||
public void SetEncoding(Encoding textEncoding) |
||||
{ |
||||
this.StringEncoding = textEncoding; |
||||
} |
||||
|
||||
public Queue<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) |
||||
{ |
||||
GD.PrintErr("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) |
||||
{ |
||||
GD.PrintErr(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) |
||||
{ |
||||
GD.PrintErr(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) |
||||
{ |
||||
GD.Print(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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,100 @@
@@ -0,0 +1,100 @@
|
||||
using System.Collections.Generic; |
||||
using System.Text; |
||||
using System.IO; |
||||
|
||||
namespace EGFramework{ |
||||
public class EGFileStream : IEGFramework, IModule,IProtocolSend,IProtocolReceived |
||||
{ |
||||
public Encoding StringEncoding { set; get; } = Encoding.UTF8; |
||||
|
||||
public Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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) |
||||
{ |
||||
Godot.GD.Print("e:" + e); |
||||
throw; |
||||
} |
||||
} |
||||
|
||||
public void SetEncoding(Encoding textEncoding) |
||||
{ |
||||
this.StringEncoding = textEncoding; |
||||
} |
||||
|
||||
public Queue<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); |
||||
} |
||||
} |
||||
} |
@ -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) |
||||
{ |
||||
Godot.GD.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>(); |
||||
} |
||||
} |
||||
} |
@ -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.GetTimeStamp().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"); |
||||
} |
||||
|
||||
} |
||||
Godot.GD.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); |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,163 @@
@@ -0,0 +1,163 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Net; |
||||
using System.Net.Sockets; |
||||
using System.Text; |
||||
using System.Threading; |
||||
using System.Threading.Tasks; |
||||
using Godot; |
||||
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 Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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); |
||||
GD.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); |
||||
GD.Print("Success Connect!"+MqttDevices[serverURL].IsConnected); |
||||
OnMqttConnect.Invoke(serverURL); |
||||
}else{ |
||||
GD.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{ |
||||
GD.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); |
||||
GD.Print("Subscribe "+Theme+" success!"); |
||||
}else{ |
||||
GD.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); |
||||
GD.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 Queue<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>(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,140 @@
@@ -0,0 +1,140 @@
|
||||
using System.Collections.Generic; |
||||
using System.Threading.Tasks; |
||||
using Godot; |
||||
|
||||
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 Queue<ModbusRTU_Response> RTUCache = new Queue<ModbusRTU_Response>(); |
||||
public Queue<ModbusTCP_Response> TCPCache = new Queue<ModbusTCP_Response>(); |
||||
|
||||
public int Delay = 2000; |
||||
|
||||
public Queue<int> WaitForSendRTU = new Queue<int>(); |
||||
public int NextSendRTU = 0; |
||||
public int SendPointerRTU = 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>(); |
||||
} |
||||
|
||||
public bool IsReadingRTU { set; get; } |
||||
public async Task<ModbusRTU_Response?> ReadRTUAsync(ModbusRegisterType registerType,string serialPort,byte deviceAddress,ushort start,ushort count){ |
||||
if(IsReadingRTU){ |
||||
SendPointerRTU++; |
||||
int messageId = SendPointerRTU; |
||||
WaitForSendRTU.Enqueue(messageId); |
||||
await Task.Run(async () => |
||||
{ |
||||
while (IsReadingRTU || NextSendRTU != messageId) |
||||
{ |
||||
await Task.Delay(10); |
||||
//break; |
||||
} |
||||
}); |
||||
GD.Print("-----Read"+messageId+" ----"); |
||||
//return null; |
||||
} |
||||
RTUCache.Clear(); |
||||
IsReadingRTU = true; |
||||
IRequest ReadRequest; |
||||
ModbusRTU_Response? res = null; |
||||
switch(registerType){ |
||||
case ModbusRegisterType.HoldingRegister: |
||||
ReadRequest = new ModbusRTU_ReadHoldingRegisters(deviceAddress,start,count); |
||||
// this.AppendMessage("【发送-"+DataModbusItem.SerialPort+"】 "+ReadRequest.ToProtocolByteData().ToStringByHex()); |
||||
this.EGSendMessage(ReadRequest,serialPort,ProtocolType.SerialPort); |
||||
// this.EGSerialPort().SetExpectReceivedDataLength(5+count*2); |
||||
this.EGSerialPort().SetExpectReceivedDataLength(5); |
||||
break; |
||||
} |
||||
await Task.Run(async ()=>{ |
||||
int timeout = 0; |
||||
while(RTUCache.Count==0 && timeout < Delay){ |
||||
await Task.Delay(10); |
||||
timeout+=10; |
||||
} |
||||
if(RTUCache.Count>0){ |
||||
res = RTUCache.Dequeue(); |
||||
}else{ |
||||
//Print Error Timeout |
||||
OnReadTimeOut.Invoke(); |
||||
this.EGSerialPort().ClearBuffer(serialPort); |
||||
} |
||||
}); |
||||
IsReadingRTU = false; |
||||
if(this.WaitForSendRTU.Count>0){ |
||||
NextSendRTU = this.WaitForSendRTU.Dequeue(); |
||||
} |
||||
return res; |
||||
} |
||||
|
||||
public bool IsReadingTCP { set; get; } |
||||
public async Task<ModbusTCP_Response?> ReadTCPAsync(ModbusRegisterType registerType,string ipPort,byte deviceAddress,ushort start,ushort count){ |
||||
if(IsReadingTCP){ |
||||
await Task.Run(async () => |
||||
{ |
||||
while (IsReadingTCP) |
||||
{ |
||||
await Task.Delay(10); |
||||
//break; |
||||
} |
||||
}); |
||||
//return null; |
||||
} |
||||
TCPCache.Clear(); |
||||
IsReadingTCP = 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){ |
||||
res = TCPCache.Dequeue(); |
||||
}else{ |
||||
//Print Error Timeout |
||||
OnReadTimeOut.Invoke(); |
||||
} |
||||
}); |
||||
IsReadingTCP = false; |
||||
return res; |
||||
} |
||||
|
||||
public IArchitecture GetArchitecture() |
||||
{ |
||||
return EGArchitectureImplement.Interface; |
||||
} |
||||
} |
||||
public static class CanGetEGModbusExtension{ |
||||
public static EGModbus EGModbus(this IEGFramework self){ |
||||
return self.GetModule<EGModbus>(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,71 @@
@@ -0,0 +1,71 @@
|
||||
using Godot; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
|
||||
namespace EGFramework{ |
||||
/// <summary> |
||||
/// In Godot engine, the async method return cannot operate the godot main thread such as Screen Trees Node. |
||||
/// The protocol schedule provide a main thread to check the message in protocol tools 's response message. |
||||
/// If you have more idea ,please issue to me, thanks. |
||||
/// </summary> |
||||
public partial class EGProtocolSchedule : Node, IModule,IEGFramework |
||||
{ |
||||
public Dictionary<Type,IProtocolReceived> ProtocolTools = new Dictionary<Type, IProtocolReceived>(); |
||||
public void Init() |
||||
{ |
||||
|
||||
} |
||||
|
||||
public override void _Process(double delta) |
||||
{ |
||||
foreach(IProtocolReceived tool in ProtocolTools.Values){ |
||||
if(tool.GetReceivedMsg().Count>0){ |
||||
this.GetModule<EGMessage>().OnDataReceived.Invoke(tool.GetReceivedMsg().Dequeue()); |
||||
} |
||||
} |
||||
} |
||||
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; |
||||
} |
||||
|
||||
} |
||||
public static class CanGetEGProtocolExtension{ |
||||
public static EGProtocolSchedule EGProtocolSchedule(this Node self){ |
||||
return self.NodeModule<EGProtocolSchedule>(); |
||||
} |
||||
public static void EGEnabledProtocolTools(this Node self){ |
||||
self.NodeModule<EGProtocolSchedule>().EnabledAllTools(); |
||||
} |
||||
public static void EGEnabledProtocolTool<TProtocolReceived>(this Node self) where TProtocolReceived : class, IModule,IProtocolReceived,new(){ |
||||
self.NodeModule<EGProtocolSchedule>().EnabledTool<TProtocolReceived>(); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,216 @@
@@ -0,0 +1,216 @@
|
||||
using System.IO.Ports; |
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
|
||||
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 Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<ResponseMsg>(); |
||||
|
||||
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 Queue<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; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Open serial port with check if target serial port isOpen. |
||||
/// </summary> |
||||
/// <param name="serialPort"></param> |
||||
public bool Open(string serialPort){ |
||||
try{ |
||||
if(!SerialPortDevices.ContainsKey(serialPort)){ |
||||
SerialPort newPort = new SerialPort(serialPort, DefaultBaudRate, Parity.None, 8, StopBits.One); |
||||
SerialPortDevices.Add(serialPort,newPort); |
||||
if (!SerialPortDevices[serialPort].IsOpen) |
||||
{ |
||||
SerialPortDevices[serialPort].Open(); |
||||
SerialPortDevices[serialPort].DataReceived += SerialPort_DataReceived; |
||||
} |
||||
}else{ |
||||
if(!SerialPortDevices[serialPort].IsOpen){ |
||||
SerialPortDevices[serialPort].Open(); |
||||
} |
||||
} |
||||
return true; |
||||
} |
||||
catch(Exception e){ |
||||
ErrorLogs = "[open port error]" + e.ToString(); |
||||
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].Close(); |
||||
SerialPortDevices.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 >= MinDataPackLength){ |
||||
int bufferSize = serialPort.BytesToRead; |
||||
byte[] buffer = new byte[bufferSize]; |
||||
serialPort.Read(buffer,0,serialPort.BytesToRead); |
||||
string str = StringEncoding.GetString(buffer); |
||||
Godot.GD.Print("[Receive]"+buffer.ToStringByHex()); |
||||
ResponseMsgs.Enqueue(new ResponseMsg(str,buffer,serialPort.PortName,ProtocolType.SerialPort)); |
||||
MinDataPackLength = 0; |
||||
//this.EGOnReceivedData(new ResponseMsg(str,buffer,serialPort.PortName,ProtocolType.SerialPort)); |
||||
}else{ |
||||
Godot.GD.Print("[Data Get]" + serialPort.BytesToRead); |
||||
} |
||||
} |
||||
|
||||
public void SetExpectReceivedDataLength(int leastLength){ |
||||
this.MinDataPackLength = leastLength; |
||||
} |
||||
|
||||
public void ClearBuffer(string serialPort){ |
||||
if(SerialPortDevices.ContainsKey(serialPort)){ |
||||
if (SerialPortDevices[serialPort].IsOpen) |
||||
{ |
||||
SerialPortDevices[serialPort].DiscardInBuffer(); |
||||
} |
||||
}else{ |
||||
//Not found in SerialPortDevices,need add? |
||||
} |
||||
} |
||||
|
||||
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]; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,181 @@
@@ -0,0 +1,181 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
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 Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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 Queue<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]; |
||||
} |
||||
} |
||||
|
||||
} |
@ -0,0 +1,138 @@
@@ -0,0 +1,138 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Net; |
||||
using System.Net.Sockets; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace EGFramework{ |
||||
public class EGTCPServer : IModule, IEGFramework,IProtocolReceived |
||||
{ |
||||
public TcpListener TcpServer { set; get; } |
||||
|
||||
public bool IsListening { set; get; } |
||||
public Dictionary<string, TcpClient> LinkedClients { set; get; } = new Dictionary<string, TcpClient>(); |
||||
public Encoding StringEncoding { set; get; } = Encoding.UTF8; |
||||
public List<string> ClientNames = new List<string>(); |
||||
|
||||
public EasyEvent<string> OnClientConnect { set; get; } = new EasyEvent<string>(); |
||||
public EasyEvent<string> OnClientDisconnect { set; get; } = new EasyEvent<string>(); |
||||
|
||||
public Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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 Queue<ResponseMsg> GetReceivedMsg() |
||||
{ |
||||
return ResponseMsgs; |
||||
} |
||||
|
||||
public async void StartServer(int port) |
||||
{ |
||||
IPEndPoint ipEndPoint = new IPEndPoint(IPAddress.Any, port); |
||||
TcpServer = new(ipEndPoint); |
||||
try |
||||
{ |
||||
TcpServer.Start(); |
||||
IsListening = true; |
||||
while (IsListening) |
||||
{ |
||||
TcpClient client = await TcpServer.AcceptTcpClientAsync(); |
||||
ClientNames.Add(client.Client.RemoteEndPoint.ToString()); |
||||
LinkedClients.Add(client.Client.RemoteEndPoint.ToString(), client); |
||||
OnClientConnect.Invoke(client.Client.RemoteEndPoint.ToString()); |
||||
_ = HandleClientAsync(client); |
||||
} |
||||
TcpServer.Stop(); |
||||
} |
||||
catch (Exception) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public async Task HandleClientAsync(TcpClient client) |
||||
{ |
||||
try |
||||
{ |
||||
NetworkStream stream = client.GetStream(); |
||||
string ClientName = client.Client.RemoteEndPoint.ToString(); |
||||
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); |
||||
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); |
||||
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 (ClientNames.Contains(clientName)) { |
||||
ClientNames.Remove(clientName); |
||||
} |
||||
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); |
||||
} |
||||
|
||||
} |
||||
} |
||||
|
@ -0,0 +1,123 @@
@@ -0,0 +1,123 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Net; |
||||
using System.Net.Sockets; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
|
||||
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 Queue<ResponseMsg> ResponseMsgs { set; get; } = new Queue<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); |
||||
HandleUDPListenAsync(udpDevice); |
||||
//StartListening(localPort); |
||||
} |
||||
catch (Exception e){ |
||||
Godot.GD.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 |
||||
{ |
||||
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) |
||||
{ |
||||
} |
||||
} |
||||
|
||||
public void SendByteData(string host,int port,byte[] data){ |
||||
UdpClient udpClient = new UdpClient(); |
||||
try{ |
||||
udpClient.Send(data, data.Length, host, port); |
||||
} |
||||
catch ( Exception e ){ |
||||
Godot.GD.Print(e.ToString()); |
||||
} |
||||
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 Queue<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); |
||||
} |
||||
} |
||||
} |
||||
|
@ -0,0 +1,19 @@
@@ -0,0 +1,19 @@
|
||||
using System.Collections.Generic; |
||||
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 Queue<ResponseMsg> GetReceivedMsg(); |
||||
} |
||||
|
||||
public interface IProtocolListener{ |
||||
public bool IsEnabled(string ServiceName); |
||||
} |
||||
|
||||
|
||||
} |
@ -0,0 +1,247 @@
@@ -0,0 +1,247 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.IO; |
||||
using Microsoft.Data.Sqlite; |
||||
using Newtonsoft.Json; |
||||
|
||||
namespace EGFramework{ |
||||
public interface IEGSqlite{ |
||||
void SaveData<TData>(TData data) where TData : new(); |
||||
List<TData> GetDataSet<TData>() where TData : new(); |
||||
void InitDatabase(string dataBaseName); |
||||
} |
||||
public class EGSqlite : EGModule,IEGSqlite |
||||
{ |
||||
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).GetFields(); |
||||
foreach(var property in properties){ |
||||
if(property.FieldType == typeof(int) || property.FieldType == typeof(bool) || property.FieldType.IsEnum){ |
||||
sqlCommand += "\"" + property.Name + "\" INTEGER" + " NOT NULL,"; |
||||
}else if(property.FieldType == typeof(double) || property.FieldType == typeof(float)){ |
||||
sqlCommand += "\"" + property.Name + "\" REAL" + " NOT NULL,"; |
||||
} |
||||
else{ |
||||
sqlCommand += "\"" + property.Name + "\" TEXT" + " NOT NULL,"; |
||||
} |
||||
} |
||||
sqlCommand += "PRIMARY KEY(\"ID\" AUTOINCREMENT))"; |
||||
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).GetFields(); |
||||
Dictionary<string,object> dataParams = new Dictionary<string, object>(); |
||||
foreach(var property in properties){ |
||||
dataParams.Add(property.Name,property.GetValue(data)); |
||||
if(property.FieldType==typeof(bool) || property.FieldType.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.FieldType.IsClass || property.FieldType.IsValueType && !property.FieldType.IsPrimitive && property.FieldType != 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).GetFields(); |
||||
|
||||
while (reader.Read()) |
||||
{ |
||||
TData dataRow = new TData(); |
||||
foreach(var property in properties){ |
||||
if(property.FieldType == reader[property.Name].GetType()){ |
||||
property.SetValue(dataRow,reader[property.Name]); |
||||
}else if(property.FieldType.IsEnum){ |
||||
object propertyEnum = Enum.Parse(property.FieldType,reader[property.Name].ToString()); |
||||
property.SetValue(dataRow,propertyEnum); |
||||
} |
||||
else if(property.FieldType.IsPrimitive) { |
||||
object propertyObject = System.Convert.ChangeType(reader[property.Name],property.FieldType); |
||||
property.SetValue(dataRow,propertyObject); |
||||
}else{ |
||||
object classObject = JsonConvert.DeserializeObject(reader[property.Name].ToString(),property.FieldType); |
||||
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>(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
using System; |
||||
using System.IO; |
||||
using System.Collections.Generic; |
||||
using Newtonsoft.Json; |
||||
using Newtonsoft.Json.Linq; |
||||
|
||||
namespace EGFramework |
||||
{ |
||||
public interface IEGSave{ |
||||
void SetDataToFile<TData>(TData data); |
||||
TData GetDataByFile<TData>() where TData : class,new(); |
||||
void InitSaveData(string fileName); |
||||
} |
||||
public class EGSave : EGModule,IEGSave |
||||
{ |
||||
private string DefaultSaveFile = "Default"; |
||||
private string DefaultSaveFolder = "SaveData"; |
||||
private JObject _SaveObject; |
||||
private JObject SaveObject{ |
||||
get { |
||||
if(_SaveObject == null){ |
||||
InitSaveObject(); |
||||
} |
||||
return _SaveObject; |
||||
} |
||||
} |
||||
|
||||
public EGSave(){ |
||||
|
||||
} |
||||
/// <summary> |
||||
/// if you want to define default save data file name, please use "this.RegisterModule(new EGSave("FileName"))"in your architecture code(Init function); |
||||
/// </summary> |
||||
/// <param name="fileName"></param> |
||||
public EGSave(string fileName){ |
||||
this.DefaultSaveFile = fileName; |
||||
} |
||||
public override void Init() |
||||
{ |
||||
if (!Directory.Exists(DefaultSaveFolder)) |
||||
{ |
||||
Directory.CreateDirectory(DefaultSaveFolder); |
||||
File.WriteAllText(DefaultSaveFolder + "/" + DefaultSaveFile + ".json","{}"); |
||||
}else if(!File.Exists(DefaultSaveFolder + "/" + DefaultSaveFile + ".json")){ |
||||
File.WriteAllText(DefaultSaveFolder + "/" + DefaultSaveFile + ".json","{}"); |
||||
} |
||||
} |
||||
|
||||
private void InitSaveObject(){ |
||||
using (StreamReader reader = File.OpenText(DefaultSaveFolder + "/" + DefaultSaveFile + ".json")) |
||||
{ |
||||
_SaveObject = (JObject)JToken.ReadFrom(new JsonTextReader(reader)); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Push SaveObject data set to file |
||||
/// </summary> |
||||
public void SaveToFile(){ |
||||
SaveToFile(DefaultSaveFile); |
||||
} |
||||
private void SaveToFile(string fileName){ |
||||
File.WriteAllText(DefaultSaveFolder + "/" + fileName + ".json",JsonConvert.SerializeObject(SaveObject,Formatting.Indented)); |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Push data to SaveObject object cache, this function will not save data to file, if you hope not to IO operation frequently, you can use this with SaveToFile. |
||||
/// </summary> |
||||
/// <param name="data"></param> |
||||
/// <typeparam name="TData"></typeparam> |
||||
public void SetData<TData>(TData data){ |
||||
//SaveObject = JObject.FromObject(data); |
||||
if(SaveObject.ContainsKey(typeof(TData).ToString())){ |
||||
SaveObject[typeof(TData).ToString()] = JToken.FromObject(data); |
||||
}else{ |
||||
SaveObject.Add(typeof(TData).ToString(),JToken.FromObject(data)); |
||||
} |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Get data from file, if your data is not in file, then get null. |
||||
/// </summary> |
||||
/// <typeparam name="TData"></typeparam> |
||||
public TData GetDataByFile<TData>() where TData : class,new(){ |
||||
if(!SaveObject.ContainsKey(typeof(TData).ToString())){ |
||||
return null; |
||||
} |
||||
TData data = SaveObject[typeof(TData).ToString()].ToObject<TData>(); |
||||
return data; |
||||
} |
||||
|
||||
/// <summary> |
||||
/// Save data to file |
||||
/// </summary> |
||||
/// <param name="data">your any type of data</param> |
||||
/// <typeparam name="TData"></typeparam> |
||||
public void SetDataToFile<TData>(TData data) |
||||
{ |
||||
SetData(data); |
||||
SaveToFile(); |
||||
} |
||||
|
||||
/// <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> |
||||
/// <param name="fileName"></param> |
||||
public void InitSaveData(string fileName) |
||||
{ |
||||
DefaultSaveFile = fileName; |
||||
if(!File.Exists(DefaultSaveFolder + "/" + DefaultSaveFile + ".json")){ |
||||
File.WriteAllText(DefaultSaveFolder + "/" + DefaultSaveFile + ".json","{}"); |
||||
} |
||||
InitSaveObject(); |
||||
} |
||||
} |
||||
|
||||
public static class CanGetEGSaveExtension{ |
||||
public static EGSave EGSave(this IEGFramework self){ |
||||
return EGArchitectureImplement.Interface.GetModule<EGSave>(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,230 @@
@@ -0,0 +1,230 @@
|
||||
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 , |
||||
ContentLength = 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 , |
||||
ContentLength = 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{ |
||||
public string FileName { set; get; } |
||||
public bool IsCollection { set; get; } |
||||
|
||||
/// <summary> |
||||
/// unit is kb |
||||
/// </summary> |
||||
public long? ContentLength { set; get; } |
||||
public string Uri { set; get; } |
||||
public DateTime? LastUpdateTime { set; get; } |
||||
} |
||||
|
||||
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; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
[remap] |
||||
|
||||
importer="texture" |
||||
type="CompressedTexture2D" |
||||
uid="uid://31r216hix0wk" |
||||
path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" |
||||
metadata={ |
||||
"vram_texture": false |
||||
} |
||||
|
||||
[deps] |
||||
|
||||
source_file="res://icon.svg" |
||||
dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] |
||||
|
||||
[params] |
||||
|
||||
compress/mode=0 |
||||
compress/high_quality=false |
||||
compress/lossy_quality=0.7 |
||||
compress/hdr_compression=1 |
||||
compress/normal_map=0 |
||||
compress/channel_pack=0 |
||||
mipmaps/generate=false |
||||
mipmaps/limit=-1 |
||||
roughness/mode=0 |
||||
roughness/src_normal="" |
||||
process/fix_alpha_border=true |
||||
process/premult_alpha=false |
||||
process/normal_map_invert_y=false |
||||
process/hdr_as_srgb=false |
||||
process/hdr_clamp_exposure=false |
||||
process/size_limit=0 |
||||
detect_3d/compress_to=1 |
||||
svg/scale=1.0 |
||||
editor/scale_with_editor_scale=false |
||||
editor/convert_colors_with_editor_theme=false |
@ -0,0 +1,26 @@
@@ -0,0 +1,26 @@
|
||||
; Engine configuration file. |
||||
; It's best edited using the editor UI and not directly, |
||||
; since the parameters that go here are not all obvious. |
||||
; |
||||
; Format: |
||||
; [section] ; section goes between [] |
||||
; param=value ; assign values to parameters |
||||
|
||||
config_version=5 |
||||
|
||||
[application] |
||||
|
||||
config/name="EGFramework" |
||||
config/tags=PackedStringArray("official") |
||||
run/main_scene="res://Example/Gateway/ModbusGateway.tscn" |
||||
config/features=PackedStringArray("4.2", "C#", "GL Compatibility") |
||||
config/icon="res://icon.svg" |
||||
|
||||
[dotnet] |
||||
|
||||
project/assembly_name="EGFramework" |
||||
|
||||
[rendering] |
||||
|
||||
renderer/rendering_method="gl_compatibility" |
||||
renderer/rendering_method.mobile="gl_compatibility" |
Loading…
Reference in new issue