New functions

This commit is contained in:
Felix Weiß
2023-07-23 15:29:29 +02:00
parent eec1479406
commit bf78156a9d
17 changed files with 701 additions and 175 deletions

View File

@@ -1,6 +1,8 @@
using System.Collections.Specialized;
using System.Diagnostics;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using HtmlAgilityPack;
using MewtocolNet;
@@ -10,8 +12,7 @@ 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";
const string funcNamesLoc = @"Panasonic-ID SUNX Control\Control FPWIN Pro 7\Mak\Res_Eng\FPWINPro.chm";
static Dictionary<string, List<PlcType>> plcGroups = new() {
{ "FP7 CPS41/31 E/ES", new List<PlcType> {
@@ -112,21 +113,136 @@ internal class Program {
}
internal class FPFunction {
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string RedundantName { get; set; } = null!;
public string Description { get; set; } = null!;
}
static void Main(string[] args) => Task.Run(AsyncMain).Wait();
static async Task AsyncMain () {
CheckGroupCoverage();
await GetSystemRegisters();
GetFunctionNames();
//await GetSystemRegisters();
}
static void CheckGroupCoverage () {
static void GetFunctionNames () {
//foreach (var key in Enum.GetNames(PlcType)) {
var functions = new Dictionary<string, FPFunction>();
//}
var progLoc = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!;
var progFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
var sysVarsPath = Path.Combine(progFilesPath, funcNamesLoc);
Directory.SetCurrentDirectory(progLoc);
File.Copy(sysVarsPath, "./FPWINPro.chm", true);
var startInfo = new ProcessStartInfo {
WorkingDirectory = progLoc,
FileName = "hh.exe",
Arguments = $"-decompile ./DecompFuncs ./FPWINPro.chm",
};
//call the hh.exe decompiler for chm
if (!File.Exists("./DecompFuncs/topics/availability.html")) {
var proc = Process.Start(startInfo)!;
proc.WaitForExit();
}
var doc = new HtmlDocument();
doc.Load("./DecompFuncs/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;
foreach (var row in rows) {
var columns = row.SelectNodes("td");
if (columns == null) continue;
var itemRow = columns?.FirstOrDefault()?.SelectSingleNode("p/a[contains(@class,'xref')]");
string rowName = itemRow?.InnerText ?? "Unnamed";
if (!Regex.IsMatch(rowName, @"^F[0-9]{1,3}_.*$")) continue;
FPFunction functionIns = new FPFunction();
//Console.Write($"Var: {rowName, -50}");
var href = itemRow?.GetAttributeValue("href", null);
if (href != null) {
//Console.Write($" {href}");
var docSub = new HtmlDocument();
docSub.Load($"./DecompFuncs{href}");
var noteSection = docSub.DocumentNode.SelectSingleNode("//section/div[contains(@class,'note note')]");
var xrefRedundant = noteSection?.SelectSingleNode("p/a[contains(@class,'xref')]");
var xrefNodeContent = noteSection?.SelectSingleNode("p/span");
HtmlNode? descrSection = null;
if (xrefRedundant != null && xrefNodeContent != null && xrefNodeContent.InnerText.StartsWith("This is a redundant F instruction")) {
descrSection = docSub.DocumentNode.SelectSingleNode("//section[2]");
functionIns.RedundantName = xrefRedundant.InnerText;
//Console.Write($"{xrefRedundant.InnerText}");
} else {
descrSection = docSub.DocumentNode.SelectSingleNode("//section[1]");
}
if (descrSection != null) {
var descrText = descrSection?.InnerText;
if(descrText != null) {
descrText = descrText.Replace("\r", "").Replace("\n", "").Trim();
functionIns.Description = descrText;
//Console.Write($" {descrText}");
}
}
}
functions.Add(rowName, functionIns);
//compatibility matrix
//for (int i = 1; i < columns?.Count - 1; i++) {
// bool isChecked = columns?.ElementAtOrDefault(i)?.SelectSingleNode("p")?.InnerHtml != "";
// Console.Write($"{(isChecked ? "1" : "0")}, ");
//}
}
}
var funcsJson = JsonSerializer.Serialize(functions, new JsonSerializerOptions { WriteIndented = true });
Console.WriteLine(funcsJson);
}

View File

@@ -1,5 +1,5 @@
# PLC Type Table
Auto Generated @ **2023-07-21 16:30:21Z**
Auto Generated @ **2023-07-22 17:21:07Z**
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.
@@ -7,9 +7,9 @@ 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
07 <= extended code (00 for non Mewtocol 7 devices)
0120 <= for 120k (Prog capacity), with RT/EXRT/MEW7 override order
A5 <= Is the actual typecode, with RT/EXRT/MEW7 override order
```
> <b>Discontinued PLCs</b><br>
> These are PLCs that are no longer sold by Panasonic. Marked with ⚠️
@@ -33,7 +33,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> ELC500 </td>
<td> 0k </td>
<td><code>0x070010</code></td>
<td><code>0x7000010</code></td>
<td><i>ECOLOGIX_0k__ELC500</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -48,26 +48,26 @@ A5 <= Is the actual typecode, can overlap with others
<td><code>0x000340</code></td>
<td><i>FP0_2c7k__C10_C14_C16</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> C32, SL1 </td>
<td> 5k </td>
<td><code>0x000041</code></td>
<td><code>0x000541</code></td>
<td><i>FP0_5k__C32_SL1</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> T32 </td>
<td> 10k </td>
<td><code>0x000A42</code></td>
<td><code>0x001042</code></td>
<td><i>FP0_10c0k__T32</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td colspan="7" height=50>📟 <b>FP0H</b> </td>
@@ -75,7 +75,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C32ET/EP </td>
<td> 32k </td>
<td><code>0x0020B1</code></td>
<td><code>0x0032B1</code></td>
<td colspan="2"><i>FP0H_32k__C32ETsEP</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -83,7 +83,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C32T/P </td>
<td> 32k </td>
<td><code>0x0020B0</code></td>
<td><code>0x0032B0</code></td>
<td colspan="2"><i>FP0H_32k__C32TsP</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -94,34 +94,34 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C10, C14, C16 </td>
<td> 16k </td>
<td><code>0x000046</code></td>
<td><code>0x001646</code></td>
<td colspan="2"><i>FP0R_16k__C10_C14_C16</i></td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> C32 </td>
<td> 32k </td>
<td><code>0x002047</code></td>
<td><code>0x003247</code></td>
<td colspan="2"><i>FP0R_32k__C32</i></td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> F32 </td>
<td> 32k </td>
<td><code>0x002049</code></td>
<td><code>0x003249</code></td>
<td colspan="2"><i>FP0R_32k__F32</i></td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> T32 </td>
<td> 32k </td>
<td><code>0x002048</code></td>
<td><code>0x003248</code></td>
<td colspan="2"><i>FP0R_32k__T32</i></td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td colspan="7" height=50>📟 <b>FP1</b> </td>
@@ -147,7 +147,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C56, C72 </td>
<td> 5k </td>
<td><code>0x000006</code></td>
<td><code>0x000506</code></td>
<td><i>FP1_5k__C56_C72</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -159,7 +159,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 30k </td>
<td><code>0x001E20</code></td>
<td><code>0x003020</code></td>
<td><i>FP10_30k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -168,7 +168,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 60k </td>
<td><code>0x003C20</code></td>
<td><code>0x006020</code></td>
<td><i>FP10_60k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -180,7 +180,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 30k </td>
<td><code>0x001E20</code></td>
<td><code>0x003020</code></td>
<td><i>FP10S_30k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -192,28 +192,28 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 30k </td>
<td><code>0x001E30</code></td>
<td><code>0x003030</code></td>
<td><i>FP10SH_30k</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> ❌ </td>
</tr>
<tr>
<td> - </td>
<td> 60k </td>
<td><code>0x003C30</code></td>
<td><code>0x006030</code></td>
<td><i>FP10SH_60k</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> ❌ </td>
</tr>
<tr>
<td> - </td>
<td> 120k </td>
<td><code>0x007830</code></td>
<td><code>0x012030</code></td>
<td><i>FP10SH_120k</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> ❌ </td>
</tr>
<tr>
@@ -222,20 +222,20 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 16k </td>
<td><code>0x001050</code></td>
<td><code>0x001650</code></td>
<td><i>FP2_16k</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> - </td>
<td> 32k </td>
<td><code>0x002050</code></td>
<td><code>0x003250</code></td>
<td><i>FP2_32k</i></td>
<td align=center>⚠️</td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td colspan="7" height=50>📟 <b>FP2SH</b> </td>
@@ -243,25 +243,25 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 32k </td>
<td><code>0x002062</code></td>
<td><code>0x003262</code></td>
<td><i>FP2SH_32k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> - </td>
<td> 60k </td>
<td><code>0x003C60</code></td>
<td><code>0x006060</code></td>
<td><i>FP2SH_60k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> - </td>
<td> 120k </td>
<td><code>0x0078E0</code></td>
<td><code>0x012060</code></td>
<td><i>FP2SH_120k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -273,7 +273,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 10k </td>
<td><code>0x000A03</code></td>
<td><code>0x001003</code></td>
<td><i>FP3_10k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -282,7 +282,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 16k </td>
<td><code>0x001013</code></td>
<td><code>0x001613</code></td>
<td><i>FP3_16k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -294,7 +294,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 16k </td>
<td><code>0x001002</code></td>
<td><code>0x001602</code></td>
<td><i>FP5_16k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -303,7 +303,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 24k </td>
<td><code>0x001812</code></td>
<td><code>0x002412</code></td>
<td><i>FP5_24k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -315,7 +315,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS21 </td>
<td> 64k </td>
<td><code>0x074009</code></td>
<td><code>0x7006409</code></td>
<td colspan="2"><i>FP7_64k__CPS21</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -323,7 +323,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS31 </td>
<td> 120k </td>
<td><code>0x077805</code></td>
<td><code>0x7012005</code></td>
<td colspan="2"><i>FP7_120k__CPS31</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -331,7 +331,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS31E </td>
<td> 120k </td>
<td><code>0x077804</code></td>
<td><code>0x7012004</code></td>
<td colspan="2"><i>FP7_120k__CPS31E</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -339,7 +339,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS31ES </td>
<td> 120k </td>
<td><code>0x077807</code></td>
<td><code>0x7012007</code></td>
<td colspan="2"><i>FP7_120k__CPS31ES</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -347,7 +347,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS31S </td>
<td> 120k </td>
<td><code>0x077808</code></td>
<td><code>0x7012008</code></td>
<td colspan="2"><i>FP7_120k__CPS31S</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -355,7 +355,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS41E </td>
<td> 196k </td>
<td><code>0x07C403</code></td>
<td><code>0x7019603</code></td>
<td colspan="2"><i>FP7_196k__CPS41E</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -363,7 +363,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> CPS41ES </td>
<td> 196k </td>
<td><code>0x07C406</code></td>
<td><code>0x7019606</code></td>
<td colspan="2"><i>FP7_196k__CPS41ES</i></td>
<td align=center> ❌ </td>
<td align=center> ❌ </td>
@@ -374,7 +374,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 16k </td>
<td><code>0x001013</code></td>
<td><code>0x001613</code></td>
<td><i>FPdC_16k</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -416,7 +416,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C20RC, C20TC, C32TC </td>
<td> 5k </td>
<td><code>0x000006</code></td>
<td><code>0x000506</code></td>
<td><i>FPdM_5k__C20RC_C20TC_C32TC</i></td>
<td align=center>⚠️</td>
<td align=center> ❌ </td>
@@ -428,7 +428,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 12k </td>
<td><code>0x000C43</code></td>
<td><code>0x001243</code></td>
<td><i>FPdSIGMA_12k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -437,7 +437,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 16k </td>
<td><code>0x0010E1</code></td>
<td><code>0x0016E1</code></td>
<td><i>FPdSIGMA_16k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -446,16 +446,16 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> - </td>
<td> 32k </td>
<td><code>0x002044</code></td>
<td><code>0x003244</code></td>
<td><i>FPdSIGMA_32k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
<td align=center> </td>
<td align=center> </td>
</tr>
<tr>
<td> - </td>
<td> 40k </td>
<td><code>0x0028E1</code></td>
<td><code>0x0040E1</code></td>
<td><i>FPdSIGMA_40k</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -476,7 +476,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C14R </td>
<td> 16k </td>
<td><code>0x001070</code></td>
<td><code>0x001670</code></td>
<td><i>FPdX_16k__C14R</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -485,7 +485,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C14T/P </td>
<td> 16k </td>
<td><code>0x001076</code></td>
<td><code>0x001676</code></td>
<td><i>FPdX_16k__C14TsP</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -494,7 +494,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> L14 </td>
<td> 16k </td>
<td><code>0x001073</code></td>
<td><code>0x001673</code></td>
<td><i>FPdX_16k__L14</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -503,7 +503,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C30R, C60R </td>
<td> 32k </td>
<td><code>0x002071</code></td>
<td><code>0x003271</code></td>
<td><i>FPdX_32k__C30R_C60R</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -512,7 +512,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C30T/P, C60T/P, C38AT, C40T </td>
<td> 32k </td>
<td><code>0x002077</code></td>
<td><code>0x003277</code></td>
<td><i>FPdX_32k__C30TsP_C60TsP_C38AT_C40T</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -521,7 +521,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> L30, L60 </td>
<td> 32k </td>
<td><code>0x002074</code></td>
<td><code>0x003274</code></td>
<td><i>FPdX_32k__L30_L60</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -551,7 +551,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> L40, L60 </td>
<td> 16k </td>
<td><code>0x00107F</code></td>
<td><code>0x00167F</code></td>
<td><i>FPdX0_16k__L40_L60</i></td>
<td align=center>⚠️</td>
<td align=center> ✅ </td>
@@ -563,7 +563,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C14R </td>
<td> 16k </td>
<td><code>0x0010A0</code></td>
<td><code>0x0016A0</code></td>
<td colspan="2"><i>FPdXH_16k__C14R</i></td>
<td align=center> ✅ </td>
<td align=center> ✅ </td>
@@ -571,7 +571,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C14T/P </td>
<td> 16k </td>
<td><code>0x0010A4</code></td>
<td><code>0x0016A4</code></td>
<td colspan="2"><i>FPdXH_16k__C14TsP</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -579,7 +579,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C30R, C40R, C60R </td>
<td> 32k </td>
<td><code>0x0020A1</code></td>
<td><code>0x0032A1</code></td>
<td colspan="2"><i>FPdXH_32k__C30R_C40R_C60R</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -587,7 +587,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C30T/P, C40T, C60T/P </td>
<td> 32k </td>
<td><code>0x0020A5</code></td>
<td><code>0x0032A5</code></td>
<td colspan="2"><i>FPdXH_32k__C30TsP_C40T_C60TsP</i></td>
<td align=center> ✅ </td>
<td align=center> ✅ </td>
@@ -595,7 +595,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C38AT </td>
<td> 32k </td>
<td><code>0x0020A7</code></td>
<td><code>0x0032A7</code></td>
<td colspan="2"><i>FPdXH_32k__C38AT</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -603,7 +603,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C40ET, C60ET </td>
<td> 32k </td>
<td><code>0x0020AE</code></td>
<td><code>0x0032AE</code></td>
<td colspan="2"><i>FPdXH_32k__C40ET_C60ET</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -611,7 +611,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> C60ETF </td>
<td> 32k </td>
<td><code>0x0020AF</code></td>
<td><code>0x0032AF</code></td>
<td colspan="2"><i>FPdXH_32k__C60ETF</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -619,7 +619,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> M4T/L </td>
<td> 32k </td>
<td><code>0x0020A8</code></td>
<td><code>0x0032A8</code></td>
<td colspan="2"><i>FPdXH_32k__M4TsL</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -627,7 +627,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> M8N16T/P </td>
<td> 32k </td>
<td><code>0x0020AC</code></td>
<td><code>0x0032AC</code></td>
<td colspan="2"><i>FPdXH_32k__M8N16TsP</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>
@@ -635,7 +635,7 @@ A5 <= Is the actual typecode, can overlap with others
<tr>
<td> M8N30T </td>
<td> 32k </td>
<td><code>0x0020AD</code></td>
<td><code>0x0032AD</code></td>
<td colspan="2"><i>FPdXH_32k__M8N30T</i></td>
<td align=center> ✅ </td>
<td align=center> ❌ </td>

View File

@@ -0,0 +1,2 @@
# Reading and writing programs

View File

@@ -145,6 +145,111 @@ FP-XH 16k C14R
| 2819 | System register size
| 20130000080070004 | ?
## FP0 5k C32,SL1
### %EE$RT
|Reponse Byte|Description|
|------------|-----------|
| 06 | Model code |
| 12 | Version |
| 05 | 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
| 41 | 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
| 0501 | Header size (no. of words) bcd
| 2819 | System register size
| 20130000080070004 | ?
## FP0 10k
### %EE$RT
|Reponse Byte|Description|
|------------|-----------|
| 42 | Model code |
| 12 | Version |
| 10 | 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
| 42 | Machine type
| 00 | Version (Fixed to 00)
| 10 | 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
| 1001 | Header size (no. of words) bcd
| 2819 | System register size
| 20130000080070004 | ?
## FP2SH 60k
### %EE$RT
|Reponse Byte|Description|
|------------|-----------|
| 60 | Model code |
| 12 | Version |
| 00 | 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
| 60 | Machine type
| 00 | Version (Fixed to 00)
| 00 | 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
| 6001 | Header size (no. of words) bcd
| 2819 | System register size
| 20130000000080004 | ?
# Mewtocol-7 Com
## Getting the status of the plc

View File

@@ -0,0 +1,16 @@
3 byte system registers, read with RR
|RR Adress|Interpreting type|Description|
|-|-|-|
|RR000|uint16|Program size steps capacity|
|RR005|uint16|Start address counter|
|RR006|uint16|Start address timer/counter|
|RR007|uint16|Start WR area (self reliant)|
|RR008 - RR009|uint32|Start DT area (self reliant)|
4 byte / 1 word system registers read with R
|WR Adress|Interpreting type|Description|
|-|-|-|
|R900|uint16|Self diag error|
|R902|uint16|Mode info|

View File

@@ -133,9 +133,9 @@ $"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" +
$"07 <= extended code (00 for non Mewtocol 7 devices)\n" +
$"0120 <= for 120k (Prog capacity), with RT/EXRT/MEW7 override order\n" +
$"A5 <= Is the actual typecode, with RT/EXRT/MEW7 override order\n" +
$"```"
);

View File

@@ -26,6 +26,7 @@ internal class Program {
//connect async to the plc
await plc.ConnectAsync();
await plc.SendCommandAsync($"%EE#RP0000000004");
//check if the connection was established
if (!plc.IsConnected) {
@@ -62,6 +63,14 @@ internal class Program {
plc.ConfigureConnection("192.168.115.214", 9094);
await plc.ConnectAsync();
plc.Disconnect();
plc.ConfigureConnection("192.168.178.55", 9094);
await plc.ConnectAsync();
//await plc.SendCommandAsync($"%EE#RR0000100");
//await plc.SendCommandAsync($"%EE#RCCR09030903");
await plc.SendCommandAsync($"%EE#RP0000000067");
}
//you can also find any applicable source endpoints by using:

View File

@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\MewtocolNet\MewtocolNet.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,11 @@
namespace Examples.ProgramReadWrite;
internal class Program {
static void Main(string[] args) {
MewtocolNet.ProgramParsing.PlcBinaryProgram.ParseFromFile(@"C:\Users\feli1\Documents\Test\prog4.fp").AnalyzeProgram();
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using CommandLine;
using MewtocolNet;
using MewtocolNet.ComCassette;
@@ -21,8 +22,9 @@ internal class ListSupportCommand : CommandLineExcecuteable {
var decomp = plcT.ToNameDecompose();
foreach (var name in decomp)
lst.Add(name);
if (decomp == null) continue;
lst.Add(decomp);
}

View File

@@ -19,9 +19,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Examples.Polling", "Example
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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "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}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AutoTools.DocBuilder", "AutoTools.DocBuilder\AutoTools.DocBuilder.csproj", "{00ACA0AB-3988-4EF7-98A6-B39A36B136DA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Examples.ProgramReadWrite", "Examples.ProgramReadWrite\Examples.ProgramReadWrite.csproj", "{51BDABAA-05B0-4802-AA37-243DAE22D5DC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -129,6 +131,18 @@ Global
{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
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|x64.ActiveCfg = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|x64.Build.0 = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|x86.ActiveCfg = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Debug|x86.Build.0 = Debug|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|Any CPU.Build.0 = Release|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|x64.ActiveCfg = Release|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|x64.Build.0 = Release|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|x86.ActiveCfg = Release|Any CPU
{51BDABAA-05B0-4802-AA37-243DAE22D5DC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -139,6 +153,7 @@ Global
{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}
{51BDABAA-05B0-4802-AA37-243DAE22D5DC} = {323729B0-5FB2-4592-9FA6-220C46BBF84C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {4ABB8137-CD8F-4691-9802-9ED371012F47}

View File

@@ -292,6 +292,16 @@ namespace MewtocolNet {
#region PLC Type Enum Parsing
/// <summary>
/// Gets synonim names for a plc type enum
/// </summary>
/// <returns>All or just one of there are no synonims for the same <see cref="PlcType"/></returns>
public static string[] GetSynonims (this PlcType plcType) {
return Enum.GetNames(typeof(PlcType)).Where(n => Enum.Parse(typeof(PlcType), n).Equals(plcType)).ToArray();
}
/// <summary>
/// Converts the enum to a plc name string
/// </summary>

View File

@@ -97,6 +97,13 @@ namespace MewtocolNet {
/// <returns>The success state of the write operation</returns>
Task<bool> RestartProgramAsync();
/// <summary>
/// Factory resets the PLC, this includes the current program
/// and data in the EEPROM
/// </summary>
/// <returns></returns>
Task FactoryResetAsync();
/// <summary>
/// Use this to await the first poll iteration after connecting,
/// This also completes if the initial connection fails

View File

@@ -102,6 +102,18 @@ namespace MewtocolNet {
}
/// <inheritdoc/>
public async Task FactoryResetAsync () {
//set to prog mode
await SetOperationModeAsync(false);
//reset plc
await SendCommandAsync($"%EE#0F");
await SendCommandAsync($"%EE#21");
}
#endregion
#region Byte range writing / reading to registers

View File

@@ -0,0 +1,152 @@
using System.Text;
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
namespace MewtocolNet.ProgramParsing {
public class PlcBinaryProgram {
static readonly Dictionary<ushort, string> stepCommands = new Dictionary<ushort, string> {
{ 0x00FF, "SUB 0" },
{ 0xB0FF, "DF" },
{ 0xFAF8, "ED" },
{ 0xFDF8, "RET" }, //return
{ 0xF6F8, "CALL" },
{ 0x21CC, "OT R501" },
{ 0x21AC, "ST R501" },
{ 0xF7FF, "ST R9010" },
};
// ST R50_1 21 AC => WR system area start was set to 50
// ST R57_1 91 AC => WR system area start was set to 57
// ST R901_3 F7 FF 53 A9
// ST R901_C F7 FF 5C A9
// AN/ R900_B F7 FF 4B 49
static readonly Dictionary<string, string> stepFunctions = new Dictionary<string, string> {
{ "F0", "MV" },
{ "F1", "DMV" },
{ "F2", "MVN" },
{ "F3", "DMVN" },
{ "F5", "BTM" },
{ "F8", "DMV2" },
{ "F11", "COPY" },
{ "F61", "DCMP" },
{ "F246", "CALL" },
};
const int STEP_BYTE_LEN = 2;
const int PROG_AUTHOR_INDEX = 57;
const int PROG_AUTHOR_MAX_CHARS = 12;
const int PROG_DESCRIPTION_INDEX = 17;
const int PROG_DESCRIPTION_MAX_CHARS = 40;
const int PROG_SIZE_START = 1139;
const int PROG_DATA_START = 1179;
public List<byte[]> rawSteps;
public string Author { get; internal set; }
public string Description { get; internal set; }
public static PlcBinaryProgram ParseFromFile (string path) {
var retInstance = new PlcBinaryProgram();
var rawBytes = File.ReadAllBytes(path);
if (rawBytes.Length < 2 || (rawBytes[0] != 0x46 && rawBytes[1] != 0x50))
throw new NotSupportedException("The loaded file was no FP file");
var rawString = Encoding.ASCII.GetString(rawBytes);
//get author and description
var progAuthor = Encoding.ASCII.GetString(rawBytes, PROG_AUTHOR_INDEX, PROG_AUTHOR_MAX_CHARS).Replace("\0", "");
var progDescription = Encoding.ASCII.GetString(rawBytes, PROG_DESCRIPTION_INDEX, PROG_DESCRIPTION_MAX_CHARS).Replace("\0", "");
var progSizeSteps = BitConverter.ToInt32(rawBytes, PROG_SIZE_START);
//improve performance later
var steps = new List<byte[]>();
for (int i = 0; i < progSizeSteps; i++) {
//00-FF F8 => 0-255 default function
//FF F8 => extended function, look for next step
var step = rawBytes.Skip(PROG_DATA_START + (i * STEP_BYTE_LEN)).Take(STEP_BYTE_LEN).ToArray();
steps.Add(step);
}
retInstance.rawSteps = steps;
return retInstance;
}
public void AnalyzeProgram () {
for (int i = 0; i < rawSteps.Count; i++) {
var step = rawSteps[i];
var stepAscii = Encoding.ASCII.GetString(step);
var stepBytesString = string.Join(" ", step.Select(x => x.ToString("X2")));
Console.Write($"{i,3} => {stepBytesString} ");
var stepKey = BitConverter.ToUInt16(step.Reverse().ToArray(), 0);
if (stepCommands.ContainsKey(stepKey)) {
Console.Write($"{stepCommands[stepKey]}");
} else if (stepKey == 0xFFF8) {
//custom function that goes over FF, the F instruction number is calced by
//the next step first byte plus 190
var nextStep = rawSteps[i + 1];
var stepID = nextStep[0] + 190;
string funcName = GetFunctionName($"F{stepID}");
Console.Write(funcName);
} else if (step[1] == 0xF8) {
string funcName = GetFunctionName($"F{step[0]}");
Console.Write(funcName);
}
//if (stepBytesString.StartsWith("F")) {
// Console.Write(" STEP COMMAND");
//}
Console.WriteLine();
}
Console.WriteLine();
}
private string GetFunctionName (string funcName) {
return stepFunctions.ContainsKey(funcName) ? $"{funcName} ({stepFunctions[funcName]})" : funcName;
}
}
}

View File

@@ -8,31 +8,33 @@ 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
// left to right
// 07 => Mewtocol7 type code (only for FP7 / ELC500 at this time)
// 0120 => prog size received from RT / EXRT message, the EXRT code always overrides the RT one (0x0120 == 120k)
// 41 => special identfier from RT / EXRT message, the EXRT code always overrides the RT one
//special codes prog size for float point vals are: ?? = 0.9k, 02 = 2.5k, 03 = 2.7k
/// <summary>
/// Type identifier of the plc
/// </summary>
public enum PlcType {
public enum PlcType : uint {
//NON SIMULATION TEST POSSIBLE
#region FP5 Family (Legacy)
/// <summary>
/// FP5 16k
/// </summary>
[PlcLegacy]
FP5_16k = 0x10_02,
FP5_16k = 0x0016_02,
/// <summary>
/// FP5 24k
/// </summary>
[PlcLegacy]
FP5_24k = 0x18_12,
FP5_24k = 0x0024_12,
#endregion
@@ -41,44 +43,46 @@ namespace MewtocolNet {
/// <summary>
/// FP2 16k
/// </summary>
[PlcLegacy]
FP2_16k = 0x10_50,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP2_16k = 0x0016_50,
/// <summary>
/// FP2 32k
/// </summary>
[PlcLegacy]
FP2_32k = 0x20_50,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP2_32k = 0x0032_50,
#endregion
//NON SIMULATION TEST POSSIBLE
#region FP3/FP-C Family (Legacy)
/// <summary>
/// FP3 10k
/// </summary>
[PlcLegacy]
FP3_10k = 0x0A_03,
FP3_10k = 0x0010_03,
/// <summary>
/// FP-C 16k
/// </summary>
[PlcLegacy]
FPdC_16k = 0x10_13,
FPdC_16k = 0x0016_13,
/// <summary>
/// FP3
/// </summary>
[PlcLegacy]
FP3_16k = FPdC_16k,
#endregion
//NON SIMULATION TEST POSSIBLE
#region FP1 / FPM Family (Legacy)
/// <summary>
/// FP1 0.9k C14,C16
/// </summary>
[PlcLegacy]
FP1_0c9k__C14_C16 = 0x00_04,
FP1_0c9k__C14_C16 = 0x0000_04,
/// <summary>
/// FP-M 0.9k C16T
/// </summary>
@@ -88,7 +92,7 @@ namespace MewtocolNet {
/// FP1 2.7k C24,C40
/// </summary>
[PlcLegacy]
FP1_2c7k__C24_C40 = 0x03_05,
FP1_2c7k__C24_C40 = 0x0003_05,
/// <summary>
/// FP-M 2.7k C20R,C20T,C32T
/// </summary>
@@ -98,7 +102,7 @@ namespace MewtocolNet {
/// FP1 5.0k C56,C72
/// </summary>
[PlcLegacy]
FP1_5k__C56_C72 = 0x00_06,
FP1_5k__C56_C72 = 0x0005_06,
/// <summary>
/// FPM 5.0k C20RC,C20TC,C32TC
/// </summary>
@@ -107,13 +111,14 @@ namespace MewtocolNet {
#endregion
//NON SIMULATION TEST POSSIBLE
#region FP10 Family (Legacy)
/// <summary>
/// FP10S 30k
/// </summary>
[PlcLegacy]
FP10S_30k = 0x1E_20,
FP10S_30k = 0x0030_20,
/// <summary>
/// FP10 30k
/// </summary>
@@ -123,27 +128,28 @@ namespace MewtocolNet {
/// FP10 60k
/// </summary>
[PlcLegacy]
FP10_60k = 0x3C_20,
FP10_60k = 0x0060_20,
#endregion
//NON SIMULATION TEST POSSIBLE
#region FP10SH Family (Legacy)
/// <summary>
/// FP10SH 30k
/// </summary>
[PlcLegacy]
FP10SH_30k = 0x1E_30,
[PlcLegacy, PlcEXRT]
FP10SH_30k = 0x0030_30,
/// <summary>
/// FP10SH 60k
/// </summary>
[PlcLegacy]
FP10SH_60k = 0x3C_30,
[PlcLegacy, PlcEXRT]
FP10SH_60k = 0x0060_30,
/// <summary>
/// FP10SH 120k
/// </summary>
[PlcLegacy]
FP10SH_120k = 0x78_30,
[PlcLegacy, PlcEXRT]
FP10SH_120k = 0x0120_30,
#endregion
@@ -152,53 +158,55 @@ namespace MewtocolNet {
/// <summary>
/// FP0 2.7k C10,C14,C16
/// </summary>
[PlcLegacy]
FP0_2c7k__C10_C14_C16 = 0x03_40,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP0_2c7k__C10_C14_C16 = 0x0003_40,
/// <summary>
/// FP0 5k
/// </summary>
[PlcLegacy]
FP0_5k__C32_SL1 = 0x00_41,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP0_5k__C32_SL1 = 0x0005_41,
/// <summary>
/// FP0 10k
/// </summary>
[PlcLegacy]
FP0_10c0k__T32 = 0x0A_42,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP0_10c0k__T32 = 0x0010_42,
#endregion
//PARTIAL SIMULATION TEST POSSIBLE
#region FP-Sigma Family (Legacy)
/// <summary>
/// FP-SIGMA 12k
/// </summary>
[PlcLegacy, PlcEXRT]
FPdSIGMA_12k = 0x0C_43,
FPdSIGMA_12k = 0x0012_43,
/// <summary>
/// FP-SIGMA 32k
/// </summary>
[PlcLegacy, PlcEXRT]
FPdSIGMA_32k = 0x20_44,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FPdSIGMA_32k = 0x0032_44,
/// <summary>
/// FP-SIGMA 16k
/// </summary>
[PlcLegacy, PlcEXRT]
FPdSIGMA_16k = 0x10_E1,
FPdSIGMA_16k = 0x0016_E1,
/// <summary>
/// FP-SIGMA 40k (never supported)
/// </summary>
[PlcLegacy, PlcEXRT]
FPdSIGMA_40k = 0x28_E1,
FPdSIGMA_40k = 0x0040_E1,
#endregion
//NON SIMULATION TEST POSSIBLE
#region FP-e Family (Legacy)
/// <summary>
/// FP-e 2.7k
/// </summary>
[PlcLegacy, PlcEXRT]
FPde_2c7k = 0x03_45,
FPde_2c7k = 0x0003_45,
#endregion
@@ -207,23 +215,23 @@ namespace MewtocolNet {
/// <summary>
/// FP0R 16k C10,C14,C16
/// </summary>
[PlcEXRT]
FP0R_16k__C10_C14_C16 = 0x46,
[PlcEXRT, PlcCodeTested]
FP0R_16k__C10_C14_C16 = 0x0016_46,
/// <summary>
/// FP0R 32k C32
/// </summary>
[PlcEXRT]
FP0R_32k__C32 = 0x20_47,
[PlcEXRT, PlcCodeTested]
FP0R_32k__C32 = 0x0032_47,
/// <summary>
/// FP0R 32k T32
/// </summary>
[PlcEXRT]
FP0R_32k__T32 = 0x20_48,
[PlcEXRT, PlcCodeTested]
FP0R_32k__T32 = 0x0032_48,
/// <summary>
/// FP0R 32k F32
/// </summary>
[PlcEXRT]
FP0R_32k__F32 = 0x20_49,
[PlcEXRT, PlcCodeTested]
FP0R_32k__F32 = 0x0032_49,
#endregion
@@ -232,18 +240,18 @@ namespace MewtocolNet {
/// <summary>
/// FP2SH 32k
/// </summary>
[PlcLegacy, PlcEXRT]
FP2SH_32k = 0x20_62,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP2SH_32k = 0x0032_62,
/// <summary>
/// FP2SH 60k
/// </summary>
[PlcLegacy, PlcEXRT]
FP2SH_60k = 0x3C_60,
[PlcLegacy, PlcEXRT, PlcCodeTested]
FP2SH_60k = 0x0060_60,
/// <summary>
/// FP2SH 120k
/// </summary>
[PlcLegacy, PlcEXRT]
FP2SH_120k = 0x78_E0,
FP2SH_120k = 0x0120_60,
#endregion
@@ -253,52 +261,52 @@ namespace MewtocolNet {
/// FP-X 16k C14R
/// </summary>
[PlcLegacy, PlcEXRT, PlcCodeTested]
FPdX_16k__C14R = 0x10_70,
FPdX_16k__C14R = 0x0016_70,
/// <summary>
/// FP-X 32k C30R,C60R
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX_32k__C30R_C60R = 0x20_71,
FPdX_32k__C30R_C60R = 0x0032_71,
/// <summary>
/// FP-X0 2.5k L14,L30
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX0_2c5k__L14_L30 = 0x02_72,
FPdX0_2c5k__L14_L30 = 0x0002_72,
/// <summary>
/// FP-X 16k L14
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX_16k__L14 = 0x10_73,
FPdX_16k__L14 = 0x0016_73,
/// <summary>
/// FP-X 32k L30,L60
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX_32k__L30_L60 = 0x20_74,
FPdX_32k__L30_L60 = 0x0032_74,
/// <summary>
/// FP-X0 8k L40,L60
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX0_8k__L40_L60 = 0x08_75,
FPdX0_8k__L40_L60 = 0x0008_75,
/// <summary>
/// FP-X 16k C14T/P
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX_16k__C14TsP = 0x10_76,
FPdX_16k__C14TsP = 0x0016_76,
/// <summary>
/// FP-X 32k C30T/P,C60T/P,C38AT,C40T
/// </summary>
[PlcLegacy, PlcEXRT, PlcCodeTested]
FPdX_32k__C30TsP_C60TsP_C38AT_C40T = 0x20_77,
FPdX_32k__C30TsP_C60TsP_C38AT_C40T = 0x0032_77,
/// <summary>
/// FP-X 2.5k C40RT0A
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX_2c5k__C40RT0A = 0x02_7A,
FPdX_2c5k__C40RT0A = 0x0002_7A,
/// <summary>
/// FP-X0 16k L40,L60
/// </summary>
[PlcLegacy, PlcEXRT]
FPdX0_16k__L40_L60 = 0x10_7F,
FPdX0_16k__L40_L60 = 0x0016_7F,
#endregion
@@ -308,52 +316,52 @@ namespace MewtocolNet {
/// FP-XH 16k C14R
/// </summary>
[PlcEXRT, PlcCodeTested]
FPdXH_16k__C14R = 0x10_A0,
FPdXH_16k__C14R = 0x0016_A0,
/// <summary>
/// FP-XH 32k C30R,C40R,C60R
/// </summary>
[PlcEXRT]
FPdXH_32k__C30R_C40R_C60R = 0x20_A1,
FPdXH_32k__C30R_C40R_C60R = 0x0032_A1,
/// <summary>
/// FP-XH 16k C14T/P
/// </summary>
[PlcEXRT]
FPdXH_16k__C14TsP = 0x10_A4,
FPdXH_16k__C14TsP = 0x0016_A4,
/// <summary>
/// FP-XH 32k C30T/P,C40T,C60T/P
/// </summary>
[PlcEXRT, PlcCodeTested]
FPdXH_32k__C30TsP_C40T_C60TsP = 0x20_A5,
FPdXH_32k__C30TsP_C40T_C60TsP = 0x0032_A5,
/// <summary>
/// FP-XH 32k C38AT
/// </summary>
[PlcEXRT]
FPdXH_32k__C38AT = 0x20_A7,
FPdXH_32k__C38AT = 0x0032_A7,
/// <summary>
/// FP-XH 32k M4T/L
/// </summary>
[PlcEXRT]
FPdXH_32k__M4TsL = 0x20_A8,
FPdXH_32k__M4TsL = 0x0032_A8,
/// <summary>
/// FP-XH 32k M8N16T/P (RTEX)
/// </summary>
[PlcEXRT]
FPdXH_32k__M8N16TsP = 0x20_AC,
FPdXH_32k__M8N16TsP = 0x0032_AC,
/// <summary>
/// FP-XH 32k M8N30T (RTEX)
/// </summary>
[PlcEXRT]
FPdXH_32k__M8N30T = 0x20_AD,
FPdXH_32k__M8N30T = 0x0032_AD,
/// <summary>
/// FP-XH 32k C40ET,C60ET
/// </summary>
[PlcEXRT]
FPdXH_32k__C40ET_C60ET = 0x20_AE,
FPdXH_32k__C40ET_C60ET = 0x0032_AE,
/// <summary>
/// FP-XH 32k C60ETF
/// </summary>
[PlcEXRT]
FPdXH_32k__C60ETF = 0x20_AF,
FPdXH_32k__C60ETF = 0x0032_AF,
#endregion
@@ -363,12 +371,12 @@ namespace MewtocolNet {
/// FP0H 32k C32T/P
/// </summary>
[PlcEXRT]
FP0H_32k__C32TsP = 0x20_B0,
FP0H_32k__C32TsP = 0x0032_B0,
/// <summary>
/// FP0H 32k C32ET/EP
/// </summary>
[PlcEXRT]
FP0H_32k__C32ETsEP = 0x20_B1,
FP0H_32k__C32ETsEP = 0x0032_B1,
#endregion
@@ -377,31 +385,31 @@ namespace MewtocolNet {
/// <summary>
/// FP7 CPS41E (Series code 7)
/// </summary>
FP7_196k__CPS41E = 0x07_C4_03,
FP7_196k__CPS41E = 0x07_0196_03,
/// <summary>
/// FP7 CPS31E (Series code 7)
/// </summary>
FP7_120k__CPS31E = 0x07_78_04,
FP7_120k__CPS31E = 0x07_0120_04,
/// <summary>
/// FP7 CPS31 (Series code 7)
/// </summary>
FP7_120k__CPS31 = 0x07_78_05,
FP7_120k__CPS31 = 0x07_0120_05,
/// <summary>
/// FP7 CPS41ES (Series code 7)
/// </summary>
FP7_196k__CPS41ES = 0x07_C4_06,
FP7_196k__CPS41ES = 0x07_0196_06,
/// <summary>
/// FP7 CPS31ES (Series code 7)
/// </summary>
FP7_120k__CPS31ES = 0x07_78_07,
FP7_120k__CPS31ES = 0x07_0120_07,
/// <summary>
/// FP7 CPS31S (Series code 7)
/// </summary>
FP7_120k__CPS31S = 0x07_78_08,
FP7_120k__CPS31S = 0x07_0120_08,
/// <summary>
/// FP7 CPS21 (Series code 7)
/// </summary>
FP7_64k__CPS21 = 0x07_40_09,
FP7_64k__CPS21 = 0x07_0064_09,
#endregion
@@ -411,7 +419,7 @@ namespace MewtocolNet {
/// EcoLogiX (Series code 7)
/// </summary>
[PlcLegacy]
ECOLOGIX_0k__ELC500 = 0x07_00_10,
ECOLOGIX_0k__ELC500 = 0x07_0000_10,
#endregion

View File

@@ -3,17 +3,64 @@ using Xunit;
using Xunit.Abstractions;
using MewtocolNet.Helpers;
using Newtonsoft.Json.Linq;
using System.Linq;
namespace MewtocolTests {
public class TestPlcTypeEnumDuplicates {
private readonly List<string[]> allowedSynonims = new() {
PlcType.FP1_0c9k__C14_C16.GetSynonims(),
PlcType.FPdM_2c7k__C20R_C20T_C32T.GetSynonims(),
PlcType.FPdM_5k__C20RC_C20TC_C32TC.GetSynonims(),
PlcType.FPdC_16k.GetSynonims(),
PlcType.FP10S_30k.GetSynonims(),
};
private readonly ITestOutputHelper output;
public TestPlcTypeEnumDuplicates(ITestOutputHelper output) {
this.output = output;
}
[Fact(DisplayName = "Check if the PLC type enums contain duplicates")]
public void NumericRegisterMewtocolIdentifiers() {
int nameCount = Enum.GetNames<PlcType>().Length;
int enumCount = Enum.GetValues<PlcType>().Cast<int>().Distinct().Count();
var groupedCodes = Enum.GetValues<PlcType>().Cast<int>().GroupBy(x => x);
foreach (var item in groupedCodes) {
if (item.Count() <= 1) continue;
output.WriteLine($"Code: {item.Key.ToString("X6")}");
var synonims = ((PlcType)item.Key).GetSynonims();
var sononymousGroup = allowedSynonims.FirstOrDefault(x => x.Contains(synonims.First()));
if (sononymousGroup == null) Assert.Fail($"The synonymous group doesn't exist ({synonims.First()})");
Assert.Equal(sononymousGroup.OrderBy(x => x).ToArray(), synonims.OrderBy(x => x).ToArray());
foreach (var syn in synonims) {
output.WriteLine($"Synonim: {syn}");
}
}
output.WriteLine($"Indivual names: {nameCount}");
output.WriteLine($"Indivual enums: {enumCount}");
}
}
}