From a399e0fa16b1a9f012d13829bcda98a2acc0a7d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Fri, 21 Jul 2023 18:23:20 +0200 Subject: [PATCH] Fix typecodes --- .github/workflows/test-pipeline.yml | 4 +- .../AutoTools.ChmDataExtract.csproj | 17 + AutoTools.ChmDataExtract/Program.cs | 241 ++++++++++ .../AutoTools.DocBuilder.csproj | 16 + .../Docs/plctypes.md | 419 +++++++++--------- .../Docs/reverse_engineering_data.md | 91 +++- .../Program.cs | 87 ++-- DocBuilder/DocBuilder.csproj | 18 - Examples.BasicEthernet/Program.cs | 8 +- Examples.BasicRegisterReadWrite/Program.cs | 5 +- MewtocolNet.sln | 50 ++- MewtocolNet/Helpers/MewtocolHelpers.cs | 31 +- MewtocolNet/Helpers/ParsedPlcName.cs | 86 ++-- MewtocolNet/MewtocolNet.csproj | 2 +- MewtocolNet/PLCInfo.cs | 34 +- MewtocolNet/PublicEnums/PlcType.cs | 196 +++++--- .../{RegisterType.cs => RegisterPrefix.cs} | 6 +- .../{IOType.cs => SingleBitPrefix.cs} | 2 +- MewtocolNet/RegisterBuilding/AddressTools.cs | 74 +--- .../RegisterBuilding/RegisterAssembler.cs | 4 +- MewtocolNet/RegisterBuilding/StepData.cs | 2 +- MewtocolNet/Registers/Base/IRegister.cs | 2 +- MewtocolNet/Registers/Base/Register.cs | 4 +- .../Registers/Classes/ArrayRegister.cs | 2 +- MewtocolNet/Registers/Classes/BoolRegister.cs | 8 +- .../Registers/Classes/StringRegister.cs | 2 +- .../Registers/Classes/StructRegister.cs | 42 +- MewtocolNet/TypeConversion/Conversions.cs | 46 +- .../TypeConversion/IPlcTypeConverter.cs | 2 +- .../TypeConversion/PlcTypeConversion.cs | 6 +- MewtocolNet/TypeConversion/PlcValueParser.cs | 2 +- .../TypeConversion/PlcVarTypeConversions.cs | 4 +- MewtocolNet/UnderlyingRegisters/DTArea.cs | 2 +- .../UnderlyingRegisters/MemoryAreaManager.cs | 17 +- MewtocolNet/UnderlyingRegisters/WRArea.cs | 2 +- MewtocolTests/TestPlcTypeEnumDuplicates.cs | 19 + MewtocolTests/TestRegisterBuilder.cs | 120 ++--- MewtocolTests/TestRegisterInterface.cs | 4 +- 38 files changed, 1058 insertions(+), 619 deletions(-) create mode 100644 AutoTools.ChmDataExtract/AutoTools.ChmDataExtract.csproj create mode 100644 AutoTools.ChmDataExtract/Program.cs create mode 100644 AutoTools.DocBuilder/AutoTools.DocBuilder.csproj rename {DocBuilder => AutoTools.DocBuilder}/Docs/plctypes.md (77%) rename {DocBuilder => AutoTools.DocBuilder}/Docs/reverse_engineering_data.md (69%) rename {DocBuilder => AutoTools.DocBuilder}/Program.cs (52%) delete mode 100644 DocBuilder/DocBuilder.csproj rename MewtocolNet/PublicEnums/{RegisterType.cs => RegisterPrefix.cs} (79%) rename MewtocolNet/PublicEnums/{IOType.cs => SingleBitPrefix.cs} (94%) create mode 100644 MewtocolTests/TestPlcTypeEnumDuplicates.cs diff --git a/.github/workflows/test-pipeline.yml b/.github/workflows/test-pipeline.yml index 984668a..5ece87a 100644 --- a/.github/workflows/test-pipeline.yml +++ b/.github/workflows/test-pipeline.yml @@ -41,7 +41,7 @@ jobs: - name: 'Run docbuilder' continue-on-error: true - run: dotnet run --project "./DocBuilder/DocBuilder.csproj" "./DocBuilder/Docs/plctypes.md" + run: dotnet run --project "./AutoTools.DocBuilder/DocBuilder.csproj" "./AutoTools.DocBuilder/Docs/plctypes.md" - name: 'Commit generated docs to branch' continue-on-error: true @@ -50,7 +50,7 @@ jobs: git checkout ${{ steps.extract_branch.outputs.branch }} git config --local user.email "action@github.com" git config --local user.name "GitHub Action" - git add "./DocBuilder/Docs/plctypes.md" -f + git add "./AutoTools.DocBuilder/Docs/plctypes.md" -f git commit -m "(AUTO_DOC) add documentation for branch ${{ steps.extract_branch.outputs.branch }}" - name: 'Push docs commit' diff --git a/AutoTools.ChmDataExtract/AutoTools.ChmDataExtract.csproj b/AutoTools.ChmDataExtract/AutoTools.ChmDataExtract.csproj new file mode 100644 index 0000000..f6aebd5 --- /dev/null +++ b/AutoTools.ChmDataExtract/AutoTools.ChmDataExtract.csproj @@ -0,0 +1,17 @@ + + + + false + false + Exe + net6.0 + enable + enable + + + + + + + + diff --git a/AutoTools.ChmDataExtract/Program.cs b/AutoTools.ChmDataExtract/Program.cs new file mode 100644 index 0000000..93701da --- /dev/null +++ b/AutoTools.ChmDataExtract/Program.cs @@ -0,0 +1,241 @@ +using System.Collections.Specialized; +using System.Diagnostics; +using System.Reflection; +using System.Text.RegularExpressions; +using HtmlAgilityPack; +using MewtocolNet; + +namespace AutoTools.ChmDataExtract; + +internal class Program { + + const string sysVarsLoc = @"Panasonic-ID SUNX Control\Control FPWIN Pro 7\Mak\Res_Eng\SysVars.chm"; + + const string sysVarsTempPath = @"Decomp"; + + static Dictionary> plcGroups = new() { + { "FP7 CPS41/31 E/ES", new List { + PlcType.FP7_120k__CPS31E, + PlcType.FP7_196k__CPS41E, + PlcType.FP7_120k__CPS31ES, + PlcType.FP7_196k__CPS41ES, + }}, + { "FP7 CPS31/31S", new List { + PlcType.FP7_120k__CPS31, + PlcType.FP7_120k__CPS31S, + }}, + { "FP7 CPS21", new List { + PlcType.FP7_64k__CPS21, + }}, + { "ELC500", new List { + PlcType.ECOLOGIX_0k__ELC500, + }}, + { "FP-SIGMA 12k", new List { + PlcType.FPdSIGMA_12k, + PlcType.FPdSIGMA_16k, + }}, + { "FP-SIGMA 32k", new List { + PlcType.FPdSIGMA_32k, + PlcType.FPdSIGMA_40k, + }}, + { "FP0R 16k/32k C types", new List { + PlcType.FP0R_16k__C10_C14_C16, + PlcType.FP0R_32k__C32, + }}, + { "FP0R 32k T32", new List { + PlcType.FP0R_32k__T32, + PlcType.FP0R_32k__F32, + }}, + { "FP2 16k", new List { + PlcType.FP2_16k, + }}, + { "FP2 32k", new List { + PlcType.FP2_32k, + }}, + { "FP2SH 32k/60k/120k", new List { + PlcType.FP2SH_60k, + PlcType.FP2SH_60k, + PlcType.FP2SH_120k, + }}, + { "FP-X 16k/32k R-types", new List { + PlcType.FPdX_16k__C14R, + PlcType.FPdX_32k__C30R_C60R, + }}, + { "FP-X 16k/32k T-types", new List { + PlcType.FPdX_16k__C14TsP, + PlcType.FPdX_32k__C30TsP_C60TsP_C38AT_C40T, + }}, + {"FP0H C32T/P ET/EP", new List { + PlcType.FP0H_32k__C32TsP, + PlcType.FP0H_32k__C32ETsEP, + }}, + { "FP-X 16k/32k L-types", new List { + PlcType.FPdX_16k__L14, + PlcType.FPdX_32k__L30_L60, + }}, + { "FP-X 2.5k C40RT0A", new List { + PlcType.FPdX_2c5k__C40RT0A, + }}, + { "FP-X0 2.5k L14,L30", new List { + PlcType.FPdX0_2c5k__L14_L30, + }}, + { "FP-X0 8k L40,L60", new List { + PlcType.FPdX0_8k__L40_L60, + }}, + { "FP-e 2.7k", new List { + PlcType.FPde_2c7k, + }}, + { "FP-XH 16k/32k R-types", new List { + PlcType.FPdXH_16k__C14R, + PlcType.FPdXH_32k__C30R_C40R_C60R, + }}, + { "FP-XH 16k/32k T-types", new List { + PlcType.FPdXH_16k__C14TsP, + PlcType.FPdXH_32k__C30TsP_C40T_C60TsP, + PlcType.FPdXH_32k__C30TsP_C40T_C60TsP, + PlcType.FPdXH_32k__C38AT, + PlcType.FPdXH_32k__C40ET_C60ET, + PlcType.FPdXH_32k__C60ETF, + }}, + { "FP-XH M4/M8 types", new List { + PlcType.FPdXH_32k__M4TsL, + PlcType.FPdXH_32k__M8N16TsP, + PlcType.FPdXH_32k__M8N30T, + }}, + }; + + class AddressException { + + public string ExceptionTitle; + + public string ForSysRegister; + + } + + static void Main(string[] args) => Task.Run(AsyncMain).Wait(); + + static async Task AsyncMain () { + + CheckGroupCoverage(); + + await GetSystemRegisters(); + + } + + static void CheckGroupCoverage () { + + //foreach (var key in Enum.GetNames(PlcType)) { + + //} + + } + + static async Task GetSystemRegisters () { + + var addressExceptions = new List(); + + var progLoc = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!; + var progFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86); + var sysVarsPath = Path.Combine(progFilesPath, sysVarsLoc); + + Directory.SetCurrentDirectory(progLoc); + File.Copy(sysVarsPath, "./SysVars.chm", true); + + var startInfo = new ProcessStartInfo { + WorkingDirectory = progLoc, + FileName = "hh.exe", + Arguments = $"-decompile ./Decomp ./SysVars.chm", + }; + + //call the hh.exe decompiler for chm + if (!File.Exists("./Decomp/topics/availability.html")) { + var proc = Process.Start(startInfo)!; + proc.WaitForExit(); + } + + var doc = new HtmlDocument(); + doc.Load("./Decomp/topics/availability.html"); + + //[contains(@class, 'table mainbody')] + foreach (HtmlNode table in doc.DocumentNode.SelectNodes("//table[1]")) { + + var rows = table?.SelectSingleNode("tbody")?.SelectNodes("tr"); + if (rows == null) continue; + + string lastRegisterName = "Name"; + + int iSystemRegister = 0; + + foreach (var row in rows) { + + var columns = row.SelectNodes("td"); + if (columns == null) continue; + + //get var name + var varNameNode = columns?.FirstOrDefault()?.SelectSingleNode("p/a[contains(@class,'xref')]"); + + string registerAddress; + int iterateStart; + + if (varNameNode != null) { + + lastRegisterName = varNameNode.InnerText; + + //get second col + var regAddressNode = columns?.ElementAtOrDefault(1)?.SelectSingleNode("p"); + registerAddress = regAddressNode?.InnerText ?? "Null"; + iterateStart = 2; + + } else { + + //get first col + var regAddressNode = columns?.ElementAtOrDefault(0)?.SelectSingleNode("p"); + registerAddress = regAddressNode?.InnerText ?? "Null"; + iterateStart = 1; + } + + //filter the address for annotations + var regexAnnotation = new Regex(@"\(.*\)"); + var matchAnnotation = regexAnnotation.Match(registerAddress); + if (matchAnnotation.Success) { + + registerAddress = regexAnnotation.Replace(registerAddress, ""); + + addressExceptions.Add(new AddressException { + ForSysRegister = lastRegisterName, + ExceptionTitle = matchAnnotation.Value, + }); + + } + + Console.Write($"Var: {lastRegisterName} | {registerAddress} ".PadRight(100, ' ')); + + for (int i = iterateStart, j = 0; i < columns?.Count + 1; i++) { + + if (j >= plcGroups.Count - 1) continue; + + var group = plcGroups.Keys.ToList()[j]; + + bool isChecked = columns?.ElementAtOrDefault(i)?.SelectSingleNode("p")?.InnerHtml != ""; + + Console.Write($"{(isChecked ? "1" : "0")}, "); + + j++; + + } + + Console.WriteLine(); + + } + + } + + foreach (var item in addressExceptions.DistinctBy(x => x.ExceptionTitle)) { + + Console.WriteLine($"{item.ForSysRegister} - {item.ExceptionTitle}"); + + } + + } + +} diff --git a/AutoTools.DocBuilder/AutoTools.DocBuilder.csproj b/AutoTools.DocBuilder/AutoTools.DocBuilder.csproj new file mode 100644 index 0000000..b511e37 --- /dev/null +++ b/AutoTools.DocBuilder/AutoTools.DocBuilder.csproj @@ -0,0 +1,16 @@ + + + + false + false + Exe + net6.0 + enable + enable + + + + + + + diff --git a/DocBuilder/Docs/plctypes.md b/AutoTools.DocBuilder/Docs/plctypes.md similarity index 77% rename from DocBuilder/Docs/plctypes.md rename to AutoTools.DocBuilder/Docs/plctypes.md index 560648c..758260a 100644 --- a/DocBuilder/Docs/plctypes.md +++ b/AutoTools.DocBuilder/Docs/plctypes.md @@ -1,5 +1,16 @@ # PLC Type Table -All supported PLC types for auto recognition are listed in this table. Other ones might also be supported but are shown as unknown in the library +Auto Generated @ **2023-07-21 15:07:27Z** + +All supported PLC types for auto recognition are listed in this table. Other ones might also be supported but are shown as unknown in the library. Some models are never uniquely identifiable by their typecode and need extra hints like Prog Capacity in EXRT or RT. + +Typecode explained: +``` +From left to right +0x +07 <= extended code (00 non mewtocol 7 devices) +20 <= Is hex for 32 (Prog capacity) +A5 <= Is the actual typecode, can overlap with others +``` > Discontinued PLCs
> These are PLCs that are no longer sold by Panasonic. Marked with ⚠️ @@ -22,7 +33,7 @@ All supported PLC types for auto recognition are listed in this table. Other one ELC500 0k -0x0710 +0x070010 ECOLOGIX_0k__ELC500 ⚠️ ❌ @@ -34,7 +45,7 @@ All supported PLC types for auto recognition are listed in this table. Other one C10, C14, C16 2.7k -0x0040 +0x000040 FP0_2c7k__C10_C14_C16 ⚠️ ❌ @@ -43,7 +54,7 @@ All supported PLC types for auto recognition are listed in this table. Other one C32, SL1 5k -0x0041 +0x000041 FP0_5k__C32_SL1 ⚠️ ❌ @@ -52,7 +63,7 @@ All supported PLC types for auto recognition are listed in this table. Other one T32 10k -0x0042 +0x000A42 FP0_10c0k__T32 ⚠️ ❌ @@ -62,18 +73,18 @@ All supported PLC types for auto recognition are listed in this table. Other one 📟 FP0H - C32T/P + C32ET/EP 32k -0x00B0 -FP0H_32k__C32TsP +0x0020B1 +FP0H_32k__C32ETsEP ✅ ❌ - C32ET/EP + C32T/P 32k -0x00B1 -FP0H_32k__C32ETsEP +0x0020B0 +FP0H_32k__C32TsP ✅ ❌ @@ -83,7 +94,7 @@ All supported PLC types for auto recognition are listed in this table. Other one C10, C14, C16 16k -0x0046 +0x000046 FP0R_16k__C10_C14_C16 ✅ ❌ @@ -91,44 +102,35 @@ All supported PLC types for auto recognition are listed in this table. Other one C32 32k -0x0047 +0x002047 FP0R_32k__C32 ✅ ❌ - T32 - 32k -0x0048 -FP0R_32k__T32 - ✅ - ❌ - - F32 32k -0x0049 +0x002049 FP0R_32k__F32 ✅ ❌ -📟 FP1, FP-M + T32 + 32k +0x002048 +FP0R_32k__T32 + ✅ + ❌ + + +📟 FP1 C14, C16 0.9k -0x0004 -FP1_0c9k__C14_C16_OR_FPdM_0c9k__C16T -⚠️ - ❌ - ❌ - - - C16T - 0.9k -0x0004 -FP1_0c9k__C14_C16_OR_FPdM_0c9k__C16T +0x000004 +FP1_0c9k__C14_C16 ⚠️ ❌ ❌ @@ -136,17 +138,8 @@ All supported PLC types for auto recognition are listed in this table. Other one C24, C40 2.7k -0x0005 -FP1_2c7k__C24_C40_OR_FPdM_2c7k__C20R_C20T_C32T -⚠️ - ❌ - ❌ - - - C20R, C20T, C32T - 2.7k -0x0005 -FP1_2c7k__C24_C40_OR_FPdM_2c7k__C20R_C20T_C32T +0x000005 +FP1_2c7k__C24_C40 ⚠️ ❌ ❌ @@ -154,29 +147,20 @@ All supported PLC types for auto recognition are listed in this table. Other one C56, C72 5k -0x0006 -FP1_5k__C56_C72_OR_FPdM_5k__C20RC_C20TC_C32TC +0x000006 +FP1_5k__C56_C72 ⚠️ ❌ ❌ - C20RC, C20TC, C32TC - 5k -0x0006 -FP1_5k__C56_C72_OR_FPdM_5k__C20RC_C20TC_C32TC -⚠️ - ❌ - ❌ - - -📟 FP10, FP10S +📟 FP10 - 30k -0x0020 -FP10_30k_OR_FP10_60k_OR_FP10S_30k +0x001E20 +FP10_30k ⚠️ ❌ ❌ @@ -184,17 +168,20 @@ All supported PLC types for auto recognition are listed in this table. Other one - 60k -0x0020 -FP10_30k_OR_FP10_60k_OR_FP10S_30k +0x003C20 +FP10_60k ⚠️ ❌ ❌ +📟 FP10S + + - 30k -0x0020 -FP10_30k_OR_FP10_60k_OR_FP10S_30k +0x001E20 +FP10S_30k ⚠️ ❌ ❌ @@ -205,8 +192,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - 30k -0x0030 -FP10SH_30k_OR_FP10SH_60k_OR_FP10SH_120k +0x001E30 +FP10SH_30k ⚠️ ❌ ❌ @@ -214,8 +201,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - 60k -0x0030 -FP10SH_30k_OR_FP10SH_60k_OR_FP10SH_120k +0x003C30 +FP10SH_60k ⚠️ ❌ ❌ @@ -223,8 +210,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - 120k -0x0030 -FP10SH_30k_OR_FP10SH_60k_OR_FP10SH_120k +0x007830 +FP10SH_120k ⚠️ ❌ ❌ @@ -235,8 +222,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - 16k -0x0050 -FP2_16k_OR_FP2_32k +0x001050 +FP2_16k ⚠️ ❌ ❌ @@ -244,8 +231,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - 32k -0x0050 -FP2_16k_OR_FP2_32k +0x002050 +FP2_32k ⚠️ ❌ ❌ @@ -255,17 +242,8 @@ All supported PLC types for auto recognition are listed in this table. Other one - - 60k -0x0060 -FP2SH_60k -⚠️ - ✅ - ❌ - - - - 32k -0x0062 +0x002062 FP2SH_32k ⚠️ ✅ @@ -273,8 +251,17 @@ All supported PLC types for auto recognition are listed in this table. Other one - + 60k +0x003C60 +FP2SH_60k +⚠️ + ✅ + ❌ + + + - 120k -0x00E0 +0x0078E0 FP2SH_120k ⚠️ ✅ @@ -286,29 +273,17 @@ All supported PLC types for auto recognition are listed in this table. Other one - 10k -0x0003 +0x000A03 FP3_10k ⚠️ ❌ ❌ -📟 FP3, FP-C - - - 16k -0x0013 -FP3_16k_OR_FPdC_16k -⚠️ - ❌ - ❌ - - - - - 16k -0x0013 -FP3_16k_OR_FPdC_16k +0x001013 +FP3_16k ⚠️ ❌ ❌ @@ -319,7 +294,7 @@ All supported PLC types for auto recognition are listed in this table. Other one - 16k -0x0002 +0x001002 FP5_16k ⚠️ ❌ @@ -328,7 +303,7 @@ All supported PLC types for auto recognition are listed in this table. Other one - 24k -0x0012 +0x001812 FP5_24k ⚠️ ❌ @@ -338,41 +313,33 @@ All supported PLC types for auto recognition are listed in this table. Other one 📟 FP7 - CPS41E - 196k -0x0703 -FP7_196k__CPS41E - ❌ - ❌ - - - CPS31E - 120k -0x0704 -FP7_120k__CPS31E + CPS21 + 64k +0x074009 +FP7_64k__CPS21 ❌ ❌ CPS31 120k -0x0705 +0x077805 FP7_120k__CPS31 ❌ ❌ - CPS41ES - 196k -0x0706 -FP7_196k__CPS41ES + CPS31E + 120k +0x077804 +FP7_120k__CPS31E ❌ ❌ CPS31ES 120k -0x0707 +0x077807 FP7_120k__CPS31ES ❌ ❌ @@ -380,16 +347,36 @@ All supported PLC types for auto recognition are listed in this table. Other one CPS31S 120k -0x0708 +0x077808 FP7_120k__CPS31S ❌ ❌ - CPS21 - 64k -0x0709 -FP7_64k__CPS21 + CPS41E + 196k +0x07C403 +FP7_196k__CPS41E + ❌ + ❌ + + + CPS41ES + 196k +0x07C406 +FP7_196k__CPS41ES + ❌ + ❌ + + +📟 FP-C + + + - + 16k +0x001013 +FPdC_16k +⚠️ ❌ ❌ @@ -399,19 +386,49 @@ All supported PLC types for auto recognition are listed in this table. Other one - 2.7k -0x0045 +0x000045 FPde_2c7k ⚠️ ✅ ❌ +📟 FP-M + + + C16T + 0.9k +0x000004 +FPdM_0c9k__C16T +⚠️ + ❌ + ❌ + + + C20R, C20T, C32T + 2.7k +0x000005 +FPdM_2c7k__C20R_C20T_C32T +⚠️ + ❌ + ❌ + + + C20RC, C20TC, C32TC + 5k +0x000006 +FPdM_5k__C20RC_C20TC_C32TC +⚠️ + ❌ + ❌ + + 📟 FP-SIGMA - 12k -0x0043 +0x000C43 FPdSIGMA_12k ⚠️ ✅ @@ -419,8 +436,17 @@ All supported PLC types for auto recognition are listed in this table. Other one - + 16k +0x0010E1 +FPdSIGMA_16k +⚠️ + ✅ + ❌ + + + - 32k -0x0044 +0x002044 FPdSIGMA_32k ⚠️ ✅ @@ -428,18 +454,9 @@ All supported PLC types for auto recognition are listed in this table. Other one - - 16k -0x00E1 -FPdSIGMA_16k_OR_FPdSIGMA_40k -⚠️ - ✅ - ❌ - - - - 40k -0x00E1 -FPdSIGMA_16k_OR_FPdSIGMA_40k +0x0028E1 +FPdSIGMA_40k ⚠️ ✅ ❌ @@ -448,19 +465,28 @@ All supported PLC types for auto recognition are listed in this table. Other one 📟 FP-X + C40RT0A + 2.5k +0x00007A +FPdX_2c5k__C40RT0A +⚠️ + ✅ + ❌ + + C14R 16k -0x0070 +0x001070 FPdX_16k__C14R ⚠️ ✅ ✅ - C30R, C60R - 32k -0x0071 -FPdX_32k__C30R_C60R + C14T/P + 16k +0x001076 +FPdX_16k__C14TsP ⚠️ ✅ ❌ @@ -468,26 +494,17 @@ All supported PLC types for auto recognition are listed in this table. Other one L14 16k -0x0073 +0x001073 FPdX_16k__L14 ⚠️ ✅ ❌ - L30, L60 + C30R, C60R 32k -0x0074 -FPdX_32k__L30_L60 -⚠️ - ✅ - ❌ - - - C14T/P - 16k -0x0076 -FPdX_16k__C14TsP +0x002071 +FPdX_32k__C30R_C60R ⚠️ ✅ ❌ @@ -495,17 +512,17 @@ All supported PLC types for auto recognition are listed in this table. Other one C30T/P, C60T/P, C38AT, C40T 32k -0x0077 +0x002077 FPdX_32k__C30TsP_C60TsP_C38AT_C40T ⚠️ ✅ ✅ - C40RT0A - 2.5k -0x007A -FPdX_2c5k__C40RT0A + L30, L60 + 32k +0x002074 +FPdX_32k__L30_L60 ⚠️ ✅ ❌ @@ -516,7 +533,7 @@ All supported PLC types for auto recognition are listed in this table. Other one L14, L30 2.5k -0x0072 +0x000072 FPdX0_2c5k__L14_L30 ⚠️ ✅ @@ -525,7 +542,7 @@ All supported PLC types for auto recognition are listed in this table. Other one L40, L60 8k -0x0075 +0x000875 FPdX0_8k__L40_L60 ⚠️ ✅ @@ -534,7 +551,7 @@ All supported PLC types for auto recognition are listed in this table. Other one L40, L60 16k -0x007F +0x00107F FPdX0_16k__L40_L60 ⚠️ ✅ @@ -546,31 +563,31 @@ All supported PLC types for auto recognition are listed in this table. Other one C14R 16k -0x00A0 +0x0010A0 FPdXH_16k__C14R ✅ ✅ - C30R, C40R, C60R - 32k -0x00A1 -FPdXH_32k__C30R_C40R_C60R + C14T/P + 16k +0x0010A4 +FPdXH_16k__C14TsP ✅ ❌ - C14T/P - 16k -0x00A4 -FPdXH_16k__C14TsP + C30R, C40R, C60R + 32k +0x0020A1 +FPdXH_32k__C30R_C40R_C60R ✅ ❌ C30T/P, C40T, C60T/P 32k -0x00A5 +0x0020A5 FPdXH_32k__C30TsP_C40T_C60TsP ✅ ✅ @@ -578,39 +595,15 @@ All supported PLC types for auto recognition are listed in this table. Other one C38AT 32k -0x00A7 +0x0020A7 FPdXH_32k__C38AT ✅ ❌ - M4T/L - 32k -0x00A8 -FPdXH_32k__M4TsL - ✅ - ❌ - - - M8N16T/P - 32k -0x00AC -FPdXH_32k__M8N16TsP - ✅ - ❌ - - - M8N30T - 32k -0x00AD -FPdXH_32k__M8N30T - ✅ - ❌ - - C40ET, C60ET 32k -0x00AE +0x0020AE FPdXH_32k__C40ET_C60ET ✅ ❌ @@ -618,11 +611,35 @@ All supported PLC types for auto recognition are listed in this table. Other one C60ETF 32k -0x00AF +0x0020AF FPdXH_32k__C60ETF ✅ ❌ + + M4T/L + 32k +0x0020A8 +FPdXH_32k__M4TsL + ✅ + ❌ + + + M8N16T/P + 32k +0x0020AC +FPdXH_32k__M8N16TsP + ✅ + ❌ + + + M8N30T + 32k +0x0020AD +FPdXH_32k__M8N30T + ✅ + ❌ + diff --git a/DocBuilder/Docs/reverse_engineering_data.md b/AutoTools.DocBuilder/Docs/reverse_engineering_data.md similarity index 69% rename from DocBuilder/Docs/reverse_engineering_data.md rename to AutoTools.DocBuilder/Docs/reverse_engineering_data.md index 7d17094..46629e4 100644 --- a/DocBuilder/Docs/reverse_engineering_data.md +++ b/AutoTools.DocBuilder/Docs/reverse_engineering_data.md @@ -47,27 +47,6 @@ | 1604 | System register size | 96230000001480004 | ? -### %EE$EX00RT with error - -|Reponse Byte|Description| -|------------|-----------| -| 00 | Extended mode -| 32 | Data item count -| 70 | Machine type -| 00 | Version (Fixed to 00) -| 16 | Prog capacity in K -| 81 | Operation mode / status -| 00 | Link unit -| 60 | Error flag -| 0000 | Self diag error -| 50 | Version -| 02 | Hardware information -| 0 | Number of programs -| 4100 | Program size BCD -| 1600 | Header size (no. of words) bcd -| 1604 | System register size -| 96230000001480004 | ? - What are the last bytes? FP-X 16k C14R @@ -96,6 +75,76 @@ FP-XH 16k C14R | 60 | Error flag | | 0000 | Self diag error | +## FP-X0 2.5k L14,L30 + +### %EE$RT + +|Reponse Byte|Description| +|------------|-----------| +| 72 | Model code | +| 12 | Version | +| 02 | Prog capacity | +| 82 | Op mode | +| 00 | Link unit | +| 00 | Error flag | +| 0000 | Self diag error | + +### %EE$EX00RT + +|Reponse Byte|Description| +|------------|-----------| +| 00 | Extended mode +| 32 | Data item count +| 72 | Machine type +| 00 | Version (Fixed to 00) +| 02 | Prog capacity in K +| 82 | Operation mode / status +| 00 | Link unit +| 00 | Error flag +| 0000 | Self diag error +| 23 | Version +| 01 | Hardware information +| 0 | Number of programs +| 4100 | Program size BCD +| 0301 | Header size (no. of words) bcd +| 2819 | System register size +| 0000001480004 | ? + +## FP0 2.7k C10,C14 + +### %EE$RT + +|Reponse Byte|Description| +|------------|-----------| +| 05 | Model code | +| 12 | Version | +| 03 | Prog capacity | +| 82 | Op mode | +| 00 | Link unit | +| 00 | Error flag | +| 0000 | Self diag error | + +### %EE$EX00RT + +|Reponse Byte|Description| +|------------|-----------| +| 00 | Extended mode +| 32 | Data item count +| 40 | Machine type +| 00 | Version (Fixed to 00) +| 03 | Prog capacity in K +| 82 | Operation mode / status +| 00 | Link unit +| 00 | Error flag +| 0000 | Self diag error +| 23 | Version +| 01 | Hardware information +| 0 | Number of programs +| 4100 | Program size BCD +| 0301 | Header size (no. of words) bcd +| 2819 | System register size +| 20130000080070004 | ? + # Mewtocol-7 Com ## Getting the status of the plc diff --git a/DocBuilder/Program.cs b/AutoTools.DocBuilder/Program.cs similarity index 52% rename from DocBuilder/Program.cs rename to AutoTools.DocBuilder/Program.cs index fb0a63c..a884180 100644 --- a/DocBuilder/Program.cs +++ b/AutoTools.DocBuilder/Program.cs @@ -16,34 +16,30 @@ Console.WriteLine("Building docs for PLC types..."); var entryLoc = Assembly.GetEntryAssembly(); ArgumentNullException.ThrowIfNull(entryLoc); -string filePath = null!; +string filePath = null!; -if(args.Length == 0) { +if (args.Length == 0) { filePath = Path.Combine(entryLoc.Location, @"..\..\..\..\Docs\plctypes.md"); - + } else { - filePath = args[0]; + filePath = args[0]; } Console.WriteLine($"{filePath}"); -StringBuilder markdownBuilder = new StringBuilder(); +StringBuilder markdownBuilder = new StringBuilder(); -var plcs = Enum.GetValues(typeof(PlcType)).Cast().OrderBy(x => x.ToString()); +var plcNames = Enum.GetNames().OrderBy(x => x).ToArray(); -void WritePlcTypeTable(IEnumerable vals) { +void WritePlcTypeTable(string[] names) { - var groups = vals.GroupBy(x => x.ToNameDecompose()[0].Group) - .SelectMany(grouping => grouping.OrderBy(b => (int)b)) - .GroupBy( - x => string.Join(", ", - x.ToNameDecompose() - .DistinctBy(y => y.Group) - .Select(y => y.Group)) - ); + var groups = names.Select(x => x.ToNameDecompose()) + .GroupBy(x => x.Group) + .SelectMany(g => g.OrderBy(x => x.Size)) + .GroupBy(x => x.Group); markdownBuilder.AppendLine(""); @@ -51,19 +47,16 @@ void WritePlcTypeTable(IEnumerable vals) { foreach (var group in groups) { - group.OrderBy(x => (int)x); + group.OrderBy(x => x.TypeCode); bool isFirstGroup = true; foreach (var enu in group) { - ParsedPlcName[] decomposed = null!; string cpuOrMachCode = null!; - decomposed = enu.ToNameDecompose(); - - cpuOrMachCode = ((int)enu).ToString("X4"); - ArgumentNullException.ThrowIfNull(decomposed); + cpuOrMachCode = enu.TypeCode.ToString("X6"); + ArgumentNullException.ThrowIfNull(enu); //first iteration if (isFirstIt) { @@ -84,7 +77,7 @@ void WritePlcTypeTable(IEnumerable vals) { } - if(isFirstGroup) { + if (isFirstGroup) { markdownBuilder.AppendLine(""); @@ -96,32 +89,28 @@ void WritePlcTypeTable(IEnumerable vals) { } - foreach (var decomp in decomposed) { + markdownBuilder.AppendLine(""); - markdownBuilder.AppendLine(""); + markdownBuilder.AppendLine($""); + markdownBuilder.AppendLine($""); + markdownBuilder.AppendLine($""); - markdownBuilder.AppendLine($""); - markdownBuilder.AppendLine($""); - markdownBuilder.AppendLine($""); - - if(enu.IsDiscontinued()) { + if (enu.IsDiscontinuedModel) { - markdownBuilder.AppendLine($""); - markdownBuilder.AppendLine($""); + markdownBuilder.AppendLine($""); + markdownBuilder.AppendLine($""); - } else { + } else { - markdownBuilder.AppendLine($""); - - } - - markdownBuilder.AppendLine($""); - markdownBuilder.AppendLine($""); - - markdownBuilder.AppendLine(""); + markdownBuilder.AppendLine($""); } + markdownBuilder.AppendLine($""); + markdownBuilder.AppendLine($""); + + markdownBuilder.AppendLine(""); + } @@ -135,8 +124,20 @@ void WritePlcTypeTable(IEnumerable vals) { } markdownBuilder.AppendLine($"# PLC Type Table"); -markdownBuilder.AppendLine($"All supported PLC types for auto recognition are listed in this table. " + - $"Other ones might also be supported but are shown as unknown in the library"); +markdownBuilder.AppendLine($"Auto Generated @ **{DateTime.Now.ToUniversalTime().ToString("u", CultureInfo.InvariantCulture)}**\n"); +markdownBuilder.AppendLine( +$"All supported PLC types for auto recognition are listed in this table. " + +$"Other ones might also be supported but are shown as unknown in the library. " + +$"Some models are never uniquely identifiable by their typecode and need extra hints like Prog Capacity in EXRT or RT. \n\n" + +$"Typecode explained:\n" + +$"```\n" + +$"From left to right\n" + +$"0x\n" + +$"07 <= extended code (00 non mewtocol 7 devices)\n" + +$"20 <= Is hex for 32 (Prog capacity)\n" + +$"A5 <= Is the actual typecode, can overlap with others\n" + +$"```" +); markdownBuilder.AppendLine($"> Discontinued PLCs
"); markdownBuilder.AppendLine($"> These are PLCs that are no longer sold by Panasonic. Marked with ⚠️\n"); @@ -144,6 +145,6 @@ markdownBuilder.AppendLine($"> These are PLCs that are no longer sold by Panason markdownBuilder.AppendLine($"> EXRT PLCs
"); markdownBuilder.AppendLine($"> These are PLCs that utilize the basic `%EE#RT` and `%EE#EX00RT` command. All newer models do this. Old models only use the `%EE#RT` command.\n"); -WritePlcTypeTable(plcs); +WritePlcTypeTable(plcNames); File.WriteAllText(filePath, markdownBuilder.ToString()); \ No newline at end of file diff --git a/DocBuilder/DocBuilder.csproj b/DocBuilder/DocBuilder.csproj deleted file mode 100644 index c2b9011..0000000 --- a/DocBuilder/DocBuilder.csproj +++ /dev/null @@ -1,18 +0,0 @@ - - - - - false - false - Exe - net6.0 - enable - enable - - - - - - - - diff --git a/Examples.BasicEthernet/Program.cs b/Examples.BasicEthernet/Program.cs index cb3d1f3..e201899 100644 --- a/Examples.BasicEthernet/Program.cs +++ b/Examples.BasicEthernet/Program.cs @@ -13,8 +13,7 @@ internal class Program { static async Task AsyncMain () { //the library provides a logging tool, comment this out if needed - Logger.LogLevel = LogLevel.Verbose; - Logger.OnNewLogMessage((d, l, m) => Console.WriteLine($"{d}: {m}")); + Logger.LogLevel = LogLevel.Critical; //create a new interface to the plc using ethernet / tcp ip //the using keyword is optional, if you want to use your PLC instance @@ -58,6 +57,11 @@ internal class Program { plc.ConfigureConnection("192.168.115.212", 9094); await plc.ConnectAsync(); + plc.Disconnect(); + + plc.ConfigureConnection("192.168.115.214", 9094); + await plc.ConnectAsync(); + } //you can also find any applicable source endpoints by using: diff --git a/Examples.BasicRegisterReadWrite/Program.cs b/Examples.BasicRegisterReadWrite/Program.cs index 2cdff82..723ac56 100644 --- a/Examples.BasicRegisterReadWrite/Program.cs +++ b/Examples.BasicRegisterReadWrite/Program.cs @@ -6,7 +6,8 @@ namespace Examples.BasicRegisterReadWrite; internal class Program { - const string PLC_IP = "192.168.178.55"; + //const string PLC_IP = "192.168.178.55"; + const string PLC_IP = "192.168.115.210"; static void Main(string[] args) => Task.Run(AsyncMain).Wait(); @@ -54,6 +55,8 @@ internal class Program { //a simple 2 dimensional ARRAY [0..2, 0..2] OF INT at DT2003 b.Struct("DT2003").AsArray(3, 3).Build(out simpleNumberRegister2Dim); + b.Struct("R19A").Build(); + }) .Build(); diff --git a/MewtocolNet.sln b/MewtocolNet.sln index 8a98cbe..8a191a0 100644 --- a/MewtocolNet.sln +++ b/MewtocolNet.sln @@ -7,17 +7,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolNet", "MewtocolNet\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewtocolTests", "MewtocolTests\MewtocolTests.csproj", "{C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DocBuilder", "DocBuilder\DocBuilder.csproj", "{50F2D23F-C875-4006-A0B6-7F5A181BC944}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MewTerminal", "MewTerminal\MewTerminal.csproj", "{D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{323729B0-5FB2-4592-9FA6-220C46BBF84C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.BasicEthernet", "Examples.BasicEthernet\Examples.BasicEthernet.csproj", "{80806065-163D-43F3-90CD-9221F391793F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.BasicRegisterReadWrite", "Examples.BasicRegisterReadWrite\Examples.BasicRegisterReadWrite.csproj", "{A24444C8-691D-44CB-8DE8-19618C6DE94B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.BasicRegisterReadWrite", "Examples.BasicRegisterReadWrite\Examples.BasicRegisterReadWrite.csproj", "{A24444C8-691D-44CB-8DE8-19618C6DE94B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.Polling", "Examples.Polling\Examples.Polling.csproj", "{9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.Polling", "Examples.Polling\Examples.Polling.csproj", "{9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AutoTools", "AutoTools", "{BAEF983A-EFF2-48DF-A74E-57084166BB4D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTools.ChmDataExtract", "AutoTools.ChmDataExtract\AutoTools.ChmDataExtract.csproj", "{5A9DE453-AD64-4F8D-8215-3BB26674D164}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AutoTools.DocBuilder", "AutoTools.DocBuilder\AutoTools.DocBuilder.csproj", "{00ACA0AB-3988-4EF7-98A6-B39A36B136DA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -53,18 +57,6 @@ Global {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Release|x64.Build.0 = Release|Any CPU {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Release|x86.ActiveCfg = Release|Any CPU {C1BF3AB0-CDFE-4070-A759-C3B25A20ABE1}.Release|x86.Build.0 = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|Any CPU.Build.0 = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|x64.ActiveCfg = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|x64.Build.0 = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|x86.ActiveCfg = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Debug|x86.Build.0 = Debug|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|Any CPU.ActiveCfg = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|Any CPU.Build.0 = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|x64.ActiveCfg = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|x64.Build.0 = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|x86.ActiveCfg = Release|Any CPU - {50F2D23F-C875-4006-A0B6-7F5A181BC944}.Release|x86.Build.0 = Release|Any CPU {D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}.Debug|Any CPU.Build.0 = Debug|Any CPU {D1E751C6-296F-4CF1-AE28-C6D4388C7CF1}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -113,6 +105,30 @@ Global {9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61}.Release|x64.Build.0 = Release|Any CPU {9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61}.Release|x86.ActiveCfg = Release|Any CPU {9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61}.Release|x86.Build.0 = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|x64.ActiveCfg = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|x64.Build.0 = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|x86.ActiveCfg = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Debug|x86.Build.0 = Debug|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|Any CPU.Build.0 = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|x64.ActiveCfg = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|x64.Build.0 = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|x86.ActiveCfg = Release|Any CPU + {5A9DE453-AD64-4F8D-8215-3BB26674D164}.Release|x86.Build.0 = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|x64.ActiveCfg = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|x64.Build.0 = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|x86.ActiveCfg = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Debug|x86.Build.0 = Debug|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|Any CPU.Build.0 = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|x64.ActiveCfg = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|x64.Build.0 = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|x86.ActiveCfg = Release|Any CPU + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -121,6 +137,8 @@ Global {80806065-163D-43F3-90CD-9221F391793F} = {323729B0-5FB2-4592-9FA6-220C46BBF84C} {A24444C8-691D-44CB-8DE8-19618C6DE94B} = {323729B0-5FB2-4592-9FA6-220C46BBF84C} {9A36F2B1-FF9E-47BF-9931-3D3EB3C46B61} = {323729B0-5FB2-4592-9FA6-220C46BBF84C} + {5A9DE453-AD64-4F8D-8215-3BB26674D164} = {BAEF983A-EFF2-48DF-A74E-57084166BB4D} + {00ACA0AB-3988-4EF7-98A6-B39A36B136DA} = {BAEF983A-EFF2-48DF-A74E-57084166BB4D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {4ABB8137-CD8F-4691-9802-9ED371012F47} diff --git a/MewtocolNet/Helpers/MewtocolHelpers.cs b/MewtocolNet/Helpers/MewtocolHelpers.cs index 78d3844..48e41a5 100644 --- a/MewtocolNet/Helpers/MewtocolHelpers.cs +++ b/MewtocolNet/Helpers/MewtocolHelpers.cs @@ -230,27 +230,27 @@ namespace MewtocolNet { /// /// Checks if the register type is boolean /// - internal static bool IsBoolean(this RegisterType type) { + internal static bool IsBoolean(this RegisterPrefix type) { - return type == RegisterType.X || type == RegisterType.Y || type == RegisterType.R; + return type == RegisterPrefix.X || type == RegisterPrefix.Y || type == RegisterPrefix.R; } /// /// Checks if the register type numeric /// - internal static bool IsNumericDTDDT(this RegisterType type) { + internal static bool IsNumericDTDDT(this RegisterPrefix type) { - return type == RegisterType.DT || type == RegisterType.DDT; + return type == RegisterPrefix.DT || type == RegisterPrefix.DDT; } /// /// Checks if the register type is an physical in or output of the plc /// - internal static bool IsPhysicalInOutType(this RegisterType type) { + internal static bool IsPhysicalInOutType(this RegisterPrefix type) { - return type == RegisterType.X || type == RegisterType.Y; + return type == RegisterPrefix.X || type == RegisterPrefix.Y; } @@ -299,18 +299,29 @@ namespace MewtocolNet { if (plcT == 0) return "Unknown"; - return string.Join(" or ", ParsedPlcName.PlcDeconstruct(plcT).Select(x => x.WholeName)); + if(!Enum.IsDefined(typeof(PlcType), plcT)) return "Unknown"; + + return ParsedPlcName.PlcDeconstruct(plcT.ToString()).ToString(); } /// /// Converts the enum to a decomposed struct /// - public static ParsedPlcName[] ToNameDecompose(this PlcType plcT) { + public static ParsedPlcName ToNameDecompose(this PlcType plcT) { - if ((int)plcT == 0) return Array.Empty(); + if ((int)plcT == 0) + throw new NotSupportedException("No plc type found"); - return ParsedPlcName.PlcDeconstruct(plcT); + if (!Enum.IsDefined(typeof(PlcType), plcT)) return null; + + return ParsedPlcName.PlcDeconstruct(plcT.ToString()); + + } + + internal static ParsedPlcName ToNameDecompose(this string plcEnumString) { + + return ParsedPlcName.PlcDeconstruct(plcEnumString); } diff --git a/MewtocolNet/Helpers/ParsedPlcName.cs b/MewtocolNet/Helpers/ParsedPlcName.cs index b2c8a2c..d24f395 100644 --- a/MewtocolNet/Helpers/ParsedPlcName.cs +++ b/MewtocolNet/Helpers/ParsedPlcName.cs @@ -9,7 +9,7 @@ namespace MewtocolNet { /// /// A structure containing the PLC name parsed /// - public struct ParsedPlcName { + public class ParsedPlcName { /// /// Whole name of the PLC @@ -31,51 +31,75 @@ namespace MewtocolNet { /// public string[] SubTypes { get; internal set; } + /// + /// Typecode of the parsed string + /// + public int TypeCode { get; internal set; } + + /// + /// The encoded name, same as enum name + /// + public string EncodedName { get; internal set; } + + /// + /// True if the model is discontinued + /// + public bool IsDiscontinuedModel { get; internal set; } + + internal bool WasTestedLive { get; set; } + + internal bool UsesEXRT { get; set; } + /// public override string ToString() => WholeName; - internal static ParsedPlcName[] PlcDeconstruct(PlcType plcT) { + internal static ParsedPlcName PlcDeconstruct(string wholeStr) { - string wholeStr = plcT.ToString(); - - var split = wholeStr.Replace("_OR_", "|").Split('|'); var reg = new Regex(@"(?[A-Za-z0-9]*)_(?[A-Za-z0-9]*)(?:__)?(?.*)"); + var match = reg.Match(wholeStr); - var retList = new List(); + if (match.Success) { - foreach (var item in split) { + string groupStr = SanitizePlcEncodedString(match.Groups["group"].Value); + string sizeStr = SanitizePlcEncodedString(match.Groups["size"].Value); + float sizeFl = float.Parse(sizeStr.Replace("k", ""), NumberStyles.Float, CultureInfo.InvariantCulture); + string additionalStr = match.Groups["additional"].Value; + string[] subTypes = additionalStr.Split('_').Select(x => SanitizePlcEncodedString(x)).ToArray(); - var match = reg.Match(item); + string wholeName = $"{groupStr} {sizeFl:0.##}k{(subTypes.Length > 0 ? " " : "")}{string.Join(",", subTypes)}"; - if (match.Success) { + if (string.IsNullOrEmpty(subTypes[0])) + subTypes = Array.Empty(); - string groupStr = SanitizePlcEncodedString(match.Groups["group"].Value); - string sizeStr = SanitizePlcEncodedString(match.Groups["size"].Value); - float sizeFl = float.Parse(sizeStr.Replace("k", ""), NumberStyles.Float, CultureInfo.InvariantCulture); - string additionalStr = match.Groups["additional"].Value; - string[] subTypes = additionalStr.Split('_').Select(x => SanitizePlcEncodedString(x)).ToArray(); + int typeCode = 999; + bool discontinued = false, exrt = false, tested = false; + + if(Enum.TryParse(wholeStr, out PlcType t)) { - string wholeName = $"{groupStr} {sizeFl:0.##}k{(subTypes.Length > 0 ? " " : "")}{string.Join(",", subTypes)}"; - - if (string.IsNullOrEmpty(subTypes[0])) - subTypes = Array.Empty(); - - retList.Add(new ParsedPlcName { - Group = groupStr, - Size = sizeFl, - SubTypes = subTypes, - WholeName = wholeName, - }); - - } else { - - throw new FormatException($"The plc enum was not formatted correctly: {item}"); + typeCode = (int)t; + discontinued = t.IsDiscontinued(); + exrt = t.IsEXRTPLC(); + tested = t.WasTestedLive(); } - } + return new ParsedPlcName { + Group = groupStr, + Size = sizeFl, + SubTypes = subTypes, + WholeName = wholeName, + EncodedName = wholeStr, + TypeCode = typeCode, + IsDiscontinuedModel = discontinued, + UsesEXRT = exrt, + WasTestedLive = tested, + }; - return retList.ToArray(); + } else { + + throw new FormatException($"The plc enum was not formatted correctly: {wholeStr}"); + + } } diff --git a/MewtocolNet/MewtocolNet.csproj b/MewtocolNet/MewtocolNet.csproj index 7a357ce..cca51a0 100644 --- a/MewtocolNet/MewtocolNet.csproj +++ b/MewtocolNet/MewtocolNet.csproj @@ -33,7 +33,7 @@ - <_Parameter1>DocBuilder + <_Parameter1>AutoTools.DocBuilder diff --git a/MewtocolNet/PLCInfo.cs b/MewtocolNet/PLCInfo.cs index e32ea34..adbaf6c 100644 --- a/MewtocolNet/PLCInfo.cs +++ b/MewtocolNet/PLCInfo.cs @@ -1,5 +1,7 @@ -using System.ComponentModel; +using System; +using System.ComponentModel; using System.Globalization; +using System.Linq; using System.Runtime.CompilerServices; using System.Text.RegularExpressions; @@ -38,7 +40,7 @@ namespace MewtocolNet { /// /// Program capacity in 1K steps /// - public int ProgramCapacity { get; internal set; } + public float ProgramCapacity { get; internal set; } /// /// Version of the cpu @@ -94,9 +96,11 @@ namespace MewtocolNet { if (match.Success) { byte typeCodeByte = byte.Parse(match.Groups["mc"].Value, NumberStyles.HexNumber); + var overWriteBytes = BitConverter.GetBytes((int)this.TypeCode); + overWriteBytes[0] = typeCodeByte; - this.TypeCode = (PlcType)typeCodeByte; - this.CpuVersion = match.Groups["ver"].Value; + this.TypeCode = (PlcType)BitConverter.ToInt32(overWriteBytes, 0); + this.CpuVersion = match.Groups["ver"].Value.Insert(1, "."); this.HardwareInformation = (HWInformation)byte.Parse(match.Groups["hwif"].Value, NumberStyles.HexNumber); return true; @@ -114,11 +118,27 @@ namespace MewtocolNet { if (match.Success) { byte typeCodeByte = byte.Parse(match.Groups["cputype"].Value, NumberStyles.HexNumber); + byte capacity = byte.Parse(match.Groups["cap"].Value, NumberStyles.Number); + var typeCodeFull = (PlcType)BitConverter.ToInt32(new byte[] { typeCodeByte, capacity, 0, 0}, 0); + + float definedProgCapacity = 0; + var composedNow = typeCodeFull.ToNameDecompose(); + + if (composedNow != null) { + + //already recognized the type code, use the capacity value encoded in the enum + definedProgCapacity = composedNow.Size; + + } else { + + definedProgCapacity = int.Parse(match.Groups["cap"].Value); + + } inf = new PLCInfo { - TypeCode = (PlcType)typeCodeByte, - CpuVersion = match.Groups["cpuver"].Value, - ProgramCapacity = int.Parse(match.Groups["cap"].Value), + TypeCode = typeCodeFull, + CpuVersion = match.Groups["cpuver"].Value.Insert(1, "."), + ProgramCapacity = definedProgCapacity, SelfDiagnosticError = match.Groups["sdiag"].Value, OperationMode = (OPMode)byte.Parse(match.Groups["op"].Value, NumberStyles.HexNumber), }; diff --git a/MewtocolNet/PublicEnums/PlcType.cs b/MewtocolNet/PublicEnums/PlcType.cs index 5f92a92..2b0965a 100644 --- a/MewtocolNet/PublicEnums/PlcType.cs +++ b/MewtocolNet/PublicEnums/PlcType.cs @@ -7,9 +7,16 @@ namespace MewtocolNet { //MISSING! FP7 and EcoLogix + // Byte layout explained: + // PLCs that are identifiable by just one byte have just one byte as their code 0x00 + // PLCs that are not identifiable by just one byte and also need a prog size param to identfy use the second byte for capacity 0x32_00 => 32k of type 00 + // PLCs that use the mewtocol 7 identifcation method (currently only fp7 and EL500) use the third byte for their inital identifier (07 for fp7) => 0x07_00_09 + // Sometimes the type is no directly identifable, then two types share the same code and make logically no difference + + //special codes for mem size are: 02 = 2.5k, 03 = 2.7k + /// - /// The type of the PLC. Plcs that don't use the Mewtocol-7-Com protocol have only 2 hex digits, - /// All newer ones have 4 hex digits where the first byte defines the series type + /// Type identifier of the plc /// public enum PlcType { @@ -19,25 +26,29 @@ namespace MewtocolNet { /// FP5 16k /// [PlcLegacy] - FP5_16k = 0x02, + FP5_16k = 0x10_02, /// /// FP5 24k /// [PlcLegacy] - FP5_24k = 0x12, + FP5_24k = 0x18_12, #endregion #region FP2 Family (Legacy) /// - /// FP2 16k OR FP2 32k + /// FP2 16k /// [PlcLegacy] - FP2_16k_OR_FP2_32k = 0x50, + FP2_16k = 0x10_50, - //misses entry FP2 32k + /// + /// FP2 32k + /// + [PlcLegacy] + FP2_32k = 0x20_50, #endregion @@ -47,54 +58,92 @@ namespace MewtocolNet { /// FP3 10k /// [PlcLegacy] - FP3_10k = 0x03, + FP3_10k = 0x0A_03, /// - /// FP3 or FP-C 16k + /// FP-C 16k /// [PlcLegacy] - FP3_16k_OR_FPdC_16k = 0x13, - + FPdC_16k = 0x10_13, + /// + /// FP3 + /// + [PlcLegacy] + FP3_16k = FPdC_16k, + #endregion #region FP1 / FPM Family (Legacy) /// - /// FP1 0.9k C14,C16 or FP-M 0.9k C16T + /// FP1 0.9k C14,C16 /// [PlcLegacy] - FP1_0c9k__C14_C16_OR_FPdM_0c9k__C16T = 0x04, + FP1_0c9k__C14_C16 = 0x00_04, /// - /// FP1 2.7k C24,C40 or FP-M 2.7k C20R,C20T,C32T + /// FP-M 0.9k C16T /// [PlcLegacy] - FP1_2c7k__C24_C40_OR_FPdM_2c7k__C20R_C20T_C32T = 0x05, + FPdM_0c9k__C16T = FP1_0c9k__C14_C16, /// - /// FP1 5.0k C56,C72 or FPM 5k C20RC,C20TC,C32TC + /// FP1 2.7k C24,C40 /// [PlcLegacy] - FP1_5k__C56_C72_OR_FPdM_5k__C20RC_C20TC_C32TC = 0x06, + FP1_2c7k__C24_C40 = 0x03_05, + /// + /// FP-M 2.7k C20R,C20T,C32T + /// + [PlcLegacy] + FPdM_2c7k__C20R_C20T_C32T = FP1_2c7k__C24_C40, + /// + /// FP1 5.0k C56,C72 + /// + [PlcLegacy] + FP1_5k__C56_C72 = 0x00_06, + /// + /// FPM 5.0k C20RC,C20TC,C32TC + /// + [PlcLegacy] + FPdM_5k__C20RC_C20TC_C32TC = FP1_5k__C56_C72, #endregion #region FP10 Family (Legacy) /// - /// FP10 30k,60k OR FP10S 30k + /// FP10S 30k /// [PlcLegacy] - FP10_30k_OR_FP10_60k_OR_FP10S_30k = 0x20, - - //misses entry FP10 60k + FP10S_30k = 0x1E_20, + /// + /// FP10 30k + /// + [PlcLegacy] + FP10_30k = FP10S_30k, + /// + /// FP10 60k + /// + [PlcLegacy] + FP10_60k = 0x3C_20, #endregion #region FP10SH Family (Legacy) /// - /// FP10SH 30k, 60k, 120k + /// FP10SH 30k /// [PlcLegacy] - FP10SH_30k_OR_FP10SH_60k_OR_FP10SH_120k = 0x30, + FP10SH_30k = 0x1E_30, + /// + /// FP10SH 60k + /// + [PlcLegacy] + FP10SH_60k = 0x3C_30, + /// + /// FP10SH 120k + /// + [PlcLegacy] + FP10SH_120k = 0x78_30, #endregion @@ -104,17 +153,17 @@ namespace MewtocolNet { /// FP0 2.7k C10,C14,C16 /// [PlcLegacy] - FP0_2c7k__C10_C14_C16 = 0x40, + FP0_2c7k__C10_C14_C16 = 0x03_40, /// /// FP0 5k /// [PlcLegacy] - FP0_5k__C32_SL1 = 0x41, + FP0_5k__C32_SL1 = 0x00_41, /// /// FP0 10k /// [PlcLegacy] - FP0_10c0k__T32 = 0x42, + FP0_10c0k__T32 = 0x0A_42, #endregion @@ -124,17 +173,22 @@ namespace MewtocolNet { /// FP-SIGMA 12k /// [PlcLegacy, PlcEXRT] - FPdSIGMA_12k = 0x43, + FPdSIGMA_12k = 0x0C_43, /// /// FP-SIGMA 32k /// [PlcLegacy, PlcEXRT] - FPdSIGMA_32k = 0x44, + FPdSIGMA_32k = 0x20_44, /// - /// FP-SIGMA 16k or FP-SIGMA 40k + /// FP-SIGMA 16k /// [PlcLegacy, PlcEXRT] - FPdSIGMA_16k_OR_FPdSIGMA_40k = 0xE1, + FPdSIGMA_16k = 0x10_E1, + /// + /// FP-SIGMA 40k (never supported) + /// + [PlcLegacy, PlcEXRT] + FPdSIGMA_40k = 0x28_E1, #endregion @@ -144,7 +198,7 @@ namespace MewtocolNet { /// FP-e 2.7k /// [PlcLegacy, PlcEXRT] - FPde_2c7k = 0x45, + FPde_2c7k = 0x03_45, #endregion @@ -159,37 +213,37 @@ namespace MewtocolNet { /// FP0R 32k C32 /// [PlcEXRT] - FP0R_32k__C32 = 0x47, + FP0R_32k__C32 = 0x20_47, /// /// FP0R 32k T32 /// [PlcEXRT] - FP0R_32k__T32 = 0x48, + FP0R_32k__T32 = 0x20_48, /// /// FP0R 32k F32 /// [PlcEXRT] - FP0R_32k__F32 = 0x49, + FP0R_32k__F32 = 0x20_49, #endregion #region FP2SH Family (Legacy) - /// - /// FP2SH 60k - /// - [PlcLegacy, PlcEXRT] - FP2SH_60k = 0x60, /// /// FP2SH 32k /// [PlcLegacy, PlcEXRT] - FP2SH_32k = 0x62, + FP2SH_32k = 0x20_62, + /// + /// FP2SH 60k + /// + [PlcLegacy, PlcEXRT] + FP2SH_60k = 0x3C_60, /// /// FP2SH 120k /// [PlcLegacy, PlcEXRT] - FP2SH_120k = 0xE0, + FP2SH_120k = 0x78_E0, #endregion @@ -199,52 +253,52 @@ namespace MewtocolNet { /// FP-X 16k C14R /// [PlcLegacy, PlcEXRT, PlcCodeTested] - FPdX_16k__C14R = 0x70, + FPdX_16k__C14R = 0x10_70, /// /// FP-X 32k C30R,C60R /// [PlcLegacy, PlcEXRT] - FPdX_32k__C30R_C60R = 0x71, + FPdX_32k__C30R_C60R = 0x20_71, /// /// FP-X0 2.5k L14,L30 /// [PlcLegacy, PlcEXRT] - FPdX0_2c5k__L14_L30 = 0x72, + FPdX0_2c5k__L14_L30 = 0x02_72, /// /// FP-X 16k L14 /// [PlcLegacy, PlcEXRT] - FPdX_16k__L14 = 0x73, + FPdX_16k__L14 = 0x10_73, /// /// FP-X 32k L30,L60 /// [PlcLegacy, PlcEXRT] - FPdX_32k__L30_L60 = 0x74, + FPdX_32k__L30_L60 = 0x20_74, /// /// FP-X0 8k L40,L60 /// [PlcLegacy, PlcEXRT] - FPdX0_8k__L40_L60 = 0x75, + FPdX0_8k__L40_L60 = 0x08_75, /// /// FP-X 16k C14T/P /// [PlcLegacy, PlcEXRT] - FPdX_16k__C14TsP = 0x76, + FPdX_16k__C14TsP = 0x10_76, /// /// FP-X 32k C30T/P,C60T/P,C38AT,C40T /// [PlcLegacy, PlcEXRT, PlcCodeTested] - FPdX_32k__C30TsP_C60TsP_C38AT_C40T = 0x77, + FPdX_32k__C30TsP_C60TsP_C38AT_C40T = 0x20_77, /// /// FP-X 2.5k C40RT0A /// [PlcLegacy, PlcEXRT] - FPdX_2c5k__C40RT0A = 0x7A, + FPdX_2c5k__C40RT0A = 0x02_7A, /// /// FP-X0 16k L40,L60 /// [PlcLegacy, PlcEXRT] - FPdX0_16k__L40_L60 = 0x7F, + FPdX0_16k__L40_L60 = 0x10_7F, #endregion @@ -254,52 +308,52 @@ namespace MewtocolNet { /// FP-XH 16k C14R /// [PlcEXRT, PlcCodeTested] - FPdXH_16k__C14R = 0xA0, + FPdXH_16k__C14R = 0x10_A0, /// /// FP-XH 32k C30R,C40R,C60R /// [PlcEXRT] - FPdXH_32k__C30R_C40R_C60R = 0xA1, + FPdXH_32k__C30R_C40R_C60R = 0x20_A1, /// /// FP-XH 16k C14T/P /// [PlcEXRT] - FPdXH_16k__C14TsP = 0xA4, + FPdXH_16k__C14TsP = 0x10_A4, /// /// FP-XH 32k C30T/P,C40T,C60T/P /// [PlcEXRT, PlcCodeTested] - FPdXH_32k__C30TsP_C40T_C60TsP = 0xA5, + FPdXH_32k__C30TsP_C40T_C60TsP = 0x20_A5, /// /// FP-XH 32k C38AT /// [PlcEXRT] - FPdXH_32k__C38AT = 0xA7, + FPdXH_32k__C38AT = 0x20_A7, /// /// FP-XH 32k M4T/L /// [PlcEXRT] - FPdXH_32k__M4TsL = 0xA8, + FPdXH_32k__M4TsL = 0x20_A8, /// /// FP-XH 32k M8N16T/P (RTEX) /// [PlcEXRT] - FPdXH_32k__M8N16TsP = 0xAC, + FPdXH_32k__M8N16TsP = 0x20_AC, /// /// FP-XH 32k M8N30T (RTEX) /// [PlcEXRT] - FPdXH_32k__M8N30T = 0xAD, + FPdXH_32k__M8N30T = 0x20_AD, /// /// FP-XH 32k C40ET,C60ET /// [PlcEXRT] - FPdXH_32k__C40ET_C60ET = 0xAE, + FPdXH_32k__C40ET_C60ET = 0x20_AE, /// /// FP-XH 32k C60ETF /// [PlcEXRT] - FPdXH_32k__C60ETF = 0xAF, + FPdXH_32k__C60ETF = 0x20_AF, #endregion @@ -309,12 +363,12 @@ namespace MewtocolNet { /// FP0H 32k C32T/P /// [PlcEXRT] - FP0H_32k__C32TsP = 0xB0, + FP0H_32k__C32TsP = 0x20_B0, /// /// FP0H 32k C32ET/EP /// [PlcEXRT] - FP0H_32k__C32ETsEP = 0xB1, + FP0H_32k__C32ETsEP = 0x20_B1, #endregion @@ -323,31 +377,31 @@ namespace MewtocolNet { /// /// FP7 CPS41E (Series code 7) /// - FP7_196k__CPS41E = 0x0703, + FP7_196k__CPS41E = 0x07_C4_03, /// /// FP7 CPS31E (Series code 7) /// - FP7_120k__CPS31E = 0x0704, + FP7_120k__CPS31E = 0x07_78_04, /// /// FP7 CPS31 (Series code 7) /// - FP7_120k__CPS31 = 0x0705, + FP7_120k__CPS31 = 0x07_78_05, /// /// FP7 CPS41ES (Series code 7) /// - FP7_196k__CPS41ES = 0x0706, + FP7_196k__CPS41ES = 0x07_C4_06, /// /// FP7 CPS31ES (Series code 7) /// - FP7_120k__CPS31ES = 0x0707, + FP7_120k__CPS31ES = 0x07_78_07, /// /// FP7 CPS31S (Series code 7) /// - FP7_120k__CPS31S = 0x0708, + FP7_120k__CPS31S = 0x07_78_08, /// /// FP7 CPS21 (Series code 7) /// - FP7_64k__CPS21 = 0x0709, + FP7_64k__CPS21 = 0x07_40_09, #endregion @@ -357,7 +411,7 @@ namespace MewtocolNet { /// EcoLogiX (Series code 7) /// [PlcLegacy] - ECOLOGIX_0k__ELC500 = 0x0710, + ECOLOGIX_0k__ELC500 = 0x07_00_10, #endregion diff --git a/MewtocolNet/PublicEnums/RegisterType.cs b/MewtocolNet/PublicEnums/RegisterPrefix.cs similarity index 79% rename from MewtocolNet/PublicEnums/RegisterType.cs rename to MewtocolNet/PublicEnums/RegisterPrefix.cs index 13376c0..c4abafc 100644 --- a/MewtocolNet/PublicEnums/RegisterType.cs +++ b/MewtocolNet/PublicEnums/RegisterPrefix.cs @@ -3,7 +3,7 @@ /// /// The register prefixed type /// - public enum RegisterType { + public enum RegisterPrefix { /// /// Physical input as a bool (Relay) @@ -25,10 +25,6 @@ /// Double word area (Register) /// DDT = 4, - /// - /// Area of a byte sequence longer than 2 words - /// - DT_BYTE_RANGE = 5, } diff --git a/MewtocolNet/PublicEnums/IOType.cs b/MewtocolNet/PublicEnums/SingleBitPrefix.cs similarity index 94% rename from MewtocolNet/PublicEnums/IOType.cs rename to MewtocolNet/PublicEnums/SingleBitPrefix.cs index dde6f35..075c8d6 100644 --- a/MewtocolNet/PublicEnums/IOType.cs +++ b/MewtocolNet/PublicEnums/SingleBitPrefix.cs @@ -6,7 +6,7 @@ /// /// The type of an input/output register /// - public enum IOType { + public enum SingleBitPrefix { /// /// Physical input as a bool (Relay) diff --git a/MewtocolNet/RegisterBuilding/AddressTools.cs b/MewtocolNet/RegisterBuilding/AddressTools.cs index ae07479..e2ebabb 100644 --- a/MewtocolNet/RegisterBuilding/AddressTools.cs +++ b/MewtocolNet/RegisterBuilding/AddressTools.cs @@ -23,7 +23,6 @@ namespace MewtocolNet.RegisterBuilding { (x) => TryBuildBoolean(x), (x) => TryBuildNumericBased(x), - (x) => TryBuildByteRangeBased(x), }; @@ -44,7 +43,7 @@ namespace MewtocolNet.RegisterBuilding { string area = match.Groups["area"].Value; string special = match.Groups["special"].Value; - IOType regType; + SingleBitPrefix regType; uint areaAdd = 0; byte specialAdd = 0x0; @@ -111,7 +110,7 @@ namespace MewtocolNet.RegisterBuilding { return new ParseResult { state = ParseResultState.Success, stepData = new StepData { - regType = (RegisterType)(int)regType, + regType = (RegisterPrefix)(int)regType, memAddress = areaAdd, specialAddress = specialAdd, } @@ -134,7 +133,7 @@ namespace MewtocolNet.RegisterBuilding { string prefix = match.Groups["prefix"].Value; string area = match.Groups["area"].Value; - RegisterType regType; + RegisterPrefix regType; uint areaAdd = 0; //try cast the prefix @@ -166,73 +165,6 @@ namespace MewtocolNet.RegisterBuilding { } - // one to two word registers - private static ParseResult TryBuildByteRangeBased(string plcAddrName) { - - var split = plcAddrName.Split('-'); - - if (split.Length > 2) - return new ParseResult { - state = ParseResultState.FailedHard, - hardFailReason = $"Cannot parse '{plcAddrName}', to many delimters '-'" - }; - - uint[] addresses = new uint[2]; - - for (int i = 0; i < split.Length; i++) { - - string addr = split[i]; - var patternByte = new Regex(@"(?DT|DDT)(?[0-9]{1,5})"); - - var match = patternByte.Match(addr); - - if (!match.Success) - return new ParseResult { - state = ParseResultState.FailedSoft - }; - - string prefix = match.Groups["prefix"].Value; - string area = match.Groups["area"].Value; - - RegisterType regType; - uint areaAdd = 0; - - //try cast the prefix - if (!Enum.TryParse(prefix, out regType)) { - - return new ParseResult { - state = ParseResultState.FailedHard, - hardFailReason = $"Cannot parse '{plcAddrName}', the prefix is not allowed for word range registers" - }; - - } - - if (!string.IsNullOrEmpty(area) && !uint.TryParse(area, out areaAdd)) { - - return new ParseResult { - state = ParseResultState.FailedHard, - hardFailReason = $"Cannot parse '{plcAddrName}', the area address: '{area}' is wrong" - }; - - } - - addresses[i] = areaAdd; - - } - - return new ParseResult { - state = ParseResultState.Success, - stepData = new StepData { - regType = RegisterType.DT_BYTE_RANGE, - wasAddressStringRangeBased = true, - dotnetVarType = typeof(byte[]), - memAddress = addresses[0], - byteSizeHint = (addresses[1] - addresses[0] + 1) * 2 - } - }; - - } - internal static StepData ParseAddress(string plcAddrName, string name = null) { foreach (var method in parseMethods) { diff --git a/MewtocolNet/RegisterBuilding/RegisterAssembler.cs b/MewtocolNet/RegisterBuilding/RegisterAssembler.cs index 7cdbe77..b7e9ade 100644 --- a/MewtocolNet/RegisterBuilding/RegisterAssembler.cs +++ b/MewtocolNet/RegisterBuilding/RegisterAssembler.cs @@ -62,8 +62,6 @@ namespace MewtocolNet.RegisterBuilding { var instance = (Register)constr.Invoke(parameters); - instance.RegisterType = RegisterType.DT_BYTE_RANGE; - if (data.boundProperty != null && data.boundProperty.PropertyType != data.dotnetVarType) throw new TypeAccessException($"The bound property {data.boundProperty} must by of type: {data.dotnetVarType}"); @@ -129,7 +127,7 @@ namespace MewtocolNet.RegisterBuilding { //------------------------------------------- //as boolean register - var io = (IOType)(int)data.regType; + var io = (SingleBitPrefix)(int)data.regType; var spAddr = data.specialAddress; var areaAddr = data.memAddress; diff --git a/MewtocolNet/RegisterBuilding/StepData.cs b/MewtocolNet/RegisterBuilding/StepData.cs index 9c258e1..287078d 100644 --- a/MewtocolNet/RegisterBuilding/StepData.cs +++ b/MewtocolNet/RegisterBuilding/StepData.cs @@ -21,7 +21,7 @@ namespace MewtocolNet.RegisterBuilding { internal bool wasAddressStringRangeBased; internal string originalParseStr; internal string name; - internal RegisterType regType; + internal RegisterPrefix regType; internal uint memAddress; internal byte specialAddress; internal Type dotnetVarType; diff --git a/MewtocolNet/Registers/Base/IRegister.cs b/MewtocolNet/Registers/Base/IRegister.cs index ebecb81..1eedbf5 100644 --- a/MewtocolNet/Registers/Base/IRegister.cs +++ b/MewtocolNet/Registers/Base/IRegister.cs @@ -17,7 +17,7 @@ namespace MewtocolNet.Registers { /// /// Type of the underlying register /// - RegisterType RegisterType { get; } + RegisterPrefix RegisterType { get; } /// /// The name of the register diff --git a/MewtocolNet/Registers/Base/Register.cs b/MewtocolNet/Registers/Base/Register.cs index e5b114f..ced697c 100644 --- a/MewtocolNet/Registers/Base/Register.cs +++ b/MewtocolNet/Registers/Base/Register.cs @@ -48,7 +48,7 @@ namespace MewtocolNet.Registers { public object ValueObj => lastValue; /// - public RegisterType RegisterType { get; internal set; } + public RegisterPrefix RegisterType { get; internal set; } /// public string Name => name; @@ -106,7 +106,7 @@ namespace MewtocolNet.Registers { public virtual string GetAsPLC() => ValueObj?.ToString() ?? "null"; - public virtual string GetRegisterString() => RegisterType == RegisterType.DT_BYTE_RANGE ? "DT" : RegisterType.ToString(); + public virtual string GetRegisterString() => RegisterType.ToString(); public virtual string GetCombinedName() => $"{GetContainerName()}{(GetContainerName() != null ? "." : "")}{Name ?? "Unnamed"}"; diff --git a/MewtocolNet/Registers/Classes/ArrayRegister.cs b/MewtocolNet/Registers/Classes/ArrayRegister.cs index 96a2afd..33f4eba 100644 --- a/MewtocolNet/Registers/Classes/ArrayRegister.cs +++ b/MewtocolNet/Registers/Classes/ArrayRegister.cs @@ -56,7 +56,7 @@ namespace MewtocolNet.Registers { byteSizePerItem = (int)_reservedByteSize / itemCount; reservedByteSize = _reservedByteSize; - RegisterType = RegisterType.DT_BYTE_RANGE; + RegisterType = byteSizePerItem == 4 ? RegisterPrefix.DDT : RegisterPrefix.DT; addressLength = Math.Max((_reservedByteSize / 2), 1); CheckAddressOverflow(memoryAddress, addressLength); diff --git a/MewtocolNet/Registers/Classes/BoolRegister.cs b/MewtocolNet/Registers/Classes/BoolRegister.cs index 3ac657b..7c9233a 100644 --- a/MewtocolNet/Registers/Classes/BoolRegister.cs +++ b/MewtocolNet/Registers/Classes/BoolRegister.cs @@ -18,7 +18,7 @@ namespace MewtocolNet.Registers { public BoolRegister() => throw new NotSupportedException("Direct register instancing is not supported, use the builder pattern"); - internal BoolRegister(IOType _io, byte _spAddress = 0x0, uint _areaAdress = 0, string _name = null) { + internal BoolRegister(SingleBitPrefix _io, byte _spAddress = 0x0, uint _areaAdress = 0, string _name = null) { lastValue = null; @@ -26,7 +26,7 @@ namespace MewtocolNet.Registers { specialAddress = _spAddress; name = _name; - RegisterType = (RegisterType)(int)_io; + RegisterType = (RegisterPrefix)(int)_io; CheckAddressOverflow(memoryAddress, 0); @@ -34,10 +34,10 @@ namespace MewtocolNet.Registers { protected override void CheckAddressOverflow(uint addressStart, uint addressLen) { - if ((int)RegisterType == (int)IOType.R && addressStart >= 512) + if ((int)RegisterType == (int)SingleBitPrefix.R && addressStart >= 512) throw new NotSupportedException("R area addresses cant be greater than 511"); - if (((int)RegisterType == (int)IOType.X || (int)RegisterType == (int)IOType.Y) && addressStart >= 110) + if (((int)RegisterType == (int)SingleBitPrefix.X || (int)RegisterType == (int)SingleBitPrefix.Y) && addressStart >= 110) throw new NotSupportedException("XY area addresses cant be greater than 110"); if (specialAddress > 0xF) diff --git a/MewtocolNet/Registers/Classes/StringRegister.cs b/MewtocolNet/Registers/Classes/StringRegister.cs index 586f66b..e2088f0 100644 --- a/MewtocolNet/Registers/Classes/StringRegister.cs +++ b/MewtocolNet/Registers/Classes/StringRegister.cs @@ -39,7 +39,7 @@ namespace MewtocolNet.Registers { reservedStringLength = (int)_reservedByteSize; Resize(_reservedByteSize); - RegisterType = RegisterType.DT_BYTE_RANGE; + RegisterType = RegisterPrefix.DT; CheckAddressOverflow(memoryAddress, addressLength); diff --git a/MewtocolNet/Registers/Classes/StructRegister.cs b/MewtocolNet/Registers/Classes/StructRegister.cs index 328662f..36776dd 100644 --- a/MewtocolNet/Registers/Classes/StructRegister.cs +++ b/MewtocolNet/Registers/Classes/StructRegister.cs @@ -16,6 +16,7 @@ namespace MewtocolNet.Registers { /// The type of the numeric value public class StructRegister : Register, IRegister where T : struct { + internal byte specialAddress; internal uint addressLength; /// @@ -23,22 +24,29 @@ namespace MewtocolNet.Registers { /// public uint AddressLength => addressLength; + /// + /// The registers memory adress if not a special register + /// + public byte SpecialAddress => specialAddress; + public T? Value => (T?)ValueObj; [Obsolete("Creating registers directly is not supported use IPlc.Register instead")] public StructRegister() => throw new NotSupportedException("Direct register instancing is not supported, use the builder pattern"); + //struct for 16-32bit registers internal StructRegister(uint _address, uint _reservedByteSize, string _name = null) { memoryAddress = _address; + specialAddress = 0x0; name = _name; addressLength = _reservedByteSize / 2; if (_reservedByteSize % 2 != 0) addressLength++; - if (_reservedByteSize == 2) RegisterType = RegisterType.DT; - if(_reservedByteSize == 4) RegisterType = RegisterType.DDT; + if (_reservedByteSize == 2) RegisterType = RegisterPrefix.DT; + if(_reservedByteSize == 4) RegisterType = RegisterPrefix.DDT; CheckAddressOverflow(memoryAddress, addressLength); @@ -47,6 +55,36 @@ namespace MewtocolNet.Registers { } + //struct for one bit registers + internal StructRegister(SingleBitPrefix _io, byte _spAddress = 0x0, uint _areaAdress = 0, string _name = null) { + + lastValue = null; + + memoryAddress = _areaAdress; + specialAddress = _spAddress; + name = _name; + + RegisterType = (RegisterPrefix)(int)_io; + + CheckAddressOverflow(memoryAddress, 0); + + } + + protected override void CheckAddressOverflow(uint addressStart, uint addressLen) { + + if ((int)RegisterType == (int)SingleBitPrefix.R && addressStart >= 512) + throw new NotSupportedException("R area addresses cant be greater than 511"); + + if (((int)RegisterType == (int)SingleBitPrefix.X || (int)RegisterType == (int)SingleBitPrefix.Y) && addressStart >= 110) + throw new NotSupportedException("XY area addresses cant be greater than 110"); + + if (specialAddress > 0xF) + throw new NotSupportedException("Special address cant be greater than 15 or 0xF"); + + base.CheckAddressOverflow(addressStart, addressLen); + + } + /// public override string GetAsPLC() { diff --git a/MewtocolNet/TypeConversion/Conversions.cs b/MewtocolNet/TypeConversion/Conversions.cs index 31997bd..d41589e 100644 --- a/MewtocolNet/TypeConversion/Conversions.cs +++ b/MewtocolNet/TypeConversion/Conversions.cs @@ -8,18 +8,18 @@ namespace MewtocolNet.TypeConversion { internal static class Conversions { - internal static Dictionary dictPlcTypeToRegisterType = new Dictionary { + internal static Dictionary dictPlcTypeToRegisterType = new Dictionary { - { PlcVarType.BOOL, RegisterType.R }, - { PlcVarType.INT, RegisterType.DT }, - { PlcVarType.UINT, RegisterType.DT }, - { PlcVarType.DINT, RegisterType.DDT }, - { PlcVarType.UDINT, RegisterType.DDT }, - { PlcVarType.REAL, RegisterType.DDT }, - { PlcVarType.TIME, RegisterType.DDT }, - { PlcVarType.WORD, RegisterType.DT }, - { PlcVarType.DWORD, RegisterType.DDT }, - { PlcVarType.STRING, RegisterType.DT_BYTE_RANGE }, + { PlcVarType.BOOL, RegisterPrefix.R }, + { PlcVarType.INT, RegisterPrefix.DT }, + { PlcVarType.UINT, RegisterPrefix.DT }, + { PlcVarType.DINT, RegisterPrefix.DDT }, + { PlcVarType.UDINT, RegisterPrefix.DDT }, + { PlcVarType.REAL, RegisterPrefix.DDT }, + { PlcVarType.TIME, RegisterPrefix.DDT }, + { PlcVarType.WORD, RegisterPrefix.DT }, + { PlcVarType.DWORD, RegisterPrefix.DDT }, + { PlcVarType.STRING, RegisterPrefix.DT }, }; @@ -29,7 +29,7 @@ namespace MewtocolNet.TypeConversion { internal static List items = new List { //default bool R conversion - new PlcTypeConversion(RegisterType.R) { + new PlcTypeConversion(RegisterPrefix.R) { HoldingRegisterType = typeof(BoolRegister), PlcVarType = PlcVarType.BOOL, FromRaw = (reg, bytes) => (bool)(bytes[0] == 1), @@ -37,7 +37,7 @@ namespace MewtocolNet.TypeConversion { }, //default bool X conversion - new PlcTypeConversion(RegisterType.X) { + new PlcTypeConversion(RegisterPrefix.X) { HoldingRegisterType = typeof(BoolRegister), PlcVarType = PlcVarType.BOOL, FromRaw = (reg, bytes) => (bool)(bytes[0] == 1), @@ -45,7 +45,7 @@ namespace MewtocolNet.TypeConversion { }, //default bool Y conversion - new PlcTypeConversion(RegisterType.Y) { + new PlcTypeConversion(RegisterPrefix.Y) { HoldingRegisterType = typeof(BoolRegister), PlcVarType = PlcVarType.BOOL, FromRaw = (reg, bytes) => (bool)(bytes[0] == 1), @@ -53,7 +53,7 @@ namespace MewtocolNet.TypeConversion { }, //default short DT conversion - new PlcTypeConversion(RegisterType.DT) { + new PlcTypeConversion(RegisterPrefix.DT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.INT, FromRaw = (reg, bytes) => BitConverter.ToInt16(bytes, 0), @@ -61,7 +61,7 @@ namespace MewtocolNet.TypeConversion { }, //default ushort DT conversion - new PlcTypeConversion(RegisterType.DT) { + new PlcTypeConversion(RegisterPrefix.DT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.UINT, FromRaw = (reg, bytes) => BitConverter.ToUInt16(bytes, 0), @@ -69,7 +69,7 @@ namespace MewtocolNet.TypeConversion { }, //default Word DT conversion - new PlcTypeConversion(RegisterType.DT) { + new PlcTypeConversion(RegisterPrefix.DT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.WORD, FromRaw = (reg, bytes) => new Word(bytes), @@ -77,7 +77,7 @@ namespace MewtocolNet.TypeConversion { }, //default int DDT conversion - new PlcTypeConversion(RegisterType.DDT) { + new PlcTypeConversion(RegisterPrefix.DDT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.DINT, FromRaw = (reg, bytes) => BitConverter.ToInt32(bytes, 0), @@ -85,7 +85,7 @@ namespace MewtocolNet.TypeConversion { }, //default uint DDT conversion - new PlcTypeConversion(RegisterType.DDT) { + new PlcTypeConversion(RegisterPrefix.DDT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.UDINT, FromRaw = (reg, bytes) => BitConverter.ToUInt32(bytes, 0), @@ -93,7 +93,7 @@ namespace MewtocolNet.TypeConversion { }, //default DWord DDT conversion - new PlcTypeConversion(RegisterType.DDT) { + new PlcTypeConversion(RegisterPrefix.DDT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.DWORD, FromRaw = (reg, bytes) => new DWord(bytes), @@ -101,7 +101,7 @@ namespace MewtocolNet.TypeConversion { }, //default float DDT conversion - new PlcTypeConversion(RegisterType.DDT) { + new PlcTypeConversion(RegisterPrefix.DDT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.REAL, FromRaw = (reg, bytes) => BitConverter.ToSingle(bytes, 0), @@ -109,7 +109,7 @@ namespace MewtocolNet.TypeConversion { }, //default TimeSpan DDT conversion - new PlcTypeConversion(RegisterType.DDT) { + new PlcTypeConversion(RegisterPrefix.DDT) { HoldingRegisterType = typeof(StructRegister), PlcVarType = PlcVarType.TIME, FromRaw = (reg, bytes) => { @@ -130,7 +130,7 @@ namespace MewtocolNet.TypeConversion { //default string DT Range conversion Example bytes: (04 00 03 00 XX XX XX) //first 4 bytes are reserved size (2 bytes) and used size (2 bytes) //the remaining bytes are the ascii bytes for the string - new PlcTypeConversion(RegisterType.DT_BYTE_RANGE) { + new PlcTypeConversion(RegisterPrefix.DT) { HoldingRegisterType = typeof(StringRegister), PlcVarType = PlcVarType.STRING, FromRaw = (reg, bytes) => { diff --git a/MewtocolNet/TypeConversion/IPlcTypeConverter.cs b/MewtocolNet/TypeConversion/IPlcTypeConverter.cs index 164a8cf..96b8705 100644 --- a/MewtocolNet/TypeConversion/IPlcTypeConverter.cs +++ b/MewtocolNet/TypeConversion/IPlcTypeConverter.cs @@ -13,7 +13,7 @@ namespace MewtocolNet { Type GetHoldingRegisterType(); - RegisterType GetPlcRegisterType(); + RegisterPrefix GetPlcRegisterType(); PlcVarType GetPlcVarType(); diff --git a/MewtocolNet/TypeConversion/PlcTypeConversion.cs b/MewtocolNet/TypeConversion/PlcTypeConversion.cs index 8f76db4..9b04003 100644 --- a/MewtocolNet/TypeConversion/PlcTypeConversion.cs +++ b/MewtocolNet/TypeConversion/PlcTypeConversion.cs @@ -7,7 +7,7 @@ namespace MewtocolNet { public Type MainType { get; private set; } - public RegisterType PlcType { get; private set; } + public RegisterPrefix PlcType { get; private set; } public PlcVarType PlcVarType { get; set; } @@ -17,7 +17,7 @@ namespace MewtocolNet { public Func ToRaw { get; set; } - public PlcTypeConversion(RegisterType plcType) { + public PlcTypeConversion(RegisterPrefix plcType) { MainType = typeof(T); PlcType = plcType; @@ -28,7 +28,7 @@ namespace MewtocolNet { public Type GetHoldingRegisterType() => HoldingRegisterType; - public RegisterType GetPlcRegisterType() => PlcType; + public RegisterPrefix GetPlcRegisterType() => PlcType; public PlcVarType GetPlcVarType() => PlcVarType; diff --git a/MewtocolNet/TypeConversion/PlcValueParser.cs b/MewtocolNet/TypeConversion/PlcValueParser.cs index 2366bbe..0be1835 100644 --- a/MewtocolNet/TypeConversion/PlcValueParser.cs +++ b/MewtocolNet/TypeConversion/PlcValueParser.cs @@ -182,7 +182,7 @@ namespace MewtocolNet { public static List GetAllowRegisterTypes() => conversions.Select(x => x.GetHoldingRegisterType()).ToList(); - public static RegisterType? GetDefaultRegisterType(Type type) => + public static RegisterPrefix? GetDefaultRegisterType(Type type) => conversions.FirstOrDefault(x => x.GetDotnetType() == type)?.GetPlcRegisterType(); public static Type GetDefaultRegisterHoldingType(this PlcVarType type) => diff --git a/MewtocolNet/TypeConversion/PlcVarTypeConversions.cs b/MewtocolNet/TypeConversion/PlcVarTypeConversions.cs index 86890f4..34bd3e4 100644 --- a/MewtocolNet/TypeConversion/PlcVarTypeConversions.cs +++ b/MewtocolNet/TypeConversion/PlcVarTypeConversions.cs @@ -32,9 +32,9 @@ namespace MewtocolNet { } - internal static RegisterType ToRegisterTypeDefault(this Type type) { + internal static RegisterPrefix ToRegisterTypeDefault(this Type type) { - if (type.IsEnum) return RegisterType.DT; + if (type.IsEnum) return RegisterPrefix.DT; var found = PlcValueParser.GetDefaultRegisterType(type); diff --git a/MewtocolNet/UnderlyingRegisters/DTArea.cs b/MewtocolNet/UnderlyingRegisters/DTArea.cs index 961d02c..6c36a90 100644 --- a/MewtocolNet/UnderlyingRegisters/DTArea.cs +++ b/MewtocolNet/UnderlyingRegisters/DTArea.cs @@ -9,7 +9,7 @@ namespace MewtocolNet.UnderlyingRegisters { private MewtocolInterface mewInterface; - internal RegisterType registerType; + internal RegisterPrefix registerType; internal ulong addressStart; internal ulong addressEnd; diff --git a/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs b/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs index 967f941..600fc0a 100644 --- a/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs +++ b/MewtocolNet/UnderlyingRegisters/MemoryAreaManager.cs @@ -75,14 +75,13 @@ namespace MewtocolNet.UnderlyingRegisters { TestPollLevelExistence(reg); switch (reg.RegisterType) { - case RegisterType.X: - case RegisterType.Y: - case RegisterType.R: + case RegisterPrefix.X: + case RegisterPrefix.Y: + case RegisterPrefix.R: AddToWRArea(reg); break; - case RegisterType.DT: - case RegisterType.DDT: - case RegisterType.DT_BYTE_RANGE: + case RegisterPrefix.DT: + case RegisterPrefix.DDT: AddToDTArea(reg); break; } @@ -148,13 +147,13 @@ namespace MewtocolNet.UnderlyingRegisters { List collection = null; switch (insertReg.RegisterType) { - case RegisterType.X: + case RegisterPrefix.X: collection = pollLevelFound.externalRelayInAreas; break; - case RegisterType.Y: + case RegisterPrefix.Y: collection = pollLevelFound.externalRelayOutAreas; break; - case RegisterType.R: + case RegisterPrefix.R: collection = pollLevelFound.internalRelayAreas; break; } diff --git a/MewtocolNet/UnderlyingRegisters/WRArea.cs b/MewtocolNet/UnderlyingRegisters/WRArea.cs index 21eba23..a1ebfb5 100644 --- a/MewtocolNet/UnderlyingRegisters/WRArea.cs +++ b/MewtocolNet/UnderlyingRegisters/WRArea.cs @@ -9,7 +9,7 @@ namespace MewtocolNet.UnderlyingRegisters { private MewtocolInterface mewInterface; - internal RegisterType registerType; + internal RegisterPrefix registerType; internal ulong addressStart; internal byte[] wordData = new byte[2]; diff --git a/MewtocolTests/TestPlcTypeEnumDuplicates.cs b/MewtocolTests/TestPlcTypeEnumDuplicates.cs new file mode 100644 index 0000000..13df0af --- /dev/null +++ b/MewtocolTests/TestPlcTypeEnumDuplicates.cs @@ -0,0 +1,19 @@ +using MewtocolNet; +using Xunit; +using Xunit.Abstractions; + +using MewtocolNet.Helpers; + +namespace MewtocolTests { + + public class TestPlcTypeEnumDuplicates { + + private readonly ITestOutputHelper output; + + public TestPlcTypeEnumDuplicates(ITestOutputHelper output) { + this.output = output; + } + + } + +} \ No newline at end of file diff --git a/MewtocolTests/TestRegisterBuilder.cs b/MewtocolTests/TestRegisterBuilder.cs index 64a99a6..98efb85 100644 --- a/MewtocolTests/TestRegisterBuilder.cs +++ b/MewtocolTests/TestRegisterBuilder.cs @@ -23,27 +23,27 @@ public class TestRegisterBuilder { var tests = new Dictionary() { - {"Y0", new BoolRegister(IOType.Y)}, - {"Y1", new BoolRegister(IOType.Y, 0x1)}, - {"Y2", new BoolRegister(IOType.Y, 0x2)}, - {"Y3", new BoolRegister(IOType.Y, 0x3)}, - {"Y4", new BoolRegister(IOType.Y, 0x4)}, - {"Y5", new BoolRegister(IOType.Y, 0x5)}, - {"Y6", new BoolRegister(IOType.Y, 0x6)}, - {"Y7", new BoolRegister(IOType.Y, 0x7)}, - {"Y8", new BoolRegister(IOType.Y, 0x8)}, - {"Y9", new BoolRegister(IOType.Y, 0x9)}, + {"Y0", new BoolRegister(SingleBitPrefix.Y)}, + {"Y1", new BoolRegister(SingleBitPrefix.Y, 0x1)}, + {"Y2", new BoolRegister(SingleBitPrefix.Y, 0x2)}, + {"Y3", new BoolRegister(SingleBitPrefix.Y, 0x3)}, + {"Y4", new BoolRegister(SingleBitPrefix.Y, 0x4)}, + {"Y5", new BoolRegister(SingleBitPrefix.Y, 0x5)}, + {"Y6", new BoolRegister(SingleBitPrefix.Y, 0x6)}, + {"Y7", new BoolRegister(SingleBitPrefix.Y, 0x7)}, + {"Y8", new BoolRegister(SingleBitPrefix.Y, 0x8)}, + {"Y9", new BoolRegister(SingleBitPrefix.Y, 0x9)}, - {"YA", new BoolRegister(IOType.Y, 0xA)}, - {"YB", new BoolRegister(IOType.Y, 0xB)}, - {"YC", new BoolRegister(IOType.Y, 0xC)}, - {"YD", new BoolRegister(IOType.Y, 0xD)}, - {"YE", new BoolRegister(IOType.Y, 0xE)}, - {"YF", new BoolRegister(IOType.Y, 0xF)}, + {"YA", new BoolRegister(SingleBitPrefix.Y, 0xA)}, + {"YB", new BoolRegister(SingleBitPrefix.Y, 0xB)}, + {"YC", new BoolRegister(SingleBitPrefix.Y, 0xC)}, + {"YD", new BoolRegister(SingleBitPrefix.Y, 0xD)}, + {"YE", new BoolRegister(SingleBitPrefix.Y, 0xE)}, + {"YF", new BoolRegister(SingleBitPrefix.Y, 0xF)}, - {"Y1A", new BoolRegister(IOType.Y, 0xA, 1)}, - {"Y10B", new BoolRegister(IOType.Y, 0xB, 10)}, - {"Y109C", new BoolRegister(IOType.Y, 0xC, 109)}, + {"Y1A", new BoolRegister(SingleBitPrefix.Y, 0xA, 1)}, + {"Y10B", new BoolRegister(SingleBitPrefix.Y, 0xB, 10)}, + {"Y109C", new BoolRegister(SingleBitPrefix.Y, 0xC, 109)}, }; @@ -56,27 +56,27 @@ public class TestRegisterBuilder { var tests = new Dictionary() { - {"X0", new BoolRegister(IOType.X)}, - {"X1", new BoolRegister(IOType.X, 0x1)}, - {"X2", new BoolRegister(IOType.X, 0x2)}, - {"X3", new BoolRegister(IOType.X, 0x3)}, - {"X4", new BoolRegister(IOType.X, 0x4)}, - {"X5", new BoolRegister(IOType.X, 0x5)}, - {"X6", new BoolRegister(IOType.X, 0x6)}, - {"X7", new BoolRegister(IOType.X, 0x7)}, - {"X8", new BoolRegister(IOType.X, 0x8)}, - {"X9", new BoolRegister(IOType.X, 0x9)}, + {"X0", new BoolRegister(SingleBitPrefix.X)}, + {"X1", new BoolRegister(SingleBitPrefix.X, 0x1)}, + {"X2", new BoolRegister(SingleBitPrefix.X, 0x2)}, + {"X3", new BoolRegister(SingleBitPrefix.X, 0x3)}, + {"X4", new BoolRegister(SingleBitPrefix.X, 0x4)}, + {"X5", new BoolRegister(SingleBitPrefix.X, 0x5)}, + {"X6", new BoolRegister(SingleBitPrefix.X, 0x6)}, + {"X7", new BoolRegister(SingleBitPrefix.X, 0x7)}, + {"X8", new BoolRegister(SingleBitPrefix.X, 0x8)}, + {"X9", new BoolRegister(SingleBitPrefix.X, 0x9)}, - {"XA", new BoolRegister(IOType.X, 0xA)}, - {"XB", new BoolRegister(IOType.X, 0xB)}, - {"XC", new BoolRegister(IOType.X, 0xC)}, - {"XD", new BoolRegister(IOType.X, 0xD)}, - {"XE", new BoolRegister(IOType.X, 0xE)}, - {"XF", new BoolRegister(IOType.X, 0xF)}, + {"XA", new BoolRegister(SingleBitPrefix.X, 0xA)}, + {"XB", new BoolRegister(SingleBitPrefix.X, 0xB)}, + {"XC", new BoolRegister(SingleBitPrefix.X, 0xC)}, + {"XD", new BoolRegister(SingleBitPrefix.X, 0xD)}, + {"XE", new BoolRegister(SingleBitPrefix.X, 0xE)}, + {"XF", new BoolRegister(SingleBitPrefix.X, 0xF)}, - {"X1A", new BoolRegister(IOType.X, 0xA, 1)}, - {"X10B", new BoolRegister(IOType.X, 0xB, 10)}, - {"X109C", new BoolRegister(IOType.X, 0xC, 109)}, + {"X1A", new BoolRegister(SingleBitPrefix.X, 0xA, 1)}, + {"X10B", new BoolRegister(SingleBitPrefix.X, 0xB, 10)}, + {"X109C", new BoolRegister(SingleBitPrefix.X, 0xC, 109)}, }; @@ -89,30 +89,30 @@ public class TestRegisterBuilder { var tests = new Dictionary() { - {"R0", new BoolRegister(IOType.R)}, - {"R1", new BoolRegister(IOType.R, 0x1)}, - {"R2", new BoolRegister(IOType.R, 0x2)}, - {"R3", new BoolRegister(IOType.R, 0x3)}, - {"R4", new BoolRegister(IOType.R, 0x4)}, - {"R5", new BoolRegister(IOType.R, 0x5)}, - {"R6", new BoolRegister(IOType.R, 0x6)}, - {"R7", new BoolRegister(IOType.R, 0x7)}, - {"R8", new BoolRegister(IOType.R, 0x8)}, - {"R9", new BoolRegister(IOType.R, 0x9)}, + {"R0", new BoolRegister(SingleBitPrefix.R)}, + {"R1", new BoolRegister(SingleBitPrefix.R, 0x1)}, + {"R2", new BoolRegister(SingleBitPrefix.R, 0x2)}, + {"R3", new BoolRegister(SingleBitPrefix.R, 0x3)}, + {"R4", new BoolRegister(SingleBitPrefix.R, 0x4)}, + {"R5", new BoolRegister(SingleBitPrefix.R, 0x5)}, + {"R6", new BoolRegister(SingleBitPrefix.R, 0x6)}, + {"R7", new BoolRegister(SingleBitPrefix.R, 0x7)}, + {"R8", new BoolRegister(SingleBitPrefix.R, 0x8)}, + {"R9", new BoolRegister(SingleBitPrefix.R, 0x9)}, - {"RA", new BoolRegister(IOType.R, 0xA)}, - {"RB", new BoolRegister(IOType.R, 0xB)}, - {"RC", new BoolRegister(IOType.R, 0xC)}, - {"RD", new BoolRegister(IOType.R, 0xD)}, - {"RE", new BoolRegister(IOType.R, 0xE)}, - {"RF", new BoolRegister(IOType.R, 0xF)}, + {"RA", new BoolRegister(SingleBitPrefix.R, 0xA)}, + {"RB", new BoolRegister(SingleBitPrefix.R, 0xB)}, + {"RC", new BoolRegister(SingleBitPrefix.R, 0xC)}, + {"RD", new BoolRegister(SingleBitPrefix.R, 0xD)}, + {"RE", new BoolRegister(SingleBitPrefix.R, 0xE)}, + {"RF", new BoolRegister(SingleBitPrefix.R, 0xF)}, - {"R1A", new BoolRegister(IOType.R, 0xA, 1)}, - {"R10B", new BoolRegister(IOType.R, 0xB, 10)}, - {"R109C", new BoolRegister(IOType.R, 0xC, 109)}, - {"R1000", new BoolRegister(IOType.R, 0x0, 100)}, - {"R511", new BoolRegister(IOType.R, 0x0, 511)}, - {"R511A", new BoolRegister(IOType.R, 0xA, 511)}, + {"R1A", new BoolRegister(SingleBitPrefix.R, 0xA, 1)}, + {"R10B", new BoolRegister(SingleBitPrefix.R, 0xB, 10)}, + {"R109C", new BoolRegister(SingleBitPrefix.R, 0xC, 109)}, + {"R1000", new BoolRegister(SingleBitPrefix.R, 0x0, 100)}, + {"R511", new BoolRegister(SingleBitPrefix.R, 0x0, 511)}, + {"R511A", new BoolRegister(SingleBitPrefix.R, 0xA, 511)}, }; diff --git a/MewtocolTests/TestRegisterInterface.cs b/MewtocolTests/TestRegisterInterface.cs index 8e004ec..18f0c4d 100644 --- a/MewtocolTests/TestRegisterInterface.cs +++ b/MewtocolTests/TestRegisterInterface.cs @@ -31,7 +31,7 @@ namespace MewtocolTests { var ex1 = Assert.Throws(() => { - new BoolRegister(IOType.R, _areaAdress: 512); + new BoolRegister(SingleBitPrefix.R, _areaAdress: 512); }); @@ -39,7 +39,7 @@ namespace MewtocolTests { var ex2 = Assert.Throws(() => { - new BoolRegister(IOType.X, _areaAdress: 110); + new BoolRegister(SingleBitPrefix.X, _areaAdress: 110); });
{(enu.SubTypes.Length == 0 ? "-" : string.Join(", ", enu.SubTypes))} {enu.Size}k 0x{cpuOrMachCode} {(decomp.SubTypes.Length == 0 ? "-" : string.Join(", ", decomp.SubTypes))} {decomp.Size}k 0x{cpuOrMachCode}{enu.ToString()}⚠️{enu.EncodedName}⚠️{enu.ToString()} {(enu.IsEXRTPLC() ? "✅" : "❌")} {(enu.WasTestedLive() ? "✅" : "❌")}
{enu.EncodedName} {(enu.UsesEXRT ? "✅" : "❌")} {(enu.WasTestedLive ? "✅" : "❌")}