mirror of
https://github.com/OpenLogics/MewtocolNet.git
synced 2025-12-06 03:01:24 +00:00
Merge branch 'master' of https://github.com/WOmed/MewtocolNet
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -13,6 +13,8 @@
|
||||
#ignore builds
|
||||
Builds/
|
||||
|
||||
.vscode
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
|
||||
26
.vscode/launch.json
vendored
26
.vscode/launch.json
vendored
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"name": ".NET Core Launch (console)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/Examples/bin/Debug/net5.0/Examples.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}/Examples",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach"
|
||||
}
|
||||
]
|
||||
}
|
||||
42
.vscode/tasks.json
vendored
42
.vscode/tasks.json
vendored
@@ -1,42 +0,0 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"build",
|
||||
"${workspaceFolder}/Examples/Examples.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "publish",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"publish",
|
||||
"${workspaceFolder}/Examples/Examples.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "watch",
|
||||
"command": "dotnet",
|
||||
"type": "process",
|
||||
"args": [
|
||||
"watch",
|
||||
"run",
|
||||
"${workspaceFolder}/Examples/Examples.csproj",
|
||||
"/property:GenerateFullPaths=true",
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 WOLF Medizintechnik GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
194
README.md
194
README.md
@@ -1,39 +1,187 @@
|
||||
# MewtocolNet
|
||||
A Mewtocol protocol library to interface with Panasonic PLCs over TCP/Serial.
|
||||
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).
|
||||
|
||||
# Features
|
||||
|
||||
> Features that are not checked still need implementation
|
||||
|
||||
- [x] Read out stats from your PLC
|
||||
- [x] Read and write registers in real time
|
||||
- [X] Dynamic register type casting from properties
|
||||
- [ ] Change run / prog modes
|
||||
- [ ] Write byte blocks in a whole chain
|
||||
- [ ] Upload programs to the PLC
|
||||
- [ ] Download programs from the PLC
|
||||
- [ ] Reading / writing PLC system registers
|
||||
|
||||
# Support
|
||||
|
||||
## .NET Support
|
||||
|
||||
This library was written in **netstandard2.0** and should by compatible with a lot of .NET environments.
|
||||
|
||||
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
|
||||
|
||||
|PLC Type|Supported|Tested|
|
||||
|--------|---------|------|
|
||||
FPX C14 |✔ |✔ |
|
||||
FPX C30 |✔ |✔ |
|
||||
FPX-H C14|✔ |✔ |
|
||||
FPX-H C30|✔ |✔ |
|
||||
FP Sigma |✔ |❌ |
|
||||
|
||||
Where is the RS232/Serial support?
|
||||
|
||||
> Support for the serial protocol will be added soon, feel free to contribute
|
||||
|
||||
# Protocol description
|
||||
|
||||
Panasonic has published a [protocol definition](https://mediap.industry.panasonic.eu/assets/custom-upload/Factory%20&%20Automation/PLC/Manuals/mn_all_plcs_mewtocol_user_pidsx_en.pdf) on their site.
|
||||
Refer to this site if you want to see the general functionality or add / report missing features.
|
||||
|
||||
> This library is at the time not feature complete, but all essential features are provided
|
||||
|
||||
# Usage
|
||||
|
||||
1. Connecting to a PLC
|
||||
See [More examples](/Examples) here
|
||||
|
||||
## Connecting to a PLC
|
||||
|
||||
Connecting to a PLC is as simple as
|
||||
|
||||
```C#
|
||||
//Create a new interface class with your PLCs IP address and port
|
||||
MewtocolInterface interf = new MewtocolInterface("127.0.0.1", 9094);
|
||||
//attaching a logger
|
||||
Logger.LogLevel = LogLevel.Verbose;
|
||||
Logger.OnNewLogMessage((date, msg) => {
|
||||
Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}");
|
||||
});
|
||||
|
||||
//Setup the dataregisters of the PLC you want to read
|
||||
interf.AddRegister<short>("Test Integer",1204);
|
||||
interf.AddRegister<string>(1101, 4);
|
||||
//setting up a new PLC interface
|
||||
MewtocolInterface interf = new MewtocolInterface("10.237.191.3");
|
||||
|
||||
//attaches an auto reader that polls the registers
|
||||
interf.WithPoller();
|
||||
await interf.ConnectAsync();
|
||||
```
|
||||
|
||||
//triggers when a dataregister changes its value
|
||||
interf.RegisterChanged += (o) => {
|
||||
Console.WriteLine($"DT{o.MemoryAdress} {(o.Name != null ? $"({o.Name}) " : "")}changed to {o.GetValueString()}");
|
||||
};
|
||||
You can also use the callbacks of the `ConnectAsync()` method to do something after the initial connection establishment.
|
||||
|
||||
//Connects to the PLC asynchronous and invokes connected or failed
|
||||
```C#
|
||||
await interf.ConnectAsync(
|
||||
(plcinf) => {
|
||||
|
||||
Console.WriteLine("Connected to PLC:\n" + plcinf.ToString());
|
||||
|
||||
//read back a register value
|
||||
var statusNum = (NRegister<short>)interf.Registers[1204];
|
||||
Console.WriteLine($"Status num is: {statusNum.Value}");
|
||||
|
||||
//PLC connected
|
||||
(plc) => {
|
||||
if(plcinf.OperationMode.RunMode)
|
||||
Console.WriteLine("PLC is in RUN");
|
||||
},
|
||||
//Connection failed
|
||||
() => {
|
||||
Console.WriteLine("Failed connection");
|
||||
Console.WriteLine("PLC failed to connect");
|
||||
}
|
||||
);
|
||||
```
|
||||
## Reading data registers / contacts
|
||||
|
||||
- Create a new class that inherits from `RegisterCollectionBase`
|
||||
|
||||
```C#
|
||||
public class TestRegisters : RegisterCollectionBase {
|
||||
|
||||
//corresponds to a R100 boolean register in the PLC
|
||||
[Register(100, RegisterType.R)]
|
||||
public bool TestBool1 { get; private set; }
|
||||
|
||||
//corresponds to a XD input of the PLC
|
||||
[Register(RegisterType.X, SpecialAddress.D)]
|
||||
public bool TestBoolInputXD { get; private set; }
|
||||
|
||||
//corresponds to a DT7012 - DT7013 as a 32bit time value that gets parsed as a timespan (TIME)
|
||||
//the smallest value to communicate to the PLC is 10ms
|
||||
[Register(7012)]
|
||||
public TimeSpan TestTime { get; private set; }
|
||||
|
||||
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
|
||||
[Register(1101, 4)]
|
||||
public string TestString1 { get; private set; }
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
- Connect to the PLC and attach the register collection and logger
|
||||
- attach an automatic poller by chaining `.WithPoller()` after the register attachment
|
||||
|
||||
```C#
|
||||
//attaching a logger
|
||||
Logger.LogLevel = LogLevel.Verbose;
|
||||
Logger.OnNewLogMessage((date, msg) => {
|
||||
Console.WriteLine($"{date.ToString("HH:mm:ss")} {msg}");
|
||||
});
|
||||
|
||||
//setting up a new PLC interface and register collection
|
||||
MewtocolInterface interf = new MewtocolInterface("192.168.115.3");
|
||||
TestRegisters registers = new TestRegisters();
|
||||
|
||||
//attaching the register collection and an automatic poller
|
||||
interf.WithRegisterCollection(registers).WithPoller();
|
||||
|
||||
await interf.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
|
||||
|
||||
⚠ **Never set a register by setting the property, always use one of the provided methods**
|
||||
|
||||
### Synchronous
|
||||
|
||||
Sets the register without feedback if it was set
|
||||
|
||||
```C#
|
||||
//inverts the boolean register
|
||||
interf.SetRegister(nameof(registers.TestBool1), !registers.TestBool1);
|
||||
|
||||
//set the current second to the PLCs TIME register
|
||||
interf.SetRegister(nameof(registers.TestTime), TimeSpan.FromSeconds(DateTime.Now.Second));
|
||||
|
||||
//writes 'Test' to the PLCs string register
|
||||
interf.SetRegister(nameof(registers.TestString1), "Test");
|
||||
```
|
||||
|
||||
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#
|
||||
interf.AddRegister<bool>(105, _name: "ManualBoolRegister");
|
||||
```
|
||||
|
||||
Reading the value of the manually added register
|
||||
```C#
|
||||
//get the value as a string
|
||||
string value = interf.GetRegister("ManualBoolRegister").GetValueString();
|
||||
//get the value by casting
|
||||
bool value2 = interf.GetRegister<BRegister>("ManualBoolRegister").Value;
|
||||
//for double casted ones like numbers
|
||||
var value2 = interf.GetRegister<NRegister<short>>("NumberRegister").Value;
|
||||
```
|
||||
|
||||
### Asynchronous
|
||||
|
||||
Sets the register waiting for the PLC to confirm it was set
|
||||
|
||||
```C#
|
||||
//inverts the boolean register
|
||||
interf.SetRegisterAsync(nameof(registers.TestBool1), !registers.TestBool1);
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user