├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── azure-pipelines.yml ├── buildDocs.ps1 ├── dacs7 ├── .gitattributes ├── .gitignore ├── Directory.Build.props ├── benchmarks │ └── Dacs7.Benchmarks │ │ ├── Dacs7.Benchmarks.csproj │ │ ├── Program.cs │ │ ├── ReadBenchmark.cs │ │ └── TypeOfBenchmarks.cs ├── dacs7.sln ├── nuget.config ├── src │ ├── Dacs7 │ │ ├── Communication │ │ │ ├── IConfiguration.cs │ │ │ ├── ISocketConfiguration.cs │ │ │ ├── Socket │ │ │ │ ├── ClientSocket.cs │ │ │ │ ├── ClientSocketConfiguration.cs │ │ │ │ ├── ServerSocket.cs │ │ │ │ ├── ServerSocketConfiguration.cs │ │ │ │ └── TcpTransport.cs │ │ │ ├── SocketBase.cs │ │ │ └── Transport.cs │ │ ├── Dacs7.csproj │ │ ├── Dacs7Client.cs │ │ ├── Dacs7ClientAlarmOperations.cs │ │ ├── Dacs7ClientMetadataOperations.cs │ │ ├── Dacs7ClientReadOperations.cs │ │ ├── Dacs7ClientRegisterOperations.cs │ │ ├── Dacs7ClientWriteOperations.cs │ │ ├── Dacs7Server.cs │ │ ├── DataProvider │ │ │ ├── IPlcDataProvider.cs │ │ │ ├── RelayPlcDataProvider.cs │ │ │ └── SimulationPlcDataProvider.cs │ │ ├── Domain │ │ │ ├── AlarmSubscription.cs │ │ │ ├── AlarmUpdateResult.cs │ │ │ ├── Alarms │ │ │ │ ├── AlarmMessageType.cs │ │ │ │ ├── IPlcAlarm.cs │ │ │ │ ├── IPlcAlarmAssotiatedValue.cs │ │ │ │ └── IPlcAlarmDetails.cs │ │ │ ├── Blocks │ │ │ │ ├── IBlocksCount.cs │ │ │ │ ├── IPlcBlockInfo.cs │ │ │ │ └── IPlcBlocks.cs │ │ │ ├── Control │ │ │ │ └── PlcStates.cs │ │ │ ├── Converters │ │ │ │ ├── ConvertDataToMemoryExtensions.cs │ │ │ │ ├── ConvertMemoryToDataExtensions.cs │ │ │ │ └── Helpers.cs │ │ │ ├── Dacs7ConnectionState.cs │ │ │ ├── DataTransportSize.cs │ │ │ ├── DataValue.cs │ │ │ ├── DataValueFormatterExtensions.cs │ │ │ ├── ErrorClass.cs │ │ │ ├── ErrorHandling.cs │ │ │ ├── ErrorParameter.cs │ │ │ ├── Internal │ │ │ │ ├── FunctionCodes.cs │ │ │ │ ├── ItemDataTransportSize.cs │ │ │ │ ├── ItemSyntaxId.cs │ │ │ │ ├── PduType.cs │ │ │ │ ├── UserDataFunctionGroup.cs │ │ │ │ ├── UserDataFunctionGroups.cs │ │ │ │ ├── UserDataFunctionType.cs │ │ │ │ ├── UserDataParamTypeType.cs │ │ │ │ ├── UserDataSubFunctionBlock.cs │ │ │ │ ├── UserDataSubFunctionCpu.cs │ │ │ │ ├── UserDataSubFunctionCyclic.cs │ │ │ │ ├── UserDataSubFunctionProg.cs │ │ │ │ └── UserDataSubFunctionSecurity.cs │ │ │ ├── ItemExtensions.cs │ │ │ ├── ItemResponseRetValue.cs │ │ │ ├── Metadata │ │ │ │ ├── BlockSecurity.cs │ │ │ │ ├── PlcBlockAttributes.cs │ │ │ │ ├── PlcBlockInfo.cs │ │ │ │ ├── PlcBlockLanguage.cs │ │ │ │ ├── PlcBlockType.cs │ │ │ │ ├── PlcBlocks.cs │ │ │ │ ├── PlcBlocksCount.cs │ │ │ │ └── PlcSubBlockType.cs │ │ │ ├── PlcArea.cs │ │ │ ├── PlcConnectionType.cs │ │ │ ├── PlcDataEntry.cs │ │ │ ├── PlcEncoding.cs │ │ │ ├── ReadItem.cs │ │ │ ├── ReadRequestItem.cs │ │ │ ├── ReadResultItem.cs │ │ │ ├── RequestItem.cs │ │ │ ├── TagParser.cs │ │ │ ├── TagParserState.cs │ │ │ ├── WriteItem.cs │ │ │ ├── WriteRequestItem.cs │ │ │ └── WriteResultItem.cs │ │ ├── Exceptions │ │ │ ├── Dacs7ContentException.cs │ │ │ ├── Dacs7Exception.cs │ │ │ ├── Dacs7NotConnectedException.cs │ │ │ ├── Dacs7ParameterException.cs │ │ │ ├── Dacs7ReadTimeoutException.cs │ │ │ ├── Dacs7ReturnCodeException.cs │ │ │ ├── Dacs7TagParserException.cs │ │ │ ├── Dacs7ToMuchDataPerCallException.cs │ │ │ ├── Dacs7TypeNotSupportedException.cs │ │ │ ├── Dacs7WriteTimeoutException.cs │ │ │ └── ExceptionThrowHelper.cs │ │ ├── GlobalSuppressions.cs │ │ ├── Helper │ │ │ ├── AsyncAutoResetEvent.cs │ │ │ ├── CollectionExtensions.cs │ │ │ ├── Converter.cs │ │ │ ├── DescriptionAttribute.cs │ │ │ ├── InternalExtensions.cs │ │ │ ├── SemaphoreGuard.cs │ │ │ └── SpecializedLinqExtensions.cs │ │ └── Protocols │ │ │ ├── CallbackHandler.cs │ │ │ ├── ConnectionState.cs │ │ │ ├── IProtocolContext.cs │ │ │ ├── ProtocolHandler.Alarms.cs │ │ │ ├── ProtocolHandler.Metadata.cs │ │ │ ├── ProtocolHandler.Read.cs │ │ │ ├── ProtocolHandler.Server.CommSetup.cs │ │ │ ├── ProtocolHandler.Server.Read.cs │ │ │ ├── ProtocolHandler.Server.Write.cs │ │ │ ├── ProtocolHandler.Write.cs │ │ │ ├── ProtocolHandler.cs │ │ │ ├── ReadPackage.cs │ │ │ ├── Rfc1006 │ │ │ ├── Datagrams │ │ │ │ ├── ConnectionConfirmedDatagram.cs │ │ │ │ ├── ConnectionRequestDatagram.cs │ │ │ │ ├── DataTransferDatagram.cs │ │ │ │ └── TpktDatagram.cs │ │ │ └── Rfc1006ProtocolContext.cs │ │ │ ├── SiemensPlc │ │ │ ├── Datagrams │ │ │ │ ├── S7AckDataDatagram.cs │ │ │ │ ├── S7AddressItemSpecificationDatagram.cs │ │ │ │ ├── S7AlarmIndicationDatagram.cs │ │ │ │ ├── S7AlarmMessage.cs │ │ │ │ ├── S7AlarmUpdateAckDatagram.cs │ │ │ │ ├── S7CommAckDataDatagram.cs │ │ │ │ ├── S7CommSetupDatagram.cs │ │ │ │ ├── S7CommSetupParameterDatagram.cs │ │ │ │ ├── S7DataItemSpecification.cs │ │ │ │ ├── S7DataItemWriteResult.cs │ │ │ │ ├── S7HeaderDatagram.cs │ │ │ │ ├── S7HeaderErrorCodesDatagram.cs │ │ │ │ ├── S7PendingAlarmAckDatagram.cs │ │ │ │ ├── S7PlcAlarmItemDatagram.cs │ │ │ │ ├── S7PlcBlockInfoAckDatagram.cs │ │ │ │ ├── S7PlcBlocksCountAckDatagram.cs │ │ │ │ ├── S7PlcBlocksOfTypeAckDatagram.cs │ │ │ │ ├── S7ReadJobAckDatagram.cs │ │ │ │ ├── S7ReadJobDatagram.cs │ │ │ │ ├── S7UserData.cs │ │ │ │ ├── S7UserDataDatagram.cs │ │ │ │ ├── S7UserDataParameter.cs │ │ │ │ ├── S7WriteJobAckDatagram.cs │ │ │ │ └── S7WriteJobDatagram.cs │ │ │ └── SiemensPlcProtocolContext.cs │ │ │ └── WritePackage.cs │ └── Dacs7Cli │ │ ├── BlockinfoCommand.cs │ │ ├── BlocksCountCommand.cs │ │ ├── BlocksOfTypeCommand.cs │ │ ├── Dacs7Cli.csproj │ │ ├── Options │ │ ├── OptionsBase.cs │ │ ├── ReadAlarmsOptions.cs │ │ ├── ReadOptions.cs │ │ ├── ServerOptions.cs │ │ ├── WatchAlarmsOptions.cs │ │ ├── WatchOptions.cs │ │ └── WriteOptions.cs │ │ ├── Parameters.txt │ │ ├── Program.cs │ │ ├── Properties │ │ └── launchSettings.json │ │ ├── ReadAlarmsCommand.cs │ │ ├── ReadCommand.cs │ │ ├── ServeCommand.cs │ │ ├── Shared.cs │ │ ├── TaskReadCommand.cs │ │ ├── WatchAlarmsCommand.cs │ │ └── WriteCommand.cs └── test │ ├── Dacs7.Papper.Tests │ ├── DB1991_DB_Setup_AGV_BST1.cs │ ├── DB1993_DB_SpindlePos_BST1.cs │ ├── DB463_DB_IPSC_Konfig.cs │ ├── Dacs7.Papper.Tests.csproj │ └── PapperConnectionTest.cs │ └── Dacs7Tests │ ├── ConnectionTests.cs │ ├── CreateTests.cs │ ├── Dacs7.Tests.csproj │ ├── DataConsistentTests.cs │ ├── DataValueTests.cs │ ├── ExtensionsTests.cs │ ├── MetadataTests.cs │ ├── ReUseTest.cs │ ├── ReadWriteExceptionsTests.cs │ ├── ReadWriteIEnumerableTests.cs │ ├── ReadWriteIEnumerableValuesTests.cs │ ├── ReadWriteParamsTests.cs │ ├── ServerHelper │ └── PlcTestServer.cs │ ├── ServerTests.cs │ ├── TagParserTests.cs │ └── TypeConversionTests.cs ├── docfx ├── .gitignore ├── api │ ├── .gitignore │ ├── .manifest │ └── index.md ├── articles │ ├── Overview.md │ ├── openclose.md │ ├── read.md │ ├── tagsyntax.md │ └── write.md ├── docfx.json ├── images │ ├── BlockSettings.PNG │ ├── Connectionmechanism.PNG │ ├── FullAccess.PNG │ ├── GitHub120px.png │ ├── GitHub32px.png │ ├── GitHub64px.png │ ├── GitHubWhite120px.png │ ├── GitHubWhite32px.png │ ├── GitHubWhite64px.png │ ├── font-logo.png │ ├── logo.png │ ├── me.png │ └── websiteLogoTile.png ├── index.md ├── templates │ └── default │ │ ├── ManagedReference.common.js │ │ ├── ManagedReference.extension.js │ │ ├── ManagedReference.html.primary.js │ │ ├── ManagedReference.html.primary.tmpl │ │ ├── RestApi.common.js │ │ ├── RestApi.extension.js │ │ ├── RestApi.html.primary.js │ │ ├── RestApi.html.primary.tmpl │ │ ├── common.js │ │ ├── conceptual.extension.js │ │ ├── conceptual.html.primary.js │ │ ├── conceptual.html.primary.tmpl │ │ ├── favicon.ico │ │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ │ ├── gulpfile.js │ │ ├── logo.svg │ │ ├── partials │ │ ├── affix.tmpl.partial │ │ ├── breadcrumb.tmpl.partial │ │ ├── class.header.tmpl.partial │ │ ├── class.tmpl.partial │ │ ├── classSubtitle.tmpl.partial │ │ ├── enum.tmpl.partial │ │ ├── footer.tmpl.partial │ │ ├── head.tmpl.partial │ │ ├── insiteLogo.tmpl.partial │ │ ├── li.tmpl.partial │ │ ├── logo.tmpl.partial │ │ ├── namespace.tmpl.partial │ │ ├── namespaceSubtitle.tmpl.partial │ │ ├── navbar.tmpl.partial │ │ ├── rest.child.tmpl.partial │ │ ├── rest.tmpl.partial │ │ ├── scripts.tmpl.partial │ │ ├── searchResults.tmpl.partial │ │ ├── title.tmpl.partial │ │ └── toc.tmpl.partial │ │ ├── search-stopwords.json │ │ ├── styles │ │ ├── docfx.css │ │ ├── docfx.js │ │ ├── docfx.vendor.css │ │ ├── docfx.vendor.js │ │ ├── encrypter.js │ │ ├── lunr.min.js │ │ ├── main.css │ │ ├── main.js │ │ └── search-worker.js │ │ ├── toc.html.js │ │ ├── toc.html.tmpl │ │ └── token.json └── toc.yml ├── docs-pdf ├── docfx_api.pdf └── docs-pdf │ ├── api │ ├── Dacs7.Alarms.AlarmMessageType.html │ ├── Dacs7.Alarms.AlarmSubscription.html │ ├── Dacs7.Alarms.AlarmUpdateResult.html │ ├── Dacs7.Alarms.Dacs7ClientAlarmExtensions.html │ ├── Dacs7.Alarms.IPlcAlarm.html │ ├── Dacs7.Alarms.IPlcAlarmAssotiatedValue.html │ ├── Dacs7.Alarms.IPlcAlarmDetails.html │ ├── Dacs7.Alarms.html │ ├── Dacs7.AsyncAutoResetEvent-1.html │ ├── Dacs7.Communication.ClientSocketConfiguration.html │ ├── Dacs7.Communication.IConfiguration.html │ ├── Dacs7.Communication.ISocketConfiguration.html │ ├── Dacs7.Communication.html │ ├── Dacs7.ConnectionStateChangedEventHandler.html │ ├── Dacs7.Control.PlcStateInfo.html │ ├── Dacs7.Control.PlcStates.html │ ├── Dacs7.Control.html │ ├── Dacs7.Dacs7Client.html │ ├── Dacs7.Dacs7ClientRegisterExtensions.html │ ├── Dacs7.Dacs7ConnectionState.html │ ├── Dacs7.Dacs7ContentException.html │ ├── Dacs7.Dacs7Exception.html │ ├── Dacs7.Dacs7NotConnectedException.html │ ├── Dacs7.Dacs7ParameterException.html │ ├── Dacs7.Dacs7ReadTimeoutException.html │ ├── Dacs7.Dacs7ReturnCodeException.html │ ├── Dacs7.Dacs7TagParserException.html │ ├── Dacs7.Dacs7ToMuchDataPerCallException.html │ ├── Dacs7.Dacs7TypeNotSupportedException.html │ ├── Dacs7.Dacs7WriteTimeoutException.html │ ├── Dacs7.DataValue.html │ ├── Dacs7.DataValueFormatter.html │ ├── Dacs7.DataValueFormatterExtensions.html │ ├── Dacs7.Domain.DataTransportSize.html │ ├── Dacs7.Domain.TagParserState.html │ ├── Dacs7.Domain.html │ ├── Dacs7.ErrorClass.html │ ├── Dacs7.ErrorHandling.html │ ├── Dacs7.ErrorParameter.html │ ├── Dacs7.Helper.Converter.html │ ├── Dacs7.Helper.DescriptionAttribute.html │ ├── Dacs7.Helper.html │ ├── Dacs7.ItemExtensions.html │ ├── Dacs7.ItemResponseRetValue.html │ ├── Dacs7.Metadata.BlockSecurity.html │ ├── Dacs7.Metadata.Dacs7ClientMetadataExtensions.html │ ├── Dacs7.Metadata.IPlcBlock.html │ ├── Dacs7.Metadata.IPlcBlockInfo.html │ ├── Dacs7.Metadata.IPlcBlocksCount.html │ ├── Dacs7.Metadata.PlcBlockAttributes.html │ ├── Dacs7.Metadata.PlcBlockInfo.html │ ├── Dacs7.Metadata.PlcBlockLanguage.html │ ├── Dacs7.Metadata.PlcBlockType.html │ ├── Dacs7.Metadata.PlcSubBlockType.html │ ├── Dacs7.Metadata.html │ ├── Dacs7.PlcArea.html │ ├── Dacs7.PlcConnectionType.html │ ├── Dacs7.PlcEncoding.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmAssotiatedValue.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmDetails.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmItemDatagram.html │ ├── Dacs7.Protocols.SiemensPlc.html │ ├── Dacs7.ReadItem.html │ ├── Dacs7.ReadWrite.Dacs7ClientReadExtensions.html │ ├── Dacs7.ReadWrite.Dacs7ClientWriteExtensions.html │ ├── Dacs7.ReadWrite.html │ ├── Dacs7.WriteItem.html │ ├── Dacs7.html │ ├── Dacs7Cli.Options.OptionsBase.html │ ├── Dacs7Cli.Options.ReadAlarmsOptions.html │ ├── Dacs7Cli.Options.ReadOptions.html │ ├── Dacs7Cli.Options.WatchAlarmsOptions.html │ ├── Dacs7Cli.Options.WatchOptions.html │ ├── Dacs7Cli.Options.WriteOptions.html │ ├── Dacs7Cli.Options.html │ ├── index.html │ ├── toc.html │ └── toc.json │ ├── articles │ ├── Overview.html │ ├── openclose.html │ ├── read.html │ ├── tagsyntax.html │ └── write.html │ ├── images │ ├── BlockSettings.PNG │ ├── Connectionmechanism.PNG │ ├── FullAccess.PNG │ ├── GitHub120px.png │ ├── GitHub32px.png │ ├── GitHub64px.png │ ├── GitHubWhite120px.png │ ├── GitHubWhite32px.png │ ├── GitHubWhite64px.png │ ├── font-logo.png │ ├── logo.png │ ├── websiteLogoTile.png │ └── whitefontlogo.png │ ├── index.html │ ├── manifest.json │ ├── styles │ ├── default.css │ ├── docfx.js │ ├── docfx.vendor.css │ ├── docfx.vendor.js │ ├── main.css │ └── main.js │ └── xrefmap.yml ├── docs ├── api │ ├── Dacs7.Alarms.AlarmMessageType.html │ ├── Dacs7.Alarms.AlarmSubscription.html │ ├── Dacs7.Alarms.AlarmUpdateResult.html │ ├── Dacs7.Alarms.Dacs7ClientAlarmExtensions.html │ ├── Dacs7.Alarms.IPlcAlarm.html │ ├── Dacs7.Alarms.IPlcAlarmAssotiatedValue.html │ ├── Dacs7.Alarms.IPlcAlarmDetails.html │ ├── Dacs7.Alarms.html │ ├── Dacs7.AsyncAutoResetEvent-1.html │ ├── Dacs7.Communication.ClientSocketConfiguration.html │ ├── Dacs7.Communication.IConfiguration.html │ ├── Dacs7.Communication.ISocketConfiguration.html │ ├── Dacs7.Communication.html │ ├── Dacs7.ConnectionStateChangedEventHandler.html │ ├── Dacs7.Control.PlcStateInfo.html │ ├── Dacs7.Control.PlcStates.html │ ├── Dacs7.Control.html │ ├── Dacs7.Dacs7Client.html │ ├── Dacs7.Dacs7ClientRegisterExtensions.html │ ├── Dacs7.Dacs7ConnectionState.html │ ├── Dacs7.Dacs7ContentException.html │ ├── Dacs7.Dacs7Exception.html │ ├── Dacs7.Dacs7NotConnectedException.html │ ├── Dacs7.Dacs7ParameterException.html │ ├── Dacs7.Dacs7ReadTimeoutException.html │ ├── Dacs7.Dacs7ReturnCodeException.html │ ├── Dacs7.Dacs7TagParserException.html │ ├── Dacs7.Dacs7ToMuchDataPerCallException.html │ ├── Dacs7.Dacs7TypeNotSupportedException.html │ ├── Dacs7.Dacs7WriteTimeoutException.html │ ├── Dacs7.DataValue.html │ ├── Dacs7.DataValueFormatter.html │ ├── Dacs7.DataValueFormatterExtensions.html │ ├── Dacs7.Domain.DataTransportSize.html │ ├── Dacs7.Domain.TagParserState.html │ ├── Dacs7.Domain.html │ ├── Dacs7.ErrorClass.html │ ├── Dacs7.ErrorHandling.html │ ├── Dacs7.ErrorParameter.html │ ├── Dacs7.Helper.Converter.html │ ├── Dacs7.Helper.DescriptionAttribute.html │ ├── Dacs7.Helper.html │ ├── Dacs7.ItemExtensions.html │ ├── Dacs7.ItemResponseRetValue.html │ ├── Dacs7.Metadata.BlockSecurity.html │ ├── Dacs7.Metadata.Dacs7ClientMetadataExtensions.html │ ├── Dacs7.Metadata.IPlcBlock.html │ ├── Dacs7.Metadata.IPlcBlockInfo.html │ ├── Dacs7.Metadata.IPlcBlocksCount.html │ ├── Dacs7.Metadata.PlcBlockAttributes.html │ ├── Dacs7.Metadata.PlcBlockInfo.html │ ├── Dacs7.Metadata.PlcBlockLanguage.html │ ├── Dacs7.Metadata.PlcBlockType.html │ ├── Dacs7.Metadata.PlcSubBlockType.html │ ├── Dacs7.Metadata.html │ ├── Dacs7.PlcArea.html │ ├── Dacs7.PlcConnectionType.html │ ├── Dacs7.PlcEncoding.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmAssotiatedValue.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmDetails.html │ ├── Dacs7.Protocols.SiemensPlc.S7PlcAlarmItemDatagram.html │ ├── Dacs7.Protocols.SiemensPlc.html │ ├── Dacs7.ReadItem.html │ ├── Dacs7.ReadWrite.Dacs7ClientReadExtensions.html │ ├── Dacs7.ReadWrite.Dacs7ClientWriteExtensions.html │ ├── Dacs7.ReadWrite.html │ ├── Dacs7.WriteItem.html │ ├── Dacs7.html │ ├── Dacs7Cli.Options.OptionsBase.html │ ├── Dacs7Cli.Options.ReadAlarmsOptions.html │ ├── Dacs7Cli.Options.ReadOptions.html │ ├── Dacs7Cli.Options.WatchAlarmsOptions.html │ ├── Dacs7Cli.Options.WatchOptions.html │ ├── Dacs7Cli.Options.WriteOptions.html │ ├── Dacs7Cli.Options.html │ └── index.html ├── articles │ ├── Overview.html │ ├── openclose.html │ ├── read.html │ ├── tagsyntax.html │ └── write.html ├── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── images │ ├── BlockSettings.PNG │ ├── Connectionmechanism.PNG │ ├── FullAccess.PNG │ ├── GitHub120px.png │ ├── GitHub32px.png │ ├── GitHub64px.png │ ├── GitHubWhite120px.png │ ├── GitHubWhite32px.png │ ├── GitHubWhite64px.png │ ├── font-logo.png │ ├── logo.png │ ├── me.png │ ├── websiteLogoTile.png │ └── whitefontlogo.png ├── index.html ├── logo.svg ├── manifest.json ├── search-stopwords.json ├── styles │ ├── docfx.css │ ├── docfx.js │ ├── docfx.vendor.css │ ├── docfx.vendor.js │ ├── encrypter.js │ ├── lunr.min.js │ ├── main.css │ ├── main.js │ └── search-worker.js ├── toc.html └── xrefmap.yml ├── eng ├── run.yml └── templates │ ├── dotnet-build.yml │ ├── dotnet-pack.yml │ ├── dotnet-publish.yml │ ├── dotnet-test.yml │ └── nuget-authenticate.yml ├── images ├── BlockSettings.PNG ├── Connectionmechanism.PNG └── FullAccess.PNG └── serveDocs.ps1 /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # ASP.NET Core 2 | # Build and test ASP.NET Core projects targeting .NET Core. 3 | # Add steps that run tests, create a NuGet package, deploy, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core 5 | 6 | # specify triggers 7 | trigger: 8 | branches: 9 | include: 10 | - master 11 | - releases/* 12 | paths: 13 | exclude: 14 | - data/* 15 | - Samples/* 16 | - licenses/* 17 | - docfx/* 18 | - IlsTools/* 19 | 20 | pr: 21 | - master 22 | - releases/* 23 | 24 | pool: 25 | vmImage: 'windows-latest' 26 | 27 | variables: 28 | buildConfiguration: 'Release' 29 | pushAsRelease: $[startsWith(variables['Build.SourceBranch'], 'refs/heads/releases/')] 30 | nugetChannelName: 'dev' 31 | 32 | steps: 33 | - script: "echo Build.SourceBranch: $(Build.SourceBranch); buildConfiguration: $(buildConfiguration); pushAsRelease: $(pushAsRelease)" 34 | 35 | - template: eng/run.yml 36 | parameters: 37 | solution: './dacs7/dacs7.sln' 38 | artifactNamePrefix: 'dacs7' 39 | framework: 'netcoreapp2.2' 40 | runTests: 'false' 41 | dotnetCoreSdk: '2.2.203' 42 | nugetConfig: './dacs7/nuget.config' 43 | nugetChannelName: $(nugetChannelName) 44 | 45 | -------------------------------------------------------------------------------- /buildDocs.ps1: -------------------------------------------------------------------------------- 1 | 2 | docfx docfx/docfx.json -------------------------------------------------------------------------------- /dacs7/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | latest 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /dacs7/benchmarks/Dacs7.Benchmarks/Dacs7.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | net6.0 6 | false 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /dacs7/benchmarks/Dacs7.Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Dacs7.Benchmarks 4 | { 5 | internal class Program 6 | { 7 | private static void Main(string[] args) 8 | { 9 | //var summary = BenchmarkRunner.Run(); 10 | BenchmarkDotNet.Reports.Summary summary = BenchmarkRunner.Run(); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dacs7/benchmarks/Dacs7.Benchmarks/ReadBenchmark.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Attributes; 2 | using BenchmarkDotNet.Diagnostics.Windows.Configs; 3 | using BenchmarkDotNet.Engines; 4 | using Dacs7.ReadWrite; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace Dacs7.Benchmarks 9 | { 10 | [SimpleJob(RunStrategy.Monitoring, launchCount: 0, warmupCount: 0, targetCount: 100)] 11 | [RankColumn] 12 | [MemoryDiagnoser] 13 | [InliningDiagnoser] 14 | public class ReadBenchmark 15 | { 16 | 17 | private Dacs7Client _client; 18 | private ReadItem _item; 19 | 20 | [Params("192.168.0.148:102,0,2")] 21 | public string Address; 22 | 23 | [Params("DB250.0,b,100", "DB250.0,b,1000", "DB250.1000,x1", "DB250.1100,w,10")] 24 | public string Tag { get; set; } 25 | 26 | [Params(300)] 27 | public int Loops { get; set; } 28 | 29 | 30 | [GlobalSetup] 31 | public async Task Setup() 32 | { 33 | _client = new Dacs7Client(Address, PlcConnectionType.Pg, 5000) 34 | { 35 | MaxAmQCalled = 5, 36 | MaxAmQCalling = 5 37 | }; 38 | await _client.ConnectAsync(); 39 | _item = ReadItem.CreateFromTag(Tag); 40 | } 41 | 42 | [GlobalCleanup] 43 | public void GlobalCleanup() 44 | { 45 | _client?.DisconnectAsync(); 46 | } 47 | 48 | [Benchmark] 49 | public async Task ReadAsync() 50 | { 51 | List>> results = new(); 52 | for (int i = 0; i < Loops; i++) 53 | { 54 | results.Add(_client.ReadAsync(_item)); 55 | } 56 | await Task.WhenAll(results.ToArray()).ConfigureAwait(false); 57 | } 58 | 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /dacs7/nuget.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Communication/IConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Communication 6 | { 7 | public interface IConfiguration 8 | { 9 | int ReceiveBufferSize { get; set; } 10 | int AutoconnectTime { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Communication/ISocketConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Communication 6 | { 7 | public interface ISocketConfiguration : IConfiguration 8 | { 9 | string Hostname { get; set; } 10 | int ServiceName { get; set; } 11 | string NetworkAdapter { get; set; } 12 | bool KeepAlive { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Communication/Socket/ClientSocketConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System.Net; 5 | using System.Net.Sockets; 6 | 7 | namespace Dacs7.Communication 8 | { 9 | public class ClientSocketConfiguration : ISocketConfiguration 10 | { 11 | public string Hostname { get; set; } = "localhost"; 12 | public int ServiceName { get; set; } = 22112; 13 | public int ReceiveBufferSize { get; set; } = 10 * 1024; // buffer size to use for each socket I/O operation 14 | public int AutoconnectTime { get; set; } = 5000; // <= 0 means disabled 15 | public string NetworkAdapter { get; set; } 16 | public bool KeepAlive { get; set; } = false; 17 | 18 | public ClientSocketConfiguration() 19 | { 20 | } 21 | 22 | public static ClientSocketConfiguration FromSocket(System.Net.Sockets.Socket socket) 23 | { 24 | IPEndPoint ep = socket.RemoteEndPoint as IPEndPoint; 25 | object keepAlive = socket.GetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.KeepAlive); 26 | return new ClientSocketConfiguration 27 | { 28 | Hostname = ep.Address.ToString(), 29 | ServiceName = ep.Port, 30 | ReceiveBufferSize = socket.ReceiveBufferSize, // buffer size to use for each socket I/O operation 31 | KeepAlive = keepAlive != null 32 | }; 33 | } 34 | 35 | public sealed override string ToString() 36 | { 37 | return $"Socket: Hostname={Hostname}; ServiceName={ServiceName}; ReceiveBufferSize={ReceiveBufferSize}; KeepAlive={KeepAlive}"; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Communication/Socket/ServerSocketConfiguration.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Communication.Socket 5 | { 6 | public class ServerSocketConfiguration : ISocketConfiguration 7 | { 8 | public string Hostname { get; set; } = "localhost"; 9 | public int ServiceName { get; set; } = 22112; 10 | public int ReceiveBufferSize { get; set; } = 10 * 1024; // buffer size to use for each socket I/O operation 11 | public int AutoconnectTime { get; set; } = 5000; // <= 0 means disabled 12 | public string NetworkAdapter { get; set; } 13 | public bool KeepAlive { get; set; } = false; 14 | 15 | public ServerSocketConfiguration() 16 | { 17 | } 18 | 19 | public sealed override string ToString() 20 | { 21 | return $"Socket: Hostname={Hostname}; ServiceName={ServiceName}; ReceiveBufferSize={ReceiveBufferSize}; KeepAlive={KeepAlive}"; 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Communication/Transport.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Protocols; 5 | using Microsoft.Extensions.Logging; 6 | using System; 7 | using System.Buffers; 8 | 9 | namespace Dacs7.Communication 10 | { 11 | /// 12 | /// This is the baseclass of the transport mechanism. Currently we support sockets, but there could also be some other transport methods. 13 | /// 14 | internal abstract class Transport 15 | { 16 | public OnUpdateConnectionState OnUpdateConnectionState; 17 | public OnDetectAndReceive OnDetectAndReceive; 18 | public OnGetConnectionState OnGetConnectionState; 19 | public OnNewSocketConnected OnNewSocketConnected; 20 | 21 | public Transport(IProtocolContext context, IConfiguration config) 22 | { 23 | ProtocolContext = context; 24 | Configuration = config; 25 | } 26 | 27 | 28 | public SocketBase Connection { get; protected set; } 29 | public IConfiguration Configuration { get; private set; } 30 | public IProtocolContext ProtocolContext { get; private set; } 31 | 32 | 33 | public abstract void ConfigureClient(ILoggerFactory loggerFactory); 34 | public abstract void ConfigureServer(ILoggerFactory loggerFactory); 35 | public abstract IMemoryOwner Build(Memory buffer, out int length); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Dacs7ClientAlarmOperations.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading; 7 | using System.Threading.Tasks; 8 | 9 | namespace Dacs7.Alarms 10 | { 11 | public static class Dacs7ClientAlarmExtensions 12 | { 13 | 14 | /// 15 | /// Reads all pending alarms from the plc 16 | /// 17 | /// 18 | /// A list of 19 | public static Task> ReadPendingAlarmsAsync(this Dacs7Client client) 20 | { 21 | return client.ProtocolHandler.ReadPendingAlarmsAsync(); 22 | } 23 | 24 | /// 25 | /// This method returns if the plcalarms get updated. 26 | /// 27 | /// 28 | /// 29 | /// 30 | [Obsolete("ReceiveAlarmUpdatesAsync is deprecated, please use AlarmSubscription class instead.")] 31 | public static Task ReceiveAlarmUpdatesAsync(this Dacs7Client client, CancellationToken ct) 32 | { 33 | return client.ProtocolHandler.ReceiveAlarmUpdatesAsync(ct); 34 | } 35 | 36 | 37 | /// 38 | /// Create a alarm subscription. 39 | /// 40 | /// 41 | /// 42 | public static AlarmSubscription CreateAlarmSubscription(this Dacs7Client client) 43 | { 44 | return client.ProtocolHandler.CreateAlarmSubscription(); 45 | } 46 | 47 | /// 48 | /// Wait for a alarm event 49 | /// 50 | /// 51 | /// 52 | /// 53 | public static Task ReceiveAlarmUpdatesAsync(this AlarmSubscription subscription, CancellationToken ct) 54 | { 55 | return subscription.ProtocolHandler.ReceiveAlarmUpdatesAsync(subscription, ct); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/DataProvider/IPlcDataProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | 7 | namespace Dacs7.DataProvider 8 | { 9 | 10 | public interface IPlcDataProvider 11 | { 12 | /// 13 | /// The server will invoke this method if a read request is received and injects a list of . 14 | /// 15 | /// These items contains the requested data to read. 16 | /// a list of 17 | Task> ReadAsync(List readItems); 18 | 19 | /// 20 | /// The server will invoke this method if a write request is received and injects a list of . 21 | /// 22 | /// These items contains the requested data to write. 23 | /// a list of 24 | Task> WriteAsync(List writeItems); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/DataProvider/RelayPlcDataProvider.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.ReadWrite; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | 10 | namespace Dacs7.DataProvider 11 | { 12 | public class RelayPlcDataProvider : IPlcDataProvider 13 | { 14 | private static readonly Lazy _default = new(() => new RelayPlcDataProvider()); 15 | private Dacs7Client _client; 16 | 17 | 18 | public static RelayPlcDataProvider Instance => _default.Value; 19 | 20 | 21 | public void UseClient(Dacs7Client client) 22 | { 23 | _client = client; 24 | } 25 | 26 | public async Task> ReadAsync(List readItems) 27 | { 28 | IEnumerable reads = readItems.Select(ri => ri.ToTag()); 29 | IEnumerable readResult = await _client.ReadAsync(reads).ConfigureAwait(false); 30 | 31 | List.Enumerator enumerator = readItems.GetEnumerator(); 32 | List result = new(); 33 | foreach (DataValue item in readResult) 34 | { 35 | if (!enumerator.MoveNext()) 36 | { 37 | break; 38 | } 39 | 40 | result.Add(new ReadResultItem(enumerator.Current, item.ReturnCode, item.Data)); 41 | } 42 | return result; 43 | } 44 | 45 | 46 | public async Task> WriteAsync(List writeItems) 47 | { 48 | IEnumerable> writes = writeItems.Select(ri => new KeyValuePair(ri.ToTag(), ri.Data)); 49 | IEnumerable writeResult = await _client.WriteAsync(writes).ConfigureAwait(false); 50 | 51 | List.Enumerator enumerator = writeItems.GetEnumerator(); 52 | List result = new(); 53 | foreach (ItemResponseRetValue item in writeResult) 54 | { 55 | if (!enumerator.MoveNext()) 56 | { 57 | break; 58 | } 59 | 60 | result.Add(new WriteResultItem(enumerator.Current, item)); 61 | } 62 | return result; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/AlarmSubscription.cs: -------------------------------------------------------------------------------- 1 | using Dacs7.Protocols; 2 | using Dacs7.Protocols.SiemensPlc; 3 | using System; 4 | using System.Collections.Concurrent; 5 | 6 | namespace Dacs7.Alarms 7 | { 8 | 9 | public class AlarmSubscription : IDisposable 10 | { 11 | private bool _disposedValue; 12 | private readonly ConcurrentQueue _alarms = new(); 13 | internal ProtocolHandler ProtocolHandler { get; private set; } 14 | internal CallbackHandler CallbackHandler { get; private set; } 15 | 16 | internal AlarmSubscription(ProtocolHandler ph, CallbackHandler cbh) 17 | { 18 | ProtocolHandler = ph; 19 | CallbackHandler = cbh; 20 | } 21 | 22 | internal bool TryGetDatagram(out S7AlarmIndicationDatagram datagram) 23 | { 24 | return _alarms.TryDequeue(out datagram); 25 | } 26 | 27 | internal void AddDatagram(S7AlarmIndicationDatagram datagram) 28 | { 29 | _alarms.Enqueue(datagram); 30 | CallbackHandler.Event.Set(datagram); // set but ignore the datagram in code 31 | } 32 | 33 | protected virtual void Dispose(bool disposing) 34 | { 35 | if (!_disposedValue) 36 | { 37 | if (disposing) 38 | { 39 | _ = ProtocolHandler.RemoveAlarmSubscriptionAsync(this); 40 | while (_alarms.TryDequeue(out _)) 41 | { 42 | ; // clear the queue 43 | } 44 | } 45 | 46 | _disposedValue = true; 47 | } 48 | } 49 | 50 | public void Dispose() 51 | { 52 | // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method 53 | Dispose(disposing: true); 54 | GC.SuppressFinalize(this); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/AlarmUpdateResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace Dacs7.Alarms 9 | { 10 | public class AlarmUpdateResult : IDisposable 11 | { 12 | private readonly Func _closeAction; 13 | private bool _disposed; 14 | 15 | public AlarmUpdateResult(bool channelCompleted, Func closeAction) : this(channelCompleted, null, closeAction) 16 | { 17 | ChannelClosed = channelCompleted; 18 | } 19 | 20 | public AlarmUpdateResult(bool channelCompleted, IEnumerable alarms, Func closeAction) 21 | { 22 | ChannelClosed = channelCompleted; 23 | Alarms = alarms; 24 | _closeAction = closeAction; 25 | } 26 | 27 | public bool HasAlarms => Alarms != null; 28 | public IEnumerable Alarms { get; } 29 | public bool ChannelClosed { get; } 30 | 31 | [Obsolete("This method is obsolet if you use the alarm subscription.")] 32 | public Task CloseUpdateChannel() 33 | { 34 | return _closeAction?.Invoke(); 35 | } 36 | 37 | public void Dispose() 38 | { 39 | Dispose(true); 40 | GC.SuppressFinalize(this); 41 | } 42 | 43 | protected virtual void Dispose(bool disposing) 44 | { 45 | if (_disposed) 46 | { 47 | return; 48 | } 49 | 50 | if (disposing) 51 | { 52 | CloseUpdateChannel().ConfigureAwait(false) 53 | .GetAwaiter() 54 | .GetResult(); 55 | } 56 | 57 | _disposed = true; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Alarms/AlarmMessageType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Alarms 5 | { 6 | public enum AlarmMessageType 7 | { 8 | Unknown = 0, 9 | AlarmAck = 12, 10 | AlarmSQ = 17, 11 | AlarmS = 18 12 | } 13 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Alarms/IPlcAlarm.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Alarms 6 | { 7 | 8 | /// 9 | /// Represent a alarm of the alarm interface of Step7 10 | /// 11 | public interface IPlcAlarm 12 | { 13 | byte Length { get; } 14 | ushort TransportSize { get; } 15 | AlarmMessageType AlarmType { get; } 16 | uint MsgNumber { get; } 17 | ushort Id { get; } 18 | ushort Unknown2 { get; } 19 | 20 | 21 | byte EventState { get; } 22 | 23 | byte State { get; set; } 24 | 25 | byte AckStateGoing { get; } 26 | 27 | byte AckStateComing { get; } 28 | 29 | 30 | IPlcAlarmDetails Coming { get; } 31 | IPlcAlarmDetails Going { get; } 32 | 33 | 34 | bool IsAck { get; } 35 | bool IsGoing { get; } 36 | bool IsComing { get; } 37 | } 38 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Alarms/IPlcAlarmAssotiatedValue.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Alarms 7 | { 8 | public interface IPlcAlarmAssotiatedValue 9 | { 10 | int Length { get; } 11 | Memory Data { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Alarms/IPlcAlarmDetails.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Alarms 7 | { 8 | public interface IPlcAlarmDetails 9 | { 10 | DateTime Timestamp { get; } 11 | IPlcAlarmAssotiatedValue AssotiatedValues { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Blocks/IBlocksCount.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Metadata 6 | { 7 | public interface IPlcBlocksCount 8 | { 9 | int Ob { get; } 10 | int Fb { get; } 11 | int Fc { get; } 12 | int Sfb { get; } 13 | int Sfc { get; } 14 | int Db { get; } 15 | int Sdb { get; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Blocks/IPlcBlockInfo.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | using System; 6 | 7 | namespace Dacs7.Metadata 8 | { 9 | public interface IPlcBlockInfo 10 | { 11 | 12 | PlcBlockAttributes BlockFlags { get; } 13 | PlcBlockLanguage BlockLanguage { get; } 14 | PlcSubBlockType SubBlockType { get; } 15 | ushort BlockNumber { get; } 16 | uint LengthLoadMemory { get; } 17 | uint BlockSecurity { get; } 18 | 19 | DateTime LastCodeChange { get; } 20 | DateTime LastInterfaceChange { get; } 21 | 22 | 23 | ushort SSBLength { get; } 24 | ushort ADDLength { get; } 25 | 26 | ushort LocalDataSize { get; } 27 | ushort CodeSize { get; } 28 | 29 | 30 | string Author { get; } 31 | string Family { get; } 32 | string Name { get; } 33 | 34 | 35 | int VersionHeaderMajor { get; } 36 | int VersionHeaderMinor { get; } 37 | 38 | 39 | 40 | ushort Checksum { get; } 41 | 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Blocks/IPlcBlocks.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Metadata 6 | { 7 | 8 | public interface IPlcBlock 9 | { 10 | int Number { get; } 11 | byte Flags { get; } 12 | string Language { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Control/PlcStates.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Control 7 | { 8 | public enum PlcStates 9 | { 10 | Unknown = 0x00, 11 | Stop = 0x04, 12 | Run = 0x08 13 | } 14 | 15 | 16 | public class PlcStateInfo 17 | { 18 | /// 19 | /// Current state of the plc 20 | /// 21 | public PlcStates State { get; internal set; } 22 | 23 | /// 24 | /// Previous State of the plc 25 | /// 26 | public PlcStates PreviousState { get; internal set; } 27 | 28 | /// 29 | /// timestamp is only valid if PreviousState is not unknown 30 | /// 31 | public DateTime Timestamp { get; internal set; } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Converters/Helpers.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace Dacs7.Domain 8 | { 9 | internal static class ConvertHelpers 10 | { 11 | public static Memory WriteSingleBigEndian(float value, byte[] buffer = null, int offset = 0) 12 | { 13 | byte[] rawdata = buffer ?? new byte[Marshal.SizeOf(value)]; 14 | GCHandle handle = GCHandle.Alloc(rawdata, GCHandleType.Pinned); 15 | Marshal.StructureToPtr(value, handle.AddrOfPinnedObject() + offset, false); 16 | handle.Free(); 17 | Swap4BytesInBuffer(rawdata, offset); 18 | return rawdata; 19 | } 20 | 21 | public static byte[] Swap4BytesInBuffer(byte[] rawdata, int offset = 0) 22 | { 23 | byte b = rawdata[offset]; 24 | rawdata[offset] = rawdata[offset + 3]; 25 | rawdata[offset + 3] = b; 26 | b = rawdata[offset + 1]; 27 | rawdata[offset + 1] = rawdata[offset + 2]; 28 | rawdata[offset + 2] = b; 29 | return rawdata; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Dacs7ConnectionState.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7 6 | { 7 | public enum Dacs7ConnectionState 8 | { 9 | Closed, 10 | Connecting, 11 | Opened 12 | 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/DataTransportSize.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | 7 | public enum DataTransportSize 8 | { 9 | Null = 0, 10 | Bit = 3, //bit access, length is in bits 11 | Byte = 4, //byte/word/dword access, length is in bits 12 | Int = 5, //integer access, length is in bits 13 | Dint = 6, //integer access, length is in bytes 14 | Real = 7, //real access, length is in bytes 15 | OctetString = 9 //octet string, length is in bytes 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/DataValue.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Domain; 5 | using Dacs7.Protocols.SiemensPlc; 6 | using System; 7 | 8 | namespace Dacs7 9 | { 10 | public class DataValue 11 | { 12 | private readonly ReadItem _meta; 13 | private object _value; 14 | 15 | 16 | public ItemResponseRetValue ReturnCode { get; } 17 | 18 | public bool IsSuccessReturnCode => ReturnCode == ItemResponseRetValue.Success; 19 | 20 | public Type Type => _meta.ResultType; 21 | public Memory Data { get; } 22 | 23 | /// 24 | /// The value as an object. 25 | /// 26 | public object Value => _value ??= _meta.ConvertMemoryToData(Data); 27 | 28 | 29 | /// 30 | /// Get the value converted to the generic type. 31 | /// In this method there is also an validation included 32 | /// 33 | /// expected result type 34 | /// 35 | public T GetValue() 36 | { 37 | Type expected = typeof(T); 38 | if (expected != _meta.ResultType) 39 | { 40 | ThrowHelper.ThrowTypesNotMatching(expected, _meta.ResultType); 41 | } 42 | return (T)Value; 43 | } 44 | 45 | internal DataValue(ReadItem meta, S7DataItemSpecification data) 46 | { 47 | _meta = meta; 48 | ReturnCode = (ItemResponseRetValue)data.ReturnCode; 49 | Data = data.Data; 50 | } 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/DataValueFormatterExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System.Collections; 5 | using System.Text; 6 | 7 | namespace Dacs7 8 | { 9 | 10 | public delegate string DataValueFormatter(object value, string formattedValue); 11 | 12 | 13 | public static class DataValueFormatterExtensions 14 | { 15 | 16 | public static string GetValueAsString(this DataValue dataValue, string separator = " ") 17 | { 18 | return GetValueAsString(dataValue, null, separator); 19 | } 20 | 21 | public static string GetValueAsString(this DataValue dataValue, DataValueFormatter formatter, string separator = " ") 22 | { 23 | string result = FormattedResult(dataValue, separator); 24 | return formatter != null ? formatter(dataValue.Value, result) : result; 25 | } 26 | 27 | private static string FormattedResult(DataValue dataValue, string seperator) 28 | { 29 | if (dataValue.Type.IsArray) 30 | { 31 | if (seperator == null) 32 | { 33 | seperator = string.Empty; 34 | } 35 | 36 | StringBuilder result = new(); 37 | IEnumerable enumerable = dataValue.Value as IEnumerable; 38 | foreach (object item in enumerable) 39 | { 40 | result.Append(item.ToString()); 41 | result.Append(seperator); 42 | } 43 | return result.Length > 0 ? result.ToString(0, result.Length - seperator.Length) : string.Empty; 44 | } 45 | return dataValue.Value.ToString(); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ErrorClass.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Helper; 5 | 6 | namespace Dacs7 7 | { 8 | public enum ErrorClass : byte 9 | { 10 | [Description("No error")] 11 | None = 0x00, 12 | 13 | [Description("Application relationship")] 14 | ApplicationRelationship = 0x81, 15 | 16 | [Description("Object definition")] 17 | ObjectDefinition = 0x82, 18 | 19 | [Description("No resources available")] 20 | Resources = 0x83, 21 | 22 | [Description("Error on service processing")] 23 | Service = 0x84, 24 | 25 | [Description("Error on supplies")] 26 | Supplies = 0x85, 27 | 28 | [Description("Access error")] 29 | Access = 0x87 30 | } 31 | 32 | 33 | 34 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ErrorHandling.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Helper; 5 | using System; 6 | using System.Globalization; 7 | 8 | namespace Dacs7 9 | { 10 | public static class ErrorHandling 11 | { 12 | 13 | public static string ResolveErrorCode(byte b) where T : struct 14 | { 15 | return Enum.IsDefined(typeof(T), b) ? ResolveErrorCode(Enum.GetName(typeof(T), b)) : b.ToString(CultureInfo.InvariantCulture); 16 | } 17 | 18 | public static string ResolveErrorCode(ushort sh) where T : struct 19 | { 20 | return Enum.IsDefined(typeof(T), sh) ? ResolveErrorCode(Enum.GetName(typeof(T), sh)) : sh.ToString(CultureInfo.InvariantCulture); 21 | } 22 | 23 | public static string ResolveErrorCode(string s) where T : struct 24 | { 25 | if (Enum.TryParse(s, out T result)) 26 | { 27 | string r = GetEnumDescription(result); 28 | if (!r.IsNullOrEmpty()) 29 | { 30 | return r; 31 | } 32 | } 33 | return s; 34 | } 35 | 36 | public static string GetEnumDescription(object e) 37 | { 38 | System.Reflection.FieldInfo fieldInfo = e.GetType().GetField(e.ToString()); 39 | if (fieldInfo != null) 40 | { 41 | if (fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false) is DescriptionAttribute[] enumAttributes && enumAttributes.Length > 0) 42 | { 43 | return enumAttributes[0].Description; 44 | } 45 | } 46 | return e.ToString(); 47 | } 48 | 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/FunctionCodes.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | 7 | internal enum FunctionCode : byte 8 | { 9 | Cpu = 0x00, //CPU service 10 | SetupComm = 0xF0, //Setup communication 11 | ReadVar = 0x04, //Read Var 12 | WriteVar = 0x05, //Write var 13 | 14 | RequestDownload = 0x1A, //Request download 15 | DownloadBlock = 0x1B, //Download block 16 | DownloadEnded = 0x1C, //Download ended 17 | StartUpload = 0x1D, //Start upload 18 | Upload = 0x1E, //Upload 19 | EndUpload = 0x1F, //End upload 20 | PlcControl = 0x28, //PLC Control 21 | PlcStop = 0x29 //PLC Stop 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/ItemDataTransportSize.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | public enum ItemDataTransportSize 7 | { 8 | //types of 1 byte length 9 | Bit = 1, 10 | Byte = 2, 11 | Char = 3, 12 | //types of 2 bytes length 13 | Word = 4, 14 | Int = 5, 15 | //types of 4 bytes length 16 | Dword = 6, 17 | Dint = 7, 18 | Real = 8, 19 | //Special types 20 | Date = 9, 21 | Tod = 10, 22 | Time = 11, 23 | S5Time = 12, 24 | Dt = 15, 25 | //Timer or counter 26 | Counter = 28, 27 | Timer = 29, 28 | IecCounter = 30, 29 | IecTimer = 31, 30 | HsCounter = 32 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/ItemSyntaxId.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | internal enum ItemSyntaxId : byte 7 | { 8 | S7Any = 0x10, // Address data S7-Any pointer-like DB1.DBX10.2 9 | DriveEsAny = 0xa2, // seen on Drive ES Starter with routing over S7 10 | Sym1200 = 0xb2, // Symbolic address mode of S7-1200 11 | DbRead = 0xb0, // Kind of DB block read, seen only at an S7-400 12 | Nck = 0x82, // Sinumerik NCK HMI access 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/PduType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | internal enum PduType : byte 7 | { 8 | Job = 0x01, 9 | Ack = 0x02, 10 | AckData = 0x03, 11 | UserData = 0x07 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataFunctionGroup.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataFunctionGroup : byte 8 | { 9 | Prog = 0x1, 10 | Cyclic = 0x2, 11 | Block = 0x3, 12 | Cpu = 0x4, 13 | Sec = 0x5, //Security functions e.g. plc password 14 | Time = 0x7 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataFunctionGroups.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | 8 | internal enum UserDataFunctionGroups : byte 9 | { 10 | Read = 0x1, //Read clock 11 | Set = 0x2, //Set clock 12 | ReadDf = 0x3, //Read clock (following) 13 | Set2 = 0x4, //Set clock 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataFunctionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | internal enum UserDataFunctionType : byte 7 | { 8 | Request = 0x04, 9 | Response = 0x08 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataParamTypeType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataParamTypeType : byte 8 | { 9 | Request = 0x11, 10 | Response = 0x12 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataSubFunctionBlock.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataSubFunctionBlock : byte 8 | { 9 | List = 0x01, //List blocks 10 | ListType = 0x02, // List blocks of type 11 | BlockInfo = 0x03 //Get block info 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataSubFunctionCpu.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataSubFunctionCpu : byte 8 | { 9 | ReadSsl = 0x01, //"Read SZL" 10 | Msgs = 0x02, //"Message service" Header constant is also different here 11 | TransStop = 0x03, //"Transition to STOP" //PLC changed state to STOP 12 | AlarmSQInd = 0x11, 13 | AlarmInd = 0x12, //"ALARM indication" //PLC is indicating a ALARM message 14 | AlarmInit = 0x13, //"ALARM initiate" //HMI/SCADA initiating ALARM subscription 15 | AlarmAck1 = 0x0b, //"ALARM ack 1" //Alarm was acknowledged in HMI/SCADA 16 | AlarmAck2 = 0x0c, //"ALARM ack 2" //Alarm was acknowledged in HMI/SCADA 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataSubFunctionCyclic.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataSubFunctionCyclic : byte 8 | { 9 | Mem = 0x01, //"Memory" //read data from memory (DB/M/etc.) 10 | Unsubscribe = 0x04, //"unsubscribe" //unsubcribe (disable) cyclic data 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataSubFunctionProg.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataSubFunctionProg : byte 8 | { 9 | Reqdiagdata1 = 0x01, // Request diag data (Type 1) //Start online block view 10 | Vartab1 = 0x02, // VarTab //Variable table 11 | Erase = 0x0c, // Read diag data //online block view 12 | Readdiagdata = 0x0e, // Remove diag data //Stop online block view 13 | Removediagdata = 0x0f, // Erase" 14 | Force = 0x10, // Forces 15 | Reqdiagdata2 = 0x13 // Request diag data (Type 2) //Start online block view 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Internal/UserDataSubFunctionSecurity.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Domain 6 | { 7 | internal enum UserDataSubFunctionSecurity : byte 8 | { 9 | Password = 0x1, //PLC password 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ItemExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public static class ItemExtensions 9 | { 10 | 11 | public static WriteItem From(this ReadItem ri, Memory data) 12 | { 13 | WriteItem result = ri.Clone(); 14 | result.Data = data; 15 | return result; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ItemResponseRetValue.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Helper; 5 | 6 | namespace Dacs7 7 | { 8 | public enum ItemResponseRetValue : byte 9 | { 10 | Reserved = 0x00, 11 | [Description("Hardware error")] 12 | HardwareFault = 0x01, 13 | 14 | [Description("Accessing the object not allowed")] 15 | AccessFault = 0x03, 16 | 17 | [Description("Invalid address")] 18 | OutOfRange = 0x05, //the desired address is beyond limit for this PLC 19 | 20 | [Description("Data type not supported")] 21 | NotSupported = 0x06, //Type is not supported 22 | 23 | [Description("Data type inconsistent")] 24 | SizeMismatch = 0x07, //Data type inconsistent 25 | 26 | [Description("Object does not exist")] 27 | DataError = 0x0a, //the desired item is not available in the PLC, e.g. when trying to read a non existing DB 28 | 29 | [Description("Success")] 30 | Success = 0xFF, 31 | } 32 | 33 | 34 | 35 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/BlockSecurity.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Metadata 5 | { 6 | public enum BlockSecurity 7 | { 8 | Off = 0, 9 | KnowHowProtected = 3 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcBlockAttributes.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Metadata 7 | { 8 | [Flags] 9 | public enum PlcBlockAttributes : byte 10 | { 11 | None = 0, 12 | Linked = 1, 13 | StandardBlock = 2, 14 | KnowHowProtected = 4, 15 | NotRetain = 6 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcBlockLanguage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Metadata 5 | { 6 | public enum PlcBlockLanguage : byte 7 | { 8 | Undefined = 0x00, 9 | Awl = 0x01, 10 | Kop = 0x02, 11 | Fup = 0x03, 12 | Scl = 0x04, 13 | Db = 0x05, 14 | Graph = 0x06, 15 | Sdb = 0x07, 16 | CpuDb = 0x08, // DB was created from Plc program (CREAT_DB) 17 | SdbAOR = 0x11,// another SDB, don't know what it means, in SDB 1 and SDB 2, uncertain 18 | RoutingSdb = 0x12, // another SDB, in SDB 999 and SDB 1000 (routing information), uncertain 19 | Encrypted = 0x29 // block is encrypted with S7-Block-Privacy 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcBlockType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Metadata 5 | { 6 | public enum PlcBlockType : byte 7 | { 8 | Ob = 0x38, 9 | Db = 0x41, 10 | Sdb = 0x42, 11 | Fc = 0x43, 12 | Sfc = 0x44, 13 | Fb = 0x45, 14 | Sfb = 0x46 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcBlocks.cs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | namespace Dacs7.Metadata 5 | { 6 | internal sealed class PlcBlock : IPlcBlock 7 | { 8 | public int Number { get; set; } 9 | public byte Flags { get; set; } 10 | public string Language { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcBlocksCount.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | 5 | namespace Dacs7.Metadata 6 | { 7 | internal sealed class PlcBlocksCount : IPlcBlocksCount 8 | { 9 | public int Ob { get; set; } 10 | public int Fb { get; set; } 11 | public int Fc { get; set; } 12 | public int Sfb { get; set; } 13 | public int Sfc { get; set; } 14 | public int Db { get; set; } 15 | public int Sdb { get; set; } 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/Metadata/PlcSubBlockType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Metadata 5 | { 6 | public enum PlcSubBlockType : byte 7 | { 8 | Ob = 0x08, 9 | Db = 0x0a, 10 | Sdb = 0x0b, 11 | Fc = 0x0c, 12 | Sfc = 0x0d, 13 | Fb = 0x0e, 14 | Sfb = 0x0f 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/PlcArea.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7 5 | { 6 | public enum PlcArea : byte 7 | { 8 | SI = 0x03, //System info of 200 family 9 | SF = 0x05, //System flags of 200 family 10 | AI = 0x06, //analog inputs of 200 family 11 | AQ = 0x07, //analog outputs of 200 family 12 | DP = 0x80, //direct peripheral access 13 | IB = 0x81, //InputByte 14 | QB = 0x82, //OutputByte 15 | FB = 0x83, //FlagByte 16 | DB = 0x84, //Data Block 17 | DI = 0x85, //instance data blocks 18 | LO = 0x86, //local data (should not be accessible over network) 19 | PR = 0x87, //previous local data (should not be accessible over network) 20 | CT = 0x1C, //S7 counters 21 | TM = 0x1D, //S7 timers 22 | CI = 0x1E, //IEC counters (200 family) 23 | TI = 0x1F //IEC timers (200 family) 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/PlcConnectionType.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7 5 | { 6 | public enum PlcConnectionType : ushort 7 | { 8 | Pg = 0x01, 9 | Op = 0x02, 10 | Basic = 0x03 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/PlcDataEntry.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | 4 | namespace Dacs7.Domain 5 | { 6 | internal class PlcDataEntry : IDisposable 7 | { 8 | private readonly IMemoryOwner _owner; 9 | private readonly Memory _externalData; 10 | 11 | 12 | public PlcDataEntry(PlcArea area, ushort dbNumber, ushort length, Memory data = default) 13 | { 14 | Area = area; 15 | DbNumber = dbNumber; 16 | Length = length; 17 | if (!data.IsEmpty) 18 | { 19 | _externalData = data; 20 | } 21 | else 22 | { 23 | _owner = MemoryPool.Shared.Rent(length); 24 | } 25 | } 26 | 27 | public PlcArea Area { get; private set; } 28 | public ushort DbNumber { get; private set; } 29 | public ushort Length { get; private set; } 30 | 31 | 32 | public Memory Data => _owner == null ? _externalData : _owner.Memory; 33 | 34 | public void Dispose() 35 | { 36 | _owner?.Dispose(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/PlcEncoding.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7 5 | { 6 | public enum PlcEncoding 7 | { 8 | UTF7, 9 | Unicode, 10 | Windows1252 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ReadRequestItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Domain; 5 | using System; 6 | 7 | namespace Dacs7 8 | { 9 | public class ReadRequestItem : RequestItem 10 | { 11 | public ReadRequestItem(PlcArea area, ushort dbNumber, ushort numberOfItems, int offset, ItemDataTransportSize transportSize, Memory address) 12 | : base(area, dbNumber, numberOfItems, offset, transportSize, address) 13 | { 14 | } 15 | 16 | internal ReadRequestItem(PlcArea area, ushort dbNumber, ushort numberOfItems, int offset, DataTransportSize transportSize, ushort elementSize, Memory address) 17 | : base(area, dbNumber, numberOfItems, offset, transportSize, elementSize, address) 18 | { 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/ReadResultItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | 9 | public class ReadResultItem : ReadRequestItem 10 | { 11 | 12 | public ItemResponseRetValue ReturnCode { get; private set; } 13 | public Memory Data { get; private set; } 14 | 15 | public ReadResultItem(ReadRequestItem req, ItemResponseRetValue returnCode, Memory data = default) : base(req.Area, req.DbNumber, req.NumberOfItems, req.Offset, req.TransportSize, req.ElementSize, req.Address) 16 | { 17 | ReturnCode = returnCode; 18 | Data = data; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/TagParserState.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Domain 5 | { 6 | public enum TagParserState 7 | { 8 | Nothing, 9 | Area, 10 | Offset, 11 | Type, 12 | NumberOfItems, 13 | TypeValidation, 14 | Success 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/WriteRequestItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Domain; 5 | using System; 6 | 7 | namespace Dacs7 8 | { 9 | public class WriteRequestItem : RequestItem 10 | { 11 | public Memory Data { get; private set; } 12 | 13 | public WriteRequestItem(PlcArea area, ushort dbNumber, ushort numberOfItems, int offset, ItemDataTransportSize transportSize, Memory address, Memory data) 14 | : base(area, dbNumber, numberOfItems, offset, transportSize, address) 15 | { 16 | Data = data; 17 | } 18 | 19 | internal WriteRequestItem(PlcArea area, ushort dbNumber, ushort numberOfItems, int offset, DataTransportSize transportSize, ushort elementSize, Memory address, Memory data) 20 | : base(area, dbNumber, numberOfItems, offset, transportSize, elementSize, address) 21 | { 22 | Data = data; 23 | } 24 | 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Domain/WriteResultItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7 5 | { 6 | 7 | public class WriteResultItem : WriteRequestItem 8 | { 9 | public ItemResponseRetValue ReturnCode { get; private set; } 10 | 11 | public WriteResultItem(WriteRequestItem req, ItemResponseRetValue returnCode) : base(req.Area, req.DbNumber, req.NumberOfItems, req.Offset, req.TransportSize, req.ElementSize, req.Address, req.Data) 12 | { 13 | ReturnCode = returnCode; 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7ContentException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public class Dacs7ContentException : Exception 9 | { 10 | public int ErrorIndex { get; private set; } 11 | public ItemResponseRetValue ErrorCode { get; private set; } 12 | 13 | public Dacs7ContentException() 14 | { 15 | } 16 | 17 | public Dacs7ContentException(string message) : base(message) 18 | { 19 | } 20 | 21 | public Dacs7ContentException(string message, Exception innerException) : base(message, innerException) 22 | { 23 | } 24 | 25 | public Dacs7ContentException(byte errorCode, int itemIndex) : 26 | this($"No success return code from item {itemIndex}: <{Dacs7Exception.ResolveErrorCode(errorCode)}>") 27 | { 28 | ErrorCode = (ItemResponseRetValue)errorCode; 29 | ErrorIndex = itemIndex; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7NotConnectedException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public class Dacs7NotConnectedException : Exception 9 | { 10 | 11 | public Dacs7NotConnectedException() : 12 | base("Dacs7 has no connection to the plc!") 13 | { 14 | } 15 | 16 | public Dacs7NotConnectedException(Exception ex) : 17 | base("Dacs7 has no connection to the plc!", ex) 18 | { 19 | } 20 | 21 | public Dacs7NotConnectedException(string message) : base(message) 22 | { 23 | } 24 | 25 | public Dacs7NotConnectedException(string message, Exception innerException) : base(message, innerException) 26 | { 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7ParameterException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | using System.Security.Permissions; 7 | 8 | namespace Dacs7 9 | { 10 | [Serializable] 11 | public class Dacs7ParameterException : Exception, ISerializable 12 | { 13 | public ErrorParameter ErrorCode { get; private set; } 14 | 15 | public Dacs7ParameterException(ushort errorCode) : 16 | base($"No success error code: <{Dacs7Exception.ResolveErrorCode(errorCode)}>") 17 | { 18 | ErrorCode = (ErrorParameter)errorCode; 19 | } 20 | 21 | public Dacs7ParameterException() 22 | { 23 | } 24 | 25 | public Dacs7ParameterException(string message) : base(message) 26 | { 27 | } 28 | 29 | public Dacs7ParameterException(string message, Exception innerException) : base(message, innerException) 30 | { 31 | } 32 | 33 | protected Dacs7ParameterException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) 34 | { 35 | ErrorCode = (ErrorParameter)serializationInfo.GetValue("ErrorCode", typeof(ErrorParameter)); 36 | } 37 | 38 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 39 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 40 | { 41 | base.GetObjectData(info, context); 42 | info.AddValue("ErrorCode", ErrorCode); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7ReadTimeoutException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public class Dacs7ReadTimeoutException : Exception 9 | { 10 | public Dacs7ReadTimeoutException(ushort id) : base($"Read operation timeout for job {id}") 11 | { 12 | } 13 | 14 | public Dacs7ReadTimeoutException() 15 | { 16 | } 17 | 18 | public Dacs7ReadTimeoutException(string message) : base(message) 19 | { 20 | } 21 | 22 | public Dacs7ReadTimeoutException(string message, Exception innerException) : base(message, innerException) 23 | { 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7ReturnCodeException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | using System.Security.Permissions; 7 | 8 | namespace Dacs7 9 | { 10 | [Serializable] 11 | public class Dacs7ReturnCodeException : Exception, ISerializable 12 | { 13 | public byte ReturnCode { get; private set; } 14 | public int ItemNumber { get; set; } 15 | 16 | public Dacs7ReturnCodeException(byte returnCode, int itemNumber = -1) : 17 | base($"No success return code {returnCode}: <{(itemNumber != -1 ? ($" for item {itemNumber}") : "")}>") 18 | { 19 | ReturnCode = returnCode; 20 | } 21 | 22 | public Dacs7ReturnCodeException() 23 | { 24 | } 25 | 26 | public Dacs7ReturnCodeException(string message) : base(message) 27 | { 28 | } 29 | 30 | public Dacs7ReturnCodeException(string message, Exception innerException) : base(message, innerException) 31 | { 32 | } 33 | 34 | protected Dacs7ReturnCodeException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) 35 | { 36 | ReturnCode = (byte)serializationInfo.GetValue("ReturnCode", typeof(byte)); 37 | ItemNumber = (int)serializationInfo.GetValue("ItemNumber", typeof(int)); 38 | } 39 | 40 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 41 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 42 | { 43 | base.GetObjectData(info, context); 44 | info.AddValue("ReturnCode", ReturnCode); 45 | info.AddValue("ItemNumber", ItemNumber); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7TagParserException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Domain; 5 | using System; 6 | using System.Runtime.Serialization; 7 | using System.Security.Permissions; 8 | 9 | namespace Dacs7 10 | { 11 | [Serializable] 12 | public class Dacs7TagParserException : Exception, ISerializable 13 | { 14 | private readonly TagParserState _parseArea; 15 | 16 | public string Tag { get; private set; } 17 | public string ParseData { get; private set; } 18 | 19 | internal Dacs7TagParserException(TagParserState parseArea, string area, string tag) : 20 | base($"Could not extract {Enum.GetName(typeof(TagParserState), parseArea)} from data '{area}'. Full tag was '{tag}'.") 21 | { 22 | _parseArea = parseArea; 23 | ParseData = area; 24 | Tag = tag; 25 | } 26 | 27 | protected Dacs7TagParserException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) 28 | { 29 | _parseArea = (TagParserState)serializationInfo.GetValue("_parseArea", typeof(TagParserState)); 30 | Tag = (string)serializationInfo.GetValue("Tag", typeof(string)); 31 | ParseData = (string)serializationInfo.GetValue("ParseData", typeof(string)); 32 | } 33 | 34 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 35 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 36 | { 37 | base.GetObjectData(info, context); 38 | info.AddValue("_parseArea", _parseArea); 39 | info.AddValue("Tag", Tag); 40 | info.AddValue("ParseData", ParseData); 41 | } 42 | 43 | public Dacs7TagParserException() 44 | { 45 | } 46 | 47 | public Dacs7TagParserException(string message) : base(message) 48 | { 49 | } 50 | 51 | public Dacs7TagParserException(string message, Exception innerException) : base(message, innerException) 52 | { 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7ToMuchDataPerCallException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public class Dacs7ToMuchDataPerCallException : Exception 9 | { 10 | public Dacs7ToMuchDataPerCallException(int expected, int actual) : 11 | base($"There is too much data ({actual} bytes) for a single job, please split jobs to a maximum of {expected} bytes per call!") 12 | { 13 | } 14 | 15 | public Dacs7ToMuchDataPerCallException() 16 | { 17 | } 18 | 19 | public Dacs7ToMuchDataPerCallException(string message) : base(message) 20 | { 21 | } 22 | 23 | public Dacs7ToMuchDataPerCallException(string message, Exception innerException) : base(message, innerException) 24 | { 25 | } 26 | 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7TypeNotSupportedException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Runtime.Serialization; 6 | using System.Security.Permissions; 7 | 8 | namespace Dacs7 9 | { 10 | [Serializable] 11 | public class Dacs7TypeNotSupportedException : Exception, ISerializable 12 | { 13 | public Type NotSupportedType { get; private set; } 14 | 15 | public Dacs7TypeNotSupportedException(Type notSupportedType) : base($"The Type {notSupportedType.Name} is not supported for read or write operations!") 16 | { 17 | NotSupportedType = notSupportedType; 18 | } 19 | 20 | public Dacs7TypeNotSupportedException() 21 | { 22 | } 23 | 24 | public Dacs7TypeNotSupportedException(string message) : base(message) 25 | { 26 | } 27 | 28 | public Dacs7TypeNotSupportedException(string message, Exception innerException) : base(message, innerException) 29 | { 30 | } 31 | 32 | protected Dacs7TypeNotSupportedException(SerializationInfo serializationInfo, StreamingContext streamingContext) : base(serializationInfo, streamingContext) 33 | { 34 | NotSupportedType = (Type)serializationInfo.GetValue("NotSupportedType", typeof(Type)); 35 | } 36 | 37 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 38 | void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) 39 | { 40 | base.GetObjectData(info, context); 41 | info.AddValue("NotSupportedType", NotSupportedType); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Exceptions/Dacs7WriteTimeoutException.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7 7 | { 8 | public class Dacs7WriteTimeoutException : Exception 9 | { 10 | public Dacs7WriteTimeoutException(ushort id) : base($"Write operation timeout for job {id}") 11 | { 12 | } 13 | 14 | public Dacs7WriteTimeoutException() 15 | { 16 | } 17 | 18 | public Dacs7WriteTimeoutException(string message) : base(message) 19 | { 20 | } 21 | 22 | public Dacs7WriteTimeoutException(string message, Exception innerException) : base(message, innerException) 23 | { 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/GlobalSuppressions.cs: -------------------------------------------------------------------------------- 1 |  2 | // This file is used by Code Analysis to maintain SuppressMessage 3 | // attributes that are applied to this project. 4 | // Project-level suppressions either have no target or are given 5 | // a specific target and scoped to a namespace, type, member, etc. 6 | 7 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.Metadata.PlcBlockAttributes")] 8 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.Metadata.PlcBlockLanguage")] 9 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.Metadata.PlcBlockType")] 10 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.Metadata.PlcSubBlockType")] 11 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.PlcArea")] 12 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.PlcConnectionType")] 13 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.ItemResponseRetValue")] 14 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.ErrorClass")] 15 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "CA1028:Enum Storage should be Int32", Justification = "", Scope = "type", Target = "~T:Dacs7.ErrorParameter")] 16 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1720:Identifier contains type name", Justification = "", Scope = "type", Target = "~T:Dacs7.Domain.DataTransportSize")] 17 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1721:Property names should not match get methods", Justification = "", Scope = "member", Target = "~P:Dacs7.DataValue.Value")] 18 | 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Helper/CollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Collections; 6 | using System.Collections.Generic; 7 | using System.ComponentModel; 8 | 9 | namespace Dacs7.Helper 10 | { 11 | [EditorBrowsable(EditorBrowsableState.Never)] 12 | public static class CollectionExtensions 13 | { 14 | //public static TResult[] ConvertAll(this T[] items, Converter transformation) 15 | //{ 16 | // return Array.ConvertAll(items, transformation); 17 | //} 18 | public static void ForEach(this IEnumerable items, Action action) 19 | { 20 | if (items == null) 21 | { 22 | return; 23 | } 24 | foreach (T current in items) 25 | { 26 | action(current); 27 | } 28 | } 29 | public static T Find(this T[] items, Predicate predicate) 30 | { 31 | return Array.Find(items, predicate); 32 | } 33 | 34 | public static T[] FindAll(this T[] items, Predicate predicate) 35 | { 36 | return Array.FindAll(items, predicate); 37 | } 38 | 39 | /// 40 | /// Checks whether or not collection is null or empty. Assumes collection can be safely enumerated multiple times. 41 | /// 42 | /// 43 | /// 44 | public static bool IsNullOrEmpty(this IEnumerable @this) 45 | { 46 | return @this == null || !@this.GetEnumerator().MoveNext(); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Helper/InternalExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System.Collections.Generic; 5 | 6 | namespace Dacs7 7 | { 8 | internal static class InternalExtensions 9 | { 10 | 11 | /// 12 | /// Removes an element from the middle of a queue without disrupting the other elements. 13 | /// 14 | /// The element to remove. 15 | /// The queue to modify. 16 | /// The value to remove. 17 | /// 18 | /// If a value appears multiple times in the queue, only its first entry is removed. 19 | /// 20 | internal static bool RemoveMidQueue(this Queue queue, TQueue valueToRemove) where TQueue : class 21 | { 22 | int originalCount = queue.Count; 23 | int dequeueCounter = 0; 24 | bool found = false; 25 | while (dequeueCounter < originalCount) 26 | { 27 | dequeueCounter++; 28 | TQueue dequeued = queue.Dequeue(); 29 | if (!found && dequeued == valueToRemove) 30 | { 31 | // only find 1 match 32 | found = true; 33 | } 34 | else 35 | { 36 | queue.Enqueue(dequeued); 37 | } 38 | } 39 | 40 | return found; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Helper/SemaphoreGuard.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace Dacs7.Helper 9 | { 10 | internal sealed class SemaphoreGuard : IDisposable 11 | { 12 | private SemaphoreSlim _semaphore; 13 | private bool IsDisposed => _semaphore == null; 14 | public SemaphoreGuard(SemaphoreSlim semaphore, bool wait = true) 15 | { 16 | _semaphore = semaphore; 17 | if (wait) 18 | { 19 | _semaphore.Wait(); 20 | } 21 | } 22 | 23 | public static async ValueTask Async(SemaphoreSlim semaphore) 24 | { 25 | if (semaphore == null) 26 | { 27 | ThrowArgumnetNullException(nameof(semaphore)); 28 | return null!; 29 | } 30 | SemaphoreGuard guard = new(semaphore, false); 31 | 32 | // try to grab it sync because it's faster 33 | if (!semaphore.Wait(0)) 34 | { 35 | await semaphore.WaitAsync().ConfigureAwait(false); 36 | } 37 | 38 | return guard; 39 | } 40 | 41 | public void Dispose() 42 | { 43 | if (IsDisposed) 44 | { 45 | ThrowObjectDisposedException(this); 46 | } 47 | 48 | _semaphore.Release(); 49 | _semaphore = null; 50 | } 51 | 52 | private static void ThrowObjectDisposedException(SemaphoreGuard guard) 53 | { 54 | throw new ObjectDisposedException(guard.ToString()); 55 | } 56 | 57 | private static void ThrowArgumnetNullException(string parameterName) 58 | { 59 | throw new ArgumentNullException(parameterName); 60 | } 61 | } 62 | 63 | 64 | } 65 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Helper/SpecializedLinqExtensions.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | 7 | namespace Dacs7.Helper 8 | { 9 | internal static class SpecializedLinqExtensions 10 | { 11 | public static bool Any(this IList source) 12 | { 13 | if (source == null) 14 | { 15 | ThrowArgumenNullException(nameof(source)); 16 | } 17 | 18 | return source.Count > 0; 19 | } 20 | 21 | 22 | public static bool Any(this IDictionary source) 23 | { 24 | if (source == null) 25 | { 26 | ThrowArgumenNullException(nameof(source)); 27 | } 28 | 29 | return source.Count > 0; 30 | } 31 | 32 | 33 | private static void ThrowArgumenNullException(string source) 34 | { 35 | throw new ArgumentNullException(source); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/CallbackHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Protocols 7 | { 8 | internal sealed class CallbackHandler 9 | { 10 | public ushort Id { get; } 11 | public Exception Exception { get; set; } 12 | public AsyncAutoResetEvent Event { get; } 13 | 14 | public CallbackHandler() 15 | { 16 | } 17 | 18 | public CallbackHandler(ushort id) 19 | { 20 | Id = id; 21 | Event = new AsyncAutoResetEvent(); 22 | Exception = null; 23 | } 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/ConnectionState.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Protocols 5 | { 6 | internal enum ConnectionState 7 | { 8 | Closed, 9 | PendingOpenTransport, 10 | TransportOpened, 11 | PendingOpenPlc, 12 | Opened 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/IProtocolContext.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Protocols 5 | { 6 | internal interface IProtocolContext 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/ProtocolHandler.Server.CommSetup.cs: -------------------------------------------------------------------------------- 1 | using Dacs7.Protocols.SiemensPlc; 2 | using System; 3 | using System.Net.Sockets; 4 | using System.Threading.Tasks; 5 | 6 | namespace Dacs7.Protocols 7 | { 8 | internal sealed partial class ProtocolHandler 9 | { 10 | 11 | private Task ReceivedCommunicationSetupJob(Memory buffer) 12 | { 13 | S7CommSetupDatagram data = S7CommSetupDatagram.TranslateFromMemory(buffer); 14 | Task.Run(() => HandleCommSetupAsync(data).ConfigureAwait(false)); 15 | return Task.CompletedTask; 16 | } 17 | 18 | private async Task HandleCommSetupAsync(S7CommSetupDatagram data) 19 | { 20 | using (System.Buffers.IMemoryOwner dg = S7CommSetupAckDataDatagram 21 | .TranslateToMemory( 22 | S7CommSetupAckDataDatagram 23 | .BuildFrom(_s7Context, data, data.Header.ProtocolDataUnitReference), out int memoryLength)) 24 | { 25 | using (System.Buffers.IMemoryOwner sendData = _transport.Build(dg.Memory.Slice(0, memoryLength), out int sendLength)) 26 | { 27 | SocketError result = await _transport.Connection.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false); 28 | if (result == SocketError.Success) 29 | { 30 | ushort oldSemaCount = _s7Context.MaxAmQCalling; 31 | _s7Context.MaxAmQCalling = data.Parameter.MaxAmQCalling; 32 | _s7Context.MaxAmQCalled = data.Parameter.MaxAmQCalled; 33 | _s7Context.PduSize = data.Parameter.PduLength; 34 | UpdateJobsSemaphore(oldSemaCount, _s7Context.MaxAmQCalling); 35 | 36 | await UpdateConnectionState(ConnectionState.Opened).ConfigureAwait(false); 37 | } 38 | } 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/ProtocolHandler.Server.Read.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Domain; 5 | using Dacs7.Protocols.SiemensPlc; 6 | using System; 7 | using System.Collections.Generic; 8 | using System.Linq; 9 | using System.Net.Sockets; 10 | using System.Threading.Tasks; 11 | 12 | namespace Dacs7.Protocols 13 | { 14 | internal sealed partial class ProtocolHandler 15 | { 16 | 17 | private Task ReceivedReadJob(Memory buffer) 18 | { 19 | if (_provider != null) 20 | { 21 | S7ReadJobDatagram data = S7ReadJobDatagram.TranslateFromMemory(buffer); 22 | Task.Run(() => HandleReadJobAsync(data).ConfigureAwait(false)); // here we do not have to wayt because the receive buffer is fully converted and is not needed anymore 23 | } 24 | return Task.CompletedTask; 25 | } 26 | 27 | private async Task HandleReadJobAsync(S7ReadJobDatagram data) 28 | { 29 | List readRequests = data.Items.Select(rq => new ReadRequestItem((PlcArea)rq.Area, rq.DbNumber, rq.ItemSpecLength, rq.Offset, (ItemDataTransportSize)rq.TransportSize, rq.Address)).ToList(); 30 | List results = await _provider.ReadAsync(readRequests).ConfigureAwait(false); 31 | await SendReadJobAck(results, data.Header.ProtocolDataUnitReference).ConfigureAwait(false); 32 | } 33 | 34 | private async Task SendReadJobAck(List readItems, ushort id) 35 | { 36 | using (System.Buffers.IMemoryOwner dgmem = S7ReadJobAckDatagram.TranslateToMemory(S7ReadJobAckDatagram.Build(_s7Context, id, readItems), out int commemLength)) 37 | { 38 | using (System.Buffers.IMemoryOwner sendData = _transport.Build(dgmem.Memory.Slice(0, commemLength), out int sendLength)) 39 | { 40 | SocketError result = await _transport.Connection.SendAsync(sendData.Memory.Slice(0, sendLength)).ConfigureAwait(false); 41 | if (result == SocketError.Success) 42 | { 43 | // OK 44 | } 45 | } 46 | } 47 | } 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/ReadPackage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Protocols.SiemensPlc; 5 | using System; 6 | using System.Collections.Generic; 7 | 8 | namespace Dacs7.Protocols 9 | { 10 | internal sealed class ReadPackage 11 | { 12 | private readonly int _maxSize; 13 | private int _sizeRequest = SiemensPlcProtocolContext.ReadHeader + SiemensPlcProtocolContext.ReadParameter; 14 | private int _sizeResponse = SiemensPlcProtocolContext.ReadAckHeader + SiemensPlcProtocolContext.ReadAckParameter; 15 | private readonly List _items = new(); 16 | 17 | 18 | public bool Handled { get; private set; } 19 | 20 | public bool Full => Free < SiemensPlcProtocolContext.ReadItemSize; 21 | 22 | public int Size { get; private set; } 23 | 24 | public int Free => _maxSize - Size; 25 | 26 | public IEnumerable Items => _items; 27 | 28 | public ReadPackage(int pduSize) 29 | { 30 | _maxSize = pduSize; // minimum header = 12 read 14 readack 31 | } 32 | 33 | public ReadPackage Return() 34 | { 35 | Handled = true; 36 | return this; 37 | } 38 | 39 | public bool TryAdd(ReadItem item) 40 | { 41 | ushort size = item.NumberOfItems; 42 | int newReqSize = _sizeRequest + SiemensPlcProtocolContext.ReadItemSize; 43 | int newRespSize = _sizeResponse + size + SiemensPlcProtocolContext.ReadItemAckHeader; 44 | int readItemSize = Math.Max(newReqSize, newRespSize); 45 | if (Free >= readItemSize) 46 | { 47 | _items.Add(item); 48 | _sizeRequest = newReqSize; 49 | _sizeResponse = newRespSize; 50 | Size = readItemSize; 51 | return true; 52 | } 53 | return false; 54 | } 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/Rfc1006/Datagrams/TpktDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | namespace Dacs7.Protocols.Rfc1006 5 | { 6 | internal sealed class TpktDatagram 7 | { 8 | public byte Sync1 { get; set; } 9 | public byte Sync2 { get; set; } 10 | public ushort Length { get; set; } = 4; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7AckDataDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Buffers; 6 | 7 | namespace Dacs7.Protocols.SiemensPlc 8 | { 9 | internal sealed class S7AckDataDatagram 10 | { 11 | public S7HeaderDatagram Header { get; set; } = new S7HeaderDatagram 12 | { 13 | PduType = 0x03, //Ack_Data - > Should be a marker 14 | }; 15 | 16 | public S7HeaderErrorCodesDatagram Error { get; set; } = new S7HeaderErrorCodesDatagram(); 17 | 18 | 19 | 20 | 21 | 22 | public int GetParameterOffset() 23 | { 24 | return Header.GetHeaderSize() + Error.GetSize(); 25 | } 26 | 27 | public static IMemoryOwner TranslateToMemory(S7AckDataDatagram datagram, out int memoryLength) 28 | { 29 | IMemoryOwner result = S7HeaderDatagram.TranslateToMemory(datagram.Header, datagram.Header.GetHeaderSize() + datagram.Error.GetSize() + datagram.Header.ParamLength + datagram.Header.DataLength, out memoryLength); 30 | int take = memoryLength - datagram.Header.GetHeaderSize(); 31 | S7HeaderErrorCodesDatagram.TranslateToMemory(datagram.Error, result.Memory.Slice(datagram.Header.GetHeaderSize(), take)); 32 | return result; 33 | } 34 | 35 | public static S7AckDataDatagram TranslateFromMemory(Memory data) 36 | { 37 | S7AckDataDatagram result = new() 38 | { 39 | Header = S7HeaderDatagram.TranslateFromMemory(data) 40 | }; 41 | result.Error = S7HeaderErrorCodesDatagram.TranslateFromMemory(data.Slice(result.Header.GetHeaderSize())); 42 | 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7AlarmIndicationDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Alarms; 5 | using System; 6 | 7 | namespace Dacs7.Protocols.SiemensPlc 8 | { 9 | internal sealed class S7AlarmIndicationDatagram 10 | { 11 | public S7UserDataDatagram UserData { get; set; } 12 | 13 | public S7AlarmMessage AlarmMessage { get; set; } 14 | 15 | public static S7AlarmIndicationDatagram TranslateFromMemory(Memory data) 16 | { 17 | S7AlarmIndicationDatagram current = new() 18 | { 19 | UserData = S7UserDataDatagram.TranslateFromMemory(data), 20 | }; 21 | 22 | current.AlarmMessage = S7AlarmMessage.TranslateFromMemory(current.UserData.Data.Data, (AlarmMessageType)current.UserData.Parameter.SubFunction); 23 | 24 | return current; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7AlarmUpdateAckDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Protocols.SiemensPlc 7 | { 8 | internal sealed class S7AlarmUpdateAckDatagram 9 | { 10 | public S7UserDataDatagram UserData { get; set; } 11 | 12 | public byte SubscribedEvents { get; set; } 13 | public byte Unknown { get; set; } 14 | public Memory Username { get; set; } = new byte[8]; 15 | public byte AlarmType { get; set; } 16 | public byte FillByte { get; set; } 17 | 18 | public static S7AlarmUpdateAckDatagram TranslateFromMemory(Memory data) 19 | { 20 | Span span = data.Span; 21 | S7AlarmUpdateAckDatagram current = new() 22 | { 23 | UserData = S7UserDataDatagram.TranslateFromMemory(data), 24 | }; 25 | int offset = 0; 26 | current.SubscribedEvents = span[offset++]; 27 | current.Unknown = span[offset++]; 28 | data.Slice(offset, current.Username.Length).CopyTo(current.Username); 29 | offset += current.Username.Length; 30 | current.AlarmType = span[offset++]; 31 | current.FillByte = span[offset++]; 32 | 33 | return current; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7CommSetupParameterDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | using System.Buffers.Binary; 6 | 7 | namespace Dacs7.Protocols.SiemensPlc 8 | { 9 | internal sealed class S7CommSetupParameterDatagram 10 | { 11 | public byte Function { get; set; } = 0xF0; //Setup communication 12 | public byte Reserved { get; set; } = 0x00; 13 | 14 | public ushort MaxAmQCalling { get; set; } 15 | 16 | public ushort MaxAmQCalled { get; set; } 17 | 18 | public ushort PduLength { get; set; } 19 | 20 | 21 | 22 | 23 | public static Memory TranslateToMemory(S7CommSetupParameterDatagram datagram, Memory memory) 24 | { 25 | Memory result = memory.IsEmpty ? new Memory(new byte[2]) : memory; // check if we could use ArrayBuffer 26 | Span span = result.Span; 27 | 28 | span[0] = datagram.Function; 29 | span[1] = datagram.Reserved; 30 | BinaryPrimitives.WriteUInt16BigEndian(span.Slice(2, 2), datagram.MaxAmQCalling); 31 | BinaryPrimitives.WriteUInt16BigEndian(span.Slice(4, 2), datagram.MaxAmQCalled); 32 | BinaryPrimitives.WriteUInt16BigEndian(span.Slice(6, 2), datagram.PduLength); 33 | 34 | return result; 35 | } 36 | 37 | public static S7CommSetupParameterDatagram TranslateFromMemory(Memory data) 38 | { 39 | Span span = data.Span; 40 | S7CommSetupParameterDatagram result = new() 41 | { 42 | Function = span[0], 43 | Reserved = span[1], 44 | MaxAmQCalling = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(2, 2)), 45 | MaxAmQCalled = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(4, 2)), 46 | PduLength = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(6, 2)) 47 | }; 48 | 49 | return result; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7DataItemWriteResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Protocols.SiemensPlc 7 | { 8 | internal struct S7DataItemWriteResult 9 | { 10 | public byte ReturnCode { get; set; } 11 | 12 | 13 | public int GetSpecificationLength() 14 | { 15 | return 1; 16 | } 17 | 18 | public static Memory TranslateToMemory(S7DataItemWriteResult datagram, Memory memory) 19 | { 20 | Memory result = memory.IsEmpty ? new Memory(new byte[1]) : memory; // normaly the got the memory, to the allocation should not occure 21 | Span span = result.Span; 22 | 23 | span[0] = datagram.ReturnCode; 24 | 25 | return result; 26 | } 27 | 28 | public static S7DataItemWriteResult TranslateFromMemory(Memory data) 29 | { 30 | Span span = data.Span; 31 | S7DataItemWriteResult result = new() 32 | { 33 | ReturnCode = span[0] 34 | }; 35 | return result; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7HeaderErrorCodesDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Protocols.SiemensPlc 7 | { 8 | 9 | internal sealed class S7HeaderErrorCodesDatagram 10 | { 11 | private const int _size = 2; 12 | 13 | 14 | public byte ErrorClass { get; set; } 15 | 16 | public byte ErrorCode { get; set; } 17 | 18 | public int GetSize() 19 | { 20 | return _size; 21 | } 22 | 23 | public static Memory TranslateToMemory(S7HeaderErrorCodesDatagram datagram, Memory memory) 24 | { 25 | Memory result = memory.IsEmpty ? new Memory(new byte[2]) : memory; // check if we could use ArrayBuffer 26 | Span span = result.Span; 27 | 28 | span[0] = datagram.ErrorClass; 29 | span[1] = datagram.ErrorCode; 30 | 31 | return result; 32 | } 33 | 34 | public static S7HeaderErrorCodesDatagram TranslateFromMemory(Memory data) 35 | { 36 | Span span = data.Span; 37 | S7HeaderErrorCodesDatagram result = new() 38 | { 39 | ErrorClass = span[0], 40 | ErrorCode = span[1] 41 | }; 42 | 43 | return result; 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7PlcBlocksOfTypeAckDatagram.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Metadata; 5 | using System; 6 | using System.Buffers.Binary; 7 | using System.Collections.Generic; 8 | 9 | namespace Dacs7.Protocols.SiemensPlc.Datagrams 10 | { 11 | internal class S7PlcBlocksOfTypeAckDatagram 12 | { 13 | 14 | public S7UserDataDatagram UserData { get; set; } 15 | 16 | public ushort TotalLength { get; set; } 17 | 18 | public static S7PlcBlocksOfTypeAckDatagram TranslateFromMemory(Memory data) 19 | { 20 | S7PlcBlocksOfTypeAckDatagram result = new() 21 | { 22 | UserData = S7UserDataDatagram.TranslateFromMemory(data), 23 | }; 24 | 25 | return result; 26 | } 27 | 28 | 29 | public static List TranslateFromSslData(Memory memory, int size) 30 | { 31 | // We do not need the header 32 | List result = new(); 33 | int offset = 0; 34 | Span span = memory.Span; 35 | while ((offset + 4) < size) 36 | { 37 | ushort number = BinaryPrimitives.ReadUInt16BigEndian(span.Slice(offset, 2)); offset += 2; 38 | byte flags = span[offset++]; 39 | string lng = PlcBlockInfo.GetLanguage(span[offset++]); 40 | 41 | result.Add(new PlcBlock 42 | { 43 | Number = number, 44 | Flags = flags, 45 | Language = lng 46 | }); 47 | } 48 | 49 | return result; 50 | } 51 | 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/SiemensPlc/Datagrams/S7UserData.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using System; 5 | 6 | namespace Dacs7.Protocols.SiemensPlc.Datagrams 7 | { 8 | internal sealed class S7UserData 9 | { 10 | public byte ReturnCode { get; set; } 11 | public byte TransportSize { get; set; } 12 | public ushort UserDataLength { get; set; } 13 | 14 | public Memory Data { get; set; } 15 | 16 | 17 | 18 | public int GetUserDataLength() 19 | { 20 | return 4 + UserDataLength; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7/Protocols/WritePackage.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Benjamin Proemmer. All rights reserved. 2 | // See License in the project root for license information. 3 | 4 | using Dacs7.Protocols.SiemensPlc; 5 | using System.Collections.Generic; 6 | 7 | namespace Dacs7.Protocols 8 | { 9 | internal sealed class WritePackage 10 | { 11 | private const int _writeItemHeaderSize = SiemensPlcProtocolContext.WriteParameterItem + SiemensPlcProtocolContext.WriteDataItem; 12 | private const int _minimumSize = _writeItemHeaderSize + 1; 13 | private readonly int _maxSize; 14 | private readonly List _items = new(); 15 | 16 | 17 | 18 | public bool Handled { get; private set; } 19 | 20 | public bool Full => Free < _minimumSize; 21 | 22 | public int Size { get; private set; } = SiemensPlcProtocolContext.WriteHeader + SiemensPlcProtocolContext.WriteParameter; 23 | 24 | public int Free => _maxSize - Size; 25 | 26 | public IEnumerable Items => _items; 27 | 28 | 29 | public WritePackage(int pduSize) 30 | { 31 | _maxSize = pduSize; // minimum header = 12 read 14 readack 32 | } 33 | 34 | public WritePackage Return() 35 | { 36 | Handled = true; 37 | return this; 38 | } 39 | 40 | public bool TryAdd(WriteItem item) 41 | { 42 | ushort size = item.NumberOfItems; 43 | int itemSize = _writeItemHeaderSize + size; 44 | 45 | if (Free >= itemSize) 46 | { 47 | _items.Add(item); 48 | Size += itemSize; 49 | if (Size % 2 != 0) 50 | { 51 | Size++; // set the next item to a even address 52 | } 53 | 54 | return true; 55 | } 56 | return false; 57 | } 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Dacs7Cli.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | latest 6 | net6.0 7 | false 8 | false 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/OptionsBase.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Logging; 2 | 3 | namespace Dacs7Cli.Options 4 | { 5 | public abstract class OptionsBase 6 | { 7 | public bool Debug { get; set; } 8 | 9 | public string Address { get; set; } = "localhost"; 10 | 11 | 12 | public int MaxJobs { get; set; } = 10; 13 | 14 | public bool Trace { get; set; } 15 | 16 | internal ILoggerFactory LoggerFactory { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/ReadAlarmsOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Dacs7Cli.Options 2 | { 3 | public class ReadAlarmsOptions : OptionsBase 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/ReadOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Dacs7Cli.Options 4 | { 5 | public class ReadOptions : OptionsBase 6 | { 7 | public IList Tags { get; set; } 8 | 9 | public bool RegisterItems { get; set; } 10 | 11 | public int Loops { get; set; } = 1; 12 | 13 | 14 | public int Wait { get; set; } = 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/ServerOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Dacs7Cli.Options 4 | { 5 | public class ServerOptions : OptionsBase 6 | { 7 | public int Port { get; set; } 8 | public List Tags { get; set; } 9 | 10 | public string DataProvider { get; set; } 11 | public ushort MaxPduSize { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/WatchAlarmsOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Dacs7Cli.Options 2 | { 3 | 4 | public class WatchAlarmsOptions : OptionsBase 5 | { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/WatchOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Dacs7Cli.Options 4 | { 5 | 6 | public class WatchOptions : OptionsBase 7 | { 8 | public IList Tags { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Options/WriteOptions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Dacs7Cli.Options 4 | { 5 | public class WriteOptions : OptionsBase 6 | { 7 | public IList Tags { get; set; } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Parameters.txt: -------------------------------------------------------------------------------- 1 | read -d -t -l 100 -w 2 --address benjipc677c DB1114.0,b,100;DB1114.100,b,500;DB1114.600,b,500;DB1114.100,b,100 2 | read --address benjipc677c DB1.800,x0 3 | 4 | 5 | watchalarms --address 192.168.0.148:102,0,2 -d 6 | 7 | 8 | 9 | 10 | serve --port 102 --tags DB1.0,B,1000 11 | dacs7cli write --address 192.168.0.148 DB253.4,x0=true 12 | dacs7cli write --address 192.168.0.148 DB253.4,x0=false 13 | 14 | Dacs7Cli.exe read --address 192.168.0.148 db1.800,w 15 | 16 | 17 | 18 | serve --port 102 --address 192.168.0.148 --tags DB1.0,B,1000 -x Relay 19 | 20 | write --address 192.168.0.148 db1.800,i=16 21 | 22 | 23 | 24 | write --address 192.168.1.60:102,0,1 DB28.10,C,8=test1234 25 | 26 | 27 | read --address 192.168.1.60:102,0,1 DB28.4,I DB28.6,DI DB28.0,R DB28.6,DI DB28.10,C,8 -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Dacs7Cli": { 4 | "commandName": "Project", 5 | "commandLineArgs": "read --address 192.168.1.60:102,0,1 DB28.4,I DB28.6,DI DB28.0,R DB28.6,DI DB28.10,C,8" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /dacs7/src/Dacs7Cli/Shared.cs: -------------------------------------------------------------------------------- 1 | using Dacs7Cli.Options; 2 | using Microsoft.Extensions.Logging; 3 | 4 | namespace Dacs7Cli 5 | { 6 | internal static class Shared 7 | { 8 | internal static T Configure(this T options) where T : OptionsBase 9 | { 10 | options.LoggerFactory = new LoggerFactory() 11 | .WithFilter(new FilterLoggerSettings 12 | { 13 | { "Microsoft", LogLevel.Warning }, 14 | { "System", LogLevel.Warning }, 15 | { "Dacs7", options.Trace ? LogLevel.Trace : LogLevel.Information } 16 | }) 17 | .AddConsole(options.Debug ? LogLevel.Debug : LogLevel.Information); 18 | return options; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7.Papper.Tests/Dacs7.Papper.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0;net461 5 | latest 6 | 7 | true 8 | C:\Projects\Tools\signatures\dacs7\dacs7.snk 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/CreateTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using Xunit; 4 | 5 | namespace Dacs7.Tests 6 | { 7 | public class CreateTests 8 | { 9 | private int _referenceValue = 0; 10 | [Fact] 11 | public void CreateTest() 12 | { 13 | ReadItem ri = ReadItem.Create("DB1", 0, 10); 14 | ReadItem r2i = ReadItem.Create("DB1081", 0, 1081); 15 | } 16 | 17 | [Fact] 18 | public void GetNextReferenceIdTest() 19 | { 20 | _referenceValue = Convert.ToInt32(ushort.MaxValue); 21 | ushort id = unchecked((ushort)Interlocked.Increment(ref _referenceValue)); 22 | if (id == 0) 23 | { 24 | id = unchecked((ushort)Interlocked.Increment(ref _referenceValue)); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/Dacs7.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0;net461 5 | latest 6 | 7 | true 8 | C:\Projects\Tools\signatures\dacs7\dacs7.snk 9 | false 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | all 18 | runtime; build; native; contentfiles; analyzers 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/MetadataTests.cs: -------------------------------------------------------------------------------- 1 | using Dacs7.Metadata; 2 | using Dacs7.ReadWrite; 3 | using Dacs7Tests.ServerHelper; 4 | using System.Collections.Generic; 5 | using System.Threading.Tasks; 6 | using Xunit; 7 | 8 | namespace Dacs7.Tests 9 | { 10 | public class MetadataTests 11 | { 12 | [Fact] 13 | public async Task ReadMetadataOfNotExistingBlock() 14 | { 15 | await PlcTestServer.ExecuteClientAsync(async (client) => 16 | { 17 | IPlcBlockInfo x = await client.ReadBlockInfoAsync(PlcBlockType.Db, 66); 18 | Assert.Equal(0, x.CodeSize); 19 | }); 20 | } 21 | 22 | [Fact] 23 | public async Task ReadOfNotExistingBlock() 24 | { 25 | await PlcTestServer.ExecuteClientAsync(async (client) => 26 | { 27 | IEnumerable x = await client.ReadAsync("DB66.0,B"); 28 | }); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/ReUseTest.cs: -------------------------------------------------------------------------------- 1 | using Dacs7.ReadWrite; 2 | using Dacs7Tests.ServerHelper; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using Xunit; 6 | 7 | namespace Dacs7.Tests 8 | { 9 | [Collection("PlcServer collection")] 10 | public class ReUseTest 11 | { 12 | [Fact()] 13 | public async Task ExecuteClientAsync() 14 | { 15 | Dacs7Client client = new(PlcTestServer.Address, PlcTestServer.ConnectionType, PlcTestServer.Timeout); 16 | 17 | for (int i = 0; i < 5; i++) 18 | { 19 | try 20 | { 21 | await client.ConnectAsync(); 22 | DataValue[] results = (await client.ReadAsync(ReadItem.Create("DB3", 0))).ToArray(); 23 | 24 | Assert.Single(results); 25 | Assert.True(results[0].IsSuccessReturnCode); 26 | } 27 | finally 28 | { 29 | await client.DisconnectAsync(); 30 | } 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/ServerTests.cs: -------------------------------------------------------------------------------- 1 | using Dacs7.DataProvider; 2 | using System.Threading.Tasks; 3 | using Xunit; 4 | 5 | namespace Dacs7.Tests 6 | { 7 | public class ServerTests 8 | { 9 | 10 | [Fact] 11 | public async Task ListenOnPort() 12 | { 13 | Dacs7Server dacs7Server = new(5011, SimulationPlcDataProvider.Instance); 14 | await dacs7Server.ConnectAsync(); 15 | 16 | //var dacstClient = new Dacs7Client("127.0.0.1:5011"); 17 | //await dacstClient.ConnectAsync(); 18 | 19 | await Task.Delay(30000); 20 | 21 | //await dacstClient.DisconnectAsync(); 22 | 23 | await dacs7Server.DisconnectAsync(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /dacs7/test/Dacs7Tests/TypeConversionTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Xunit; 4 | 5 | namespace Dacs7.Tests 6 | { 7 | public class TypeConversionTests 8 | { 9 | [Fact()] 10 | public void ConvertTest() 11 | { 12 | Assert.Equal(45, GetValue("+00045")); 13 | Assert.Equal(-45, GetValue("-00045")); 14 | Assert.Equal(100, GetValue("000100")); 15 | 16 | Assert.Equal(-99.2, GetValue("-099.2"), 2); 17 | Assert.Equal(3.123, GetValue("+003.123"), 2); 18 | 19 | } 20 | 21 | 22 | 23 | 24 | 25 | 26 | private T GetValue(string s) 27 | { 28 | return (T)Convert.ChangeType(s, typeof(T), CultureInfo.InvariantCulture); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /docfx/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | -------------------------------------------------------------------------------- /docfx/api/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # temp file # 3 | ############### 4 | *.yml 5 | -------------------------------------------------------------------------------- /docfx/api/index.md: -------------------------------------------------------------------------------- 1 | # InaxCore - Insite Automation Framework (dotnet core) 2 | 3 | API 4 | 5 | 6 | -------------------------------------------------------------------------------- /docfx/articles/Overview.md: -------------------------------------------------------------------------------- 1 | # dacs7 2 | 3 | Data access S7 is a library to connect to S7 plcs for reading and writing data. 4 | 5 | # NuGet 6 | PM> Install-Package Dacs7 7 | 8 | # Description 9 | 10 | 11 | Dacs7 is used to connect to a SIEMENS Plc by using the RFC1006 protocol to perform operations. 12 | 13 | 14 | # Compatibility 15 | 16 | | | 300 | 400 | WinAC | 1200 | 1500 | 17 | |:------------|:---:|:---:|:-----:|:----:|:----:| 18 | |DB Read/Write| X | X | X | X | X | 19 | |EB Read/Write| X | X | X | X | X | 20 | |AB Read/Write| X | X | X | X | X | 21 | |MB Read/Write| X | X | X | X | X | 22 | |TM Read/Write| X | X | X | | | 23 | |CT Read/Write| X | X | X | | | 24 | 25 | ## Additional TIA Settings (1200 and 1500 CPUs) 26 | 27 | ### DB Properties 28 | 29 | Select the DB in the left pane under 'Program blocks' and click 'Properties' in the context menu. 30 | 31 | 32 | 33 | ### FullAccess 34 | 35 | Select the CPU in the left pane and click 'Properties' in the context menu and go to 'Protection & Security'. 36 | 37 | 38 | 39 | ### Connection mechanisms 40 | 41 | Select the CPU in the left pane and click 'Properties' in the context menu and go to 'Protection & Security/Connection mechanisms'. 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /docfx/articles/openclose.md: -------------------------------------------------------------------------------- 1 | ## Open and close a connection to the PLC 2 | 3 | Creating an instance of the dacs7 client has a couple of optional settings. The minimum you have to specify is the IP address. 4 | This means you can connect to a plc by using only `127.0.0.1`. The syntax for the address parameter is 5 | 6 | ` IP:[Port],[Rack],[Slot]` 7 | 8 | where each parameter except the IP address is optional, but if you like to specify the rack, you also have to specify the port. 9 | The default parameters for the optional parameters are: 10 | 11 | * Port: 102 12 | * Rack: 0 13 | * slot: 2 14 | 15 | ```cs 16 | //create an instance of the client 17 | var client = new Dacs7Client("127.0.0.1:102,0,2"); 18 | ``` 19 | 20 | A more advanced constructor which can be used is the following one where you can specify some additional options. 21 | 22 | ```cs 23 | 24 | var client = new Dacs7Client( address: "127.0.0.1:102,0,2", 25 | connectionType: PlcConnectionType.Pg, 26 | timeout: 5000, 27 | loggerFactory = null, 28 | autoReconnectTime: 5000); 29 | ``` 30 | 31 | Parameters for connection type: 32 | 33 | ```cs 34 | public enum PlcConnectionType : ushort 35 | { 36 | Pg = 0x01, 37 | Op = 0x02, 38 | Basic = 0x03 39 | } 40 | ``` 41 | 42 | The timeout is used for read and write operations to wait for a response. In the case of the connect operation, dacs7 use 2 * timeout. 43 | 44 | 45 | Auto reconnect time is the time to wait before dacs7 tries to reconnect the socket. 46 | 47 | 48 | 49 | After an instance was created you can use `ConnectAsync` to connect to the plc and `DisconnectAsync` to disconnect. If the connection could not be established, dacs7 throws a `Dacs7NotConnectedException`. 50 | 51 | 52 | 53 | 54 | ```cs 55 | await client.ConnectAsync(); 56 | ... 57 | await client.DisconnectAsync(); 58 | ``` -------------------------------------------------------------------------------- /docfx/articles/tagsyntax.md: -------------------------------------------------------------------------------- 1 | 2 | # Tag syntax 3 | 4 | The Tag syntax of dacs7 has the format: 5 | 6 | `Area.Offset,DataType[,Length]` 7 | 8 | 9 | ## Area 10 | 11 | dacs7 supports english and german mnemonic and also its own syntax (The input is not case sensitive) 12 | Possible values for the area: 13 | 14 | * **Input**: i, e, I, E, IB, ib, Ib, iB 15 | * **Marker**: m, M, FB, Fb, fb, fB 16 | * **Output**: q, a, Q, A, Qa, QA, qa, qA 17 | * **Timer**: t, T, tm, Tm, TM, tM 18 | * **Counter**: c, z, C, Z, CT, ct, Ct, cT 19 | * **Datablock**: db1, Db1, DB1, dB1 20 | 21 | ## Offset 22 | 23 | The offset in byte from the beginning of the specified area. 24 | 25 | ## Type 26 | 27 | Possible values for the type: 28 | 29 | * **x[bit]**: Boolean using a bit you also have to specify the bit number in the datatype part. 30 | * **b**: Byte 31 | * **w**: Word (ushort) 32 | * **dw**: DWord (uint) 33 | * **lw**: LongWord (ulong) 34 | * **si**: SmallInt (sbyte) 35 | * **i**: Int (short) 36 | * **di**: DInt (int) 37 | * **li**: LongInt (long) 38 | * **r**: Real (float) 39 | * **c**: Char 40 | * **wc**: WChar (string) 41 | * **s**: String 42 | * **ws**: WString (string) 43 | 44 | **Length** 45 | 46 | This part is optional, the default value is 1. (a special case is the string type, this specifies the length of the string, so it is currently not possible to read a string array in one command); 47 | 48 | 49 | 50 | 51 | ## Samples 52 | 53 | 54 | | Tag | Area | offset | data type | length | 55 | |:------------|:--------------------:|:------:|:--------------:|:------:| 56 | |DB1.0,b,100 | Datablock number 1 | 0 | Byte | 100 | 57 | |DB3.1,x0 | Datablock number 3 | 1 | Bool[bit 0] | 1 | 58 | |DB3.1,x5 | Datablock number 3 | 1 | Bool[bit 5] | 1 | 59 | |DB2.10,w | Datablock number 2 | 10 | ushort | 1 | 60 | |DB2.10,i | Datablock number 2 | 10 | short | 1 | 61 | |DB2.10,dw | Datablock number 2 | 10 | uint | 1 | 62 | |DB2.10,di | Datablock number 2 | 10 | int | 1 | 63 | |M.10,x0 | Marker | 10 | Bool[bit 0] | 1 | -------------------------------------------------------------------------------- /docfx/docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "src/**.csproj" 8 | ], 9 | "exclude": [ 10 | "**/obj/**", 11 | "**/bin/**" 12 | ], 13 | "cwd": "../dacs7" 14 | } 15 | ], 16 | "dest": "api", 17 | "properties": { 18 | "TargetFramework": "netstandard2.0" 19 | } 20 | } 21 | ], 22 | "build": { 23 | "content": [ 24 | { 25 | "files": [ 26 | "**/**.yml", 27 | "api/**.yml", 28 | "api/index.md", 29 | "about/**.md", 30 | "articles/**.md" 31 | ] 32 | }, 33 | { 34 | "files": [ 35 | "articles/**.md", 36 | "articles/**/toc.yml", 37 | "about/**.md", 38 | "about/**/toc.yml", 39 | "toc.yml", 40 | "*.md" 41 | ], 42 | "exclude": [ 43 | "obj/**" 44 | ] 45 | } 46 | ], 47 | "resource": [ 48 | { 49 | "files": [ 50 | "images/**" 51 | ], 52 | "exclude": [ 53 | "obj/**" 54 | ] 55 | } 56 | ], 57 | "overwrite": [ 58 | { 59 | "files": [ 60 | "apidoc/**.md" 61 | ], 62 | "exclude": [ 63 | "obj/**" 64 | ] 65 | } 66 | ], 67 | "dest": "../docs", 68 | "fileMetadataFiles": [], 69 | "template": [ 70 | "templates/default" 71 | ], 72 | "postProcessors": [], 73 | "markdownEngineName": "markdig", 74 | "noLangKeyword": false, 75 | "keepFileLink": false, 76 | "cleanupCacheHistory": false 77 | } 78 | } -------------------------------------------------------------------------------- /docfx/images/BlockSettings.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/BlockSettings.PNG -------------------------------------------------------------------------------- /docfx/images/Connectionmechanism.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/Connectionmechanism.PNG -------------------------------------------------------------------------------- /docfx/images/FullAccess.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/FullAccess.PNG -------------------------------------------------------------------------------- /docfx/images/GitHub120px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHub120px.png -------------------------------------------------------------------------------- /docfx/images/GitHub32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHub32px.png -------------------------------------------------------------------------------- /docfx/images/GitHub64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHub64px.png -------------------------------------------------------------------------------- /docfx/images/GitHubWhite120px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHubWhite120px.png -------------------------------------------------------------------------------- /docfx/images/GitHubWhite32px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHubWhite32px.png -------------------------------------------------------------------------------- /docfx/images/GitHubWhite64px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/GitHubWhite64px.png -------------------------------------------------------------------------------- /docfx/images/font-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/font-logo.png -------------------------------------------------------------------------------- /docfx/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/logo.png -------------------------------------------------------------------------------- /docfx/images/me.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/me.png -------------------------------------------------------------------------------- /docfx/images/websiteLogoTile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/proemmer/dacs7/c460974660bc03306708a28c3ddca5e67672d326/docfx/images/websiteLogoTile.png -------------------------------------------------------------------------------- /docfx/index.md: -------------------------------------------------------------------------------- 1 | # dacs7 2 | 3 | Data access S7 is a library to connect to S7 plcs for reading and writing data. 4 | -------------------------------------------------------------------------------- /docfx/templates/default/ManagedReference.extension.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | 3 | /** 4 | * This method will be called at the start of exports.transform in ManagedReference.html.primary.js 5 | */ 6 | exports.preTransform = function (model) { 7 | return model; 8 | } 9 | 10 | /** 11 | * This method will be called at the end of exports.transform in ManagedReference.html.primary.js 12 | */ 13 | exports.postTransform = function (model) { 14 | return model; 15 | } -------------------------------------------------------------------------------- /docfx/templates/default/ManagedReference.html.primary.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | 3 | var mrefCommon = require('./ManagedReference.common.js'); 4 | var extension = require('./ManagedReference.extension.js') 5 | 6 | exports.transform = function (model) { 7 | model = extension.preTransform(model); 8 | 9 | model = mrefCommon.transform(model); 10 | if (model.type.toLowerCase() === "enum") { 11 | model.isClass = false; 12 | model.isEnum = true; 13 | } 14 | model._disableToc = model._disableToc || !model._tocPath || (model._navPath === model._tocPath); 15 | 16 | model = extension.postTransform(model); 17 | 18 | return { item: model }; 19 | } 20 | 21 | exports.getOptions = function (model) { 22 | return { "bookmarks": mrefCommon.getBookmarks(model) }; 23 | } -------------------------------------------------------------------------------- /docfx/templates/default/ManagedReference.html.primary.tmpl: -------------------------------------------------------------------------------- 1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} 2 | {{!include(/^styles/.*/)}} 3 | {{!include(/^fonts/.*/)}} 4 | {{!include(favicon.ico)}} 5 | {{!include(logo.svg)}} 6 | {{!include(search-stopwords.json)}} 7 | {{#item}} 8 | 9 | 10 | 11 | {{>partials/head}} 12 | 13 |
14 |
15 | {{^_disableNavbar}} 16 | {{>partials/navbar}} 17 | {{/_disableNavbar}} 18 | {{^_disableBreadcrumb}} 19 | {{>partials/breadcrumb}} 20 | {{/_disableBreadcrumb}} 21 |
22 | {{#_enableSearch}} 23 |
24 | {{>partials/searchResults}} 25 |
26 | {{/_enableSearch}} 27 |