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); ```