Removed old examples

- added instant register update if write was successful
This commit is contained in:
Felix Weiß
2023-07-06 22:20:01 +02:00
parent 616d102dea
commit d956525538
24 changed files with 135 additions and 797 deletions

View File

@@ -1,10 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<IsPublishable>false</IsPublishable>
<IsPackable>false</IsPackable>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,347 +0,0 @@
using MewtocolNet.Logging;
using MewtocolNet;
using System;
using System.Reflection;
using System.Threading.Tasks;
using System.Collections;
using MewtocolNet.RegisterBuilding;
using System.Collections.Generic;
using MewtocolNet.Registers;
using System.Diagnostics;
using System.Text;
using Microsoft.Win32;
using MewtocolNet.ComCassette;
using System.Linq;
using System.Net;
using System.IO.Ports;
namespace Examples;
public class ExampleScenarios {
public void SetupLogger () {
//attaching the logger
Logger.LogLevel = LogLevel.Info;
Logger.OnNewLogMessage((date, level, msg) => {
if (level == LogLevel.Error) Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}");
Console.ResetColor();
});
}
[Scenario("Dispose and disconnect connection")]
public async Task RunDisposalAndDisconnectAsync () {
//automatic disposal
using (var interf = Mewtocol.Ethernet("192.168.115.210")) {
await interf.ConnectAsync();
if (interf.IsConnected) {
Console.WriteLine("Opened connection");
await Task.Delay(5000);
}
}
Console.WriteLine("Disposed, closed connection");
//manual close
var interf2 = Mewtocol.Ethernet("192.168.115.210");
await interf2.ConnectAsync();
if (interf2.IsConnected) {
Console.WriteLine("Opened connection");
await Task.Delay(5000);
}
interf2.Disconnect();
Console.WriteLine("Disconnected, closed connection");
}
[Scenario("Read all kinds of example registers over ethernet")]
public async Task RunReadTestEth () {
//setting up a new PLC interface and register collection
var interf = Mewtocol.Ethernet("192.168.115.210").WithPoller();
await RunCyclicReadTest(interf);
}
[Scenario("Read all kinds of example registers over serial")]
public async Task RunReadTestSer () {
//setting up a new PLC interface and register collection
var interf = Mewtocol.SerialAuto("COM4").WithPoller();
await RunCyclicReadTest(interf);
}
private async Task RunCyclicReadTest (IPlc interf) {
//auto add all built registers to the interface
var builder = RegBuilder.ForInterface(interf);
var r0reg = builder.FromPlcRegName("R0").Build();
builder.FromPlcRegName("R1", "Testname").Build();
builder.FromPlcRegName("R1F").Build();
builder.FromPlcRegName("R101A").Build();
var shortReg = builder.FromPlcRegName("DT35").AsPlcType(PlcVarType.INT).Build();
builder.FromPlcRegName("DDT36").AsPlcType(PlcVarType.DINT).Build();
builder.FromPlcRegName("DT200").AsBytes(30).Build();
var timeReg = builder.FromPlcRegName("DDT38").AsPlcType(PlcVarType.TIME).Build();
var stringReg = builder.FromPlcRegName("DT40").AsPlcType(PlcVarType.STRING).Build();
//connect
if(interf is IPlcSerial serialPlc) {
await serialPlc.ConnectAsync(() => {
Console.WriteLine($"Trying config: {serialPlc.ConnectionInfo}");
});
} else {
await interf.ConnectAsync();
}
//await first register data
await interf.AwaitFirstDataCycleAsync();
_ = Task.Factory.StartNew(async () => {
void setTitle() {
Console.Title =
$"Speed UP: {interf.BytesPerSecondUpstream} B/s, " +
$"Speed DOWN: {interf.BytesPerSecondDownstream} B/s, " +
$"Poll cycle: {interf.PollerCycleDurationMs} ms, " +
$"Queued MSGs: {interf.QueuedMessages}";
}
while (interf.IsConnected) {
setTitle();
await Task.Delay(1000);
}
setTitle();
});
while (interf.IsConnected) {
var sw = Stopwatch.StartNew();
//set bool
await r0reg.WriteAsync(!(bool)r0reg.Value);
//set random num
await shortReg.WriteAsync((short)new Random().Next(0, 100));
await stringReg.WriteAsync($"_{DateTime.Now.Second}s_");
sw.Stop();
foreach (var reg in interf.Registers)
Console.WriteLine(reg.ToString());
Console.WriteLine($"Total write time for registers: {sw.Elapsed.TotalMilliseconds:N0}ms");
Console.WriteLine();
//await Task.Delay(new Random().Next(0, 10000));
await Task.Delay(1000);
}
}
[Scenario("Test read speed TCP (n) R registers")]
public async Task ReadRSpeedTest (string registerCount) {
var preLogLevel = Logger.LogLevel;
Logger.LogLevel = LogLevel.Critical;
//setting up a new PLC interface and register collection
using var interf = Mewtocol.Ethernet("192.168.115.210");
//auto add all built registers to the interface
var builder = RegBuilder.ForInterface(interf);
for (int i = 0; i < int.Parse(registerCount); i++) {
builder.FromPlcRegName($"R{i}A").Build();
}
//connect
await interf.ConnectAsync();
if(!interf.IsConnected) {
Console.WriteLine("Aborted, connection failed");
return;
}
Console.WriteLine("Poller cycle started");
var sw = Stopwatch.StartNew();
int cmdCount = await interf.RunPollerCylceManual();
sw.Stop();
Console.WriteLine("Poller cycle finished");
Console.WriteLine($"Single frame excec time: {sw.ElapsedMilliseconds:N0}ms for {cmdCount} commands and {interf.Registers.Count()} R registers");
await Task.Delay(1000);
}
[Scenario("Test read speed Serial (n) R registers")]
public async Task ReadRSpeedTestSerial (string registerCount) {
var preLogLevel = Logger.LogLevel;
Logger.LogLevel = LogLevel.Critical;
//setting up a new PLC interface and register collection
//MewtocolInterfaceShared interf = Mewtocol.SerialAuto("COM4");
using var interf = Mewtocol.Serial("COM4", BaudRate._115200, DataBits.Eight, Parity.Odd, StopBits.One);
//auto add all built registers to the interface
var builder = RegBuilder.ForInterface(interf);
for (int i = 0; i < int.Parse(registerCount); i++) {
builder.FromPlcRegName($"R{i}A").Build();
}
//connect
await interf.ConnectAsync();
if (!interf.IsConnected) {
Console.WriteLine("Aborted, connection failed");
return;
}
Console.WriteLine("Poller cycle started");
var sw = Stopwatch.StartNew();
int cmdCount = await interf.RunPollerCylceManual();
sw.Stop();
Console.WriteLine("Poller cycle finished");
Console.WriteLine($"Single frame excec time: {sw.ElapsedMilliseconds:N0}ms for {cmdCount} commands and {interf.Registers.Count()} R registers");
}
[Scenario("Test automatic serial port setup")]
public async Task TestAutoSerialSetup () {
var preLogLevel = Logger.LogLevel;
Logger.LogLevel = LogLevel.Critical;
//setting up a new PLC interface and register collection
var interf = Mewtocol.SerialAuto("COM4");
//connect
await interf.ConnectAsync();
if (!interf.IsConnected) {
Console.WriteLine("Aborted, connection failed");
return;
} else {
Console.WriteLine("Serial port settings found");
}
}
[Scenario("Find all COM5 cassettes in the network")]
public async Task FindCassettes () {
Console.Clear();
var casettes = await CassetteFinder.FindClientsAsync();
foreach (var cassette in casettes) {
Console.WriteLine($"{cassette.Name}");
Console.WriteLine($"IP: {cassette.IPAddress}");
Console.WriteLine($"Port: {cassette.Port}");
Console.WriteLine($"DHCP: {cassette.UsesDHCP}");
Console.WriteLine($"Subnet Mask: {cassette.SubnetMask}");
Console.WriteLine($"Gateway: {cassette.GatewayAddress}");
Console.WriteLine($"Mac: {cassette.MacAddress.ToHexString(":")}");
Console.WriteLine($"Firmware: {cassette.FirmwareVersion}");
Console.WriteLine($"Status: {cassette.Status}");
Console.WriteLine($"Endpoint: {cassette.EndpointName} - {cassette.Endpoint.Address}");
Console.WriteLine();
}
var found = casettes.FirstOrDefault(x => x.Endpoint.Address.ToString() == "10.237.191.75");
if (found == null) return;
found.IPAddress = IPAddress.Parse($"192.168.1.{new Random().Next(20, 120)}");
found.Name = $"Rand{new Random().Next(5, 15)}";
await found.SendNewConfigAsync();
}
[Scenario("Test")]
public async Task Test () {
Logger.LogLevel = LogLevel.Critical;
//fpx c14 r
var plxFpx = Mewtocol.Ethernet("192.168.178.55");
await plxFpx.ConnectAsync();
await ((MewtocolInterface)plxFpx).GetSystemRegister();
//fpx-h c30 t
var plcFpxH = Mewtocol.Ethernet("192.168.115.210");
await plcFpxH.ConnectAsync();
await ((MewtocolInterface)plcFpxH).GetSystemRegister();
//fpx-h c14 r
var plcFpxHc14 = Mewtocol.Ethernet("192.168.115.212");
await plcFpxHc14.ConnectAsync();
await ((MewtocolInterface)plcFpxHc14).GetSystemRegister();
//fpx c30 t
var plcFpxc30T = Mewtocol.Ethernet("192.168.115.213");
await plcFpxc30T.ConnectAsync();
await ((MewtocolInterface)plcFpxc30T).GetSystemRegister();
await Task.Delay(-1);
}
}

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\MewtocolNet\MewtocolNet.csproj" />
</ItemGroup>
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>

View File

@@ -1,134 +0,0 @@
using MewtocolNet.RegisterBuilding;
using MewtocolNet;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using MewtocolNet.Logging;
using System.Text.RegularExpressions;
using System.Globalization;
using System.Threading;
namespace Examples;
class Program {
static ExampleScenarios ExampleSzenarios = new ExampleScenarios();
static void Main(string[] args) {
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-us");
Console.Clear();
AppDomain.CurrentDomain.UnhandledException += (s,e) => {
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Uncatched exception: {e.ExceptionObject.ToString()}");
Console.ResetColor();
};
//TaskScheduler.UnobservedTaskException += (s,e) => {
// Console.ForegroundColor = ConsoleColor.Magenta;
// Console.WriteLine($"Unobserved Task Uncatched exception: {e.Exception.ToString()}");
// Console.ResetColor();
//};
ExampleSzenarios.SetupLogger();
LoopInput();
}
private static void LoopInput () {
Console.WriteLine("All available scenarios\n");
var methods = ExampleSzenarios.GetType().GetMethods();
var invokeableMethods = new List<MethodInfo>();
for (int i = 0, j = 0; i < methods.Length; i++) {
MethodInfo method = methods[i];
var foundAtt = method.GetCustomAttribute(typeof(ScenarioAttribute));
if(foundAtt != null && foundAtt is ScenarioAttribute att) {
string paramsStr = string.Join(" ", method.GetParameters().Select(x => x.Name));
Console.WriteLine($"[{j + 1}] {method.Name}({paramsStr}) - {att.Description}");
invokeableMethods.Add(method);
j++;
}
}
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("\nEnter a number to excecute a example");
Console.ResetColor();
Console.WriteLine("\nOther possible commands: \n");
Console.WriteLine($"'logger <level>' - set loglevel to one of: {string.Join(", ", Enum.GetNames(typeof(LogLevel)).ToList())}");
Console.WriteLine("'exit' - to close this program");
Console.WriteLine("'clear' - to clear the output");
Console.Write("> ");
var line = Console.ReadLine();
var loggerMatch = Regex.Match(line, @"logger (?<level>[a-zA-Z]{0,})");
var splitInput = Regex.Split(line, " ");
if (loggerMatch.Success && Enum.TryParse<LogLevel>(loggerMatch.Groups["level"].Value, out var loglevel)) {
Logger.LogLevel = loglevel;
Console.WriteLine($"Loglevel changed to: {loglevel}");
} else if (line == "exit") {
Environment.Exit(0);
} else if (line == "clear") {
Console.Clear();
} else if (int.TryParse(splitInput[0], out var lineNum)) {
var index = Math.Clamp(lineNum - 1, 0, invokeableMethods.Count - 1);
object[] invParams = null;
if(splitInput.Length > 1) {
invParams = splitInput.Skip(1).Cast<object>().ToArray();
}
try {
var task = (Task)invokeableMethods.ElementAt(index).Invoke(ExampleSzenarios, invParams);
task.Wait();
} catch (TargetParameterCountException) {
Console.WriteLine("Missing parameters");
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("The program ran to completition");
Console.ResetColor();
} else {
Console.WriteLine("Wrong input");
}
LoopInput();
}
}

View File

@@ -1,15 +0,0 @@
using System;
namespace Examples;
public class ScenarioAttribute : Attribute {
public string Description { get; private set; }
public ScenarioAttribute(string description) {
Description = description;
}
}

View File

@@ -1,80 +0,0 @@
using MewtocolNet;
using MewtocolNet.RegisterAttributes;
using System;
using System.Collections;
namespace Examples {
public class TestRegisters : RegisterCollection {
//corresponds to a R100 boolean register in the PLC
[Register(IOType.R, 1000)]
public bool TestBool1 { get; private set; }
private int testDuplicate;
[Register(1000)]
public int TestDuplicate {
get => testDuplicate;
set => AutoSetter(value, ref testDuplicate);
}
//corresponds to a XD input of the PLC
[Register(IOType.X, (byte)0xD)]
public bool TestBoolInputXD { get; private set; }
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
//[Register(1101, 4)]
//public string TestString1 { get; private set; }
//corresponds to a DT7000 16 bit int register in the PLC
[Register(899)]
public short TestInt16 { get; private set; }
//corresponds to a DTD7001 - DTD7002 32 bit int register in the PLC
[Register(7001)]
public int TestInt32 { get; private set; }
//corresponds to a DTD7001 - DTD7002 32 bit float register in the PLC (REAL)
[Register(7003)]
public float TestFloat32 { get; private set; }
//corresponds to a DT7005 - DT7009 string register in the PLC with (STRING[5])
[Register(7005, 5)]
public string TestString2 { get; private set; }
//corresponds to a DT7010 as a 16bit word/int and parses the word as single bits
[Register(7010)]
public BitArray TestBitRegister { get; private set; }
//corresponds to a DT1204 as a 16bit word/int takes the bit at index 9 and writes it back as a boolean
[Register(1204, BitCount.B16, 9)]
public bool BitValue { get; private set; }
[Register(1204, BitCount.B16, 5)]
public bool FillTest { get; private set; }
//corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME)
//the smallest value to communicate to the PLC is 10ms
[Register(7012)]
public TimeSpan TestTime { get; private set; }
public enum CurrentState {
Undefined = 0,
State1 = 1,
State2 = 2,
//State3 = 3,
State4 = 4,
State5 = 5,
StateBetween = 100,
State6 = 6,
State7 = 7,
}
[Register(50)]
public CurrentState TestEnum { get; private set; }
[Register(100)]
public TimeSpan TsTest2 { get; private set; }
}
}

View File

@@ -1,106 +0,0 @@
using MewtocolNet;
using MewtocolNet.RegisterAttributes;
using System;
using System.Collections;
namespace Examples {
public class TestRegistersEnumBitwise : RegisterCollection {
private bool startCyclePLC;
[Register(IOType.R, 50)]
public bool StartCyclePLC {
get => startCyclePLC;
set => AutoSetter(value, ref startCyclePLC);
}
//the enum you want to read out
public enum CurrentState {
Undefined = 0,
State1 = 1,
State2 = 2,
//If you leave an enum empty it still works
//State3 = 3,
State4 = 4,
State5 = 5,
State6 = 6,
State7 = 7,
State8 = 8,
State9 = 9,
State10 = 10,
State11 = 11,
State12 = 12,
State13 = 13,
State14 = 14,
State15 = 15,
}
//automatically convert the short (PLC int) register to an enum
[Register(500)]
public CurrentState TestEnum16 { get; private set; }
//also works for 32bit registers
[Register(501, BitCount.B32)]
public CurrentState TestEnum32 { get; private set; }
//get the whole bit array from DT503
[Register(503)]
public BitArray TestBitRegister16 { get; private set; }
//you can also extract single bits from DT503
[Register(503, BitCount.B16, 0)]
public bool BitValue0 { get; private set; }
[Register(503, BitCount.B16, 1)]
public bool BitValue1 { get; private set; }
[Register(503, BitCount.B16, 2)]
public bool BitValue2 { get; private set; }
[Register(503, BitCount.B16, 3)]
public bool BitValue3 { get; private set; }
[Register(503, BitCount.B16, 4)]
public bool BitValue4 { get; private set; }
[Register(503, BitCount.B16, 5)]
public bool BitValue5 { get; private set; }
[Register(503, BitCount.B16, 6)]
public bool BitValue6 { get; private set; }
[Register(503, BitCount.B16, 7)]
public bool BitValue7 { get; private set; }
[Register(503, BitCount.B16, 8)]
public bool BitValue8 { get; private set; }
[Register(503, BitCount.B16, 9)]
public bool BitValue9 { get; private set; }
[Register(503, BitCount.B16, 10)]
public bool BitValue10 { get; private set; }
[Register(503, BitCount.B16, 11)]
public bool BitValue11 { get; private set; }
[Register(503, BitCount.B16, 12)]
public bool BitValue12 { get; private set; }
[Register(503, BitCount.B16, 13)]
public bool BitValue13 { get; private set; }
[Register(503, BitCount.B16, 14)]
public bool BitValue14 { get; private set; }
[Register(503, BitCount.B16, 15)]
public bool BitValue15 { get; private set; }
}
}

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk.Razor"> <Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup> <PropertyGroup>
<IsPublishable>false</IsPublishable>
<TargetFrameworks>net7.0-android;</TargetFrameworks> <TargetFrameworks>net7.0-android;</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks> <TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net7.0-windows10.0.19041.0</TargetFrameworks>
<!-- Uncomment to also build the tizen app. You will need to install tizen by following this: https://github.com/Samsung/Tizen.NET -->
<!-- <TargetFrameworks>$(TargetFrameworks);net7.0-tizen</TargetFrameworks> -->
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>MewExplorer</RootNamespace> <RootNamespace>MewExplorer</RootNamespace>
<UseMaui>true</UseMaui> <UseMaui>true</UseMaui>

View File

@@ -72,7 +72,7 @@ internal class ScanCommand : CommandLineExcecuteable {
AnsiConsole.Write(found.Select(x => new { AnsiConsole.Write(found.Select(x => new {
x.Cassette.Name, x.Cassette.Name,
PLC = x.PLCInf.TypeCode.ToName(), PLC = x.PLCInf.TypeCode.ToName(),
IsRun = x.PLCInf.OperationMode.HasFlag(OPMode.Run), IsRun = x.PLCInf.OperationMode.HasFlag(OPMode.RunMode),
IP = x.Cassette.IPAddress, IP = x.Cassette.IPAddress,
x.Cassette.Port, x.Cassette.Port,
DHCP = x.Cassette.UsesDHCP, DHCP = x.Cassette.UsesDHCP,

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@@ -16,4 +17,18 @@
<ProjectReference Include="..\MewtocolNet\MewtocolNet.csproj" /> <ProjectReference Include="..\MewtocolNet\MewtocolNet.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup Condition="'$(Configuration)'=='Release'">
<PlatformTarget>x64</PlatformTarget>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>True</SelfContained>
<DebugType>None</DebugType>
<DebugSymbols>False</DebugSymbols>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<AllowedReferenceRelatedFileExtensions>none</AllowedReferenceRelatedFileExtensions>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<OutputPath>..\Builds\MewTerminal</OutputPath>
</PropertyGroup>
</Project> </Project>

View File

@@ -5,15 +5,13 @@ VisualStudioVersion = 17.5.33103.201
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolNet", "MewtocolNet\MewtocolNet.csproj", "{8B7863E7-5E82-4990-9138-2C0C24629982}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolNet", "MewtocolNet\MewtocolNet.csproj", "{8B7863E7-5E82-4990-9138-2C0C24629982}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples", "Examples\Examples.csproj", "{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolTests", "MewtocolTests\MewtocolTests.csproj", "{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolTests", "MewtocolTests\MewtocolTests.csproj", "{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewExplorer", "MewExplorer\MewExplorer.csproj", "{F243F38A-76D3-4C38-BAE6-C61729479661}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewExplorer", "MewExplorer\MewExplorer.csproj", "{F243F38A-76D3-4C38-BAE6-C61729479661}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocBuilder", "DocBuilder\DocBuilder.csproj", "{50F2D23F-C875-4006-A0B6-7F5A181BC944}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocBuilder", "DocBuilder\DocBuilder.csproj", "{50F2D23F-C875-4006-A0B6-7F5A181BC944}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MewTerminal", "MewTerminal\MewTerminal.csproj", "{D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewTerminal", "MewTerminal\MewTerminal.csproj", "{D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -37,18 +35,6 @@ Global
{8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x64.Build.0 = Release|Any CPU {8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x64.Build.0 = Release|Any CPU
{8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x86.ActiveCfg = Release|Any CPU {8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x86.ActiveCfg = Release|Any CPU
{8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x86.Build.0 = Release|Any CPU {8B7863E7-5E82-4990-9138-2C0C24629982}.Release|x86.Build.0 = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|x64.ActiveCfg = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|x64.Build.0 = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|x86.ActiveCfg = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Debug|x86.Build.0 = Debug|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|Any CPU.Build.0 = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|x64.ActiveCfg = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|x64.Build.0 = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|x86.ActiveCfg = Release|Any CPU
{D1F2FA26-3752-44BA-9DCB-4BC2436C5957}.Release|x86.Build.0 = Release|Any CPU
{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|x64.ActiveCfg = Debug|Any CPU {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Debug|x64.ActiveCfg = Debug|Any CPU

View File

@@ -69,15 +69,15 @@ namespace MewtocolNet {
/// </summary> /// </summary>
/// <param name="mode">The mode to change to</param> /// <param name="mode">The mode to change to</param>
/// <returns>The success state of the write operation</returns> /// <returns>The success state of the write operation</returns>
public async Task<bool> SetOperationMode(OPMode mode) { public async Task<bool> SetOperationMode (bool setRun) {
string modeChar = mode == OPMode.Prog ? "P" : "R"; string modeChar = setRun ? "R" : "P";
string requeststring = $"%{GetStationNumber()}#RM{modeChar}"; string requeststring = $"%{GetStationNumber()}#RM{modeChar}";
var result = await SendCommandAsync(requeststring); var result = await SendCommandAsync(requeststring);
if (result.Success) { if (result.Success) {
Logger.Log($"operation mode was changed to {mode}", LogLevel.Info, this); Logger.Log($"operation mode was changed to {(setRun ? "Run" : "Prog")}", LogLevel.Info, this);
} else { } else {
Logger.Log("Operation mode change failed", LogLevel.Error, this); Logger.Log("Operation mode change failed", LogLevel.Error, this);
} }

View File

@@ -1,8 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>netstandard2.0;</TargetFrameworks>
<IsPublishable>false</IsPublishable>
<TargetFramework>netstandard2.0</TargetFramework>
<PackageId>Mewtocol.NET</PackageId> <PackageId>Mewtocol.NET</PackageId>
<Version>0.7.1</Version> <Version>0.0.0</Version>
<Authors>Felix Weiss</Authors> <Authors>Felix Weiss</Authors>
<Company>Womed</Company> <Company>Womed</Company>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -13,22 +17,28 @@
<PackageTags>plc;panasonic;mewtocol;automation;</PackageTags> <PackageTags>plc;panasonic;mewtocol;automation;</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression> <PackageLicenseExpression>MIT</PackageLicenseExpression>
<UserSecretsId>2ccdcc9b-94a3-4e76-8827-453ab889ea33</UserSecretsId> <UserSecretsId>2ccdcc9b-94a3-4e76-8827-453ab889ea33</UserSecretsId>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DocumentationFile>..\Builds\MewtocolNet.xml</DocumentationFile> <PropertyGroup Condition="'$(Configuration)'=='Release'">
<OutputPath>..\Builds</OutputPath> <DocumentationFile>..\Builds\MewtocolNet\MewtocolNet.xml</DocumentationFile>
<OutputPath>..\Builds\MewtocolNet</OutputPath>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>MewtocolTests</_Parameter1> <_Parameter1>MewtocolTests</_Parameter1>
</AssemblyAttribute> </AssemblyAttribute>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo"> <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>DocBuilder</_Parameter1> <_Parameter1>DocBuilder</_Parameter1>
</AssemblyAttribute> </AssemblyAttribute>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="System.IO.Ports" Version="7.0.0" /> <PackageReference Include="System.IO.Ports" Version="7.0.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -1,5 +1,4 @@
using MewtocolNet.PublicEnums; using System.Globalization;
using System.Globalization;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
namespace MewtocolNet { namespace MewtocolNet {
@@ -39,6 +38,11 @@ namespace MewtocolNet {
/// </summary> /// </summary>
public string SelfDiagnosticError { get; internal set; } public string SelfDiagnosticError { get; internal set; }
/// <summary>
/// Quickcheck for the runmode flag
/// </summary>
public bool IsRunMode => OperationMode.HasFlag(OPMode.RunMode);
internal bool TryExtendFromEXRT (string msg) { internal bool TryExtendFromEXRT (string msg) {
var regexEXRT = new Regex(@"\%EE\$EX00RT00(?<icnt>..)(?<mc>..)..(?<cap>..)(?<op>..)..(?<flg>..)(?<sdiag>....)(?<ver>..)(?<hwif>..)(?<nprog>.)(?<progsz>....)(?<hdsz>....)(?<sysregsz>....).*", RegexOptions.IgnoreCase); var regexEXRT = new Regex(@"\%EE\$EX00RT00(?<icnt>..)(?<mc>..)..(?<cap>..)(?<op>..)..(?<flg>..)(?<sdiag>....)(?<ver>..)(?<hwif>..)(?<nprog>.)(?<progsz>....)(?<hdsz>....)(?<sysregsz>....).*", RegexOptions.IgnoreCase);
@@ -108,6 +112,12 @@ namespace MewtocolNet {
return !c1.Equals(c2); return !c1.Equals(c2);
} }
public override string ToString() {
return $"{TypeCode.ToName()}, OP: {OperationMode}";
}
} }
} }

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Text; using System.Text;
namespace MewtocolNet.PublicEnums { namespace MewtocolNet {
/// <summary> /// <summary>
/// Contains hardware information about the device as flags /// Contains hardware information about the device as flags
@@ -29,49 +29,4 @@ namespace MewtocolNet.PublicEnums {
} }
/// <summary>
/// Descibes the operation mode of the device as flags
/// </summary>
[Flags]
public enum OPMode : byte {
/// <summary>
/// No operation mode flag active
/// </summary>
None = 0,
/// <summary>
/// Is in RUN mode, otherwise its PROG Mode
/// </summary>
RunMode = 1,
/// <summary>
/// Is in test mode, otherwise ok
/// </summary>
TestMode = 2,
/// <summary>
/// Is BRK/1 step executed
/// </summary>
BreakPointPerOneStep = 4,
/// <summary>
/// Is BRK command enabled
/// </summary>
BreakEnabled = 16,
/// <summary>
/// Is outputting to external device
/// </summary>
ExternalOutput = 32,
/// <summary>
/// Is 1 step exec enabled
/// </summary>
OneStepExecEnabled = 64,
/// <summary>
/// Is a message displayed?
/// </summary>
MessageInstructionDisplayed = 128,
/// <summary>
/// Is in remote mode
/// </summary>
RemoteMode = 255,
}
} }

View File

@@ -1,17 +1,50 @@
namespace MewtocolNet { using System;
namespace MewtocolNet {
/// <summary> /// <summary>
/// CPU type of the PLC /// Descibes the operation mode of the device as flags
/// </summary> /// </summary>
public enum OPMode { [Flags]
public enum OPMode : byte {
/// <summary> /// <summary>
/// PLC run mode /// No operation mode flag active
/// </summary> /// </summary>
Run, None = 0,
/// <summary> /// <summary>
/// PLC programming mode /// Is in RUN mode, otherwise its PROG Mode
/// </summary> /// </summary>
Prog, RunMode = 1,
/// <summary>
/// Is in test mode, otherwise ok
/// </summary>
TestMode = 2,
/// <summary>
/// Is BRK/1 step executed
/// </summary>
BreakPointPerOneStep = 4,
/// <summary>
/// Is BRK command enabled
/// </summary>
BreakEnabled = 16,
/// <summary>
/// Is outputting to external device
/// </summary>
ExternalOutput = 32,
/// <summary>
/// Is 1 step exec enabled
/// </summary>
OneStepExecEnabled = 64,
/// <summary>
/// Is a message displayed?
/// </summary>
MessageInstructionDisplayed = 128,
/// <summary>
/// Is in remote mode
/// </summary>
RemoteMode = 255,
} }
} }

View File

@@ -78,7 +78,9 @@ namespace MewtocolNet.Registers {
if (!attachedInterface.IsConnected) return false; if (!attachedInterface.IsConnected) return false;
return await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (bool)data)); var res = await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (bool)data));
if (res) SetValueFromPLC(data);
return res;
} }

View File

@@ -89,7 +89,9 @@ namespace MewtocolNet.Registers {
if (!attachedInterface.IsConnected) return false; if (!attachedInterface.IsConnected) return false;
return await attachedInterface.WriteRawRegisterAsync(this, (byte[])data); var res = await attachedInterface.WriteRawRegisterAsync(this, (byte[])data);
if (res) SetValueFromPLC(data);
return res;
} }

View File

@@ -178,7 +178,9 @@ namespace MewtocolNet.Registers {
if (!attachedInterface.IsConnected) return false; if (!attachedInterface.IsConnected) return false;
return await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (T)data)); var res = await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (T)data));
if (res) SetValueFromPLC(data);
return res;
} }

View File

@@ -97,8 +97,10 @@ namespace MewtocolNet.Registers {
if (!attachedInterface.IsConnected) return false; if (!attachedInterface.IsConnected) return false;
var res = await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (string)data)); var res = await attachedInterface.WriteRawRegisterAsync(this, PlcValueParser.Encode(this, (string)data));
if (res) {
if (res) UsedSize = (short)((string)Value).Length; UsedSize = (short)((string)Value).Length;
SetValueFromPLC(data);
}
return res; return res;

View File

@@ -10,7 +10,7 @@ public class ExpectedPlcInformationData {
public int PLCPort { get; set; } public int PLCPort { get; set; }
public CpuType Type { get; set; } public PlcType Type { get; set; }
public int ProgCapacity { get; set; } public int ProgCapacity { get; set; }

View File

@@ -1,11 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<IsPublishable>false</IsPublishable>
<IsPackable>false</IsPackable>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>

View File

@@ -20,7 +20,7 @@ namespace MewtocolTests
PLCName = "FPX-H C30T", PLCName = "FPX-H C30T",
PLCIP = "192.168.115.210", PLCIP = "192.168.115.210",
PLCPort = 9094, PLCPort = 9094,
Type = CpuType.FP_Sigma_X_H_30K_60K_120K, Type = PlcType.FPdXH_32k__C30TsP_C40T_C60TsP,
ProgCapacity = 32, ProgCapacity = 32,
}, },
@@ -29,7 +29,7 @@ namespace MewtocolTests
PLCName = "FPX-H C14R", PLCName = "FPX-H C14R",
PLCIP = "192.168.115.212", PLCIP = "192.168.115.212",
PLCPort = 9094, PLCPort = 9094,
Type = CpuType.FP_Sigma_X_H_30K_60K_120K, Type = PlcType.FPdXH_16k__C14R,
ProgCapacity = 16, ProgCapacity = 16,
}, },
@@ -57,7 +57,7 @@ namespace MewtocolTests
this.output = output; this.output = output;
Logger.LogLevel = LogLevel.Verbose; Logger.LogLevel = LogLevel.Critical;
Logger.OnNewLogMessage((d, l, m) => { Logger.OnNewLogMessage((d, l, m) => {
output.WriteLine($"Mewtocol Logger: {d} {m}"); output.WriteLine($"Mewtocol Logger: {d} {m}");
@@ -102,8 +102,8 @@ namespace MewtocolTests
Assert.True(client.IsConnected); Assert.True(client.IsConnected);
Assert.Equal(client.PlcInfo.CpuInformation.Cputype, plc.Type); Assert.Equal(client.PlcInfo.TypeCode, plc.Type);
Assert.Equal(client.PlcInfo.CpuInformation.ProgramCapacity, plc.ProgCapacity); Assert.Equal(client.PlcInfo.ProgramCapacity, plc.ProgCapacity);
client.Disconnect(); client.Disconnect();

7
build_order.md Normal file
View File

@@ -0,0 +1,7 @@
## 1. Run the tests
`dotnet test /p:CollectCoverage=true /p:CoverletOutputFormat=opencover /p:CoverletOutput=./TestResults/coverage.opencover.xml`
## 2. Publish
`dotnet publish -c:Release --property WarningLevel=0`