Repository: fbarresi/Sharp7
Branch: master
Commit: a3f11b2e0526
Files: 23
Total size: 159.0 KB
Directory structure:
gitextract_ioo2kq9b/
├── .github/
│ └── FUNDING.yml
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── Sharp7/
│ ├── MsgSocket.cs
│ ├── S7.cs
│ ├── S7Area.cs
│ ├── S7Client.cs
│ ├── S7Consts.cs
│ ├── S7MultiVar.cs
│ ├── S7Timer.cs
│ ├── S7WordLength.cs
│ └── Sharp7.csproj
├── Sharp7.Tests/
│ ├── ClientTest.cs
│ ├── ClientWithoutServer.cs
│ ├── PropertiesTests.cs
│ ├── S7Server.cs
│ ├── ServerClientTestBase.cs
│ ├── ServerTestBase.cs
│ ├── Sharp7.Tests.csproj
│ └── TestUtilities.cs
└── Sharp7.sln
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: fbarresi
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
**/Properties/launchSettings.json
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Typescript v1 declaration files
typings/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
run_tests_and_coverage.bat
coverage/
================================================
FILE: CHANGELOG.md
================================================
# Change Log
All notable changed to this project will be documented in this file.
## [1.1.84] - 11.05.2023
### Added
### Changed
### Fixed
- Fixed ReadSZL [#36](https://github.com/fbarresi/Sharp7/issues/36)
## [1.1.82] - 18.05.2022
### Added
### Changed
### Fixed
- Fixed string length check into SetStringAt [#28](https://github.com/fbarresi/Sharp7/issues/28)
## [1.1.81] - 18.05.2022
### Added
### Changed
### Fixed
- Removed obsolete SetBitAt [#27](https://github.com/fbarresi/Sharp7/issues/27)
## [1.1.80] - 18.05.2022
### Added
### Changed
### Fixed
- Fixed casting in GetIntAt [#29](https://github.com/fbarresi/Sharp7/issues/29)
## [1.1.79] - 09.02.2021
### Added
- Constant for no errors `S7Consts.ResultOK`
### Changed
### Fixed
## [1.1.78] - 04.02.2021
### Added
- Property `PLCIpAddress`
- Overload of `ToString` for S7Client
- Property `Name` as constructor param in S7Client
### Changed
### Fixed
## [1.1.75] - 03.09.2020
### Added
### Changed
- CHANGELOG.md
- README.md
### Fixed
- [#18](https://github.com/fbarresi/Sharp7/issues/18)
- New overloaded extension method signatures for SetBitAt
- Removed not necessary casting to short for GetIntAt
- Added overloads for S7 `Time_Of_Day` functions
- Added more tests
- made old methods obsolete
## [1.1.71] - 14.08.2020
### Added
- CHANGELOG.md
### Changed
- README.md
- Referenced changelog into nuget release notes
### Fixed
## [1.1.69] - 11.06.2020
### Added
### Changed
- README.md
### Fixed
## [1.1.68] - 11.06.2020
### Added
- Added enums and methods overloads for S7Wordlength and S7Area (#11)
### Changed
- README.md
- Changed properties to expression body solution wide
- Changed S7 calls to extension methods
- Usage of overloaded methods with enums instead of constants
### Fixed
- Check connection on socket close
- Null propagation on disconnect method
- Soved usage ob obsolete constants
## [1.1.63] - 06.05.2020
### Added
### Changed
### Fixed
- style and security enhancement
## [1.1.62] - 06.05.2020
### Added
### Changed
### Fixed
- Unused exception handling
## [1.1.61] - 06.05.2020
### Added
### Changed
### Fixed
- Usage of Timeouts from [philfontaine/Sharp7@fb01cc0](https://github.com/philfontaine/Sharp7@fb01cc0)
## [1.1.60] - 06.05.2020
### Added
### Changed
### Fixed
- connection check into overload of SendPacket (#8)
## [1.1.59] - 06.05.2020
### Added
- Added unit tests
### Changed
- Created extension methods from S7
### Fixed
- Fixed naming rules
## [1.0.50] - 17.11.2019
### Added
### Changed
- README.md
### Fixed
## [1.0.49] - 17.11.2019
### Added
### Changed
- README.md
### Fixed
## [1.0.48] - 17.11.2019
### Added
### Changed
- README.md
### Fixed
## [1.0.25] - 02.04.2019
### Added
- Added nuget package description
### Changed
### Fixed
## [1.0.22] - 17.01.2019
### Added
- Added debug symbols to Nuget
### Changed
### Fixed
## [1.0.18] - 21.11.2018
### Added
### Changed
- Migrate solution to project SDK (#2)
### Fixed
## [1.0.0] - 21.01.2018
### Added
- imported initial project from source forge
### Changed
### Fixed
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 Federico Barresi
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.
================================================
FILE: README.md
================================================
# 
[](https://ci.appveyor.com/project/fbarresi/sharp7)
[](https://www.codacy.com/manual/fbarresi/Sharp7?utm_source=github.com&utm_medium=referral&utm_content=fbarresi/Sharp7&utm_campaign=Badge_Grade)
[](https://codecov.io/gh/fbarresi/Sharp7)

[](https://www.nuget.org/packages/Sharp7/)
Nuget package for Sharp7 - The multi-platform Ethernet S7 PLC communication suite
Sharp7 is a C# port of [Snap7](http://snap7.sourceforge.net) library
For usage and documentation you can visit the [official page](http://snap7.sourceforge.net)
or read the [Wiki](https://github.com/fbarresi/Sharp7/wiki).
# Changelog
See the changelog [here](https://github.com/fbarresi/Sharp7/blob/master/CHANGELOG.md)
# How to install
## Package Manager or dotnet CLI
```
PM> Install-Package Sharp7
```
or
```
> dotnet add package Sharp7
```
# Do you need more power?
Try [Sharp7Reactive](https://github.com/evopro-ag/Sharp7Reactive)
# Get Started
## Supported Targets
- S7 300/400/WinAC CPU (fully supported)
- S7 1200/1500 CPU
- CP (Communication processor - 343/443/IE)
## S7 1200/1500 Notes
An external equipment can access to S71200/1500 CPU using the S7 'base' protocol, only working as an HMI, i.e. only basic data transfer are allowed.
All other PG operations (control/directory/etc..) must follow the extended protocol, not implemented yet.
Particularly **to access a DB in S71500 some additional setting plc-side are needed**.
- Only global DBs can be accessed.
- The optimized block access must be turned off.

- The access level must be “full” and the “connection mechanism” must allow GET/PUT.

================================================
FILE: Sharp7/MsgSocket.cs
================================================
using System;
using System.Threading;
using System.Net.Sockets;
namespace Sharp7
{
class MsgSocket
{
private Socket TCPSocket;
private int _ReadTimeout = 2000;
private int _WriteTimeout = 2000;
private int _ConnectTimeout = 1000;
private int LastError;
public MsgSocket()
{
}
~MsgSocket()
{
Close();
}
public void Close()
{
if (TCPSocket != null)
{
TCPSocket.Dispose();
TCPSocket = null;
}
}
private void CreateSocket()
{
TCPSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
TCPSocket.NoDelay = true;
}
private void TCPPing(string Host, int Port)
{
// To Ping the PLC an Asynchronous socket is used rather then an ICMP packet.
// This allows the use also across Internet and Firewalls (obviously the port must be opened)
LastError = 0;
Socket PingSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
IAsyncResult result = PingSocket.BeginConnect(Host, Port, null, null);
bool success = result.AsyncWaitHandle.WaitOne(_ConnectTimeout, true);
if (!success)
{
LastError = S7Consts.errTCPConnectionFailed;
}
}
catch
{
LastError = S7Consts.errTCPConnectionFailed;
}
PingSocket.Close();
}
public int Connect(string Host, int Port)
{
LastError = 0;
if (!Connected)
{
TCPPing(Host, Port);
if (LastError == 0)
try
{
CreateSocket();
TCPSocket.Connect(Host, Port);
}
catch
{
LastError = S7Consts.errTCPConnectionFailed;
}
}
return LastError;
}
private int WaitForData(int Size, int Timeout)
{
bool Expired = false;
int SizeAvail;
int Elapsed = Environment.TickCount;
LastError = 0;
try
{
SizeAvail = TCPSocket.Available;
while ((SizeAvail < Size) && (!Expired))
{
Thread.Sleep(2);
SizeAvail = TCPSocket.Available;
Expired = Environment.TickCount - Elapsed > Timeout;
// If timeout we clean the buffer
if (Expired && (SizeAvail > 0))
{
try
{
byte[] Flush = new byte[SizeAvail];
TCPSocket.Receive(Flush, 0, SizeAvail, SocketFlags.None);
}
catch
{
LastError = S7Consts.errTCPDataReceive;
}
}
}
}
catch
{
LastError = S7Consts.errTCPDataReceive;
}
if (Expired)
{
LastError = S7Consts.errTCPDataReceive;
}
return LastError;
}
public int Receive(byte[] Buffer, int Start, int Size)
{
int BytesRead = 0;
LastError = WaitForData(Size, _ReadTimeout);
if (LastError == 0)
{
try
{
BytesRead = TCPSocket.Receive(Buffer, Start, Size, SocketFlags.None);
}
catch
{
LastError = S7Consts.errTCPDataReceive;
}
if (BytesRead == 0) // Connection Reset by the peer
{
LastError = S7Consts.errTCPDataReceive;
Close();
}
}
return LastError;
}
public int Send(byte[] Buffer, int Size)
{
LastError = 0;
try
{
TCPSocket.Send(Buffer, Size, SocketFlags.None);
}
catch
{
LastError = S7Consts.errTCPDataSend;
Close();
}
return LastError;
}
public bool Connected => (TCPSocket != null) && (TCPSocket.Connected);
public int ReadTimeout
{
get => _ReadTimeout;
set => _ReadTimeout = value;
}
public int WriteTimeout
{
get => _WriteTimeout;
set => _WriteTimeout = value;
}
public int ConnectTimeout
{
get => _ConnectTimeout;
set => _ConnectTimeout = value;
}
}
}
================================================
FILE: Sharp7/S7.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Sharp7
{
public static class S7
{
#region [Help Functions]
private static Int64
bias = 621355968000000000; // "decimicros" between 0001-01-01 00:00:00 and 1970-01-01 00:00:00
private static int BCDtoByte(byte B)
{
return ((B >> 4) * 10) + (B & 0x0F);
}
private static byte ByteToBCD(int value)
{
return (byte) (((value / 10) << 4) | (value % 10));
}
public static int DataSizeByte(this int wordLength)
{
switch (wordLength)
{
case (int)S7WordLength.Bit: return 1; // S7 sends 1 byte per bit
case (int)S7WordLength.Byte: return 1;
case (int)S7WordLength.Char: return 1;
case (int)S7WordLength.Word: return 2;
case (int)S7WordLength.DWord: return 4;
case (int)S7WordLength.Int: return 2;
case (int)S7WordLength.DInt: return 4;
case (int)S7WordLength.Real: return 4;
case (int)S7WordLength.Counter: return 2;
case (int)S7WordLength.Timer: return 2;
default: return 0;
}
}
#region Get/Set the bit at Pos.Bit
public static bool GetBitAt(this byte[] buffer, int pos, int bit)
{
byte[] Mask = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
if (bit < 0) bit = 0;
if (bit > 7) bit = 7;
return (buffer[pos] & Mask[bit]) != 0;
}
public static void SetBitAt(this byte[] buffer, int pos, int bit, bool value)
{
byte[] Mask = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
if (bit < 0)
{
bit = 0;
}
if (bit > 7)
{
bit = 7;
}
if (value)
{
buffer[pos] = (byte) (buffer[pos] | Mask[bit]);
}
else
{
buffer[pos] = (byte) (buffer[pos] & ~Mask[bit]);
}
}
#endregion
#region Get/Set 8 bit signed value (S7 SInt) -128..127
public static int GetSIntAt(this byte[] buffer, int pos)
{
int value = buffer[pos];
if (value < 128)
return value;
return (value - 256);
}
public static void SetSIntAt(this byte[] buffer, int pos, int value)
{
if (value < -128) value = -128;
if (value > 127) value = 127;
buffer[pos] = (byte) value;
}
#endregion
#region Get/Set 16 bit signed value (S7 int) -32768..32767
public static short GetIntAt(this byte[] buffer, int pos)
{
return (short)((buffer[pos] << 8) | buffer[pos + 1]);
}
public static void SetIntAt(this byte[] buffer, int pos, Int16 value)
{
buffer[pos] = (byte) (value >> 8);
buffer[pos + 1] = (byte) (value & 0x00FF);
}
#endregion
#region Get/Set 32 bit signed value (S7 DInt) -2147483648..2147483647
public static int GetDIntAt(this byte[] buffer, int pos)
{
int result;
result = buffer[pos];
result <<= 8;
result += buffer[pos + 1];
result <<= 8;
result += buffer[pos + 2];
result <<= 8;
result += buffer[pos + 3];
return result;
}
public static void SetDIntAt(this byte[] buffer, int pos, int value)
{
buffer[pos + 3] = (byte) (value & 0xFF);
buffer[pos + 2] = (byte) ((value >> 8) & 0xFF);
buffer[pos + 1] = (byte) ((value >> 16) & 0xFF);
buffer[pos] = (byte) ((value >> 24) & 0xFF);
}
#endregion
#region Get/Set 64 bit signed value (S7 LInt) -9223372036854775808..9223372036854775807
public static Int64 GetLIntAt(this byte[] buffer, int pos)
{
Int64 result;
result = buffer[pos];
result <<= 8;
result += buffer[pos + 1];
result <<= 8;
result += buffer[pos + 2];
result <<= 8;
result += buffer[pos + 3];
result <<= 8;
result += buffer[pos + 4];
result <<= 8;
result += buffer[pos + 5];
result <<= 8;
result += buffer[pos + 6];
result <<= 8;
result += buffer[pos + 7];
return result;
}
public static void SetLIntAt(this byte[] buffer, int pos, Int64 value)
{
buffer[pos + 7] = (byte) (value & 0xFF);
buffer[pos + 6] = (byte) ((value >> 8) & 0xFF);
buffer[pos + 5] = (byte) ((value >> 16) & 0xFF);
buffer[pos + 4] = (byte) ((value >> 24) & 0xFF);
buffer[pos + 3] = (byte) ((value >> 32) & 0xFF);
buffer[pos + 2] = (byte) ((value >> 40) & 0xFF);
buffer[pos + 1] = (byte) ((value >> 48) & 0xFF);
buffer[pos] = (byte) ((value >> 56) & 0xFF);
}
#endregion
#region Get/Set 8 bit unsigned value (S7 USInt) 0..255
public static byte GetUSIntAt(this byte[] buffer, int pos)
{
return buffer[pos];
}
public static void SetUSIntAt(this byte[] buffer, int pos, byte value)
{
buffer[pos] = value;
}
#endregion
#region Get/Set 16 bit unsigned value (S7 UInt) 0..65535
public static UInt16 GetUIntAt(this byte[] buffer, int pos)
{
return (UInt16) ((buffer[pos] << 8) | buffer[pos + 1]);
}
public static void SetUIntAt(this byte[] buffer, int pos, UInt16 value)
{
buffer[pos] = (byte) (value >> 8);
buffer[pos + 1] = (byte) (value & 0x00FF);
}
#endregion
#region Get/Set 32 bit unsigned value (S7 UDInt) 0..4294967296
public static UInt32 GetUDIntAt(this byte[] buffer, int pos)
{
UInt32 result;
result = buffer[pos];
result <<= 8;
result |= buffer[pos + 1];
result <<= 8;
result |= buffer[pos + 2];
result <<= 8;
result |= buffer[pos + 3];
return result;
}
public static void SetUDIntAt(this byte[] buffer, int pos, UInt32 value)
{
buffer[pos + 3] = (byte) (value & 0xFF);
buffer[pos + 2] = (byte) ((value >> 8) & 0xFF);
buffer[pos + 1] = (byte) ((value >> 16) & 0xFF);
buffer[pos] = (byte) ((value >> 24) & 0xFF);
}
#endregion
#region Get/Set 64 bit unsigned value (S7 ULint) 0..18446744073709551616
public static UInt64 GetULIntAt(this byte[] buffer, int pos)
{
UInt64 result;
result = buffer[pos];
result <<= 8;
result |= buffer[pos + 1];
result <<= 8;
result |= buffer[pos + 2];
result <<= 8;
result |= buffer[pos + 3];
result <<= 8;
result |= buffer[pos + 4];
result <<= 8;
result |= buffer[pos + 5];
result <<= 8;
result |= buffer[pos + 6];
result <<= 8;
result |= buffer[pos + 7];
return result;
}
public static void SetULintAt(this byte[] buffer, int pos, UInt64 value)
{
buffer[pos + 7] = (byte) (value & 0xFF);
buffer[pos + 6] = (byte) ((value >> 8) & 0xFF);
buffer[pos + 5] = (byte) ((value >> 16) & 0xFF);
buffer[pos + 4] = (byte) ((value >> 24) & 0xFF);
buffer[pos + 3] = (byte) ((value >> 32) & 0xFF);
buffer[pos + 2] = (byte) ((value >> 40) & 0xFF);
buffer[pos + 1] = (byte) ((value >> 48) & 0xFF);
buffer[pos] = (byte) ((value >> 56) & 0xFF);
}
#endregion
#region Get/Set 8 bit word (S7 Byte) 16#00..16#FF
public static byte GetByteAt(this byte[] buffer, int pos)
{
return buffer[pos];
}
public static void SetByteAt(this byte[] buffer, int pos, byte value)
{
buffer[pos] = value;
}
#endregion
#region Get/Set 16 bit word (S7 Word) 16#0000..16#FFFF
public static UInt16 GetWordAt(this byte[] buffer, int pos)
{
return GetUIntAt(buffer, pos);
}
public static void SetWordAt(this byte[] buffer, int pos, UInt16 value)
{
SetUIntAt(buffer, pos, value);
}
#endregion
#region Get/Set 32 bit word (S7 DWord) 16#00000000..16#FFFFFFFF
public static UInt32 GetDWordAt(this byte[] buffer, int pos)
{
return GetUDIntAt(buffer, pos);
}
public static void SetDWordAt(this byte[] buffer, int pos, UInt32 value)
{
SetUDIntAt(buffer, pos, value);
}
#endregion
#region Get/Set 64 bit word (S7 LWord) 16#0000000000000000..16#FFFFFFFFFFFFFFFF
public static UInt64 GetLWordAt(this byte[] buffer, int pos)
{
return GetULIntAt(buffer, pos);
}
public static void SetLWordAt(this byte[] buffer, int pos, UInt64 value)
{
SetULintAt(buffer, pos, value);
}
#endregion
#region Get/Set 32 bit floating point number (S7 Real) (Range of Single)
public static Single GetRealAt(this byte[] buffer, int pos)
{
UInt32 value = GetUDIntAt(buffer, pos);
byte[] bytes = BitConverter.GetBytes(value);
return BitConverter.ToSingle(bytes, 0);
}
public static void SetRealAt(this byte[] buffer, int pos, Single value)
{
byte[] FloatArray = BitConverter.GetBytes(value);
buffer[pos] = FloatArray[3];
buffer[pos + 1] = FloatArray[2];
buffer[pos + 2] = FloatArray[1];
buffer[pos + 3] = FloatArray[0];
}
#endregion
#region Get/Set 64 bit floating point number (S7 LReal) (Range of Double)
public static Double GetLRealAt(this byte[] buffer, int pos)
{
UInt64 value = GetULIntAt(buffer, pos);
byte[] bytes = BitConverter.GetBytes(value);
return BitConverter.ToDouble(bytes, 0);
}
public static void SetLRealAt(this byte[] buffer, int pos, Double value)
{
byte[] FloatArray = BitConverter.GetBytes(value);
buffer[pos] = FloatArray[7];
buffer[pos + 1] = FloatArray[6];
buffer[pos + 2] = FloatArray[5];
buffer[pos + 3] = FloatArray[4];
buffer[pos + 4] = FloatArray[3];
buffer[pos + 5] = FloatArray[2];
buffer[pos + 6] = FloatArray[1];
buffer[pos + 7] = FloatArray[0];
}
#endregion
#region Get/Set DateTime (S7 DATE_AND_TIME)
public static DateTime GetDateTimeAt(this byte[] buffer, int pos)
{
int Year, Month, Day, Hour, Min, Sec, MSec;
Year = BCDtoByte(buffer[pos]);
if (Year < 90)
Year += 2000;
else
Year += 1900;
Month = BCDtoByte(buffer[pos + 1]);
Day = BCDtoByte(buffer[pos + 2]);
Hour = BCDtoByte(buffer[pos + 3]);
Min = BCDtoByte(buffer[pos + 4]);
Sec = BCDtoByte(buffer[pos + 5]);
MSec = (BCDtoByte(buffer[pos + 6]) * 10) + (BCDtoByte(buffer[pos + 7]) / 10);
try
{
return new DateTime(Year, Month, Day, Hour, Min, Sec, MSec);
}
catch (System.ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetDateTimeAt(this byte[] buffer, int pos, DateTime value)
{
int Year = value.Year;
int Month = value.Month;
int Day = value.Day;
int Hour = value.Hour;
int Min = value.Minute;
int Sec = value.Second;
int Dow = (int) value.DayOfWeek + 1;
// MSecH = First two digits of miliseconds
int MsecH = value.Millisecond / 10;
// MSecL = Last digit of miliseconds
int MsecL = value.Millisecond % 10;
if (Year > 1999)
Year -= 2000;
buffer[pos] = ByteToBCD(Year);
buffer[pos + 1] = ByteToBCD(Month);
buffer[pos + 2] = ByteToBCD(Day);
buffer[pos + 3] = ByteToBCD(Hour);
buffer[pos + 4] = ByteToBCD(Min);
buffer[pos + 5] = ByteToBCD(Sec);
buffer[pos + 6] = ByteToBCD(MsecH);
buffer[pos + 7] = ByteToBCD(MsecL * 10 + Dow);
}
#endregion
#region Get/Set DATE (S7 DATE)
public static DateTime GetDateAt(this byte[] buffer, int pos)
{
try
{
return new DateTime(1990, 1, 1).AddDays(GetIntAt(buffer, pos));
}
catch (System.ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetDateAt(this byte[] buffer, int pos, DateTime value)
{
SetIntAt(buffer, pos, (Int16) (value - new DateTime(1990, 1, 1)).Days);
}
#endregion
#region Get/Set TOD (S7 TIME_OF_DAY)
[Obsolete("Use GetTODAsDateTimeAt or GetTODAsTimeSpanAt instead")]
public static DateTime GetTODAt(this byte[] buffer, int pos)
{
return buffer.GetTODAsDateTimeAt(pos);
}
public static DateTime GetTODAsDateTimeAt(this byte[] buffer, int pos)
{
try
{
return new DateTime(0).AddMilliseconds(buffer.GetDIntAt(pos));
}
catch (ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetTODAt(this byte[] buffer, int pos, DateTime value)
{
TimeSpan Time = value.TimeOfDay;
SetDIntAt(buffer, pos, (Int32) Math.Round(Time.TotalMilliseconds));
}
public static TimeSpan GetTODAsTimeSpanAt(this byte[] buffer, int pos)
{
try
{
return TimeSpan.FromMilliseconds(buffer.GetDIntAt(pos));
}
catch (ArgumentOutOfRangeException)
{
return TimeSpan.Zero;
}
}
public static void SetTODAt(this byte[] buffer, int pos, TimeSpan value)
{
SetDIntAt(buffer, pos, (Int32) Math.Round(value.TotalMilliseconds));
}
#endregion
#region Get/Set LTOD (S7 1500 LONG TIME_OF_DAY)
[Obsolete("Use GetLTODAsDateTimeAt or GetLTODAsTimeSpanAt instead")]
public static DateTime GetLTODAt(this byte[] buffer, int pos)
{
return buffer.GetLTODAsDateTimeAt(pos);
}
public static DateTime GetLTODAsDateTimeAt(this byte[] buffer, int pos)
{
// .NET Tick = 100 ns, S71500 Tick = 1 ns
try
{
return new DateTime(Math.Abs(GetLIntAt(buffer, pos) / 100));
}
catch (System.ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetLTODAt(this byte[] buffer, int pos, DateTime value)
{
TimeSpan Time = value.TimeOfDay;
SetLIntAt(buffer, pos, (Int64) Time.Ticks * 100);
}
public static TimeSpan GetLTODAsTimeSpanAt(this byte[] buffer, int pos)
{
try
{
return TimeSpan.FromTicks(Math.Abs(GetLIntAt(buffer, pos) / 100));
}
catch (System.ArgumentOutOfRangeException)
{
return TimeSpan.Zero;
}
}
public static void SetLTODAt(this byte[] buffer, int pos, TimeSpan value)
{
SetLIntAt(buffer, pos, (Int64) value.Ticks * 100);
}
#endregion
#region GET/SET LDT (S7 1500 Long Date and Time)
public static DateTime GetLDTAt(this byte[] buffer, int pos)
{
try
{
return new DateTime((GetLIntAt(buffer, pos) / 100) + bias);
}
catch (System.ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetLDTAt(this byte[] buffer, int pos, DateTime value)
{
SetLIntAt(buffer, pos, (value.Ticks - bias) * 100);
}
#endregion
#region Get/Set DTL (S71200/1500 Date and Time)
// Thanks to Johan Cardoen for GetDTLAt
public static DateTime GetDTLAt(this byte[] buffer, int pos)
{
int Year, Month, Day, Hour, Min, Sec, MSec;
Year = buffer[pos] * 256 + buffer[pos + 1];
Month = buffer[pos + 2];
Day = buffer[pos + 3];
Hour = buffer[pos + 5];
Min = buffer[pos + 6];
Sec = buffer[pos + 7];
MSec = (int) GetUDIntAt(buffer, pos + 8) / 1000000;
try
{
return new DateTime(Year, Month, Day, Hour, Min, Sec, MSec);
}
catch (System.ArgumentOutOfRangeException)
{
return new DateTime(0);
}
}
public static void SetDTLAt(this byte[] buffer, int pos, DateTime value)
{
short Year = (short) value.Year;
byte Month = (byte) value.Month;
byte Day = (byte) value.Day;
byte Hour = (byte) value.Hour;
byte Min = (byte) value.Minute;
byte Sec = (byte) value.Second;
byte Dow = (byte) (value.DayOfWeek + 1);
Int32 NanoSecs = value.Millisecond * 1000000;
var bytes_short = BitConverter.GetBytes(Year);
buffer[pos] = bytes_short[1];
buffer[pos + 1] = bytes_short[0];
buffer[pos + 2] = Month;
buffer[pos + 3] = Day;
buffer[pos + 4] = Dow;
buffer[pos + 5] = Hour;
buffer[pos + 6] = Min;
buffer[pos + 7] = Sec;
SetDIntAt(buffer, pos + 8, NanoSecs);
}
#endregion
#region Get/Set String (S7 String)
// Thanks to Pablo Agirre
public static string GetStringAt(this byte[] buffer, int pos)
{
int size = (int) buffer[pos + 1];
return Encoding.UTF8.GetString(buffer, pos + 2, size);
}
public static void SetStringAt(this byte[] buffer, int pos, int MaxLen, string value)
{
int length = value.Length;
// checking current length against MaxLen
if (length > MaxLen) length = MaxLen;
buffer[pos] = (byte) MaxLen;
buffer[pos + 1] = (byte) length;
Encoding.UTF8.GetBytes(value, 0, length, buffer, pos + 2);
}
#endregion
#region Get/Set Array of char (S7 ARRAY OF CHARS)
public static string GetCharsAt(this byte[] buffer, int pos, int Size)
{
return Encoding.UTF8.GetString(buffer, pos, Size);
}
public static void SetCharsAt(this byte[] buffer, int pos, string value)
{
int MaxLen = buffer.Length - pos;
// Truncs the string if there's no room enough
if (MaxLen > value.Length) MaxLen = value.Length;
Encoding.UTF8.GetBytes(value, 0, MaxLen, buffer, pos);
}
#endregion
#region Get/Set Counter
public static int GetCounter(this ushort value)
{
return BCDtoByte((byte) value) * 100 + BCDtoByte((byte) (value >> 8));
}
public static int GetCounterAt(this ushort[] buffer, int Index)
{
return GetCounter(buffer[Index]);
}
public static ushort ToCounter(this int value)
{
return (ushort) (ByteToBCD(value / 100) + (ByteToBCD(value % 100) << 8));
}
public static void SetCounterAt(this ushort[] buffer, int pos, int value)
{
buffer[pos] = ToCounter(value);
}
#endregion
#region Get/Set Timer
public static S7Timer GetS7TimerAt(this byte[] buffer, int pos)
{
return new S7Timer(new List<byte>(buffer).GetRange(pos, 12).ToArray());
}
public static void SetS7TimespanAt(this byte[] buffer, int pos, TimeSpan value)
{
SetDIntAt(buffer, pos, (Int32) value.TotalMilliseconds);
}
public static TimeSpan GetS7TimespanAt(this byte[] buffer, int pos)
{
if (buffer.Length < pos + 4)
{
return new TimeSpan();
}
Int32 a;
a = buffer[pos + 0];
a <<= 8;
a += buffer[pos + 1];
a <<= 8;
a += buffer[pos + 2];
a <<= 8;
a += buffer[pos + 3];
TimeSpan sp = new TimeSpan(0, 0, 0, 0, a);
return sp;
}
#endregion
#endregion [Help Functions]
}
}
================================================
FILE: Sharp7/S7Area.cs
================================================
namespace Sharp7
{
public enum S7Area
{
PE = 0x81,
PA = 0x82,
MK = 0x83,
DB = 0x84,
CT = 0x1C,
TM = 0x1D,
}
}
================================================
FILE: Sharp7/S7Client.cs
================================================
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Sharp7
{
public class S7Client
{
#region [Constants and TypeDefs]
// Block type
public const int Block_OB = 0x38;
public const int Block_DB = 0x41;
public const int Block_SDB = 0x42;
public const int Block_FC = 0x43;
public const int Block_SFC = 0x44;
public const int Block_FB = 0x45;
public const int Block_SFB = 0x46;
// Sub Block Type
public const byte SubBlk_OB = 0x08;
public const byte SubBlk_DB = 0x0A;
public const byte SubBlk_SDB = 0x0B;
public const byte SubBlk_FC = 0x0C;
public const byte SubBlk_SFC = 0x0D;
public const byte SubBlk_FB = 0x0E;
public const byte SubBlk_SFB = 0x0F;
// Block languages
public const byte BlockLangAWL = 0x01;
public const byte BlockLangKOP = 0x02;
public const byte BlockLangFUP = 0x03;
public const byte BlockLangSCL = 0x04;
public const byte BlockLangDB = 0x05;
public const byte BlockLangGRAPH = 0x06;
// Max number of vars (multiread/write)
public static readonly int MaxVars = 20;
// Result transport size
const byte TS_ResBit = 0x03;
const byte TS_ResByte = 0x04;
const byte TS_ResInt = 0x05;
const byte TS_ResReal = 0x07;
const byte TS_ResOctet = 0x09;
const ushort Code7Ok = 0x0000;
const ushort Code7AddressOutOfRange = 0x0005;
const ushort Code7InvalidTransportSize = 0x0006;
const ushort Code7WriteDataSizeMismatch = 0x0007;
const ushort Code7ResItemNotAvailable = 0x000A;
const ushort Code7ResItemNotAvailable1 = 0xD209;
const ushort Code7InvalidValue = 0xDC01;
const ushort Code7NeedPassword = 0xD241;
const ushort Code7InvalidPassword = 0xD602;
const ushort Code7NoPasswordToClear = 0xD604;
const ushort Code7NoPasswordToSet = 0xD605;
const ushort Code7FunNotAvailable = 0x8104;
const ushort Code7DataOverPDU = 0x8500;
// Client Connection Type
public static readonly UInt16 CONNTYPE_PG = 0x01; // Connect to the PLC as a PG
public static readonly UInt16 CONNTYPE_OP = 0x02; // Connect to the PLC as an OP
public static readonly UInt16 CONNTYPE_BASIC = 0x03; // Basic connection
public int _LastError = 0;
public struct S7DataItem
{
public int Area;
public int WordLen;
public int Result;
public int DBNumber;
public int Start;
public int Amount;
public IntPtr pData;
}
// Order Code + Version
public struct S7OrderCode
{
public string Code; // such as "6ES7 151-8AB01-0AB0"
public byte V1; // Version 1st digit
public byte V2; // Version 2nd digit
public byte V3; // Version 3th digit
};
// CPU Info
public struct S7CpuInfo
{
public string ModuleTypeName;
public string SerialNumber;
public string ASName;
public string Copyright;
public string ModuleName;
}
public struct S7CpInfo
{
public int MaxPduLength;
public int MaxConnections;
public int MaxMpiRate;
public int MaxBusRate;
};
// Block List
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S7BlocksList
{
public Int32 OBCount;
public Int32 FBCount;
public Int32 FCCount;
public Int32 SFBCount;
public Int32 SFCCount;
public Int32 DBCount;
public Int32 SDBCount;
};
// Managed Block Info
public struct S7BlockInfo
{
public int BlkType;
public int BlkNumber;
public int BlkLang;
public int BlkFlags;
public int MC7Size; // The real size in bytes
public int LoadSize;
public int LocalData;
public int SBBLength;
public int CheckSum;
public int Version;
// Chars info
public string CodeDate;
public string IntfDate;
public string Author;
public string Family;
public string Header;
};
// See §33.1 of "System Software for S7-300/400 System and Standard Functions"
// and see SFC51 description too
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SZL_HEADER
{
public UInt16 LENTHDR;
public UInt16 N_DR;
};
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S7SZL
{
public SZL_HEADER Header;
[MarshalAs(UnmanagedType.ByValArray)]
public byte[] Data;
};
// SZL List of available SZL IDs : same as SZL but List items are big-endian adjusted
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S7SZLList
{
public SZL_HEADER Header;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x2000 - 2)]
public UInt16[] Data;
};
// S7 Protection
// See §33.19 of "System Software for S7-300/400 System and Standard Functions"
public struct S7Protection
{
public ushort sch_schal;
public ushort sch_par;
public ushort sch_rel;
public ushort bart_sch;
public ushort anl_sch;
};
#endregion
#region [S7 Telegrams]
// ISO Connection Request telegram (contains also ISO Header and COTP Header)
byte[] ISO_CR = {
// TPKT (RFC1006 Header)
0x03, // RFC 1006 ID (3)
0x00, // Reserved, always 0
0x00, // High part of packet lenght (entire frame, payload and TPDU included)
0x16, // Low part of packet lenght (entire frame, payload and TPDU included)
// COTP (ISO 8073 Header)
0x11, // PDU Size Length
0xE0, // CR - Connection Request ID
0x00, // Dst Reference HI
0x00, // Dst Reference LO
0x00, // Src Reference HI
0x01, // Src Reference LO
0x00, // Class + Options Flags
0xC0, // PDU Max Length ID
0x01, // PDU Max Length HI
0x0A, // PDU Max Length LO
0xC1, // Src TSAP Identifier
0x02, // Src TSAP Length (2 bytes)
0x01, // Src TSAP HI (will be overwritten)
0x00, // Src TSAP LO (will be overwritten)
0xC2, // Dst TSAP Identifier
0x02, // Dst TSAP Length (2 bytes)
0x01, // Dst TSAP HI (will be overwritten)
0x02 // Dst TSAP LO (will be overwritten)
};
// TPKT + ISO COTP Header (Connection Oriented Transport Protocol)
byte[] TPKT_ISO = { // 7 bytes
0x03,0x00,
0x00,0x1f, // Telegram Length (Data Size + 31 or 35)
0x02,0xf0,0x80 // COTP (see above for info)
};
// S7 PDU Negotiation Telegram (contains also ISO Header and COTP Header)
byte[] S7_PN = {
0x03, 0x00, 0x00, 0x19,
0x02, 0xf0, 0x80, // TPKT + COTP (see above for info)
0x32, 0x01, 0x00, 0x00,
0x04, 0x00, 0x00, 0x08,
0x00, 0x00, 0xf0, 0x00,
0x00, 0x01, 0x00, 0x01,
0x00, 0x1e // PDU Length Requested = HI-LO Here Default 480 bytes
};
// S7 Read/Write Request Header (contains also ISO Header and COTP Header)
byte[] S7_RW = { // 31-35 bytes
0x03,0x00,
0x00,0x1f, // Telegram Length (Data Size + 31 or 35)
0x02,0xf0, 0x80, // COTP (see above for info)
0x32, // S7 Protocol ID
0x01, // Job Type
0x00,0x00, // Redundancy identification
0x05,0x00, // PDU Reference
0x00,0x0e, // Parameters Length
0x00,0x00, // Data Length = Size(bytes) + 4
0x04, // Function 4 Read Var, 5 Write Var
0x01, // Items count
0x12, // Var spec.
0x0a, // Length of remaining bytes
0x10, // Syntax ID
(byte)S7WordLength.Byte, // Transport Size idx=22
0x00,0x00, // Num Elements
0x00,0x00, // DB Number (if any, else 0)
0x84, // Area Type
0x00,0x00,0x00, // Area Offset
// WR area
0x00, // Reserved
0x04, // Transport size
0x00,0x00, // Data Length * 8 (if not bit or timer or counter)
};
private static int Size_RD = 31; // Header Size when Reading
private static int Size_WR = 35; // Header Size when Writing
// S7 Variable MultiRead Header
byte[] S7_MRD_HEADER = {
0x03,0x00,
0x00,0x1f, // Telegram Length
0x02,0xf0, 0x80, // COTP (see above for info)
0x32, // S7 Protocol ID
0x01, // Job Type
0x00,0x00, // Redundancy identification
0x05,0x00, // PDU Reference
0x00,0x0e, // Parameters Length
0x00,0x00, // Data Length = Size(bytes) + 4
0x04, // Function 4 Read Var, 5 Write Var
0x01 // Items count (idx 18)
};
// S7 Variable MultiRead Item
byte[] S7_MRD_ITEM = {
0x12, // Var spec.
0x0a, // Length of remaining bytes
0x10, // Syntax ID
(byte)S7WordLength.Byte, // Transport Size idx=3
0x00,0x00, // Num Elements
0x00,0x00, // DB Number (if any, else 0)
0x84, // Area Type
0x00,0x00,0x00 // Area Offset
};
// S7 Variable MultiWrite Header
byte[] S7_MWR_HEADER = {
0x03,0x00,
0x00,0x1f, // Telegram Length
0x02,0xf0, 0x80, // COTP (see above for info)
0x32, // S7 Protocol ID
0x01, // Job Type
0x00,0x00, // Redundancy identification
0x05,0x00, // PDU Reference
0x00,0x0e, // Parameters Length (idx 13)
0x00,0x00, // Data Length = Size(bytes) + 4 (idx 15)
0x05, // Function 5 Write Var
0x01 // Items count (idx 18)
};
// S7 Variable MultiWrite Item (Param)
byte[] S7_MWR_PARAM = {
0x12, // Var spec.
0x0a, // Length of remaining bytes
0x10, // Syntax ID
(byte)S7WordLength.Byte, // Transport Size idx=3
0x00,0x00, // Num Elements
0x00,0x00, // DB Number (if any, else 0)
0x84, // Area Type
0x00,0x00,0x00, // Area Offset
};
// SZL First telegram request
byte[] S7_SZL_FIRST = {
0x03, 0x00, 0x00, 0x21,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00,
0x05, 0x00, // Sequence out
0x00, 0x08, 0x00,
0x08, 0x00, 0x01, 0x12,
0x04, 0x11, 0x44, 0x01,
0x00, 0xff, 0x09, 0x00,
0x04,
0x00, 0x00, // ID (29)
0x00, 0x00 // Index (31)
};
// SZL Next telegram request
byte[] S7_SZL_NEXT = {
0x03, 0x00, 0x00, 0x21,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x06,
0x00, 0x00, 0x0c, 0x00,
0x04, 0x00, 0x01, 0x12,
0x08, 0x12, 0x44, 0x01,
0x01, // Sequence
0x00, 0x00, 0x00, 0x00,
0x0a, 0x00, 0x00, 0x00
};
// Get Date/Time request
byte[] S7_GET_DT = {
0x03, 0x00, 0x00, 0x1d,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x38,
0x00, 0x00, 0x08, 0x00,
0x04, 0x00, 0x01, 0x12,
0x04, 0x11, 0x47, 0x01,
0x00, 0x0a, 0x00, 0x00,
0x00
};
// Set Date/Time command
byte[] S7_SET_DT = {
0x03, 0x00, 0x00, 0x27,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x89,
0x03, 0x00, 0x08, 0x00,
0x0e, 0x00, 0x01, 0x12,
0x04, 0x11, 0x47, 0x02,
0x00, 0xff, 0x09, 0x00,
0x0a, 0x00,
0x19, // Hi part of Year (idx=30)
0x13, // Lo part of Year
0x12, // Month
0x06, // Day
0x17, // Hour
0x37, // Min
0x13, // Sec
0x00, 0x01 // ms + Day of week
};
// S7 Set Session Password
byte[] S7_SET_PWD = {
0x03, 0x00, 0x00, 0x25,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x27,
0x00, 0x00, 0x08, 0x00,
0x0c, 0x00, 0x01, 0x12,
0x04, 0x11, 0x45, 0x01,
0x00, 0xff, 0x09, 0x00,
0x08,
// 8 Char Encoded Password
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
// S7 Clear Session Password
byte[] S7_CLR_PWD = {
0x03, 0x00, 0x00, 0x1d,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x29,
0x00, 0x00, 0x08, 0x00,
0x04, 0x00, 0x01, 0x12,
0x04, 0x11, 0x45, 0x02,
0x00, 0x0a, 0x00, 0x00,
0x00
};
// S7 STOP request
byte[] S7_STOP = {
0x03, 0x00, 0x00, 0x21,
0x02, 0xf0, 0x80, 0x32,
0x01, 0x00, 0x00, 0x0e,
0x00, 0x00, 0x10, 0x00,
0x00, 0x29, 0x00, 0x00,
0x00, 0x00, 0x00, 0x09,
0x50, 0x5f, 0x50, 0x52,
0x4f, 0x47, 0x52, 0x41,
0x4d
};
// S7 HOT Start request
byte[] S7_HOT_START = {
0x03, 0x00, 0x00, 0x25,
0x02, 0xf0, 0x80, 0x32,
0x01, 0x00, 0x00, 0x0c,
0x00, 0x00, 0x14, 0x00,
0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xfd, 0x00, 0x00, 0x09,
0x50, 0x5f, 0x50, 0x52,
0x4f, 0x47, 0x52, 0x41,
0x4d
};
// S7 COLD Start request
byte[] S7_COLD_START = {
0x03, 0x00, 0x00, 0x27,
0x02, 0xf0, 0x80, 0x32,
0x01, 0x00, 0x00, 0x0f,
0x00, 0x00, 0x16, 0x00,
0x00, 0x28, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0xfd, 0x00, 0x02, 0x43,
0x20, 0x09, 0x50, 0x5f,
0x50, 0x52, 0x4f, 0x47,
0x52, 0x41, 0x4d
};
const byte pduStart = 0x28; // CPU start
const byte pduStop = 0x29; // CPU stop
const byte pduAlreadyStarted = 0x02; // CPU already in run mode
const byte pduAlreadyStopped = 0x07; // CPU already in stop mode
// S7 Get PLC Status
byte[] S7_GET_STAT = {
0x03, 0x00, 0x00, 0x21,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x2c,
0x00, 0x00, 0x08, 0x00,
0x08, 0x00, 0x01, 0x12,
0x04, 0x11, 0x44, 0x01,
0x00, 0xff, 0x09, 0x00,
0x04, 0x04, 0x24, 0x00,
0x00
};
// S7 Get Block Info Request Header (contains also ISO Header and COTP Header)
byte[] S7_BI = {
0x03, 0x00, 0x00, 0x25,
0x02, 0xf0, 0x80, 0x32,
0x07, 0x00, 0x00, 0x05,
0x00, 0x00, 0x08, 0x00,
0x0c, 0x00, 0x01, 0x12,
0x04, 0x11, 0x43, 0x03,
0x00, 0xff, 0x09, 0x00,
0x08, 0x30,
0x41, // Block Type
0x30, 0x30, 0x30, 0x30, 0x30, // ASCII Block Number
0x41
};
#endregion
#region [Internals]
// Defaults
private static int ISOTCP = 102; // ISOTCP Port
private static int MinPduSize = 16;
private static int MinPduSizeToRequest = 240;
private static int MaxPduSizeToRequest = 960;
private static int DefaultTimeout = 2000;
private static int IsoHSize = 7; // TPKT+COTP Header Size
// Properties
private int _PDULength = 0;
private int _PduSizeRequested = 480;
private int _PLCPort = ISOTCP;
// Privates
private string IPAddress;
private byte LocalTSAP_HI;
private byte LocalTSAP_LO;
private byte RemoteTSAP_HI;
private byte RemoteTSAP_LO;
private byte LastPDUType;
private ushort ConnType = CONNTYPE_PG;
private byte[] PDU = new byte[2048];
private MsgSocket Socket = null;
private int Time_ms = 0;
private void CreateSocket()
{
Socket = new MsgSocket();
Socket.ConnectTimeout = DefaultTimeout;
Socket.ReadTimeout = DefaultTimeout;
Socket.WriteTimeout = DefaultTimeout;
}
private int TCPConnect()
{
if (_LastError==0)
{
try
{
_LastError=Socket.Connect(IPAddress, _PLCPort);
}
catch
{
_LastError = S7Consts.errTCPConnectionFailed;
}
}
return _LastError;
}
private void RecvPacket(byte[] Buffer, int Start, int Size)
{
if (Connected)
_LastError = Socket.Receive(Buffer, Start, Size);
else
_LastError = S7Consts.errTCPNotConnected;
}
private void SendPacket(byte[] Buffer, int Len)
{
if (Connected)
_LastError = Socket.Send(Buffer, Len);
else
_LastError = S7Consts.errTCPNotConnected;
}
private void SendPacket(byte[] Buffer)
{
SendPacket(Buffer, Buffer.Length);
}
private int RecvIsoPacket()
{
Boolean Done = false;
int Size = 0;
while ((_LastError == 0) && !Done)
{
// Get TPKT (4 bytes)
RecvPacket(PDU, 0, 4);
if (_LastError == 0)
{
Size = PDU.GetWordAt(2);
// Check 0 bytes Data Packet (only TPKT+COTP = 7 bytes)
if (Size == IsoHSize)
RecvPacket(PDU, 4, 3); // Skip remaining 3 bytes and Done is still false
else
{
if ((Size > _PduSizeRequested + IsoHSize) || (Size < MinPduSize))
_LastError = S7Consts.errIsoInvalidPDU;
else
Done = true; // a valid Length !=7 && >16 && <247
}
}
}
if (_LastError == 0)
{
RecvPacket(PDU, 4, 3); // Skip remaining 3 COTP bytes
LastPDUType = PDU[5]; // Stores PDU Type, we need it
// Receives the S7 Payload
RecvPacket(PDU, 7, Size - IsoHSize);
}
if (_LastError == 0)
{
return Size;
}
return 0;
}
private int ISOConnect()
{
int Size;
ISO_CR[16] = LocalTSAP_HI;
ISO_CR[17] = LocalTSAP_LO;
ISO_CR[20] = RemoteTSAP_HI;
ISO_CR[21] = RemoteTSAP_LO;
// Sends the connection request telegram
SendPacket(ISO_CR);
if (_LastError == 0)
{
// Gets the reply (if any)
Size = RecvIsoPacket();
if (_LastError == 0)
{
if (Size == 22)
{
if (LastPDUType != (byte)0xD0) // 0xD0 = CC Connection confirm
_LastError = S7Consts.errIsoConnect;
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
}
return _LastError;
}
private int NegotiatePduLength()
{
int Length;
// Set PDU Size Requested
S7_PN.SetWordAt(23, (ushort)_PduSizeRequested);
// Sends the connection request telegram
SendPacket(S7_PN);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (_LastError == 0)
{
// check S7 Error
if ((Length == 27) && (PDU[17] == 0) && (PDU[18] == 0)) // 20 = size of Negotiate Answer
{
// Get PDU Size Negotiated
_PDULength = PDU.GetWordAt(25);
if (_PDULength <= 0)
_LastError = S7Consts.errCliNegotiatingPDU;
}
else
_LastError = S7Consts.errCliNegotiatingPDU;
}
}
return _LastError;
}
private int CpuError(ushort Error)
{
switch(Error)
{
case 0 : return 0;
case Code7AddressOutOfRange : return S7Consts.errCliAddressOutOfRange;
case Code7InvalidTransportSize : return S7Consts.errCliInvalidTransportSize;
case Code7WriteDataSizeMismatch : return S7Consts.errCliWriteDataSizeMismatch;
case Code7ResItemNotAvailable :
case Code7ResItemNotAvailable1 : return S7Consts.errCliItemNotAvailable;
case Code7DataOverPDU : return S7Consts.errCliSizeOverPDU;
case Code7InvalidValue : return S7Consts.errCliInvalidValue;
case Code7FunNotAvailable : return S7Consts.errCliFunNotAvailable;
case Code7NeedPassword : return S7Consts.errCliNeedPassword;
case Code7InvalidPassword : return S7Consts.errCliInvalidPassword;
case Code7NoPasswordToSet :
case Code7NoPasswordToClear : return S7Consts.errCliNoPasswordToSetOrClear;
default:
return S7Consts.errCliFunctionRefused;
};
}
#endregion
#region [Class Control]
public S7Client(string name) : this()
{
Name = name;
}
public string Name { get; }
public S7Client()
{
CreateSocket();
}
~S7Client()
{
Disconnect();
}
public override string ToString()
{
return $"PLC {Name ?? string.Empty}@{PLCIpAddress ?? "0.0.0.0"}";
}
public int Connect()
{
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
if (!Connected)
{
TCPConnect(); // First stage : TCP Connection
if (_LastError == 0)
{
ISOConnect(); // Second stage : ISOTCP (ISO 8073) Connection
if (_LastError == 0)
{
_LastError = NegotiatePduLength(); // Third stage : S7 PDU negotiation
}
}
}
if (_LastError != 0)
Disconnect();
else
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int ConnectTo(string Address, int Rack, int Slot)
{
UInt16 RemoteTSAP = (UInt16)((ConnType << 8) + (Rack * 0x20) + Slot);
SetConnectionParams(Address, 0x0100, RemoteTSAP);
return Connect();
}
public int SetConnectionParams(string Address, ushort LocalTSAP, ushort RemoteTSAP)
{
int LocTSAP = LocalTSAP & 0x0000FFFF;
int RemTSAP = RemoteTSAP & 0x0000FFFF;
IPAddress = Address;
LocalTSAP_HI = (byte)(LocTSAP >> 8);
LocalTSAP_LO = (byte)(LocTSAP & 0x00FF);
RemoteTSAP_HI = (byte)(RemTSAP >> 8);
RemoteTSAP_LO = (byte)(RemTSAP & 0x00FF);
return 0;
}
public int SetConnectionType(ushort ConnectionType)
{
ConnType = ConnectionType;
return 0;
}
public int Disconnect()
{
Socket?.Close();
return 0;
}
public int GetParam(Int32 ParamNumber, ref int Value)
{
int Result = 0;
switch (ParamNumber)
{
case S7Consts.p_u16_RemotePort:
{
Value = PLCPort;
break;
}
case S7Consts.p_i32_PingTimeout:
{
Value = ConnTimeout;
break;
}
case S7Consts.p_i32_SendTimeout:
{
Value = SendTimeout;
break;
}
case S7Consts.p_i32_RecvTimeout:
{
Value = RecvTimeout;
break;
}
case S7Consts.p_i32_PDURequest:
{
Value = PduSizeRequested;
break;
}
default:
{
Result = S7Consts.errCliInvalidParamNumber;
break;
}
}
return Result;
}
// Set Properties for compatibility with Snap7.net.cs
public int SetParam(Int32 ParamNumber, ref int Value)
{
int Result = 0;
switch(ParamNumber)
{
case S7Consts.p_u16_RemotePort:
{
PLCPort = Value;
break;
}
case S7Consts.p_i32_PingTimeout:
{
ConnTimeout = Value;
break;
}
case S7Consts.p_i32_SendTimeout:
{
SendTimeout = Value;
break;
}
case S7Consts.p_i32_RecvTimeout:
{
RecvTimeout = Value;
break;
}
case S7Consts.p_i32_PDURequest:
{
PduSizeRequested = Value;
break;
}
default:
{
Result = S7Consts.errCliInvalidParamNumber;
break;
}
}
return Result;
}
public delegate void S7CliCompletion(IntPtr usrPtr, int opCode, int opResult);
public int SetAsCallBack(S7CliCompletion Completion, IntPtr usrPtr)
{
return S7Consts.errCliFunctionNotImplemented;
}
#endregion
#region [Data I/O main functions]
public int ReadArea(S7Area Area, int DBNumber, int Start, int Amount, S7WordLength WordLen, byte[] Buffer)
{
return ReadArea((int)Area, DBNumber, Start, Amount, (int)WordLen, Buffer);
}
public int ReadArea(S7Area Area, int DBNumber, int Start, int Amount, S7WordLength WordLen, byte[] Buffer, ref int BytesRead)
{
return ReadArea((int)Area, DBNumber, Start, Amount, (int)WordLen, Buffer, ref BytesRead);
}
public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
{
int BytesRead = 0;
return ReadArea(Area, DBNumber, Start, Amount, WordLen, Buffer, ref BytesRead);
}
public int ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer, ref int BytesRead)
{
int Address;
int NumElements;
int MaxElements;
int TotElements;
int SizeRequested;
int Length;
int Offset = 0;
int WordSize = 1;
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
// Some adjustment
if (Area == (int)S7Area.CT)
WordLen = (int)S7WordLength.Counter;
if (Area == (int)S7Area.TM)
WordLen = (int)S7WordLength.Timer;
// Calc Word size
WordSize = WordLen.DataSizeByte();
if (WordSize == 0)
return S7Consts.errCliInvalidWordLen;
if (WordLen == (int)S7WordLength.Bit)
Amount = 1; // Only 1 bit can be transferred at time
else
{
if ((WordLen != (int)S7WordLength.Counter) && (WordLen != (int)S7WordLength.Timer))
{
Amount = Amount * WordSize;
WordSize = 1;
WordLen = (int)S7WordLength.Byte;
}
}
MaxElements = (_PDULength - 18) / WordSize; // 18 = Reply telegram header
TotElements = Amount;
while ((TotElements > 0) && (_LastError == 0))
{
NumElements = TotElements;
if (NumElements > MaxElements)
NumElements = MaxElements;
SizeRequested = NumElements * WordSize;
// Setup the telegram
Array.Copy(S7_RW, 0, PDU, 0, Size_RD);
// Set DB Number
PDU[27] = (byte)Area;
// Set Area
if (Area == (int)S7Area.DB)
PDU.SetWordAt(25, (ushort)DBNumber);
// Adjusts Start and word length
if ((WordLen == (int)S7WordLength.Bit) || (WordLen == (int)S7WordLength.Counter) || (WordLen == (int)S7WordLength.Timer))
{
Address = Start;
PDU[22] = (byte)WordLen;
}
else
Address = Start << 3;
// Num elements
PDU.SetWordAt(23, (ushort)NumElements);
// Address into the PLC (only 3 bytes)
PDU[30] = (byte)(Address & 0x0FF);
Address = Address >> 8;
PDU[29] = (byte)(Address & 0x0FF);
Address = Address >> 8;
PDU[28] = (byte)(Address & 0x0FF);
SendPacket(PDU, Size_RD);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (_LastError == 0)
{
if (Length<25)
_LastError = S7Consts.errIsoInvalidDataSize;
else
{
if (PDU[21] != 0xFF)
_LastError = CpuError(PDU[21]);
else
{
Array.Copy(PDU, 25, Buffer, Offset, SizeRequested);
Offset += SizeRequested;
}
}
}
}
TotElements -= NumElements;
Start += NumElements * WordSize;
}
if (_LastError == 0)
{
BytesRead = Offset;
Time_ms = Environment.TickCount - Elapsed;
}
else
BytesRead = 0;
return _LastError;
}
public int WriteArea(S7Area Area, int DBNumber, int Start, int Amount, S7WordLength WordLen, byte[] Buffer)
{
int BytesWritten = 0;
return WriteArea((int) Area, DBNumber, Start, Amount, (int) WordLen, Buffer, ref BytesWritten);
}
public int WriteArea(S7Area Area, int DBNumber, int Start, int Amount, S7WordLength WordLen, byte[] Buffer, ref int BytesWritten)
{
return WriteArea((int) Area, DBNumber, Start, Amount, (int) WordLen, Buffer, ref BytesWritten);
}
public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
{
int BytesWritten = 0;
return WriteArea(Area, DBNumber, Start, Amount, WordLen, Buffer, ref BytesWritten);
}
public int WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer, ref int BytesWritten)
{
int Address;
int NumElements;
int MaxElements;
int TotElements;
int DataSize;
int IsoSize;
int Length;
int Offset = 0;
int WordSize = 1;
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
// Some adjustment
if (Area == (int)S7Area.CT)
WordLen = (int)S7WordLength.Counter;
if (Area == (int)S7Area.TM)
WordLen = (int)S7WordLength.Timer;
// Calc Word size
WordSize = WordLen.DataSizeByte();
if (WordSize == 0)
return S7Consts.errCliInvalidWordLen;
if (WordLen == (int)S7WordLength.Bit) // Only 1 bit can be transferred at time
Amount = 1;
else
{
if ((WordLen != (int)S7WordLength.Counter) && (WordLen != (int)S7WordLength.Timer))
{
Amount = Amount * WordSize;
WordSize = 1;
WordLen = (int)S7WordLength.Byte;
}
}
MaxElements = (_PDULength - 35) / WordSize; // 35 = Reply telegram header
TotElements = Amount;
while ((TotElements > 0) && (_LastError == 0))
{
NumElements = TotElements;
if (NumElements > MaxElements)
NumElements = MaxElements;
DataSize = NumElements * WordSize;
IsoSize = Size_WR + DataSize;
// Setup the telegram
Array.Copy(S7_RW, 0, PDU, 0, Size_WR);
// Whole telegram Size
PDU.SetWordAt(2, (ushort)IsoSize);
// Data Length
Length = DataSize + 4;
PDU.SetWordAt(15, (ushort)Length);
// Function
PDU[17] = (byte)0x05;
// Set DB Number
PDU[27] = (byte)Area;
if (Area == (int)S7Area.DB)
PDU.SetWordAt(25, (ushort)DBNumber);
// Adjusts Start and word length
if ((WordLen == (int)S7WordLength.Bit) || (WordLen == (int)S7WordLength.Counter) || (WordLen == (int)S7WordLength.Timer))
{
Address = Start;
Length = DataSize;
PDU[22] = (byte)WordLen;
}
else
{
Address = Start << 3;
Length = DataSize << 3;
}
// Num elements
PDU.SetWordAt(23, (ushort)NumElements);
// Address into the PLC
PDU[30] = (byte)(Address & 0x0FF);
Address = Address >> 8;
PDU[29] = (byte)(Address & 0x0FF);
Address = Address >> 8;
PDU[28] = (byte)(Address & 0x0FF);
// Transport Size
switch (WordLen)
{
case (int)S7WordLength.Bit:
PDU[32] = TS_ResBit;
break;
case (int)S7WordLength.Counter:
case (int)S7WordLength.Timer:
PDU[32] = TS_ResOctet;
break;
default:
PDU[32] = TS_ResByte; // byte/word/dword etc.
break;
};
// Length
PDU.SetWordAt(33, (ushort)Length);
// Copies the Data
Array.Copy(Buffer, Offset, PDU, 35, DataSize);
SendPacket(PDU, IsoSize);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (_LastError == 0)
{
if (Length == 22)
{
if (PDU[21] != (byte)0xFF)
_LastError = CpuError(PDU[21]);
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
}
Offset += DataSize;
TotElements -= NumElements;
Start += NumElements * WordSize;
}
if (_LastError == 0)
{
BytesWritten = Offset;
Time_ms = Environment.TickCount - Elapsed;
}
else
BytesWritten = 0;
return _LastError;
}
public int ReadMultiVars(S7DataItem[] Items, int ItemsCount)
{
int Offset;
int Length;
int ItemSize;
byte[] S7Item = new byte[12];
byte[] S7ItemRead = new byte[1024];
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
// Checks items
if (ItemsCount > MaxVars)
return S7Consts.errCliTooManyItems;
// Fills Header
Array.Copy(S7_MRD_HEADER, 0, PDU, 0, S7_MRD_HEADER.Length);
PDU.SetWordAt(13, (ushort)(ItemsCount * S7Item.Length + 2));
PDU[18] = (byte)ItemsCount;
// Fills the Items
Offset = 19;
for (int c = 0; c < ItemsCount; c++)
{
Array.Copy(S7_MRD_ITEM, S7Item, S7Item.Length);
S7Item[3] = (byte)Items[c].WordLen;
S7Item.SetWordAt(4, (ushort)Items[c].Amount);
if (Items[c].Area == (int)S7Area.DB)
S7Item.SetWordAt(6, (ushort)Items[c].DBNumber);
S7Item[8] = (byte)Items[c].Area;
// Address into the PLC
int Address = Items[c].Start;
S7Item[11] = (byte)(Address & 0x0FF);
Address = Address >> 8;
S7Item[10] = (byte)(Address & 0x0FF);
Address = Address >> 8;
S7Item[09] = (byte)(Address & 0x0FF);
Array.Copy(S7Item, 0, PDU, Offset, S7Item.Length);
Offset += S7Item.Length;
}
if (Offset > _PDULength)
return S7Consts.errCliSizeOverPDU;
PDU.SetWordAt(2, (ushort)Offset); // Whole size
SendPacket(PDU, Offset);
if (_LastError != 0)
return _LastError;
// Get Answer
Length = RecvIsoPacket();
if (_LastError != 0)
return _LastError;
// Check ISO Length
if (Length < 22)
{
_LastError = S7Consts.errIsoInvalidPDU; // PDU too Small
return _LastError;
}
// Check Global Operation Result
_LastError = CpuError(PDU.GetWordAt(17));
if (_LastError != 0)
return _LastError;
// Get true ItemsCount
int ItemsRead = PDU.GetByteAt(20);
if ((ItemsRead != ItemsCount) || (ItemsRead>MaxVars))
{
_LastError = S7Consts.errCliInvalidPlcAnswer;
return _LastError;
}
// Get Data
Offset = 21;
for (int c = 0; c < ItemsCount; c++)
{
// Get the Item
Array.Copy(PDU, Offset, S7ItemRead, 0, Length-Offset);
if (S7ItemRead[0] == 0xff)
{
ItemSize = (int)S7ItemRead.GetWordAt(2);
if ((S7ItemRead[1] != TS_ResOctet) && (S7ItemRead[1] != TS_ResReal) && (S7ItemRead[1] != TS_ResBit))
ItemSize = ItemSize >> 3;
Marshal.Copy(S7ItemRead, 4, Items[c].pData, ItemSize);
Items[c].Result = 0;
if (ItemSize % 2 != 0)
ItemSize++; // Odd size are rounded
Offset = Offset + 4 + ItemSize;
}
else
{
Items[c].Result = CpuError(S7ItemRead[0]);
Offset += 4; // Skip the Item header
}
}
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int WriteMultiVars(S7DataItem[] Items, int ItemsCount)
{
int Offset;
int ParLength;
int DataLength;
int ItemDataSize;
byte[] S7ParItem = new byte[S7_MWR_PARAM.Length];
byte[] S7DataItem = new byte[1024];
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
// Checks items
if (ItemsCount > MaxVars)
return S7Consts.errCliTooManyItems;
// Fills Header
Array.Copy(S7_MWR_HEADER, 0, PDU, 0, S7_MWR_HEADER.Length);
ParLength = ItemsCount * S7_MWR_PARAM.Length + 2;
PDU.SetWordAt(13, (ushort)ParLength);
PDU[18] = (byte)ItemsCount;
// Fills Params
Offset = S7_MWR_HEADER.Length;
for (int c=0; c<ItemsCount; c++)
{
Array.Copy(S7_MWR_PARAM, 0, S7ParItem, 0, S7_MWR_PARAM.Length);
S7ParItem[3] = (byte)Items[c].WordLen;
S7ParItem[8] = (byte)Items[c].Area;
S7ParItem.SetWordAt(4, (ushort)Items[c].Amount);
S7ParItem.SetWordAt(6, (ushort)Items[c].DBNumber);
// Address into the PLC
int Address = Items[c].Start;
S7ParItem[11] = (byte)(Address & 0x0FF);
Address = Address >> 8;
S7ParItem[10] = (byte)(Address & 0x0FF);
Address = Address >> 8;
S7ParItem[09] = (byte)(Address & 0x0FF);
Array.Copy(S7ParItem, 0, PDU, Offset, S7ParItem.Length);
Offset += S7_MWR_PARAM.Length;
}
// Fills Data
DataLength = 0;
for (int c = 0; c < ItemsCount; c++)
{
S7DataItem[0] = 0x00;
switch (Items[c].WordLen)
{
case (int)S7WordLength.Bit:
S7DataItem[1] = TS_ResBit;
break;
case (int)S7WordLength.Counter:
case (int)S7WordLength.Timer:
S7DataItem[1] = TS_ResOctet;
break;
default:
S7DataItem[1] = TS_ResByte; // byte/word/dword etc.
break;
};
if ((Items[c].WordLen==(int)S7WordLength.Timer) || (Items[c].WordLen == (int)S7WordLength.Counter))
ItemDataSize = Items[c].Amount * 2;
else
ItemDataSize = Items[c].Amount;
if ((S7DataItem[1] != TS_ResOctet) && (S7DataItem[1] != TS_ResBit))
S7DataItem.SetWordAt(2, (ushort)(ItemDataSize*8));
else
S7DataItem.SetWordAt(2, (ushort)ItemDataSize);
Marshal.Copy(Items[c].pData, S7DataItem, 4, ItemDataSize);
if (ItemDataSize % 2 != 0)
{
S7DataItem[ItemDataSize+4] = 0x00;
ItemDataSize++;
}
Array.Copy(S7DataItem, 0, PDU, Offset, ItemDataSize+4);
Offset = Offset + ItemDataSize + 4;
DataLength = DataLength + ItemDataSize + 4;
}
// Checks the size
if (Offset > _PDULength)
return S7Consts.errCliSizeOverPDU;
PDU.SetWordAt(2, (ushort)Offset); // Whole size
PDU.SetWordAt(15, (ushort)DataLength); // Whole size
SendPacket(PDU, Offset);
RecvIsoPacket();
if (_LastError==0)
{
// Check Global Operation Result
_LastError = CpuError(PDU.GetWordAt(17));
if (_LastError != 0)
return _LastError;
// Get true ItemsCount
int ItemsWritten = PDU.GetByteAt(20);
if ((ItemsWritten != ItemsCount) || (ItemsWritten > MaxVars))
{
_LastError = S7Consts.errCliInvalidPlcAnswer;
return _LastError;
}
for (int c=0; c<ItemsCount; c++)
{
if (PDU[c + 21] == 0xFF)
Items[c].Result = 0;
else
Items[c].Result = CpuError((ushort)PDU[c + 21]);
}
Time_ms = Environment.TickCount - Elapsed;
}
return _LastError;
}
#endregion
#region [Data I/O lean functions]
public int DBRead(int DBNumber, int Start, int Size, byte[] Buffer)
{
return ReadArea(S7Area.DB, DBNumber, Start, Size, S7WordLength.Byte, Buffer);
}
public int DBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
{
return WriteArea(S7Area.DB, DBNumber, Start, Size, S7WordLength.Byte, Buffer);
}
public int MBRead(int Start, int Size, byte[] Buffer)
{
return ReadArea(S7Area.MK, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int MBWrite(int Start, int Size, byte[] Buffer)
{
return WriteArea(S7Area.MK, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int EBRead(int Start, int Size, byte[] Buffer)
{
return ReadArea(S7Area.PE, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int EBWrite(int Start, int Size, byte[] Buffer)
{
return WriteArea(S7Area.PE, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int ABRead(int Start, int Size, byte[] Buffer)
{
return ReadArea(S7Area.PA, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int ABWrite(int Start, int Size, byte[] Buffer)
{
return WriteArea(S7Area.PA, 0, Start, Size, S7WordLength.Byte, Buffer);
}
public int TMRead(int Start, int Amount, ushort[] Buffer)
{
byte[] sBuffer = new byte[Amount * 2];
int Result = ReadArea(S7Area.TM, 0, Start, Amount, S7WordLength.Timer, sBuffer);
if (Result == 0)
{
for (int c = 0; c < Amount; c++)
{
Buffer[c] = (ushort)((sBuffer[c * 2 + 1] << 8) + (sBuffer[c * 2]));
}
}
return Result;
}
public int TMWrite(int Start, int Amount, ushort[] Buffer)
{
byte[] sBuffer = new byte[Amount * 2];
for (int c = 0; c < Amount; c++)
{
sBuffer[c * 2 + 1] = (byte)((Buffer[c] & 0xFF00) >> 8);
sBuffer[c * 2] = (byte)(Buffer[c] & 0x00FF);
}
return WriteArea(S7Area.TM, 0, Start, Amount, S7WordLength.Timer, sBuffer);
}
public int CTRead(int Start, int Amount, ushort[] Buffer)
{
byte[] sBuffer = new byte[Amount * 2];
int Result = ReadArea(S7Area.CT, 0, Start, Amount, S7WordLength.Counter, sBuffer);
if (Result==0)
{
for (int c=0; c<Amount; c++)
{
Buffer[c] = (ushort)((sBuffer[c * 2 + 1] << 8) + (sBuffer[c * 2]));
}
}
return Result;
}
public int CTWrite(int Start, int Amount, ushort[] Buffer)
{
byte[] sBuffer = new byte[Amount * 2];
for (int c = 0; c < Amount; c++)
{
sBuffer[c * 2 + 1] = (byte)((Buffer[c] & 0xFF00)>>8);
sBuffer[c * 2]= (byte)(Buffer[c] & 0x00FF);
}
return WriteArea(S7Area.CT, 0, Start, Amount, S7WordLength.Counter, sBuffer);
}
#endregion
#region [Directory functions]
public int ListBlocks(ref S7BlocksList List)
{
return S7Consts.errCliFunctionNotImplemented;
}
private string SiemensTimestamp(long EncodedDate)
{
DateTime DT = new DateTime(1984, 1, 1).AddSeconds(EncodedDate*86400);
#if WINDOWS_UWP || NETFX_CORE || CORE_CLR
return DT.ToString(System.Globalization.DateTimeFormatInfo.CurrentInfo.ShortDatePattern);
#else
return DT.ToShortDateString();
#endif
}
public int GetAgBlockInfo(int BlockType, int BlockNum, ref S7BlockInfo Info)
{
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
S7_BI[30] = (byte)BlockType;
// Block Number
S7_BI[31] = (byte)((BlockNum / 10000) + 0x30);
BlockNum = BlockNum % 10000;
S7_BI[32] = (byte)((BlockNum / 1000) + 0x30);
BlockNum = BlockNum % 1000;
S7_BI[33] = (byte)((BlockNum / 100) + 0x30);
BlockNum = BlockNum % 100;
S7_BI[34] = (byte)((BlockNum / 10) + 0x30);
BlockNum = BlockNum % 10;
S7_BI[35] = (byte)((BlockNum / 1) + 0x30);
SendPacket(S7_BI);
if (_LastError == 0)
{
int Length = RecvIsoPacket();
if (Length > 32) // the minimum expected
{
ushort Result = PDU.GetWordAt(27);
if (Result == 0)
{
Info.BlkFlags= PDU[42];
Info.BlkLang = PDU[43];
Info.BlkType = PDU[44];
Info.BlkNumber = PDU.GetWordAt(45);
Info.LoadSize = PDU.GetDIntAt(47);
Info.CodeDate = SiemensTimestamp(PDU.GetWordAt(59));
Info.IntfDate = SiemensTimestamp(PDU.GetWordAt(65));
Info.SBBLength = PDU.GetWordAt(67);
Info.LocalData = PDU.GetWordAt(71);
Info.MC7Size = PDU.GetWordAt(73);
Info.Author = PDU.GetCharsAt(75, 8).Trim(new char[]{(char)0});
Info.Family = PDU.GetCharsAt(83, 8).Trim(new char[]{(char)0});
Info.Header = PDU.GetCharsAt(91, 8).Trim(new char[]{(char)0});
Info.Version = PDU[99];
Info.CheckSum = PDU.GetWordAt(101);
}
else
_LastError = CpuError(Result);
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int GetPgBlockInfo(ref S7BlockInfo Info, byte[] Buffer, int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int ListBlocksOfType(int BlockType, ushort[] List, ref int ItemsCount)
{
return S7Consts.errCliFunctionNotImplemented;
}
#endregion
#region [Blocks functions]
public int Upload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int FullUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int Download(int BlockNum, byte[] UsrData, int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int Delete(int BlockType, int BlockNum)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int DBGet(int DBNumber, byte[] UsrData, ref int Size)
{
S7BlockInfo BI = new S7BlockInfo();
int Elapsed = Environment.TickCount;
Time_ms = 0;
_LastError = GetAgBlockInfo(Block_DB, DBNumber, ref BI);
if (_LastError==0)
{
int DBSize = BI.MC7Size;
if (DBSize <= UsrData.Length)
{
Size = DBSize;
_LastError = DBRead(DBNumber, 0, DBSize, UsrData);
if (_LastError == 0)
Size = DBSize;
}
else
_LastError = S7Consts.errCliBufferTooSmall;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int DBFill(int DBNumber, int FillChar)
{
S7BlockInfo BI = new S7BlockInfo();
int Elapsed = Environment.TickCount;
Time_ms = 0;
_LastError = GetAgBlockInfo(Block_DB, DBNumber, ref BI);
if (_LastError == 0)
{
byte[] Buffer = new byte[BI.MC7Size];
for (int c = 0; c < BI.MC7Size; c++)
Buffer[c] = (byte)FillChar;
_LastError = DBWrite(DBNumber, 0, BI.MC7Size, Buffer);
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
#endregion
#region [Date/Time functions]
public int GetPlcDateTime(ref DateTime DT)
{
int Length;
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_GET_DT);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (Length > 30) // the minimum expected
{
if ((PDU.GetWordAt(27) == 0) && (PDU[29] == 0xFF))
{
DT = PDU.GetDateTimeAt(35);
}
else
_LastError = S7Consts.errCliInvalidPlcAnswer;
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if(_LastError==0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int SetPlcDateTime(DateTime DT)
{
int Length;
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
S7_SET_DT.SetDateTimeAt(31, DT);
SendPacket(S7_SET_DT);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (Length > 30) // the minimum expected
{
if (PDU.GetWordAt(27) != 0)
_LastError = S7Consts.errCliInvalidPlcAnswer;
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int SetPlcSystemDateTime()
{
return SetPlcDateTime(DateTime.Now);
}
#endregion
#region [System Info functions]
public int GetOrderCode(ref S7OrderCode Info)
{
S7SZL SZL = new S7SZL();
int Size = 1024;
SZL.Data = new byte[Size];
int Elapsed = Environment.TickCount;
_LastError = ReadSZL(0x0011, 0x000, ref SZL, ref Size);
if (_LastError == 0)
{
Info.Code = SZL.Data.GetCharsAt(2, 20);
Info.V1 = SZL.Data[Size - 3];
Info.V2 = SZL.Data[Size - 2];
Info.V3 = SZL.Data[Size - 1];
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int GetCpuInfo(ref S7CpuInfo Info)
{
S7SZL SZL = new S7SZL();
int Size = 1024;
SZL.Data = new byte[Size];
int Elapsed = Environment.TickCount;
_LastError = ReadSZL(0x001C, 0x000, ref SZL, ref Size);
if (_LastError == 0)
{
Info.ModuleTypeName = SZL.Data.GetCharsAt(172, 32);
Info.SerialNumber = SZL.Data.GetCharsAt(138, 24);
Info.ASName = SZL.Data.GetCharsAt(2, 24);
Info.Copyright = SZL.Data.GetCharsAt(104, 26);
Info.ModuleName = SZL.Data.GetCharsAt(36, 24);
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int GetCpInfo(ref S7CpInfo Info)
{
S7SZL SZL = new S7SZL();
int Size = 1024;
SZL.Data = new byte[Size];
int Elapsed = Environment.TickCount;
_LastError = ReadSZL(0x0131, 0x001, ref SZL, ref Size);
if (_LastError == 0)
{
Info.MaxPduLength = PDU.GetIntAt(2);
Info.MaxConnections = PDU.GetIntAt(4);
Info.MaxMpiRate = PDU.GetDIntAt(6);
Info.MaxBusRate = PDU.GetDIntAt(10);
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int ReadSZL(int ID, int Index, ref S7SZL SZL, ref int Size)
{
int Length;
int DataSZL;
int Offset = 0;
bool Done = false;
bool First = true;
byte Seq_in = 0x00;
ushort Seq_out = 0x0000;
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
SZL.Header.LENTHDR = 0;
do
{
if (First)
{
S7_SZL_FIRST.SetWordAt(11, ++Seq_out);
S7_SZL_FIRST.SetWordAt(29, (ushort)ID);
S7_SZL_FIRST.SetWordAt(31, (ushort)Index);
SendPacket(S7_SZL_FIRST);
}
else
{
S7_SZL_NEXT.SetWordAt(11, ++Seq_out);
S7_SZL_NEXT[24] = (byte)Seq_in;
SendPacket(S7_SZL_NEXT);
}
if (_LastError != 0)
return _LastError;
Length = RecvIsoPacket();
if (_LastError == 0)
{
if (First)
{
if (Length > 32) // the minimum expected
{
if ((PDU.GetWordAt(27) == 0) && (PDU[29] == (byte)0xFF))
{
// Gets Amount of this slice
DataSZL = PDU.GetWordAt(31) - 8; // Skips extra params (ID, Index ...)
Done = PDU[26] == 0x00;
Seq_in = (byte)PDU[24]; // Slice sequence
SZL.Header.LENTHDR = PDU.GetWordAt(37);
SZL.Header.N_DR = PDU.GetWordAt(39);
Array.Copy(PDU, 41, SZL.Data, Offset, DataSZL);
// SZL.Copy(PDU, 41, Offset, DataSZL);
Offset += DataSZL;
SZL.Header.LENTHDR += SZL.Header.LENTHDR;
}
else
_LastError = S7Consts.errCliInvalidPlcAnswer;
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
else
{
if (Length > 32) // the minimum expected
{
if ((PDU.GetWordAt(27) == 0) && (PDU[29] == (byte)0xFF))
{
// Gets Amount of this slice
DataSZL = PDU.GetWordAt(31);
Done = PDU[26] == 0x00;
Seq_in = (byte)PDU[24]; // Slice sequence
Array.Copy(PDU, 37, SZL.Data, Offset, DataSZL);
Offset += DataSZL;
SZL.Header.LENTHDR += SZL.Header.LENTHDR;
}
else
_LastError = S7Consts.errCliInvalidPlcAnswer;
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
}
First = false;
}
while (!Done && (_LastError == 0));
if (_LastError==0)
{
Size = SZL.Header.LENTHDR;
Time_ms = Environment.TickCount - Elapsed;
}
return _LastError;
}
public int ReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
{
return S7Consts.errCliFunctionNotImplemented;
}
#endregion
#region [Control functions]
public int PlcHotStart()
{
_LastError = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_HOT_START);
if (_LastError == 0)
{
int Length = RecvIsoPacket();
if (Length > 18) // 18 is the minimum expected
{
if (PDU[19] != pduStart)
_LastError = S7Consts.errCliCannotStartPLC;
else
{
if (PDU[20] == pduAlreadyStarted)
_LastError = S7Consts.errCliAlreadyRun;
else
_LastError = S7Consts.errCliCannotStartPLC;
}
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int PlcColdStart()
{
_LastError = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_COLD_START);
if (_LastError == 0)
{
int Length = RecvIsoPacket();
if (Length > 18) // 18 is the minimum expected
{
if (PDU[19] != pduStart)
_LastError = S7Consts.errCliCannotStartPLC;
else
{
if (PDU[20] == pduAlreadyStarted)
_LastError = S7Consts.errCliAlreadyRun;
else
_LastError = S7Consts.errCliCannotStartPLC;
}
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int PlcStop()
{
_LastError = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_STOP);
if (_LastError == 0)
{
int Length = RecvIsoPacket();
if (Length > 18) // 18 is the minimum expected
{
if (PDU[19]!=pduStop)
_LastError = S7Consts.errCliCannotStopPLC;
else
{
if (PDU[20]== pduAlreadyStopped)
_LastError = S7Consts.errCliAlreadyStop;
else
_LastError = S7Consts.errCliCannotStopPLC;
}
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int PlcCopyRamToRom(UInt32 Timeout)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int PlcCompress(UInt32 Timeout)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int PlcGetStatus(ref Int32 Status)
{
_LastError = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_GET_STAT);
if (_LastError == 0)
{
int Length = RecvIsoPacket();
if (Length > 30) // the minimum expected
{
ushort Result = PDU.GetWordAt(27);
if (Result == 0)
{
switch (PDU[44])
{
case S7Consts.S7CpuStatusUnknown:
case S7Consts.S7CpuStatusRun:
case S7Consts.S7CpuStatusStop:
{
Status = PDU[44];
break;
}
default:
{
// Since RUN status is always 0x08 for all CPUs and CPs, STOP status
// sometime can be coded as 0x03 (especially for old cpu...)
Status = S7Consts.S7CpuStatusStop;
break;
}
}
}
else
_LastError = CpuError(Result);
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
#endregion
#region [Security functions]
public int SetSessionPassword(string Password)
{
byte[] pwd = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
int Length;
_LastError = 0;
int Elapsed = Environment.TickCount;
// Encodes the Password
pwd.SetCharsAt(0, Password);
pwd[0] = (byte)(pwd[0] ^ 0x55);
pwd[1] = (byte)(pwd[1] ^ 0x55);
for (int c = 2; c < 8; c++)
{
pwd[c] = (byte)(pwd[c] ^ 0x55 ^ pwd[c - 2]);
}
Array.Copy(pwd, 0, S7_SET_PWD, 29, 8);
// Sends the telegrem
SendPacket(S7_SET_PWD);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (Length > 32) // the minimum expected
{
ushort Result = PDU.GetWordAt(27);
if (Result != 0)
_LastError = CpuError(Result);
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
return _LastError;
}
public int ClearSessionPassword()
{
int Length;
_LastError = 0;
int Elapsed = Environment.TickCount;
SendPacket(S7_CLR_PWD);
if (_LastError == 0)
{
Length = RecvIsoPacket();
if (Length > 30) // the minimum expected
{
ushort Result = PDU.GetWordAt(27);
if (Result != 0)
_LastError = CpuError(Result);
}
else
_LastError = S7Consts.errIsoInvalidPDU;
}
return _LastError;
}
public int GetProtection(ref S7Protection Protection)
{
S7Client.S7SZL SZL = new S7Client.S7SZL();
int Size = 256;
SZL.Data = new byte[Size];
_LastError = ReadSZL(0x0232, 0x0004, ref SZL, ref Size);
if (_LastError == 0)
{
Protection.sch_schal = SZL.Data.GetWordAt(2);
Protection.sch_par = SZL.Data.GetWordAt(4);
Protection.sch_rel = SZL.Data.GetWordAt(6);
Protection.bart_sch = SZL.Data.GetWordAt(8);
Protection.anl_sch = SZL.Data.GetWordAt(10);
}
return _LastError;
}
#endregion
#region [Low Level]
public int IsoExchangeBuffer(byte[] Buffer, ref Int32 Size)
{
_LastError = 0;
Time_ms = 0;
int Elapsed = Environment.TickCount;
Array.Copy(TPKT_ISO, 0, PDU, 0, TPKT_ISO.Length);
PDU.SetWordAt(2, (ushort)(Size + TPKT_ISO.Length));
try
{
Array.Copy(Buffer, 0, PDU, TPKT_ISO.Length, Size);
}
catch
{
return S7Consts.errIsoInvalidPDU;
}
SendPacket(PDU, TPKT_ISO.Length + Size);
if (_LastError==0)
{
int Length=RecvIsoPacket();
if (_LastError==0)
{
Array.Copy(PDU, TPKT_ISO.Length, Buffer, 0, Length - TPKT_ISO.Length);
Size = Length - TPKT_ISO.Length;
}
}
if (_LastError == 0)
Time_ms = Environment.TickCount - Elapsed;
else
Size = 0;
return _LastError;
}
#endregion
#region [Async functions (not implemented)]
public int AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsDBRead(int DBNumber, int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsDBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsMBRead(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsMBWrite(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsEBRead(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsEBWrite(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsABRead(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsABWrite(int Start, int Size, byte[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsTMRead(int Start, int Amount, ushort[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsTMWrite(int Start, int Amount, ushort[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsCTRead(int Start, int Amount, ushort[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsCTWrite(int Start, int Amount, ushort[] Buffer)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsListBlocksOfType(int BlockType, ushort[] List)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsReadSZL(int ID, int Index, ref S7SZL Data, ref Int32 Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsFullUpload(int BlockType, int BlockNum, byte[] UsrData, ref int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int ASDownload(int BlockNum, byte[] UsrData, int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsPlcCopyRamToRom(UInt32 Timeout)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsPlcCompress(UInt32 Timeout)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsDBGet(int DBNumber, byte[] UsrData, ref int Size)
{
return S7Consts.errCliFunctionNotImplemented;
}
public int AsDBFill(int DBNumber, int FillChar)
{
return S7Consts.errCliFunctionNotImplemented;
}
public bool CheckAsCompletion(ref int opResult)
{
opResult = 0;
return false;
}
public int WaitAsCompletion(int Timeout)
{
return S7Consts.errCliFunctionNotImplemented;
}
#endregion
#region [Info Functions / Properties]
public string ErrorText(int Error)
{
switch (Error)
{
case 0: return "OK";
case S7Consts.errTCPSocketCreation: return "SYS: Error creating the Socket";
case S7Consts.errTCPConnectionTimeout: return "TCP: Connection Timeout";
case S7Consts.errTCPConnectionFailed: return "TCP: Connection Error";
case S7Consts.errTCPReceiveTimeout: return "TCP: Data receive Timeout";
case S7Consts.errTCPDataReceive: return "TCP: Error receiving Data";
case S7Consts.errTCPSendTimeout: return "TCP: Data send Timeout";
case S7Consts.errTCPDataSend: return "TCP: Error sending Data";
case S7Consts.errTCPConnectionReset: return "TCP: Connection reset by the Peer";
case S7Consts.errTCPNotConnected: return "CLI: Client not connected";
case S7Consts.errTCPUnreachableHost: return "TCP: Unreachable host";
case S7Consts.errIsoConnect: return "ISO: Connection Error";
case S7Consts.errIsoInvalidPDU: return "ISO: Invalid PDU received";
case S7Consts.errIsoInvalidDataSize: return "ISO: Invalid Buffer passed to Send/Receive";
case S7Consts.errCliNegotiatingPDU: return "CLI: Error in PDU negotiation";
case S7Consts.errCliInvalidParams: return "CLI: Invalid param(s) supplied";
case S7Consts.errCliJobPending: return "CLI: Job pending";
case S7Consts.errCliTooManyItems: return "CLI: Too many items (>20) in multi read/write";
case S7Consts.errCliInvalidWordLen: return "CLI: Invalid WordLength";
case S7Consts.errCliPartialDataWritten: return "CLI: Partial data written";
case S7Consts.errCliSizeOverPDU: return "CPU: Total data exceeds the PDU size";
case S7Consts.errCliInvalidPlcAnswer: return "CLI: Invalid CPU answer";
case S7Consts.errCliAddressOutOfRange: return "CPU: Address out of range";
case S7Consts.errCliInvalidTransportSize: return "CPU: Invalid Transport size";
case S7Consts.errCliWriteDataSizeMismatch: return "CPU: Data size mismatch";
case S7Consts.errCliItemNotAvailable: return "CPU: Item not available";
case S7Consts.errCliInvalidValue: return "CPU: Invalid value supplied";
case S7Consts.errCliCannotStartPLC: return "CPU: Cannot start PLC";
case S7Consts.errCliAlreadyRun: return "CPU: PLC already RUN";
case S7Consts.errCliCannotStopPLC: return "CPU: Cannot stop PLC";
case S7Consts.errCliCannotCopyRamToRom: return "CPU: Cannot copy RAM to ROM";
case S7Consts.errCliCannotCompress: return "CPU: Cannot compress";
case S7Consts.errCliAlreadyStop: return "CPU: PLC already STOP";
case S7Consts.errCliFunNotAvailable: return "CPU: Function not available";
case S7Consts.errCliUploadSequenceFailed: return "CPU: Upload sequence failed";
case S7Consts.errCliInvalidDataSizeRecvd: return "CLI: Invalid data size received";
case S7Consts.errCliInvalidBlockType: return "CLI: Invalid block type";
case S7Consts.errCliInvalidBlockNumber: return "CLI: Invalid block number";
case S7Consts.errCliInvalidBlockSize: return "CLI: Invalid block size";
case S7Consts.errCliNeedPassword: return "CPU: Function not authorized for current protection level";
case S7Consts.errCliInvalidPassword: return "CPU: Invalid password";
case S7Consts.errCliNoPasswordToSetOrClear: return "CPU: No password to set or clear";
case S7Consts.errCliJobTimeout: return "CLI: Job Timeout";
case S7Consts.errCliFunctionRefused: return "CLI: Function refused by CPU (Unknown error)";
case S7Consts.errCliPartialDataRead: return "CLI: Partial data read";
case S7Consts.errCliBufferTooSmall: return "CLI: The buffer supplied is too small to accomplish the operation";
case S7Consts.errCliDestroying: return "CLI: Cannot perform (destroying)";
case S7Consts.errCliInvalidParamNumber: return "CLI: Invalid Param Number";
case S7Consts.errCliCannotChangeParam: return "CLI: Cannot change this param now";
case S7Consts.errCliFunctionNotImplemented: return "CLI: Function not implemented";
default: return "CLI: Unknown error (0x" + Convert.ToString(Error, 16) + ")";
};
}
public int LastError()
{
return _LastError;
}
public int RequestedPduLength()
{
return _PduSizeRequested;
}
public int NegotiatedPduLength()
{
return _PDULength;
}
public int ExecTime()
{
return Time_ms;
}
public int ExecutionTime => Time_ms;
public int PduSizeNegotiated => _PDULength;
public int PduSizeRequested
{
get => _PduSizeRequested;
set
{
if (value < MinPduSizeToRequest)
value = MinPduSizeToRequest;
if (value > MaxPduSizeToRequest)
value = MaxPduSizeToRequest;
_PduSizeRequested = value;
}
}
public string PLCIpAddress => IPAddress;
public int PLCPort
{
get => _PLCPort;
set => _PLCPort = value;
}
public int ConnTimeout
{
get => Socket.ConnectTimeout;
set => Socket.ConnectTimeout = value;
}
public int RecvTimeout
{
get => Socket.ReadTimeout;
set => Socket.ReadTimeout = value;
}
public int SendTimeout
{
get => Socket.WriteTimeout;
set => Socket.WriteTimeout = value;
}
public bool Connected => (Socket != null) && (Socket.Connected);
#endregion
}
}
================================================
FILE: Sharp7/S7Consts.cs
================================================
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Sharp7
{
public static class S7Consts
{
#region [Exported Consts]
// Error codes
//------------------------------------------------------------------------------
// ERRORS
//------------------------------------------------------------------------------
public const int ResultOK = 0x00000000;
public const int errTCPSocketCreation = 0x00000001;
public const int errTCPConnectionTimeout = 0x00000002;
public const int errTCPConnectionFailed = 0x00000003;
public const int errTCPReceiveTimeout = 0x00000004;
public const int errTCPDataReceive = 0x00000005;
public const int errTCPSendTimeout = 0x00000006;
public const int errTCPDataSend = 0x00000007;
public const int errTCPConnectionReset = 0x00000008;
public const int errTCPNotConnected = 0x00000009;
public const int errTCPUnreachableHost = 0x00002751;
public const int errIsoConnect = 0x00010000; // Connection error
public const int errIsoInvalidPDU = 0x00030000; // Bad format
public const int errIsoInvalidDataSize = 0x00040000; // Bad Datasize passed to send/recv : buffer is invalid
public const int errCliNegotiatingPDU = 0x00100000;
public const int errCliInvalidParams = 0x00200000;
public const int errCliJobPending = 0x00300000;
public const int errCliTooManyItems = 0x00400000;
public const int errCliInvalidWordLen = 0x00500000;
public const int errCliPartialDataWritten = 0x00600000;
public const int errCliSizeOverPDU = 0x00700000;
public const int errCliInvalidPlcAnswer = 0x00800000;
public const int errCliAddressOutOfRange = 0x00900000;
public const int errCliInvalidTransportSize = 0x00A00000;
public const int errCliWriteDataSizeMismatch = 0x00B00000;
public const int errCliItemNotAvailable = 0x00C00000;
public const int errCliInvalidValue = 0x00D00000;
public const int errCliCannotStartPLC = 0x00E00000;
public const int errCliAlreadyRun = 0x00F00000;
public const int errCliCannotStopPLC = 0x01000000;
public const int errCliCannotCopyRamToRom = 0x01100000;
public const int errCliCannotCompress = 0x01200000;
public const int errCliAlreadyStop = 0x01300000;
public const int errCliFunNotAvailable = 0x01400000;
public const int errCliUploadSequenceFailed = 0x01500000;
public const int errCliInvalidDataSizeRecvd = 0x01600000;
public const int errCliInvalidBlockType = 0x01700000;
public const int errCliInvalidBlockNumber = 0x01800000;
public const int errCliInvalidBlockSize = 0x01900000;
public const int errCliNeedPassword = 0x01D00000;
public const int errCliInvalidPassword = 0x01E00000;
public const int errCliNoPasswordToSetOrClear = 0x01F00000;
public const int errCliJobTimeout = 0x02000000;
public const int errCliPartialDataRead = 0x02100000;
public const int errCliBufferTooSmall = 0x02200000;
public const int errCliFunctionRefused = 0x02300000;
public const int errCliDestroying = 0x02400000;
public const int errCliInvalidParamNumber = 0x02500000;
public const int errCliCannotChangeParam = 0x02600000;
public const int errCliFunctionNotImplemented = 0x02700000;
//------------------------------------------------------------------------------
// PARAMS LIST FOR COMPATIBILITY WITH Snap7.net.cs
//------------------------------------------------------------------------------
public const Int32 p_u16_LocalPort = 1; // Not applicable here
public const Int32 p_u16_RemotePort = 2;
public const Int32 p_i32_PingTimeout = 3;
public const Int32 p_i32_SendTimeout = 4;
public const Int32 p_i32_RecvTimeout = 5;
public const Int32 p_i32_WorkInterval = 6; // Not applicable here
public const Int32 p_u16_SrcRef = 7; // Not applicable here
public const Int32 p_u16_DstRef = 8; // Not applicable here
public const Int32 p_u16_SrcTSap = 9; // Not applicable here
public const Int32 p_i32_PDURequest = 10;
public const Int32 p_i32_MaxClients = 11; // Not applicable here
public const Int32 p_i32_BSendTimeout = 12; // Not applicable here
public const Int32 p_i32_BRecvTimeout = 13; // Not applicable here
public const Int32 p_u32_RecoveryTime = 14; // Not applicable here
public const Int32 p_u32_KeepAliveTime = 15; // Not applicable here
// Area ID
[Obsolete("Use enum S7Area.PE instead")]public const byte S7AreaPE = 0x81;
[Obsolete("Use enum S7Area.PA instead")]public const byte S7AreaPA = 0x82;
[Obsolete("Use enum S7Area.MK instead")]public const byte S7AreaMK = 0x83;
[Obsolete("Use enum S7Area.DB instead")]public const byte S7AreaDB = 0x84;
[Obsolete("Use enum S7Area.CT instead")]public const byte S7AreaCT = 0x1C;
[Obsolete("Use enum S7Area.TM instead")]public const byte S7AreaTM = 0x1D;
// Word Length
[Obsolete("Use enum S7WordLength.Bit instead")]public const int S7WLBit = 0x01;
[Obsolete("Use enum S7WordLength.Byte instead")]public const int S7WLByte = 0x02;
[Obsolete("Use enum S7WordLength.Char instead")]public const int S7WLChar = 0x03;
[Obsolete("Use enum S7WordLength.Word instead")]public const int S7WLWord = 0x04;
[Obsolete("Use enum S7WordLength.Int instead")]public const int S7WLInt = 0x05;
[Obsolete("Use enum S7WordLength.DWord instead")]public const int S7WLDWord = 0x06;
[Obsolete("Use enum S7WordLength.DInt instead")]public const int S7WLDInt = 0x07;
[Obsolete("Use enum S7WordLength.Real instead")]public const int S7WLReal = 0x08;
[Obsolete("Use enum S7WordLength.Counter instead")]public const int S7WLCounter = 0x1C;
[Obsolete("Use enum S7WordLength.Timer instead")]public const int S7WLTimer = 0x1D;
// PLC Status
public const int S7CpuStatusUnknown = 0x00;
public const int S7CpuStatusRun = 0x08;
public const int S7CpuStatusStop = 0x04;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S7Tag
{
public Int32 Area;
public Int32 DBNumber;
public Int32 Start;
public Int32 Elements;
public Int32 WordLen;
}
#endregion
}
}
================================================
FILE: Sharp7/S7MultiVar.cs
================================================
using System;
using System.Linq;
using System.Runtime.InteropServices;
namespace Sharp7
{
public class S7MultiVar
{
#region [MultiRead/Write Helper]
private S7Client FClient;
private GCHandle[] Handles = new GCHandle[S7Client.MaxVars];
private int Count;
private S7Client.S7DataItem[] Items = new S7Client.S7DataItem[S7Client.MaxVars];
public int[] Results { get; } = new int[S7Client.MaxVars];
private bool AdjustWordLength(int Area, ref int WordLen, ref int Amount, ref int Start)
{
// Calc Word size
int WordSize = WordLen.DataSizeByte();
if (WordSize == 0)
return false;
if (Area == (int)S7Area.CT)
WordLen = (int)S7WordLength.Counter;
if (Area == (int)S7Area.TM)
WordLen = (int)S7WordLength.Timer;
if (WordLen == (int)S7WordLength.Bit)
Amount = 1; // Only 1 bit can be transferred at time
else
{
if ((WordLen != (int)S7WordLength.Counter) && (WordLen != (int)S7WordLength.Timer))
{
Amount = Amount * WordSize;
Start = Start * 8;
WordLen = (int)S7WordLength.Byte;
}
}
return true;
}
public S7MultiVar(S7Client Client)
{
FClient = Client;
for (int c = 0; c < S7Client.MaxVars; c++)
Results[c] = S7Consts.errCliItemNotAvailable;
}
~S7MultiVar()
{
Clear();
}
public bool Add<T>(S7Consts.S7Tag Tag, ref T[] Buffer, int Offset)
{
return Add(Tag.Area, Tag.WordLen, Tag.DBNumber, Tag.Start, Tag.Elements, ref Buffer, Offset);
}
public bool Add<T>(S7Consts.S7Tag Tag, ref T[] Buffer)
{
return Add(Tag.Area, Tag.WordLen, Tag.DBNumber, Tag.Start, Tag.Elements, ref Buffer);
}
public bool Add<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 Start, Int32 Amount, ref T[] Buffer)
{
return Add(Area, WordLen, DBNumber, Start, Amount, ref Buffer, 0);
}
public bool Add<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 Start, Int32 Amount, ref T[] Buffer, int Offset)
{
if (Count < S7Client.MaxVars)
{
if (AdjustWordLength(Area, ref WordLen, ref Amount, ref Start))
{
Items[Count].Area = Area;
Items[Count].WordLen = WordLen;
Items[Count].Result = (int)S7Consts.errCliItemNotAvailable;
Items[Count].DBNumber = DBNumber;
Items[Count].Start = Start;
Items[Count].Amount = Amount;
GCHandle handle = GCHandle.Alloc(Buffer, GCHandleType.Pinned);
if (IntPtr.Size == 4)
Items[Count].pData = (IntPtr)(handle.AddrOfPinnedObject().ToInt32() + Offset * Marshal.SizeOf(typeof(T)));
else
Items[Count].pData = (IntPtr)(handle.AddrOfPinnedObject().ToInt64() + Offset * Marshal.SizeOf(typeof(T)));
Handles[Count] = handle;
Count++;
return true;
}
return false;
}
return false;
}
public int Read()
{
int FunctionResult;
int GlobalResult;
try
{
if (Count > 0)
{
FunctionResult = FClient.ReadMultiVars(Items, Count);
if (FunctionResult == 0)
for (int c = 0; c < S7Client.MaxVars; c++)
Results[c] = Items[c].Result;
GlobalResult = FunctionResult;
}
else
GlobalResult = S7Consts.errCliFunctionRefused;
}
finally
{
Clear(); // handles are no more needed and MUST be freed
}
return GlobalResult;
}
public int Write()
{
int FunctionResult;
int GlobalResult;
try
{
if (Count > 0)
{
FunctionResult = FClient.WriteMultiVars(Items, Count);
if (FunctionResult == 0)
for (int c = 0; c < S7Client.MaxVars; c++)
Results[c] = Items[c].Result;
GlobalResult = FunctionResult;
}
else
GlobalResult = S7Consts.errCliFunctionRefused;
}
finally
{
Clear(); // handles are no more needed and MUST be freed
}
return GlobalResult;
}
public void Clear()
{
for (int c = 0; c < Count; c++)
{
if (Handles[c] != null)
Handles[c].Free();
}
Count = 0;
}
#endregion
}
}
================================================
FILE: Sharp7/S7Timer.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
namespace Sharp7
{
public class S7Timer
{
#region S7Timer
TimeSpan pt;
TimeSpan et;
bool input ;
bool q;
public S7Timer(byte[] buff, int position)
{
if (position + 12 < buff.Length)
{
SetTimer(new List<byte>(buff).GetRange(position, 12).ToArray());
}
}
public S7Timer(byte[] buff)
{
SetTimer(buff);
}
private void SetTimer(byte[] buff)
{
if (buff.Length != 12)
{
this.pt = new TimeSpan(0);
this.et = new TimeSpan(0);
}
else
{
Int32 resPT;
resPT = buff[0]; resPT <<= 8;
resPT += buff[1]; resPT <<= 8;
resPT += buff[2]; resPT <<= 8;
resPT += buff[3];
this.pt = new TimeSpan(0, 0, 0, 0, resPT);
Int32 resET;
resET = buff[4]; resET <<= 8;
resET += buff[5]; resET <<= 8;
resET += buff[6]; resET <<= 8;
resET += buff[7];
this.et = new TimeSpan(0, 0, 0, 0, resET);
this.input = (buff[8] & 0x01) == 0x01;
this.q = (buff[8] & 0x02) == 0x02;
}
}
public TimeSpan PT => pt;
public TimeSpan ET => et;
public bool IN => input;
public bool Q => q;
#endregion
}
}
================================================
FILE: Sharp7/S7WordLength.cs
================================================
namespace Sharp7
{
public enum S7WordLength
{
Bit = 0x01,
Byte = 0x02,
Char = 0x03,
Word = 0x04,
Int = 0x05,
DWord = 0x06,
DInt = 0x07,
Real = 0x08,
Counter = 0x1C,
Timer = 0x1D,
}
}
================================================
FILE: Sharp7/Sharp7.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net40;netstandard2.0</TargetFrameworks>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Authors>Federico Barresi</Authors>
<Description>The multi-platform Ethernet S7 PLC communication suite</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageProjectUrl>https://github.com/fbarresi/Sharp7</PackageProjectUrl>
<PackageLicenseUrl>https://raw.githubusercontent.com/fbarresi/Sharp7/master/LICENSE</PackageLicenseUrl>
<PackageTags>snap7 s7 simatic siemens</PackageTags>
<Company />
<Version>1.0.0</Version>
<PackageIconUrl>https://raw.githubusercontent.com/fbarresi/Sharp7/master/doc/images/logo.jpg</PackageIconUrl>
<PackageReleaseNotes>https://github.com/fbarresi/Sharp7/blob/master/CHANGELOG.md</PackageReleaseNotes>
</PropertyGroup>
</Project>
================================================
FILE: Sharp7.Tests/ClientTest.cs
================================================
using System;
using Shouldly;
using Xunit;
namespace Sharp7.Tests
{
public class ClientTest : ServerClientTestBase
{
[Fact]
public void ClientIsNotNull()
{
Client.ShouldNotBeNull();
}
[Fact]
public void ServerIsNotNull()
{
Server.ShouldNotBeNull();
}
[Fact]
public void Timeout()
{
Client.ConnTimeout.ShouldBe(2000);
}
[Fact]
public void Connected()
{
Client.Connected.ShouldBe(true);
}
[Fact]
public void Port()
{
Client.PLCPort.ShouldBe(102);
}
[Fact]
public void ReadWriteDb()
{
var bytes = new byte[] { 1, 2, 3 };
var index = 3;
Server.RegisterArea(S7Server.SrvAreaDB, index, ref bytes, bytes.Length);
var buffer = new byte[bytes.Length];
var rc = Client.DBRead(index, 0, bytes.Length, buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(bytes);
buffer = new byte[] { 3, 2, 1 };
rc = Client.DBWrite(index, 0, bytes.Length, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(buffer);
}
[Fact]
public void ReadWriteAb()
{
var bytes = new byte[] { 1, 2, 3 };
Server.RegisterArea(S7Server.SrvAreaPa, 0, ref bytes, bytes.Length);
var buffer = new byte[bytes.Length];
var rc = Client.ABRead(0, bytes.Length, buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(bytes);
buffer = new byte[] { 3, 2, 1 };
rc = Client.ABWrite(0, bytes.Length, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(buffer);
}
[Fact]
public void ReadWriteCt()
{
var bytes = new byte[] { 0,1,2,3,4,5,6,7,8};
var index = 3;
Server.RegisterArea(S7Server.SrvAreaCt, index, ref bytes, bytes.Length/2);
var buffer = new ushort[2];
var rc = Client.CTRead(0, 2, buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(new ushort[]{0x0100,0x0302});
buffer = new ushort[] {0x0403, 0x0201 };
rc = Client.CTWrite(0, 2, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(new byte[] { 3, 4, 1, 2, 4, 5, 6, 7, 8 });
}
[Fact]
public void ReadWriteMb()
{
var bytes = new byte[] { 0, 1, 2};
Server.RegisterArea(S7Server.SrvAreaMk, 0, ref bytes, bytes.Length);
var buffer = new byte[bytes.Length];
var rc = Client.MBRead(0,bytes.Length,buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(bytes);
buffer = new byte[] { 3, 2, 1 };
rc = Client.MBWrite(0, bytes.Length, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(buffer);
}
[Fact]
public void ReadWriteTm()
{
var bytes = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
var index = 5;
Server.RegisterArea(S7Server.SrvAreaTm, index, ref bytes, bytes.Length / 2);
var buffer = new ushort[2];
var rc = Client.TMRead(0, 2, buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(new ushort[] { 0x0100, 0x0302 });
buffer = new ushort[] { 0x0403, 0x0201 };
rc = Client.TMWrite(0, 2, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(new byte[] {3, 4, 1, 2, 4, 5, 6, 7, 8, 9, 10, 11});
}
[Fact]
public void ReadWriteEb()
{
var bytes = new byte[] { 0, 1, 2 };
Server.RegisterArea(S7Server.SrvAreaPe, 0, ref bytes, bytes.Length);
var buffer = new byte[bytes.Length];
var rc = Client.EBRead(0, bytes.Length, buffer);
//test read
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
buffer.ShouldBe(bytes);
buffer = new byte[] { 3, 2, 1 };
rc = Client.EBWrite(0, bytes.Length, buffer);
//test write
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
bytes.ShouldBe(buffer);
}
[Fact]
public void Multivars()
{
var bytes = new byte[] { 1, 2, 3,4,5,6,7,8,9,0 };
var index = 30;
Server.RegisterArea(S7Server.SrvAreaDB, index, ref bytes, bytes.Length);
var buffer = new byte[bytes.Length];
var multivar = new S7MultiVar(Client);
multivar.ShouldNotBeNull();
multivar.Add(new Sharp7.S7Consts.S7Tag(){Area = (int)S7Area.DB, DBNumber = index, Elements = 2,Start = 0, WordLen = 2}, ref buffer).ShouldBe(true);
multivar.Read().ShouldBe(Sharp7.S7Consts.ResultOK);
multivar.Add(new Sharp7.S7Consts.S7Tag() { Area = (int)S7Area.DB, DBNumber = index, Elements = 2, Start = 0, WordLen = 2 }, ref buffer).ShouldBe(true);
multivar.Write().ShouldBe(Sharp7.S7Consts.ResultOK);
}
}
}
================================================
FILE: Sharp7.Tests/ClientWithoutServer.cs
================================================
using System;
using System.Linq;
using Shouldly;
using Xunit;
namespace Sharp7.Tests
{
public class ClientWithoutServer
{
private S7Client client;
public ClientWithoutServer()
{
client = new S7Client();
}
public void Dispose()
{
client.Disconnect();
}
[Fact]
public void CannotConnectTest()
{
var rc = client.ConnectTo("127.0.1.2", 0, 2);
rc.ShouldBe(Sharp7.S7Consts.errTCPConnectionFailed);
}
[Fact]
public void GetLastErrorTest()
{
var rc = client.LastError();
rc.ShouldBe(0);
}
[Fact]
public void GetRequestedPduTest()
{
var rc = client.RequestedPduLength();
rc.ShouldBe(480);
client.PduSizeRequested.ShouldBe(480);
}
[Fact]
public void GetNegotiatedPduTest()
{
var rc = client.NegotiatedPduLength();
rc.ShouldBe(0);
client.PduSizeNegotiated.ShouldBe(0);
}
[Fact]
public void SetPlcPortTest()
{
client.PLCPort = 104;
client.PLCPort.ShouldBe(104);
}
[Fact]
public void SetPduRequestedTest()
{
client.PduSizeRequested = 239;
client.PduSizeRequested.ShouldBe(240);
client.PduSizeRequested = 961;
client.PduSizeRequested.ShouldBe(960);
client.PduSizeRequested = 481;
client.PduSizeRequested.ShouldBe(481);
}
[Fact]
public void SetTimeoutTest()
{
client.ConnTimeout = 239;
client.ConnTimeout.ShouldBe(239);
client.RecvTimeout = 239;
client.RecvTimeout.ShouldBe(239);
client.SendTimeout = 239;
client.SendTimeout.ShouldBe(239);
}
[Fact]
public void GetExecTimeTest()
{
client.ExecutionTime.ShouldBe(client.ExecutionTime);
}
[Theory]
[InlineData(1, 0)]
[InlineData(2, 102)]
[InlineData(3, 2000)]
[InlineData(4, 2000)]
[InlineData(5, 2000)]
[InlineData(6, 0)]
[InlineData(7, 0)]
[InlineData(8, 0)]
[InlineData(9, 0)]
[InlineData(10, 480)]
[InlineData(11, 0)]
[InlineData(12, 0)]
[InlineData(13, 0)]
[InlineData(14, 0)]
[InlineData(15, 0)]
public void GetParameterTest(int parameterNumber, int expected)
{
int value = -1;
var result = client.GetParam(parameterNumber, ref value);
if(result == 0)
value.ShouldBe(expected);
else
result.ShouldBe(0x02500000);
}
[Theory]
[InlineData(1, 0)]
[InlineData(2, 103)]
[InlineData(3, 2001)]
[InlineData(4, 2001)]
[InlineData(5, 2001)]
[InlineData(6, 0)]
[InlineData(7, 0)]
[InlineData(8, 0)]
[InlineData(9, 0)]
[InlineData(10, 482)]
[InlineData(11, 0)]
[InlineData(12, 0)]
[InlineData(13, 0)]
[InlineData(14, 0)]
[InlineData(15, 0)]
public void SetParameterTest(int parameterNumber, int newValue)
{
var result = client.SetParam(parameterNumber, ref newValue);
if (result == 0)
{
int readValue = -1;
client.GetParam(parameterNumber, ref readValue);
readValue.ShouldBe(newValue);
}
else
result.ShouldBe(0x02500000);
}
}
}
================================================
FILE: Sharp7.Tests/PropertiesTests.cs
================================================
using Shouldly;
using Xunit;
namespace Sharp7.Tests
{
public class PropertiesTests
{
[Fact]
public void PlcHasNoName()
{
var client = new S7Client();
client.Name.ShouldBeNull();
string.IsNullOrEmpty(client.Name).ShouldBeTrue();
}
[Fact]
public void PlcHasAName()
{
var name = "test";
var client = new S7Client(name);
client.Name.ShouldNotBeNull();
string.IsNullOrEmpty(client.Name).ShouldBeFalse();
client.Name.ShouldBe(name);
}
[Fact]
public void PlcHasIp()
{
var ip = "10.10.10.10";
var client = new S7Client();
client.SetConnectionParams(ip, 0, 0);
client.PLCIpAddress.ShouldNotBeNull();
string.IsNullOrEmpty(client.PLCIpAddress).ShouldBeFalse();
client.PLCIpAddress.ShouldBe(ip);
}
[Fact]
public void PlcHasNoIp()
{
var client = new S7Client();
client.PLCIpAddress.ShouldBeNull();
string.IsNullOrEmpty(client.PLCIpAddress).ShouldBeTrue();
}
[Fact]
public void PlcToString()
{
var client = new S7Client();
client.ToString().ShouldBe("PLC @0.0.0.0");
}
[Fact]
public void PlcToStringWithName()
{
var client = new S7Client("Test");
client.ToString().ShouldBe("PLC Test@0.0.0.0");
}
[Fact]
public void PlcToStringWithNameAndIp()
{
var client = new S7Client("Test");
client.SetConnectionParams("1.2.3.4", 0, 0);
client.ToString().ShouldBe("PLC Test@1.2.3.4");
}
}
}
================================================
FILE: Sharp7.Tests/S7Server.cs
================================================
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace Sharp7.Tests
{
internal class S7Consts
{
public const string S7LibName = "snap7.dll";
}
public class S7Server
{
#region [Constants, private vars and TypeDefs]
private const int MsgTextLen = 1024;
private const int MkEvent = 0;
private const int MkLog = 1;
// Server Area ID (use with Register/unregister - Lock/unlock Area)
public static readonly int SrvAreaPe = 0;
public static readonly int SrvAreaPa = 1;
public static readonly int SrvAreaMk = 2;
public static readonly int SrvAreaCt = 3;
public static readonly int SrvAreaTm = 4;
public static readonly int SrvAreaDB = 5;
// S7 Server Event Code
public static readonly uint EvcPdUincoming = 0x00010000;
public static readonly uint EvcDataRead = 0x00020000;
public static readonly uint EvcDataWrite = 0x00040000;
public static readonly uint EvcNegotiatePdu = 0x00080000;
public static readonly uint EvcReadSzl = 0x00100000;
public static readonly uint EvcClock = 0x00200000;
public static readonly uint EvcUpload = 0x00400000;
public static readonly uint EvcDownload = 0x00800000;
public static readonly uint EvcDirectory = 0x01000000;
public static readonly uint EvcSecurity = 0x02000000;
public static readonly uint EvcControl = 0x04000000;
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct USrvEvent
{
public IntPtr EvtTime; // It's platform dependent (32 or 64 bit)
public Int32 EvtSender;
public UInt32 EvtCode;
public ushort EvtRetCode;
public ushort EvtParam1;
public ushort EvtParam2;
public ushort EvtParam3;
public ushort EvtParam4;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct S7Tag
{
public Int32 Area;
public Int32 DBNumber;
public Int32 Start;
public Int32 Elements;
public Int32 WordLen;
}
private Dictionary<Int32, GCHandle> hArea;
private IntPtr server;
#endregion
#region [Class Control]
[DllImport(S7Consts.S7LibName)]
private static extern IntPtr Srv_Create();
/// <summary>
/// Create an instace of S7Server
/// </summary>
public S7Server()
{
server = Srv_Create();
hArea = new Dictionary<int, GCHandle>();
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_Destroy(ref IntPtr server);
/// <summary>
/// Destroy the S7Server and free the memory
/// </summary>
~S7Server()
{
foreach (var item in hArea)
{
GCHandle handle = item.Value;
if (handle != null)
handle.Free();
}
Srv_Destroy(ref server);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_StartTo(IntPtr server, [MarshalAs(UnmanagedType.LPStr)] string address);
/// <summary>
/// Start the server to a specific Address
/// </summary>
/// <param name="address">Address for adapter selection</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int StartTo(string address)
{
return Srv_StartTo(server, address);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_Start(IntPtr server);
/// <summary>
/// start the server
/// </summary>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int Start()
{
return Srv_Start(server);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_Stop(IntPtr server);
/// <summary>
/// Stop the server
/// </summary>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int Stop()
{
return Srv_Stop(server);
}
#endregion
#region [Data Areas functions]
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_RegisterArea(IntPtr server, Int32 areaCode, Int32 index, IntPtr pUsrData, Int32 size);
/// <summary>
/// Register a PLC Area
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="areaCode">Code for area identification (e.g. S7Server.SrvAreaDB)</param>
/// <param name="index">Area index</param>
/// <param name="pUsrData">Content of the area by reference</param>
/// <param name="size">Allocation size</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int RegisterArea<T>(Int32 areaCode, Int32 index, ref T pUsrData, Int32 size)
{
Int32 areaUid = (areaCode << 16) + index;
GCHandle handle = GCHandle.Alloc(pUsrData, GCHandleType.Pinned);
int result = Srv_RegisterArea(server, areaCode, index, handle.AddrOfPinnedObject(), size);
if (result == 0)
hArea.Add(areaUid, handle);
else
handle.Free();
return result;
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_UnregisterArea(IntPtr server, Int32 areaCode, Int32 index);
/// <summary>
/// Unregister a PLC area
/// </summary>
/// <param name="areaCode">Code for area identification (e.g. S7Server.SrvAreaDB)</param>
/// <param name="index">Area index</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int UnregisterArea(Int32 areaCode, Int32 index)
{
int result = Srv_UnregisterArea(server, areaCode, index);
if (result == 0)
{
Int32 areaUid = (areaCode << 16) + index;
if (hArea.ContainsKey(areaUid)) // should be always true
{
GCHandle handle = hArea[areaUid];
if (handle != null) // should be always true
handle.Free();
hArea.Remove(areaUid);
}
}
return result;
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_LockArea(IntPtr server, Int32 areaCode, Int32 index);
/// <summary>
/// Lock a memory area
/// </summary>
/// <param name="areaCode">Code for area identification (e.g. S7Server.SrvAreaDB)</param>
/// <param name="index">Area index</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int LockArea(Int32 areaCode, Int32 index)
{
return Srv_LockArea(server, areaCode, index);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_UnlockArea(IntPtr server, Int32 areaCode, Int32 index);
/// <summary>
/// Unlock a memory area
/// </summary>
/// <param name="areaCode">Code for area identification (e.g. S7Server.SrvAreaDB)</param>
/// <param name="index">Area index</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int UnlockArea(Int32 areaCode, Int32 index)
{
return Srv_UnlockArea(server, areaCode, index);
}
#endregion
#region [Notification functions (Events)]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RwBuffer
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)] // A telegram cannot exceed PDU size (960 bytes)
public byte[] Data;
}
/// <summary>
/// Callback delegate
/// </summary>
/// <param name="usrPtr">User pointer passed back</param>
/// <param name="Event">Event information structure</param>
/// <param name="size">Size</param>
public delegate void SrvCallback(IntPtr usrPtr, ref USrvEvent Event, int size);
/// <summary>
/// Callback delegate for RW operation
/// </summary>
/// <param name="usrPtr">User pointer passed back</param>
/// <param name="sender">Sender</param>
/// <param name="operation">Operation type</param>
/// <param name="tag">Operation Tag</param>
/// <param name="buffer">RW Buffer</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public delegate int SrvRwAreaCallback(IntPtr usrPtr, int sender, int operation, ref S7Tag tag, ref RwBuffer buffer);
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_SetEventsCallback(IntPtr server, SrvCallback callback, IntPtr usrPtr);
/// <summary>
/// Set a function callback
/// </summary>
/// <param name="callback">Callback delegate</param>
/// <param name="usrPtr">User pointer passed back</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int SetEventsCallBack(SrvCallback callback, IntPtr usrPtr)
{
return Srv_SetEventsCallback(server, callback, usrPtr);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_SetReadEventsCallback(IntPtr server, SrvCallback callback, IntPtr usrPtr);
/// <summary>
/// Set a function callback for read events
/// </summary>
/// <param name="callback">Callback delegate</param>
/// <param name="usrPtr">User pointer passed back</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int SetReadEventsCallBack(SrvCallback callback, IntPtr usrPtr)
{
return Srv_SetReadEventsCallback(server, callback, usrPtr);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_SetRWAreaCallback(IntPtr server, SrvRwAreaCallback callback, IntPtr usrPtr);
/// <summary>
/// Set a function callback for read-write events
/// </summary>
/// <param name="callback">Callback delegate</param>
/// <param name="usrPtr">User pointer passed back</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int SetRwAreaCallBack(SrvRwAreaCallback callback, IntPtr usrPtr)
{
return Srv_SetRWAreaCallback(server, callback, usrPtr);
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_PickEvent(IntPtr server, ref USrvEvent Event, ref Int32 evtReady);
/// <summary>
/// Extracts an event (if available) from the Events queue.
/// </summary>
/// <param name="Event">Reference of User event</param>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public bool PickEvent(ref USrvEvent Event)
{
Int32 evtReady = new Int32();
if (Srv_PickEvent(server, ref Event, ref evtReady) == 0)
return evtReady != 0;
else
return false;
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_ClearEvents(IntPtr server);
/// <summary>
/// clear the event queue
/// </summary>
/// <returns>0: No errors. Otherwise see errorcodes</returns>
public int ClearEvents()
{
return Srv_ClearEvents(server);
}
[DllImport(S7Consts.S7LibName, CharSet = CharSet.Ansi)]
private static extern int Srv_EventText(ref USrvEvent Event, StringBuilder evtMsg, int textSize);
/// <summary>
/// retrieve a message from an event
/// </summary>
/// <param name="Event">Reference to Event</param>
/// <returns>The message for an event</returns>
public string EventText(ref USrvEvent Event)
{
StringBuilder message = new StringBuilder(MsgTextLen);
Srv_EventText(ref Event, message, MsgTextLen);
return message.ToString();
}
/// <summary>
/// Convet an the event time to datetime object
/// </summary>
/// <param name="timeStamp">Event Time pointer</param>
/// <returns>the datetime for the timestamp</returns>
public DateTime EvtTimeToDateTime(IntPtr timeStamp)
{
DateTime unixStartEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
return unixStartEpoch.AddSeconds(Convert.ToDouble(timeStamp));
}
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_GetMask(IntPtr server, Int32 maskKind, ref UInt32 mask);
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_SetMask(IntPtr server, Int32 maskKind, UInt32 mask);
// Property LogMask R/W
/// <summary>
/// Activate o deactivate the LogMask
/// </summary>
public UInt32 LogMask
{
get
{
UInt32 mask = new UInt32();
if (Srv_GetMask(server, S7Server.MkLog, ref mask) == 0)
return mask;
else
return 0;
}
set => Srv_SetMask(server, S7Server.MkLog, value);
}
// Property EventMask R/W
/// <summary>
/// Activate o deactivate the EventMask
/// </summary>
public UInt32 EventMask
{
get
{
UInt32 mask = new UInt32();
if (Srv_GetMask(server, S7Server.MkEvent, ref mask) == 0)
return mask;
else
return 0;
}
set => Srv_SetMask(server, S7Server.MkEvent, value);
}
#endregion
#region [Info functions]
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_GetStatus(IntPtr server, ref Int32 serverStatus, ref Int32 cpuStatus, ref Int32 clientsCount);
[DllImport(S7Consts.S7LibName)]
private static extern int Srv_SetCpuStatus(IntPtr server, Int32 cpuStatus);
// Property Virtual CPU status R/W
public int CpuStatus
{
get
{
Int32 cStatus = new Int32();
Int32 sStatus = new Int32();
Int32 cCount = new Int32();
if (Srv_GetStatus(server, ref sStatus, ref cStatus, ref cCount) == 0)
return cStatus;
else
return -1;
}
set => Srv_SetCpuStatus(server, value);
}
// Property Server Status Read Only
public int ServerStatus
{
get
{
Int32 cStatus = new Int32();
Int32 sStatus = new Int32();
Int32 cCount = new Int32();
if (Srv_GetStatus(server, ref sStatus, ref cStatus, ref cCount) == 0)
return sStatus;
else
return -1;
}
}
// Property Clients Count Read Only
public int ClientsCount
{
get
{
Int32 cStatus = new Int32();
Int32 sStatus = new Int32();
Int32 cCount = new Int32();
if (Srv_GetStatus(server, ref cStatus, ref sStatus, ref cCount) == 0)
return cCount;
else
return -1;
}
}
[DllImport(S7Consts.S7LibName, CharSet = CharSet.Ansi)]
private static extern int Srv_ErrorText(int error, StringBuilder errMsg, int textSize);
/// <summary>
/// Retrieve the error message for an error code
/// </summary>
/// <param name="error">Error code</param>
/// <returns>Message for the error code</returns>
public string ErrorText(int error)
{
StringBuilder message = new StringBuilder(MsgTextLen);
Srv_ErrorText(error, message, MsgTextLen);
return message.ToString();
}
#endregion
}
}
================================================
FILE: Sharp7.Tests/ServerClientTestBase.cs
================================================
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
namespace Sharp7.Tests
{
public class ServerClientTestBase : ServerTestBase, IDisposable
{
private S7Client client;
public S7Client Client => client;
public ServerClientTestBase() : base()
{
client = new S7Client("Test Plc");
var rc = client.ConnectTo(Localhost, 0, 2);
rc.ShouldBe(Sharp7.S7Consts.ResultOK);
}
public new void Dispose()
{
client.Disconnect();
base.Dispose();
}
}
}
================================================
FILE: Sharp7.Tests/ServerTestBase.cs
================================================
using System;
using System.Linq;
using System.Threading.Tasks;
using Shouldly;
namespace Sharp7.Tests
{
public class ServerTestBase : IDisposable
{
private readonly S7Server server;
protected readonly string Localhost = "127.0.0.1";
public ServerTestBase()
{
server = new S7Server();
var rc = server.StartTo(Localhost);
rc.ShouldBe(0);
}
public S7Server Server => server;
public void Dispose()
{
server.Stop();
}
}
}
================================================
FILE: Sharp7.Tests/Sharp7.Tests.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net45</TargetFramework>
<Platforms>AnyCPU;x86</Platforms>
<IsPackable>false</IsPackable>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Shouldly" Version="3.0.2" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Sharp7\Sharp7.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="snap7.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
================================================
FILE: Sharp7.Tests/TestUtilities.cs
================================================
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Shouldly;
using Xunit;
namespace Sharp7.Tests
{
public class TestUtilities
{
[Theory]
[InlineData(1,1)]
[InlineData(2,1)]
[InlineData(3,1)]
[InlineData(4,2)]
[InlineData(5,2)]
[InlineData(6,4)]
[InlineData(7,4)]
[InlineData(8,4)]
[InlineData(0x1D,2)]
[InlineData(0x1C,2)]
[InlineData(0,0)]
public void TestDataSizeByte(int wordLength, int expected) { S7.DataSizeByte(wordLength).ShouldBe(expected); }
[Fact] public void TestGetBitAt() { S7.GetBitAt(new byte[] {1,2,3,4}, 0, 0).ShouldBe(true); }
[Fact] public void TestSetBitAt() {
var buffer = new byte[] {1,2,3,4};
S7.SetBitAt(buffer, 0, 1, true);
buffer.ShouldBe(new byte[] {3, 2, 3, 4});
}
[Fact] public void TestSetBitAtAsExtensionMethod() {
var buffer = new byte[] {1,2,3,4};
buffer.SetBitAt(0, 1, true);
buffer.ShouldBe(new byte[] {3, 2, 3, 4});
}
//unsigned
[Theory]
[InlineData(new byte[] { 1, 2, 3, 4 }, 0, 1)]
[InlineData(new byte[] { 129, 2, 3, 4 }, 0, 129)]
public void TestGetUSIntAt(byte[] buffer, int pos, byte expected) { S7.GetUSIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] { 0, 2, 3, 4 }, 0, 1, new byte[] { 1, 2, 3, 4 })]
[InlineData(new byte[] { 0, 2, 3, 4 }, 0, 127, new byte[] { 127, 2, 3, 4 })]
public void TestSetUSIntAt(byte[] buffer, int pos, byte value, byte[] expected)
{
S7.SetUSIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData( new byte[] { 1, 1, 0, 0 }, 0, 257)]
public void TestGetUIntAt(byte[] buffer, int pos, ushort expected) { S7.GetUIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[]{0,0,0,0}, 0, 1, new byte[] {0,1,0,0})]
public void TestSetUIntAt(byte[] buffer, int pos, ushort value, byte[] expected)
{
S7.SetUIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 2 }, 0, 2)]
public void TestGetUDIntAt(byte[] buffer, int pos, uint expected) { S7.GetUDIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] {0, 0, 0, 0}, 0, 1, new byte[] {0, 0, 0, 1})]
public void TestSetUDIntAt(byte[] buffer, int pos, uint value, byte[] expected)
{
S7.SetUDIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 2 }, 0, 2L)]
public void TestGetULIntAt(byte[] buffer, int pos, ulong expected) { S7.GetULIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, 0, 1L, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1})]
public void TestSetULIntAt(byte[] buffer, int pos, ulong value, byte[] expected)
{
S7.SetULintAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
// signed
[Theory]
[InlineData(new byte[] { 1, 2, 3, 4 }, 0, 1)]
[InlineData(new byte[] { 129, 2, 3, 4 }, 0, -127)]
public void TestGetSIntAt(byte[] buffer, int pos, int expected) { S7.GetSIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] { 0, 2, 3, 4 }, 0, 1, new byte[] { 1, 2, 3, 4 })]
[InlineData(new byte[] { 0, 2, 3, 4 }, 0, -127, new byte[] { 129, 2, 3, 4 })]
public void TestSetSIntAt(byte[] buffer, int pos, int value, byte[] expected)
{
S7.SetSIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 1, 1, 0, 0 }, 0, 257)]
public void TestGetIntAt(byte[] buffer, int pos, short expected) { S7.GetIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0 }, 0, 1, new byte[] { 0, 1, 0, 0 })]
public void TestSetIntAt(byte[] buffer, int pos, Int16 value, byte[] expected)
{
S7.SetIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 2 }, 0, 2)]
public void TestGetDIntAt(byte[] buffer, int pos, int expected) { S7.GetDIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0 }, 0, 1, new byte[] { 0, 0, 0, 1 })]
public void TestSetDIntAt(byte[] buffer, int pos, int value, byte[] expected)
{
S7.SetDIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 2 }, 0, 2L)]
public void TestGetLIntAt(byte[] buffer, int pos, long expected) { S7.GetLIntAt(buffer, pos).ShouldBe(expected); }
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 1L, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 })]
public void TestSetLIntAt(byte[] buffer, int pos, long value, byte[] expected)
{
S7.SetLIntAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Fact] public void TestGetByteAt() { S7.GetByteAt(new byte[] {1,2,3,4}, 1).ShouldBe((byte)2); }
[Fact]
public void TestSetByteAt()
{
var buffer = new byte[] { 1, 2, 3, 4 };
S7.SetByteAt(buffer, 0, (byte)5);
buffer.ShouldBe(new byte[] { 5, 2, 3, 4 });
}
[Theory]
[InlineData(new byte[] {0, 2, 0, 0, 0, 0, 0, 0}, 0, 2)]
public void TestGetWordAt(byte[] buffer, int pos, ushort expected)
{
S7.GetWordAt(buffer, pos).ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] {0, 0, 0, 0, 0, 0, 0, 0}, 0, 1, new byte[] {0, 1, 0, 0, 0, 0, 0, 0})]
public void TestSetWordAt(byte[] buffer, int pos, ushort value, byte[] expected)
{
S7.SetWordAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 3, 0, 0, 0, 0 }, 0, 3)]
public void TestGetDWordAt(byte[] buffer, int pos, uint expected)
{
S7.GetDWordAt(buffer, pos).ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 1, new byte[] { 0, 0, 0, 1, 0, 0, 0, 0 })]
public void TestSetDWordAt(byte[] buffer, int pos, uint value, byte[] expected)
{
S7.SetDWordAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 4 }, 0, 4L)]
public void TestGetLWordAt(byte[] buffer, int pos, ulong expected)
{
S7.GetLWordAt(buffer, pos).ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 1L, new byte[] { 0, 0, 0, 0, 0, 0, 0, 1 })]
public void TestSetLWordAt(byte[] buffer, int pos, ulong value, byte[] expected)
{
S7.SetLWordAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 1, 2, 3, 0, 0, 11, 5, 4 }, 0, 2.387938E-38f)]
public void TestGetRealAt(byte[] buffer, int pos, float expected)
{
S7.GetRealAt(buffer, pos).ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 4f, new byte[] { 64, 128, 0, 0, 0, 0, 0, 0 })]
public void TestSetRealAt(byte[] buffer, int pos, float value, byte[] expected)
{
S7.SetRealAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 64, 128, 0, 0, 0, 0, 0, 0}, 0, 512d)]
public void TestGetLRealAt(byte[] buffer, int pos, double expected)
{
S7.GetLRealAt(buffer, pos).ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 }, 0, 4d, new byte[] { 64, 16, 0, 0, 0, 0, 0, 0 })]
public void TestSetLRealAt(byte[] buffer, int pos, double value, byte[] expected)
{
S7.SetLRealAt(buffer, pos, value);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] {16,17,18,19,20,21,0,6})]
public void TestGetDateTimeAt(byte[] buffer)
{
var time = new DateTime(2010, 11, 12, 13, 14, 15);
S7.GetDateTimeAt(buffer, 0).ShouldBe(time);
}
[Theory]
[InlineData(new byte[] {16, 17, 18, 19, 20, 21, 0, 6})]
public void TestSetDateTimeAt(byte[] expected)
{
var time = new DateTime(2010, 11, 12, 13, 14, 15);
var buffer = new byte[8];
S7.SetDateTimeAt(buffer, 0, time);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] {0,2})]
public void TestGetDateAt(byte[] buffer)
{
var date = new DateTime(1990, 1, 3);
S7.GetDateAt(buffer, 0).ShouldBe(date);
}
[Theory]
[InlineData(new byte[] { 0,3 })]
public void TestSetDateAt(byte[] expected)
{
var buffer = new byte[2];
var date = new DateTime(1990,1,4);
S7.SetDateAt(buffer, 0, date);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] {0, 0,0,2}, 2)]
public void TestGetTODAt(byte[] buffer, int milliseconds)
{
S7.GetTODAt(buffer, 0).ShouldBe(new DateTime(0).AddMilliseconds(milliseconds));
S7.GetTODAsDateTimeAt(buffer, 0).ShouldBe(new DateTime(0).AddMilliseconds(milliseconds));
S7.GetTODAsTimeSpanAt(buffer, 0).ShouldBe(TimeSpan.FromMilliseconds(milliseconds));
}
[Theory]
[InlineData(new byte[] {0, 0,0,2}, 2)]
public void TestSetTODAt(byte[] expected, int milliseconds)
{
var buffer = new byte[4];
S7.SetTODAt(buffer, 0, new DateTime(0).AddMilliseconds(milliseconds));
buffer.ShouldBe(expected);
buffer = new byte[4];
S7.SetTODAt(buffer, 0, TimeSpan.FromMilliseconds(milliseconds));
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0,0,0,0,200 }, 2)]
public void TestGetLTODAt(byte[] buffer, int ticks)
{
S7.GetLTODAt(buffer, 0).ShouldBe(new DateTime(ticks));
S7.GetLTODAsDateTimeAt(buffer, 0).ShouldBe(new DateTime(ticks));
S7.GetLTODAsTimeSpanAt(buffer, 0).ShouldBe(TimeSpan.FromTicks(ticks));
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0,0,0,0,200 }, 2)]
public void TestSetLTODAt(byte[] expected, int ticks)
{
var buffer = new byte[8];
S7.SetLTODAt(buffer, 0, new DateTime(ticks));
buffer.ShouldBe(expected);
buffer = new byte[8];
S7.SetLTODAt(buffer, 0, TimeSpan.FromTicks(ticks));
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 200 }, 2)]
public void TestGetLDTAt(byte[] buffer, int ticks)
{
S7.GetLDTAt(buffer, 0).ShouldBe(new DateTime(1970, 1, 1).AddTicks(ticks));
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 0, 0, 0, 0, 200 }, 2)]
public void TestSetLDTAt(byte[] expected, int ticks)
{
var buffer = new byte[8];
S7.SetLDTAt(buffer, 0, new DateTime(1970,1,1).AddTicks(ticks));
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 10, 10, 10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 })]
public void TestGetDTLAt(byte[] buffer)
{
S7.GetDTLAt(buffer, 0).ShouldBe(new DateTime(2570, 10, 10,10,10,0));
}
[Theory]
[InlineData(new byte[] { 10, 10, 10, 10, 4, 10, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0 })]
public void TestSetDTLAt(byte[] expected)
{
var buffer = new byte[16];
S7.SetDTLAt(buffer, 0, new DateTime(2570, 10, 10, 10, 10, 0));
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] {0, 3, 55,55,55,0,0,0,0,0}, "777")]
public void TestGetStringAt(byte[] buffer, string expected)
{
S7.GetStringAt(buffer, 0).ShouldBe(expected);
}
[Theory]
[InlineData("888", 200, new byte[] {200, 3, 56,56,56})]
[InlineData("888888", 5, new byte[] {5, 5, 56,56,56,56,56})]
public void TestSetStringAt(string test, int maxLength, byte[] expected)
{
var buffer = new byte[maxLength+2];
S7.SetStringAt(buffer, 0, maxLength, test);
buffer.Take(expected.Length).ToArray().ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 55, 55, 55 }, "777")]
[InlineData(new byte[] { 56, 56, 56 }, "888")]
public void TestGetCharsAt(byte[] buffer, string expected) { S7.GetCharsAt(buffer, 0, buffer.Length).ShouldBe(expected); }
[Theory]
[InlineData("777", new byte[] {55, 55, 55})]
[InlineData("888", new byte[] {56, 56, 56})]
public void TestSetCharsAt(string chars, byte[] expected)
{
var buffer = new byte[chars.Length];
S7.SetCharsAt(buffer, 0, chars);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(12, 1200)]
[InlineData(13, 1300)]
public void TestGetCounter(ushort value, int expected) { S7.GetCounter(value).ShouldBe(expected); }
[Theory]
[InlineData(new ushort[]{12},0, 1200)]
[InlineData(new ushort[]{0,12},1, 1200)]
public void TestGetCounterAt(ushort[] buffer, int index, int expected) { S7.GetCounterAt(buffer, index).ShouldBe(expected); }
[Theory]
[InlineData(1200, 18)]
[InlineData(1300, 19)]
public void TestToCounter(int value, ushort expected) { S7.ToCounter(value).ShouldBe(expected); }
[Theory]
[InlineData(0, 1200, new ushort[] {18,0})]
[InlineData(1, 1200, new ushort[] {0, 18})]
public void TestSetCounterAt(int index, int counter, ushort[] expected)
{
var buffer = new ushort[2];
S7.SetCounterAt(buffer, index, counter);
buffer.ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 18, 0,0,0,0,4,5,6,7,8,0,0,0,0,0,0,0,0,0 })]
public void TestGetS7TimerAt(byte[] buffer) { new S7TimerEqualityComparer().Equals(S7.GetS7TimerAt(buffer, 0), new S7Timer(buffer.Take(12).ToArray())).ShouldBe(true); }
[Theory]
[InlineData(10,new byte[] { 0, 0, 0, 10 })]
public void TestSetS7TimespanAt(int milliseconds, byte[] expected)
{
var buffer = new byte[8];
S7.SetS7TimespanAt(buffer, 0, TimeSpan.FromMilliseconds(milliseconds));
buffer.Take(expected.Length).ToArray().ShouldBe(expected);
}
[Theory]
[InlineData(new byte[] { 0, 0, 0, 10 }, 10)]
public void TestGetS7TimespanAt(byte[] buffer, int milliseconds)
{
S7.GetS7TimespanAt(buffer, 0).ShouldBe(TimeSpan.FromMilliseconds(milliseconds));
}
}
internal sealed class S7TimerEqualityComparer : IEqualityComparer<S7Timer>
{
public bool Equals(S7Timer x, S7Timer y)
{
if (ReferenceEquals(x, y)) return true;
if (ReferenceEquals(x, null)) return false;
if (ReferenceEquals(y, null)) return false;
if (x.GetType() != y.GetType()) return false;
return x.PT.Equals(y.PT) && x.ET.Equals(y.ET) && x.IN == y.IN && x.Q == y.Q;
}
public int GetHashCode(S7Timer obj)
{
unchecked
{
var hashCode = obj.PT.GetHashCode();
hashCode = (hashCode * 397) ^ obj.ET.GetHashCode();
hashCode = (hashCode * 397) ^ obj.IN.GetHashCode();
hashCode = (hashCode * 397) ^ obj.Q.GetHashCode();
return hashCode;
}
}
}
}
================================================
FILE: Sharp7.sln
================================================
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29306.81
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sharp7", "Sharp7\Sharp7.csproj", "{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sharp7.Tests", "Sharp7.Tests\Sharp7.Tests.csproj", "{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|x64.ActiveCfg = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|x64.Build.0 = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|x86.ActiveCfg = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Debug|x86.Build.0 = Debug|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|Any CPU.Build.0 = Release|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|x64.ActiveCfg = Release|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|x64.Build.0 = Release|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|x86.ActiveCfg = Release|Any CPU
{4FE194AF-7FFE-48BA-9DFC-425E9D5B9F46}.Release|x86.Build.0 = Release|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|Any CPU.ActiveCfg = Debug|x86
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|Any CPU.Build.0 = Debug|x86
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|x64.ActiveCfg = Debug|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|x64.Build.0 = Debug|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|x86.ActiveCfg = Debug|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Debug|x86.Build.0 = Debug|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|Any CPU.ActiveCfg = Release|x86
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|Any CPU.Build.0 = Release|x86
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|x64.ActiveCfg = Release|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|x64.Build.0 = Release|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|x86.ActiveCfg = Release|Any CPU
{A770A4B3-8BD7-49A8-BF7B-8CE1FA2E577A}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5BDF8DCB-3749-4D92-AF54-2B6EA9C808E6}
EndGlobalSection
EndGlobal
gitextract_ioo2kq9b/ ├── .github/ │ └── FUNDING.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── Sharp7/ │ ├── MsgSocket.cs │ ├── S7.cs │ ├── S7Area.cs │ ├── S7Client.cs │ ├── S7Consts.cs │ ├── S7MultiVar.cs │ ├── S7Timer.cs │ ├── S7WordLength.cs │ └── Sharp7.csproj ├── Sharp7.Tests/ │ ├── ClientTest.cs │ ├── ClientWithoutServer.cs │ ├── PropertiesTests.cs │ ├── S7Server.cs │ ├── ServerClientTestBase.cs │ ├── ServerTestBase.cs │ ├── Sharp7.Tests.csproj │ └── TestUtilities.cs └── Sharp7.sln
SYMBOL INDEX (343 symbols across 15 files)
FILE: Sharp7.Tests/ClientTest.cs
class ClientTest (line 7) | public class ClientTest : ServerClientTestBase
method ClientIsNotNull (line 10) | [Fact]
method ServerIsNotNull (line 16) | [Fact]
method Timeout (line 22) | [Fact]
method Connected (line 28) | [Fact]
method Port (line 34) | [Fact]
method ReadWriteDb (line 40) | [Fact]
method ReadWriteAb (line 62) | [Fact]
method ReadWriteCt (line 83) | [Fact]
method ReadWriteMb (line 105) | [Fact]
method ReadWriteTm (line 126) | [Fact]
method ReadWriteEb (line 148) | [Fact]
method Multivars (line 169) | [Fact]
FILE: Sharp7.Tests/ClientWithoutServer.cs
class ClientWithoutServer (line 8) | public class ClientWithoutServer
method ClientWithoutServer (line 12) | public ClientWithoutServer()
method Dispose (line 17) | public void Dispose()
method CannotConnectTest (line 22) | [Fact]
method GetLastErrorTest (line 29) | [Fact]
method GetRequestedPduTest (line 36) | [Fact]
method GetNegotiatedPduTest (line 44) | [Fact]
method SetPlcPortTest (line 52) | [Fact]
method SetPduRequestedTest (line 59) | [Fact]
method SetTimeoutTest (line 70) | [Fact]
method GetExecTimeTest (line 83) | [Fact]
method GetParameterTest (line 89) | [Theory]
method SetParameterTest (line 115) | [Theory]
FILE: Sharp7.Tests/PropertiesTests.cs
class PropertiesTests (line 6) | public class PropertiesTests
method PlcHasNoName (line 8) | [Fact]
method PlcHasAName (line 16) | [Fact]
method PlcHasIp (line 26) | [Fact]
method PlcHasNoIp (line 37) | [Fact]
method PlcToString (line 45) | [Fact]
method PlcToStringWithName (line 52) | [Fact]
method PlcToStringWithNameAndIp (line 59) | [Fact]
FILE: Sharp7.Tests/S7Server.cs
class S7Consts (line 8) | internal class S7Consts
class S7Server (line 12) | public class S7Server
type USrvEvent (line 41) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
type S7Tag (line 54) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
method Srv_Create (line 72) | [DllImport(S7Consts.S7LibName)]
method S7Server (line 77) | public S7Server()
method Srv_Destroy (line 83) | [DllImport(S7Consts.S7LibName)]
method Srv_StartTo (line 99) | [DllImport(S7Consts.S7LibName)]
method StartTo (line 106) | public int StartTo(string address)
method Srv_Start (line 111) | [DllImport(S7Consts.S7LibName)]
method Start (line 117) | public int Start()
method Srv_Stop (line 122) | [DllImport(S7Consts.S7LibName)]
method Stop (line 128) | public int Stop()
method Srv_RegisterArea (line 137) | [DllImport(S7Consts.S7LibName)]
method RegisterArea (line 148) | public int RegisterArea<T>(Int32 areaCode, Int32 index, ref T pUsrData...
method Srv_UnregisterArea (line 160) | [DllImport(S7Consts.S7LibName)]
method UnregisterArea (line 168) | public int UnregisterArea(Int32 areaCode, Int32 index)
method Srv_LockArea (line 185) | [DllImport(S7Consts.S7LibName)]
method LockArea (line 193) | public int LockArea(Int32 areaCode, Int32 index)
method Srv_UnlockArea (line 198) | [DllImport(S7Consts.S7LibName)]
method UnlockArea (line 206) | public int UnlockArea(Int32 areaCode, Int32 index)
type RwBuffer (line 215) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
method Srv_SetEventsCallback (line 239) | [DllImport(S7Consts.S7LibName)]
method SetEventsCallBack (line 247) | public int SetEventsCallBack(SrvCallback callback, IntPtr usrPtr)
method Srv_SetReadEventsCallback (line 252) | [DllImport(S7Consts.S7LibName)]
method SetReadEventsCallBack (line 260) | public int SetReadEventsCallBack(SrvCallback callback, IntPtr usrPtr)
method Srv_SetRWAreaCallback (line 265) | [DllImport(S7Consts.S7LibName)]
method SetRwAreaCallBack (line 273) | public int SetRwAreaCallBack(SrvRwAreaCallback callback, IntPtr usrPtr)
method Srv_PickEvent (line 278) | [DllImport(S7Consts.S7LibName)]
method PickEvent (line 285) | public bool PickEvent(ref USrvEvent Event)
method Srv_ClearEvents (line 294) | [DllImport(S7Consts.S7LibName)]
method ClearEvents (line 300) | public int ClearEvents()
method Srv_EventText (line 305) | [DllImport(S7Consts.S7LibName, CharSet = CharSet.Ansi)]
method EventText (line 312) | public string EventText(ref USrvEvent Event)
method EvtTimeToDateTime (line 323) | public DateTime EvtTimeToDateTime(IntPtr timeStamp)
method Srv_GetMask (line 329) | [DllImport(S7Consts.S7LibName)]
method Srv_SetMask (line 331) | [DllImport(S7Consts.S7LibName)]
method Srv_GetStatus (line 373) | [DllImport(S7Consts.S7LibName)]
method Srv_SetCpuStatus (line 375) | [DllImport(S7Consts.S7LibName)]
method Srv_ErrorText (line 425) | [DllImport(S7Consts.S7LibName, CharSet = CharSet.Ansi)]
method ErrorText (line 432) | public string ErrorText(int error)
FILE: Sharp7.Tests/ServerClientTestBase.cs
class ServerClientTestBase (line 8) | public class ServerClientTestBase : ServerTestBase, IDisposable
method ServerClientTestBase (line 13) | public ServerClientTestBase() : base()
method Dispose (line 21) | public new void Dispose()
FILE: Sharp7.Tests/ServerTestBase.cs
class ServerTestBase (line 8) | public class ServerTestBase : IDisposable
method ServerTestBase (line 12) | public ServerTestBase()
method Dispose (line 21) | public void Dispose()
FILE: Sharp7.Tests/TestUtilities.cs
class TestUtilities (line 10) | public class TestUtilities
method TestDataSizeByte (line 12) | [Theory]
method TestGetBitAt (line 25) | [Fact] public void TestGetBitAt() { S7.GetBitAt(new byte[] {1,2,3,4}, ...
method TestSetBitAt (line 26) | [Fact] public void TestSetBitAt() {
method TestSetBitAtAsExtensionMethod (line 31) | [Fact] public void TestSetBitAtAsExtensionMethod() {
method TestGetUSIntAt (line 39) | [Theory]
method TestSetUSIntAt (line 43) | [Theory]
method TestGetUIntAt (line 52) | [Theory]
method TestSetUIntAt (line 56) | [Theory]
method TestGetUDIntAt (line 63) | [Theory]
method TestSetUDIntAt (line 67) | [Theory]
method TestGetULIntAt (line 74) | [Theory]
method TestSetULIntAt (line 78) | [Theory]
method TestGetSIntAt (line 88) | [Theory]
method TestSetSIntAt (line 92) | [Theory]
method TestGetIntAt (line 101) | [Theory]
method TestSetIntAt (line 105) | [Theory]
method TestGetDIntAt (line 112) | [Theory]
method TestSetDIntAt (line 116) | [Theory]
method TestGetLIntAt (line 123) | [Theory]
method TestSetLIntAt (line 127) | [Theory]
method TestGetByteAt (line 136) | [Fact] public void TestGetByteAt() { S7.GetByteAt(new byte[] {1,2,3,4}...
method TestSetByteAt (line 138) | [Fact]
method TestGetWordAt (line 146) | [Theory]
method TestSetWordAt (line 153) | [Theory]
method TestGetDWordAt (line 161) | [Theory]
method TestSetDWordAt (line 168) | [Theory]
method TestGetLWordAt (line 176) | [Theory]
method TestSetLWordAt (line 183) | [Theory]
method TestGetRealAt (line 191) | [Theory]
method TestSetRealAt (line 198) | [Theory]
method TestGetLRealAt (line 206) | [Theory]
method TestSetLRealAt (line 213) | [Theory]
method TestGetDateTimeAt (line 222) | [Theory]
method TestSetDateTimeAt (line 230) | [Theory]
method TestGetDateAt (line 240) | [Theory]
method TestSetDateAt (line 247) | [Theory]
method TestGetTODAt (line 257) | [Theory]
method TestSetTODAt (line 266) | [Theory]
method TestGetLTODAt (line 277) | [Theory]
method TestSetLTODAt (line 286) | [Theory]
method TestGetLDTAt (line 298) | [Theory]
method TestSetLDTAt (line 305) | [Theory]
method TestGetDTLAt (line 314) | [Theory]
method TestSetDTLAt (line 321) | [Theory]
method TestGetStringAt (line 332) | [Theory]
method TestSetStringAt (line 339) | [Theory]
method TestGetCharsAt (line 349) | [Theory]
method TestSetCharsAt (line 354) | [Theory]
method TestGetCounter (line 364) | [Theory]
method TestGetCounterAt (line 369) | [Theory]
method TestToCounter (line 374) | [Theory]
method TestSetCounterAt (line 379) | [Theory]
method TestGetS7TimerAt (line 389) | [Theory]
method TestSetS7TimespanAt (line 393) | [Theory]
method TestGetS7TimespanAt (line 402) | [Theory]
class S7TimerEqualityComparer (line 410) | internal sealed class S7TimerEqualityComparer : IEqualityComparer<S7Timer>
method Equals (line 412) | public bool Equals(S7Timer x, S7Timer y)
method GetHashCode (line 421) | public int GetHashCode(S7Timer obj)
FILE: Sharp7/MsgSocket.cs
class MsgSocket (line 8) | class MsgSocket
method MsgSocket (line 15) | public MsgSocket()
method Close (line 24) | public void Close()
method CreateSocket (line 33) | private void CreateSocket()
method TCPPing (line 39) | private void TCPPing(string Host, int Port)
method Connect (line 64) | public int Connect(string Host, int Port)
method WaitForData (line 84) | private int WaitForData(int Size, int Timeout)
method Receive (line 124) | public int Receive(byte[] Buffer, int Start, int Size)
method Send (line 148) | public int Send(byte[] Buffer, int Size)
FILE: Sharp7/S7.cs
class S7 (line 8) | public static class S7
method BCDtoByte (line 15) | private static int BCDtoByte(byte B)
method ByteToBCD (line 20) | private static byte ByteToBCD(int value)
method DataSizeByte (line 25) | public static int DataSizeByte(this int wordLength)
method GetBitAt (line 45) | public static bool GetBitAt(this byte[] buffer, int pos, int bit)
method SetBitAt (line 53) | public static void SetBitAt(this byte[] buffer, int pos, int bit, bool...
method GetSIntAt (line 81) | public static int GetSIntAt(this byte[] buffer, int pos)
method SetSIntAt (line 90) | public static void SetSIntAt(this byte[] buffer, int pos, int value)
method GetIntAt (line 101) | public static short GetIntAt(this byte[] buffer, int pos)
method SetIntAt (line 106) | public static void SetIntAt(this byte[] buffer, int pos, Int16 value)
method GetDIntAt (line 116) | public static int GetDIntAt(this byte[] buffer, int pos)
method SetDIntAt (line 129) | public static void SetDIntAt(this byte[] buffer, int pos, int value)
method GetLIntAt (line 141) | public static Int64 GetLIntAt(this byte[] buffer, int pos)
method SetLIntAt (line 162) | public static void SetLIntAt(this byte[] buffer, int pos, Int64 value)
method GetUSIntAt (line 178) | public static byte GetUSIntAt(this byte[] buffer, int pos)
method SetUSIntAt (line 183) | public static void SetUSIntAt(this byte[] buffer, int pos, byte value)
method GetUIntAt (line 192) | public static UInt16 GetUIntAt(this byte[] buffer, int pos)
method SetUIntAt (line 197) | public static void SetUIntAt(this byte[] buffer, int pos, UInt16 value)
method GetUDIntAt (line 207) | public static UInt32 GetUDIntAt(this byte[] buffer, int pos)
method SetUDIntAt (line 220) | public static void SetUDIntAt(this byte[] buffer, int pos, UInt32 value)
method GetULIntAt (line 232) | public static UInt64 GetULIntAt(this byte[] buffer, int pos)
method SetULintAt (line 253) | public static void SetULintAt(this byte[] buffer, int pos, UInt64 value)
method GetByteAt (line 269) | public static byte GetByteAt(this byte[] buffer, int pos)
method SetByteAt (line 274) | public static void SetByteAt(this byte[] buffer, int pos, byte value)
method GetWordAt (line 283) | public static UInt16 GetWordAt(this byte[] buffer, int pos)
method SetWordAt (line 288) | public static void SetWordAt(this byte[] buffer, int pos, UInt16 value)
method GetDWordAt (line 297) | public static UInt32 GetDWordAt(this byte[] buffer, int pos)
method SetDWordAt (line 302) | public static void SetDWordAt(this byte[] buffer, int pos, UInt32 value)
method GetLWordAt (line 311) | public static UInt64 GetLWordAt(this byte[] buffer, int pos)
method SetLWordAt (line 316) | public static void SetLWordAt(this byte[] buffer, int pos, UInt64 value)
method GetRealAt (line 325) | public static Single GetRealAt(this byte[] buffer, int pos)
method SetRealAt (line 332) | public static void SetRealAt(this byte[] buffer, int pos, Single value)
method GetLRealAt (line 345) | public static Double GetLRealAt(this byte[] buffer, int pos)
method SetLRealAt (line 352) | public static void SetLRealAt(this byte[] buffer, int pos, Double value)
method GetDateTimeAt (line 369) | public static DateTime GetDateTimeAt(this byte[] buffer, int pos)
method SetDateTimeAt (line 395) | public static void SetDateTimeAt(this byte[] buffer, int pos, DateTime...
method GetDateAt (line 425) | public static DateTime GetDateAt(this byte[] buffer, int pos)
method SetDateAt (line 437) | public static void SetDateAt(this byte[] buffer, int pos, DateTime value)
method GetTODAt (line 446) | [Obsolete("Use GetTODAsDateTimeAt or GetTODAsTimeSpanAt instead")]
method GetTODAsDateTimeAt (line 452) | public static DateTime GetTODAsDateTimeAt(this byte[] buffer, int pos)
method SetTODAt (line 464) | public static void SetTODAt(this byte[] buffer, int pos, DateTime value)
method GetTODAsTimeSpanAt (line 470) | public static TimeSpan GetTODAsTimeSpanAt(this byte[] buffer, int pos)
method SetTODAt (line 482) | public static void SetTODAt(this byte[] buffer, int pos, TimeSpan value)
method GetLTODAt (line 491) | [Obsolete("Use GetLTODAsDateTimeAt or GetLTODAsTimeSpanAt instead")]
method GetLTODAsDateTimeAt (line 497) | public static DateTime GetLTODAsDateTimeAt(this byte[] buffer, int pos)
method SetLTODAt (line 510) | public static void SetLTODAt(this byte[] buffer, int pos, DateTime value)
method GetLTODAsTimeSpanAt (line 516) | public static TimeSpan GetLTODAsTimeSpanAt(this byte[] buffer, int pos)
method SetLTODAt (line 528) | public static void SetLTODAt(this byte[] buffer, int pos, TimeSpan value)
method GetLDTAt (line 537) | public static DateTime GetLDTAt(this byte[] buffer, int pos)
method SetLDTAt (line 549) | public static void SetLDTAt(this byte[] buffer, int pos, DateTime value)
method GetDTLAt (line 559) | public static DateTime GetDTLAt(this byte[] buffer, int pos)
method SetDTLAt (line 581) | public static void SetDTLAt(this byte[] buffer, int pos, DateTime value)
method GetStringAt (line 611) | public static string GetStringAt(this byte[] buffer, int pos)
method SetStringAt (line 617) | public static void SetStringAt(this byte[] buffer, int pos, int MaxLen...
method GetCharsAt (line 631) | public static string GetCharsAt(this byte[] buffer, int pos, int Size)
method SetCharsAt (line 636) | public static void SetCharsAt(this byte[] buffer, int pos, string value)
method GetCounter (line 648) | public static int GetCounter(this ushort value)
method GetCounterAt (line 653) | public static int GetCounterAt(this ushort[] buffer, int Index)
method ToCounter (line 658) | public static ushort ToCounter(this int value)
method SetCounterAt (line 663) | public static void SetCounterAt(this ushort[] buffer, int pos, int value)
method GetS7TimerAt (line 672) | public static S7Timer GetS7TimerAt(this byte[] buffer, int pos)
method SetS7TimespanAt (line 677) | public static void SetS7TimespanAt(this byte[] buffer, int pos, TimeSp...
method GetS7TimespanAt (line 682) | public static TimeSpan GetS7TimespanAt(this byte[] buffer, int pos)
FILE: Sharp7/S7Area.cs
type S7Area (line 3) | public enum S7Area
FILE: Sharp7/S7Client.cs
class S7Client (line 7) | public class S7Client
type S7DataItem (line 68) | public struct S7DataItem
type S7OrderCode (line 80) | public struct S7OrderCode
type S7CpuInfo (line 89) | public struct S7CpuInfo
type S7CpInfo (line 98) | public struct S7CpInfo
type S7BlocksList (line 107) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
type S7BlockInfo (line 120) | public struct S7BlockInfo
type SZL_HEADER (line 142) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
type S7SZL (line 149) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
type S7SZLList (line 158) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
type S7Protection (line 168) | public struct S7Protection
method CreateSocket (line 499) | private void CreateSocket()
method TCPConnect (line 507) | private int TCPConnect()
method RecvPacket (line 523) | private void RecvPacket(byte[] Buffer, int Start, int Size)
method SendPacket (line 531) | private void SendPacket(byte[] Buffer, int Len)
method SendPacket (line 539) | private void SendPacket(byte[] Buffer)
method RecvIsoPacket (line 544) | private int RecvIsoPacket()
method ISOConnect (line 583) | private int ISOConnect()
method NegotiatePduLength (line 611) | private int NegotiatePduLength()
method CpuError (line 638) | private int CpuError(ushort Error)
method S7Client (line 664) | public S7Client(string name) : this()
method S7Client (line 671) | public S7Client()
method ToString (line 681) | public override string ToString()
method Connect (line 686) | public int Connect()
method ConnectTo (line 711) | public int ConnectTo(string Address, int Rack, int Slot)
method SetConnectionParams (line 718) | public int SetConnectionParams(string Address, ushort LocalTSAP, ushor...
method SetConnectionType (line 730) | public int SetConnectionType(ushort ConnectionType)
method Disconnect (line 736) | public int Disconnect()
method GetParam (line 742) | public int GetParam(Int32 ParamNumber, ref int Value)
method SetParam (line 782) | public int SetParam(Int32 ParamNumber, ref int Value)
method SetAsCallBack (line 822) | public int SetAsCallBack(S7CliCompletion Completion, IntPtr usrPtr)
method ReadArea (line 831) | public int ReadArea(S7Area Area, int DBNumber, int Start, int Amount, ...
method ReadArea (line 836) | public int ReadArea(S7Area Area, int DBNumber, int Start, int Amount, ...
method ReadArea (line 840) | public int ReadArea(int Area, int DBNumber, int Start, int Amount, int...
method ReadArea (line 846) | public int ReadArea(int Area, int DBNumber, int Start, int Amount, int...
method WriteArea (line 955) | public int WriteArea(S7Area Area, int DBNumber, int Start, int Amount,...
method WriteArea (line 961) | public int WriteArea(S7Area Area, int DBNumber, int Start, int Amount,...
method WriteArea (line 965) | public int WriteArea(int Area, int DBNumber, int Start, int Amount, in...
method WriteArea (line 971) | public int WriteArea(int Area, int DBNumber, int Start, int Amount, in...
method ReadMultiVars (line 1109) | public int ReadMultiVars(S7DataItem[] Items, int ItemsCount)
method WriteMultiVars (line 1208) | public int WriteMultiVars(S7DataItem[] Items, int ItemsCount)
method DBRead (line 1326) | public int DBRead(int DBNumber, int Start, int Size, byte[] Buffer)
method DBWrite (line 1331) | public int DBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
method MBRead (line 1336) | public int MBRead(int Start, int Size, byte[] Buffer)
method MBWrite (line 1341) | public int MBWrite(int Start, int Size, byte[] Buffer)
method EBRead (line 1346) | public int EBRead(int Start, int Size, byte[] Buffer)
method EBWrite (line 1351) | public int EBWrite(int Start, int Size, byte[] Buffer)
method ABRead (line 1356) | public int ABRead(int Start, int Size, byte[] Buffer)
method ABWrite (line 1361) | public int ABWrite(int Start, int Size, byte[] Buffer)
method TMRead (line 1366) | public int TMRead(int Start, int Amount, ushort[] Buffer)
method TMWrite (line 1380) | public int TMWrite(int Start, int Amount, ushort[] Buffer)
method CTRead (line 1391) | public int CTRead(int Start, int Amount, ushort[] Buffer)
method CTWrite (line 1405) | public int CTWrite(int Start, int Amount, ushort[] Buffer)
method ListBlocks (line 1420) | public int ListBlocks(ref S7BlocksList List)
method SiemensTimestamp (line 1425) | private string SiemensTimestamp(long EncodedDate)
method GetAgBlockInfo (line 1435) | public int GetAgBlockInfo(int BlockType, int BlockNum, ref S7BlockInfo...
method GetPgBlockInfo (line 1492) | public int GetPgBlockInfo(ref S7BlockInfo Info, byte[] Buffer, int Size)
method ListBlocksOfType (line 1497) | public int ListBlocksOfType(int BlockType, ushort[] List, ref int Item...
method Upload (line 1506) | public int Upload(int BlockType, int BlockNum, byte[] UsrData, ref int...
method FullUpload (line 1511) | public int FullUpload(int BlockType, int BlockNum, byte[] UsrData, ref...
method Download (line 1516) | public int Download(int BlockNum, byte[] UsrData, int Size)
method Delete (line 1521) | public int Delete(int BlockType, int BlockNum)
method DBGet (line 1526) | public int DBGet(int DBNumber, byte[] UsrData, ref int Size)
method DBFill (line 1552) | public int DBFill(int DBNumber, int FillChar)
method GetPlcDateTime (line 1576) | public int GetPlcDateTime(ref DateTime DT)
method SetPlcDateTime (line 1606) | public int SetPlcDateTime(DateTime DT)
method SetPlcSystemDateTime (line 1632) | public int SetPlcSystemDateTime()
method GetOrderCode (line 1641) | public int GetOrderCode(ref S7OrderCode Info)
method GetCpuInfo (line 1660) | public int GetCpuInfo(ref S7CpuInfo Info)
method GetCpInfo (line 1680) | public int GetCpInfo(ref S7CpInfo Info)
method ReadSZL (line 1699) | public int ReadSZL(int ID, int Index, ref S7SZL SZL, ref int Size)
method ReadSZLList (line 1790) | public int ReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
method PlcHotStart (line 1799) | public int PlcHotStart()
method PlcColdStart (line 1828) | public int PlcColdStart()
method PlcStop (line 1857) | public int PlcStop()
method PlcCopyRamToRom (line 1886) | public int PlcCopyRamToRom(UInt32 Timeout)
method PlcCompress (line 1891) | public int PlcCompress(UInt32 Timeout)
method PlcGetStatus (line 1896) | public int PlcGetStatus(ref Int32 Status)
method SetSessionPassword (line 1942) | public int SetSessionPassword(string Password)
method ClearSessionPassword (line 1976) | public int ClearSessionPassword()
method GetProtection (line 1997) | public int GetProtection(ref S7Protection Protection)
method IsoExchangeBuffer (line 2017) | public int IsoExchangeBuffer(byte[] Buffer, ref Int32 Size)
method AsReadArea (line 2053) | public int AsReadArea(int Area, int DBNumber, int Start, int Amount, i...
method AsWriteArea (line 2058) | public int AsWriteArea(int Area, int DBNumber, int Start, int Amount, ...
method AsDBRead (line 2063) | public int AsDBRead(int DBNumber, int Start, int Size, byte[] Buffer)
method AsDBWrite (line 2068) | public int AsDBWrite(int DBNumber, int Start, int Size, byte[] Buffer)
method AsMBRead (line 2073) | public int AsMBRead(int Start, int Size, byte[] Buffer)
method AsMBWrite (line 2078) | public int AsMBWrite(int Start, int Size, byte[] Buffer)
method AsEBRead (line 2083) | public int AsEBRead(int Start, int Size, byte[] Buffer)
method AsEBWrite (line 2088) | public int AsEBWrite(int Start, int Size, byte[] Buffer)
method AsABRead (line 2093) | public int AsABRead(int Start, int Size, byte[] Buffer)
method AsABWrite (line 2098) | public int AsABWrite(int Start, int Size, byte[] Buffer)
method AsTMRead (line 2103) | public int AsTMRead(int Start, int Amount, ushort[] Buffer)
method AsTMWrite (line 2108) | public int AsTMWrite(int Start, int Amount, ushort[] Buffer)
method AsCTRead (line 2113) | public int AsCTRead(int Start, int Amount, ushort[] Buffer)
method AsCTWrite (line 2118) | public int AsCTWrite(int Start, int Amount, ushort[] Buffer)
method AsListBlocksOfType (line 2123) | public int AsListBlocksOfType(int BlockType, ushort[] List)
method AsReadSZL (line 2128) | public int AsReadSZL(int ID, int Index, ref S7SZL Data, ref Int32 Size)
method AsReadSZLList (line 2133) | public int AsReadSZLList(ref S7SZLList List, ref Int32 ItemsCount)
method AsUpload (line 2138) | public int AsUpload(int BlockType, int BlockNum, byte[] UsrData, ref i...
method AsFullUpload (line 2143) | public int AsFullUpload(int BlockType, int BlockNum, byte[] UsrData, r...
method ASDownload (line 2148) | public int ASDownload(int BlockNum, byte[] UsrData, int Size)
method AsPlcCopyRamToRom (line 2153) | public int AsPlcCopyRamToRom(UInt32 Timeout)
method AsPlcCompress (line 2158) | public int AsPlcCompress(UInt32 Timeout)
method AsDBGet (line 2163) | public int AsDBGet(int DBNumber, byte[] UsrData, ref int Size)
method AsDBFill (line 2168) | public int AsDBFill(int DBNumber, int FillChar)
method CheckAsCompletion (line 2173) | public bool CheckAsCompletion(ref int opResult)
method WaitAsCompletion (line 2179) | public int WaitAsCompletion(int Timeout)
method ErrorText (line 2188) | public string ErrorText(int Error)
method LastError (line 2246) | public int LastError()
method RequestedPduLength (line 2251) | public int RequestedPduLength()
method NegotiatedPduLength (line 2256) | public int NegotiatedPduLength()
method ExecTime (line 2261) | public int ExecTime()
FILE: Sharp7/S7Consts.cs
class S7Consts (line 7) | public static class S7Consts
type S7Tag (line 107) | [StructLayout(LayoutKind.Sequential, Pack = 1)]
FILE: Sharp7/S7MultiVar.cs
class S7MultiVar (line 7) | public class S7MultiVar
method AdjustWordLength (line 18) | private bool AdjustWordLength(int Area, ref int WordLen, ref int Amoun...
method S7MultiVar (line 44) | public S7MultiVar(S7Client Client)
method Add (line 55) | public bool Add<T>(S7Consts.S7Tag Tag, ref T[] Buffer, int Offset)
method Add (line 60) | public bool Add<T>(S7Consts.S7Tag Tag, ref T[] Buffer)
method Add (line 65) | public bool Add<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 St...
method Add (line 70) | public bool Add<T>(Int32 Area, Int32 WordLen, Int32 DBNumber, Int32 St...
method Read (line 100) | public int Read()
method Write (line 124) | public int Write()
method Clear (line 148) | public void Clear()
FILE: Sharp7/S7Timer.cs
class S7Timer (line 7) | public class S7Timer
method S7Timer (line 14) | public S7Timer(byte[] buff, int position)
method S7Timer (line 22) | public S7Timer(byte[] buff)
method SetTimer (line 27) | private void SetTimer(byte[] buff)
FILE: Sharp7/S7WordLength.cs
type S7WordLength (line 3) | public enum S7WordLength
Condensed preview — 23 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (178K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 64,
"preview": "# These are supported funding model platforms\n\ngithub: fbarresi\n"
},
{
"path": ".gitignore",
"chars": 4869,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n##\n## G"
},
{
"path": "CHANGELOG.md",
"chars": 3050,
"preview": "# Change Log\nAll notable changed to this project will be documented in this file.\n\n## [1.1.84] - 11.05.2023\n### Added\n##"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2018 Federico Barresi\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 2224,
"preview": "# \n\n[. The extraction includes 23 files (159.0 KB), approximately 49.4k tokens, and a symbol index with 343 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.