From 40016a5fa5c6495ae90bdd632ee911cdf82c2c49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:24:33 +0200 Subject: [PATCH 1/4] Update README.md --- README.md | 168 ++++++++++++++++++++++++------------------------------ 1 file changed, 76 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 1513bce..fda323b 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,22 @@ [![Publish pipeline](https://github.com/WOmed/MewtocolNet/actions/workflows/publish-pipeline.yml/badge.svg)](https://github.com/WOmed/MewtocolNet/actions/workflows/publish-pipeline.yml) [![Test pipeline](https://github.com/WOmed/MewtocolNet/actions/workflows/test-pipeline.yml/badge.svg)](https://github.com/WOmed/MewtocolNet/actions/workflows/test-pipeline.yml) [![GitHub tag](https://img.shields.io/github/v/tag/WOmed/MewtocolNet?label=Package%20Version)](https://github.com/WOmed/MewtocolNet/pkgs/nuget/Mewtocol.NET) -[![gencov](https://github.com/WOmed/MewtocolNet/blob/badges/Builds/TestResults/badge_combined_master.svg)](https://htmlpreview.github.io/?https://github.com/WOmed/MewtocolNet/blob/badges/Builds/TestResults/summary_master.html) +[![gencov](../badges/Builds/TestResults/badge_combined_master.svg)](https://htmlpreview.github.io/?https://github.com/WOmed/MewtocolNet/blob/badges/Builds/TestResults/summary_master.html) ![GitHub](https://img.shields.io/github/license/WOmed/MewtocolNet?label=License) ![Status](https://img.shields.io/badge/Status-In%20dev-orange) # MewtocolNet An easy to use Mewtocol protocol library to interface with Panasonic PLCs over TCP/Serial. -## Disclaimer -This library is not an official panasonic product nor does panasonic provide financial support or limitations in any form. -This software was written by WOLF Medizintechnik GmbH (@WOmed/dev). +> ⚠️ This library is not an official panasonic product nor does panasonic provide financial support or limitations in any form. +> This software was written by WOLF Medizintechnik GmbH (@WOmed/dev). + +# PLC Support + +## For a full list check [this table](../master_auto_docs/plctypes.md) + +> This library was only tested with a few PLCs, other types that support the Panasonic Mewtocol protocol might work. +> Use at your own risk, others might follow with community feedback # Features @@ -32,18 +38,7 @@ This library was written in **netstandard2.0** and should be compatible with a l For a full list of supported .NET clrs see [this page](https://docs.microsoft.com/de-de/dotnet/standard/net-standard?tabs=net-standard-2-0#select-net-standard-version) -## PLC Support - -> This library was only tested with a few PLCs, other types that support the Panasonic Mewtocol protocol might work. -> Use at your own risk, others might follow with community feedback - -For a **Support List** check [this table](AutoTools.DocBuilder/Docs/plctypes.md) - -Where is the RS232/Serial support? - -> Support for the serial protocol will be added soon, feel free to contribute - -# Installing +# Installation Use the dotnet CLI and run ```Shell @@ -57,51 +52,51 @@ Refer to this site if you want to see the general functionality or add / report > This library is at the time not feature complete, but all essential features are provided -# Usage +# Examples -See [More examples](/Examples) here +To see a full list of examples [click here](/Examples). ## Connecting to a PLC Connecting to a PLC is as simple as ```C# - //attaching a logger -Logger.LogLevel = LogLevel.Verbose; -Logger.OnNewLogMessage((date, msg) => { - Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}"); -}); +using (var plc = Mewtocol.Ethernet("192.168.178.55").Build()) { -//setting up a new PLC interface -MewtocolInterface plc = new MewtocolInterface("192.168.115.5"); + await plc.ConnectAsync(); + if (!plc.IsConnected) { + Console.WriteLine("Failed to connect to the plc..."); + } else { + Console.WriteLine(plc.PlcInfo); + } -await plc.ConnectAsync(); +} ``` ## Reading data registers / contacts [Detailed instructions](https://github.com/WOmed/MewtocolNet/wiki/Attribute-handled-reading) -- Create a new class that inherits from `RegisterCollectionBase` +- Create a new class that inherits from `RegisterCollection` ```C# -public class TestRegisters : RegisterCollectionBase { +public class TestRegisters : RegisterCollection { //corresponds to a R100 boolean register in the PLC - [Register(100, RegisterType.R)] + [Register("R100")] public bool TestBool1 { get; private set; } //corresponds to a XD input of the PLC - [Register(RegisterType.X, SpecialAddress.D)] + [Register("XD")] public bool TestBoolInputXD { get; private set; } - //corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME) + //corresponds to a DDT7012 - DDT7013 as a 32bit time value that gets parsed as a timespan (TIME) //the smallest value to communicate to the PLC is 10ms - [Register(7012)] + [Register("DDT7012")] public TimeSpan TestTime { get; private set; } //corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4]) - [Register(1101, 4)] + [Register("DT1101", "STRING[4]")] public string TestString1 { get; private set; } } @@ -111,80 +106,69 @@ public class TestRegisters : RegisterCollectionBase { - attach an automatic poller by chaining `.WithPoller()` after the register attachment ```C# -//setting up a new PLC interface and register collection -MewtocolInterface plc = new MewtocolInterface("192.168.115.5"); -TestRegisters registers = new TestRegisters(); -//attaching the register collection and an automatic poller -plc.WithRegisterCollection(registers).WithPoller(); +TestRegisters registers = null; + +//setting up a new PLC serial interface and tell it to use the register collection +var plc = Mewtocol.Serial("COM4", BaudRate._19200) +.WithPoller() +.WithRegisterCollections(c => { + registers = c.AddCollection(); + // or use + // c.AddCollection(new TestRegisters()); + // if you want to pass data to a constructor +}) +.Build(); + +//connect to it +await plc.ConnectAsync(async () => { + + //restart the plc program during the connection process + await plc.RestartProgramAsync(); + +}); + +//wait for the first data cycle of the poller module +//otherwise the property value might still be unset or null +await App.ViewModel.Plc.AwaitFirstDataCycleAsync(); + +if (App.ViewModel.Plc.IsConnected) { + + Console.WriteLine(registers.TestBool1); + +} -await plc.ConnectAsync( - (plcinf) => { - //reading a value from the register collection - Console.WriteLine($"Time Value is: {registers.TestTime}"); - } -); ``` - Your properties are getting automatically updated after the initial connection > Note! this is not your only option to read registers, see here -## Writing data registers / contacts +## Reading & Writing -Registers are stored in an underlying layer for automatic handling, each register has a unique name and address. +In addition to the automatic property binding you can use these patterns: -Classes that derive from `RegisterCollectionBase` reference these registers automatically using attributes. -All the heavy lifting is done automatically for you, setting this up is described [here](https://github.com/WOmed/MewtocolNet/wiki/Attribute-handled-reading) - -### Asynchronous - -This operations awaits a task to make sure the register was actually set to your desired value before progressing +### Reading & Writing by using the anonymous builder pattern ```C# -//sets the register to false -await plc.SetRegisterAsync(nameof(registers.TestBool1), false); +await plc.Register.Struct("DT100").WriteAsync(100); -//set the current second to the PLCs TIME register -await plc.SetRegisterAsync(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second)); +var value = await plc.Register.Struct("DT100").ReadAsync(); ``` - -### Synchronous - -Sets the register without feedback if it was set - -You can use the method to set a register +### Reading & Writing by using the direct reference from the builder pattern ```C# -//inverts the boolean register -plc.SetRegister(nameof(registers.TestBool1), !registers.TestBool1); -//set the current second to the PLCs TIME register -plc.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second)); +IRegister outputContactReference; - //writes 'Test' to the PLCs string register -plc.SetRegister(nameof(registers.TestString1), "Test"); -``` - -or write to a register in your `RegisterCollectionBase` directly (you need to attach a register collection to your interface beforehand) - -```C# -//inverts the boolean register -registers.TestBool1 = true; -``` - -You can also set a register by calling its name directly (Must be either in an attached register collection or added to the list manually) - -Adding registers to a manual list -```C# -plc.AddRegister(105, _name: "ManualBoolRegister"); -``` - -Reading the value of the manually added register -```C# -//get the value as a string -string value = plc.GetRegister("ManualBoolRegister").GetValueString(); -//get the value by casting -bool value2 = plc.GetRegister("ManualBoolRegister").Value; -//for double casted ones like numbers -var value2 = plc.GetRegister>("NumberRegister").Value; +var plc = Mewtocol.Ethernet("127.0.0.1") +.WithRegisters(b => { + + b.Bool("Y4").Build(out outputContactReference); + +}) +.Build(); + +await plc.ConnectAsync(); + +await outputContactReference.WriteAsync(true); ``` From b3909e3f4b525c45ec7ddef4aade2c63efb2f598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:36:20 +0200 Subject: [PATCH 2/4] Update README.md --- README.md | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index fda323b..4da0aba 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,28 @@ An easy to use Mewtocol protocol library to interface with Panasonic PLCs over T # Features -> Features that are not checked still need implementation +## Fully implemented -- [x] Read out stats from your PLC +- [x] TCP/IP and Serial Port support +- [x] Get type and hardware information of PLCs +- [x] Get PLC program metadata such as program version and IDs - [x] Read and write registers in real time -- [x] Dynamic register type casting from properties -- [x] Change run / prog modes -- [x] Write / read byte blocks in a whole chain +- [x] Basic data types / structures support +- [x] Fast readback cycles due to a MemoryManager that optimizes TCP / Serial frames by combining areas +- [x] Fully customizable heartbeats and polling levels (tell the interface when you need register updates) +- [x] Easy to use builder patterns for interface and register generation +- [x] Register type casting from property attributes +- [x] Change RUN / PROG modes +- [x] Delete Programs +- [x] Write / read low level byte blocks to areas +- [x] Scanning for network devices and change network settings (WDConfigurator features) + +# Planned + - [ ] Upload / Download programs to the PLC - [ ] Reading / writing PLC system registers +- [ ] Advanced data structures like SDTs and SDT Arrays +- [ ] Custom open source program compiler for PLC cpus # Support From b17fcfeff99cc3125aa343a78526ed369776a2b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:38:36 +0200 Subject: [PATCH 3/4] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4da0aba..ea49c71 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,8 @@ To see a full list of examples [click here](/Examples). Connecting to a PLC is as simple as ```C# +using MewtocolNet; + using (var plc = Mewtocol.Ethernet("192.168.178.55").Build()) { await plc.ConnectAsync(); @@ -93,6 +95,9 @@ using (var plc = Mewtocol.Ethernet("192.168.178.55").Build()) { - Create a new class that inherits from `RegisterCollection` ```C# +using MewtocolNet; +using MewtocolNet.RegisterAttributes; + public class TestRegisters : RegisterCollection { //corresponds to a R100 boolean register in the PLC @@ -119,7 +124,6 @@ public class TestRegisters : RegisterCollection { - attach an automatic poller by chaining `.WithPoller()` after the register attachment ```C# - TestRegisters registers = null; //setting up a new PLC serial interface and tell it to use the register collection From bd907b80df211327823d9d8884273fbb0ce4ad4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Wei=C3=9F?= <72068105+Sandoun@users.noreply.github.com> Date: Mon, 21 Aug 2023 15:39:59 +0200 Subject: [PATCH 4/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ea49c71..867ea3d 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![GitHub tag](https://img.shields.io/github/v/tag/WOmed/MewtocolNet?label=Package%20Version)](https://github.com/WOmed/MewtocolNet/pkgs/nuget/Mewtocol.NET) [![gencov](../badges/Builds/TestResults/badge_combined_master.svg)](https://htmlpreview.github.io/?https://github.com/WOmed/MewtocolNet/blob/badges/Builds/TestResults/summary_master.html) ![GitHub](https://img.shields.io/github/license/WOmed/MewtocolNet?label=License) -![Status](https://img.shields.io/badge/Status-In%20dev-orange) +![Status](https://img.shields.io/badge/Status-Stable-orange) # MewtocolNet An easy to use Mewtocol protocol library to interface with Panasonic PLCs over TCP/Serial.