├── .gitignore ├── LICENSE ├── ProfinetTools.Gui ├── App.xaml ├── App.xaml.cs ├── GuiModuleCatalog.cs ├── ProfinetTools.Gui.csproj ├── Properties │ └── AssemblyInfo.cs ├── Resources │ └── logo.png ├── ViewModelLocator.cs ├── ViewModels │ ├── AdaptersViewModel.cs │ ├── DevicesViewModel.cs │ ├── MainViewModel.cs │ ├── SettingsViewModel.cs │ └── ViewModelBase.cs ├── Views │ ├── AdaptersView.xaml │ ├── AdaptersView.xaml.cs │ ├── DevicesView.xaml │ ├── DevicesView.xaml.cs │ ├── MainWindow.xaml │ ├── MainWindow.xaml.cs │ ├── SettingsView.xaml │ └── SettingsView.xaml.cs └── packages.config ├── ProfinetTools.Interfaces ├── Commons │ ├── IInitializable.cs │ ├── IInstanceCreator.cs │ ├── IViewModel.cs │ ├── IViewModelFactory.cs │ └── NotifyPropertyChanged.cs ├── Extensions │ └── DisposableExtensions.cs ├── Models │ ├── Device.cs │ └── SaveResult.cs ├── ProfinetTools.Interfaces.csproj ├── Properties │ └── AssemblyInfo.cs ├── Serialization │ ├── IProfinetDeserialize.cs │ └── IProfinetSerialize.cs ├── Services │ ├── IAdaptersService.cs │ ├── IDeviceService.cs │ └── ISettingsService.cs └── packages.config ├── ProfinetTools.Logic ├── LogicModuleCatalog.cs ├── ProfinetTools.Logic.csproj ├── Properties │ └── AssemblyInfo.cs ├── Protocols │ ├── DCP.cs │ ├── Ethernet.cs │ ├── RPC.cs │ ├── RT.cs │ └── VLAN.cs ├── Services │ ├── AdaptersService.cs │ ├── DeviceService.cs │ └── SettingsService.cs ├── Transport │ ├── ConnectionInfoEthernet.cs │ ├── DcpMessageArgs.cs │ └── ProfinetEthernetTransport.cs └── packages.config ├── ProfinetTools.Setup ├── Fragments │ └── Fragments.wxs ├── Paraffin │ ├── Create.bat │ ├── Update.bat │ └── Zen of Paraffin.docx ├── Product.wxs ├── ProfinetTools.Setup.wixproj └── Resources │ ├── installer_background.bmp │ └── logo.ico ├── ProfinetTools.sln ├── ProfinetTools ├── App.config ├── ProfinetTools.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings └── packages.config ├── README.md └── docs └── screenshot.png /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | /out 290 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Federico Barresi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/App.xaml: -------------------------------------------------------------------------------- 1 |  8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows; 4 | 5 | namespace ProfinetTools.Gui 6 | { 7 | /// 8 | /// Interaktionslogik für App.xaml 9 | /// 10 | public partial class App : Application 11 | { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/GuiModuleCatalog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Ninject.Modules; 4 | 5 | namespace ProfinetTools.Gui 6 | { 7 | public class GuiModuleCatalog : NinjectModule 8 | { 9 | public override void Load() 10 | { 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ProfinetTools.Gui.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB} 8 | Library 9 | Properties 10 | ProfinetTools.Gui 11 | ProfinetTools.Gui 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\out\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\out\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\JetBrains.Annotations.10.2.1\lib\net\JetBrains.Annotations.dll 35 | 36 | 37 | ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll 38 | 39 | 40 | ..\packages\PacketDotNet.0.13.0\lib\net\PacketDotNet.dll 41 | 42 | 43 | 44 | 45 | ..\packages\reactiveui-core.7.0.0\lib\Net45\ReactiveUI.dll 46 | 47 | 48 | ..\packages\SharpPcap.4.2.0\lib\net\SharpPcap.dll 49 | 50 | 51 | ..\packages\Splat.1.4.0\lib\Net45\Splat.dll 52 | 53 | 54 | 55 | 56 | ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll 57 | 58 | 59 | ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll 60 | 61 | 62 | ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll 63 | 64 | 65 | ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll 66 | 67 | 68 | ..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | App.xaml 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | AdaptersView.xaml 94 | 95 | 96 | DevicesView.xaml 97 | 98 | 99 | MainWindow.xaml 100 | 101 | 102 | SettingsView.xaml 103 | 104 | 105 | 106 | 107 | MSBuild:Compile 108 | Designer 109 | 110 | 111 | Designer 112 | MSBuild:Compile 113 | 114 | 115 | Designer 116 | MSBuild:Compile 117 | 118 | 119 | MSBuild:Compile 120 | Designer 121 | 122 | 123 | Designer 124 | MSBuild:Compile 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | {f23836b7-30f9-4a77-8ea1-8c57b7bc953f} 133 | ProfinetTools.Interfaces 134 | 135 | 136 | 137 | 138 | 139 | 140 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProfinetTools.Gui")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProfinetTools.Gui")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f7d721a7-eb1b-4688-b535-63fcbeb12dab")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Resources/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarresi/ProfinetTools/0315f0f698efd886809ba177edd7ee8e38b5166f/ProfinetTools.Gui/Resources/logo.png -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModelLocator.cs: -------------------------------------------------------------------------------- 1 | using Ninject; 2 | using Ninject.Parameters; 3 | using ProfinetTools.Interfaces.Commons; 4 | using ProfinetTools.Gui.ViewModels; 5 | using System; 6 | using IInitializable = ProfinetTools.Interfaces.Commons.IInitializable; 7 | 8 | namespace ProfinetTools.Gui 9 | { 10 | public class ViewModelLocator : IViewModelFactory, IInstanceCreator 11 | { 12 | protected readonly IKernel Kernel; 13 | 14 | private static ViewModelLocator s_Instance; 15 | 16 | public ViewModelLocator() 17 | { 18 | Kernel.Bind().To().InSingletonScope(); 19 | } 20 | 21 | public ViewModelLocator(IKernel kernel) 22 | { 23 | Kernel = kernel; 24 | kernel.Bind().ToConstant(this); 25 | 26 | Kernel.Bind().To().InSingletonScope(); 27 | } 28 | 29 | public static IInstanceCreator DesignInstanceCreator => s_Instance ?? (s_Instance = new ViewModelLocator()); 30 | 31 | public static IViewModelFactory DesignViewModelFactory => s_Instance ?? (s_Instance = new ViewModelLocator()); 32 | 33 | public MainWindowViewModel MainWindowViewModel => Kernel.Get(); 34 | 35 | public T Create() 36 | { 37 | var newObject = Kernel.Get(); 38 | InitializeInitialziable(newObject as IInitializable); 39 | return newObject; 40 | } 41 | 42 | public T CreateInstance(ConstructorArgument[] arguments) 43 | { 44 | var vm = Kernel.Get(arguments); 45 | InitializeInitialziable(vm as IInitializable); 46 | return vm; 47 | } 48 | 49 | public TVm CreateViewModel(T model) 50 | { 51 | var vm = Kernel.Get(new ConstructorArgument(@"model", model)); 52 | InitializeInitialziable(vm as IInitializable); 53 | return vm; 54 | } 55 | 56 | public TVm CreateViewModel() 57 | { 58 | var vm = Kernel.Get(); 59 | InitializeInitialziable(vm as IInitializable); 60 | return vm; 61 | } 62 | 63 | private static void InitializeInitialziable(IInitializable initializable) 64 | { 65 | initializable?.Init(); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModels/AdaptersViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using ProfinetTools.Interfaces.Extensions; 5 | using ProfinetTools.Interfaces.Services; 6 | using ReactiveUI; 7 | using SharpPcap; 8 | 9 | namespace ProfinetTools.Gui.ViewModels 10 | { 11 | public class AdaptersViewModel : ViewModelBase 12 | { 13 | private readonly IAdaptersService adaptersService; 14 | private ICaptureDevice selectedAdapter; 15 | 16 | public AdaptersViewModel(IAdaptersService adaptersService) 17 | { 18 | this.adaptersService = adaptersService; 19 | } 20 | public override void Init() 21 | { 22 | Adapters = adaptersService.GetAdapters(); 23 | 24 | this.WhenAnyValue(model => model.SelectedAdapter) 25 | .Subscribe(adaptersService.SelectAdapter) 26 | .AddDisposableTo(Disposables); 27 | 28 | SelectedAdapter = Adapters.FirstOrDefault(device => device.Description.Contains("Ethernet") && !device.Description.Contains("Virtual")); 29 | } 30 | 31 | public List Adapters { get; set; } 32 | 33 | public ICaptureDevice SelectedAdapter 34 | { 35 | get { return selectedAdapter; } 36 | set 37 | { 38 | if (Equals(value, selectedAdapter)) return; 39 | selectedAdapter = value; 40 | raisePropertyChanged(); 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModels/DevicesViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reactive; 5 | using System.Reactive.Linq; 6 | using System.Reactive.Threading.Tasks; 7 | using System.Threading.Tasks; 8 | using ProfinetTools.Interfaces.Extensions; 9 | using ProfinetTools.Interfaces.Models; 10 | using ProfinetTools.Interfaces.Services; 11 | using ReactiveUI; 12 | 13 | namespace ProfinetTools.Gui.ViewModels 14 | { 15 | public class DevicesViewModel : ViewModelBase 16 | { 17 | private readonly IDeviceService deviceService; 18 | private readonly IAdaptersService adaptersService; 19 | private List devices = new List(); 20 | private Device selectedDevice; 21 | public ReactiveUI.ReactiveCommand RefreshCommand { get; set; } 22 | 23 | public DevicesViewModel(IDeviceService deviceService, IAdaptersService adaptersService) 24 | { 25 | this.deviceService = deviceService; 26 | this.adaptersService = adaptersService; 27 | } 28 | 29 | public override void Init() 30 | { 31 | RefreshCommand = ReactiveUI.ReactiveCommand.CreateFromTask(RefreshDevicesList) 32 | .AddDisposableTo(Disposables); 33 | 34 | this.WhenAnyValue(model => model.SelectedDevice) 35 | .Subscribe(deviceService.SelectDevice) 36 | .AddDisposableTo(Disposables) 37 | ; 38 | } 39 | 40 | private async Task RefreshDevicesList() 41 | { 42 | var adapter = await adaptersService.SelectedAdapter.FirstAsync().ToTask(); 43 | if(adapter == null) return Unit.Default; 44 | 45 | try 46 | { 47 | Devices = await deviceService.GetDevices(adapter, TimeSpan.FromSeconds(0.5)); 48 | } 49 | catch (Exception e) 50 | { 51 | Console.WriteLine(e); 52 | } 53 | return Unit.Default; 54 | } 55 | 56 | public List Devices 57 | { 58 | get { return devices; } 59 | set 60 | { 61 | if (Equals(value, devices)) return; 62 | devices = value; 63 | raisePropertyChanged(); 64 | } 65 | } 66 | 67 | public Device SelectedDevice 68 | { 69 | get { return selectedDevice; } 70 | set 71 | { 72 | if (Equals(value, selectedDevice)) return; 73 | selectedDevice = value; 74 | raisePropertyChanged(); 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModels/MainViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive; 3 | using System.Threading.Tasks; 4 | using Microsoft.Win32; 5 | using ProfinetTools.Interfaces.Commons; 6 | using ProfinetTools.Interfaces.Extensions; 7 | using ReactiveUI.Legacy; 8 | 9 | namespace ProfinetTools.Gui.ViewModels 10 | { 11 | public class MainWindowViewModel : ViewModelBase 12 | { 13 | private readonly IViewModelFactory viewModelFactory; 14 | 15 | public MainWindowViewModel(IViewModelFactory viewModelFactory) 16 | { 17 | this.viewModelFactory = viewModelFactory; 18 | } 19 | public override void Init() 20 | { 21 | AdaptersViewModel = viewModelFactory.CreateViewModel(); 22 | AdaptersViewModel.Init(); 23 | AdaptersViewModel.AddDisposableTo(Disposables); 24 | 25 | DevicesViewModel = viewModelFactory.CreateViewModel(); 26 | DevicesViewModel.Init(); 27 | DevicesViewModel.AddDisposableTo(Disposables); 28 | 29 | SettingsViewModel = viewModelFactory.CreateViewModel(); 30 | SettingsViewModel.Init(); 31 | SettingsViewModel.AddDisposableTo(Disposables); 32 | } 33 | 34 | public AdaptersViewModel AdaptersViewModel { get; set; } 35 | public DevicesViewModel DevicesViewModel { get; set; } 36 | public SettingsViewModel SettingsViewModel { get; set; } 37 | } 38 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModels/SettingsViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive; 3 | using System.Reactive.Linq; 4 | using System.Reactive.Subjects; 5 | using System.Reactive.Threading.Tasks; 6 | using System.Threading.Tasks; 7 | using System.Windows; 8 | using ProfinetTools.Interfaces.Extensions; 9 | using ProfinetTools.Interfaces.Models; 10 | using ProfinetTools.Interfaces.Services; 11 | 12 | namespace ProfinetTools.Gui.ViewModels 13 | { 14 | public class SettingsViewModel : ViewModelBase 15 | { 16 | private readonly IDeviceService deviceService; 17 | private readonly IAdaptersService adaptersService; 18 | private readonly ISettingsService settingsService; 19 | private Device device1; 20 | 21 | public ReactiveUI.ReactiveCommand SaveCommand { get; set; } 22 | public ReactiveUI.ReactiveCommand ResetCommand { get; set; } 23 | 24 | 25 | public SettingsViewModel(IDeviceService deviceService, IAdaptersService adaptersService, ISettingsService settingsService) 26 | { 27 | this.deviceService = deviceService; 28 | this.adaptersService = adaptersService; 29 | this.settingsService = settingsService; 30 | } 31 | 32 | public override void Init() 33 | { 34 | deviceService.SelectedDevice 35 | .Do(device => Device = device) 36 | .ObserveOnDispatcher() 37 | .Subscribe() 38 | .AddDisposableTo(Disposables); 39 | 40 | SaveCommand = ReactiveUI.ReactiveCommand.CreateFromTask(SaveDeviceSettings) 41 | .AddDisposableTo(Disposables); 42 | 43 | ResetCommand = ReactiveUI.ReactiveCommand.CreateFromTask(ResetDevice) 44 | .AddDisposableTo(Disposables); 45 | } 46 | 47 | 48 | private async Task ResetDevice() 49 | { 50 | var adapter = await adaptersService.SelectedAdapter.FirstAsync().ToTask(); 51 | if (adapter == null) return Unit.Default; 52 | 53 | if(Device == null) return Unit.Default; 54 | 55 | var result = await settingsService.FactoryReset(adapter, Device.MAC); 56 | if (!result.Success) 57 | MessageBox.Show("Device refuse: " + result.ErrorMessage, "Device Error", MessageBoxButton.OK, MessageBoxImage.Exclamation); 58 | else 59 | MessageBox.Show("All done!", "Device Info", MessageBoxButton.OK, MessageBoxImage.Information); 60 | 61 | 62 | return Unit.Default; 63 | } 64 | 65 | private async Task SaveDeviceSettings() 66 | { 67 | var adapter = await adaptersService.SelectedAdapter.FirstAsync().ToTask(); 68 | if (adapter == null) return Unit.Default; 69 | 70 | if (Device == null || !settingsService.TryParseNetworkConfiguration(Device)) return Unit.Default; 71 | 72 | var result = await settingsService.SendSettings(adapter, Device.MAC, Device); 73 | if (!result.Success) 74 | MessageBox.Show("Device refuse: " + result.ErrorMessage, "Device Error", MessageBoxButton.OK, MessageBoxImage.Exclamation); 75 | else 76 | MessageBox.Show("All done!", "Device Info", MessageBoxButton.OK, MessageBoxImage.Information); 77 | 78 | return Unit.Default; 79 | } 80 | 81 | 82 | public Device Device 83 | { 84 | get { return device1; } 85 | set 86 | { 87 | if (Equals(value, device1)) return; 88 | device1 = value; 89 | raisePropertyChanged(); 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reactive.Disposables; 4 | using System.Runtime.CompilerServices; 5 | using JetBrains.Annotations; 6 | using ProfinetTools.Interfaces.Commons; 7 | using ReactiveUI; 8 | 9 | namespace ProfinetTools.Gui.ViewModels 10 | { 11 | public abstract class ViewModelBase : ReactiveObject, IDisposable, IInitializable 12 | { 13 | protected CompositeDisposable Disposables = new CompositeDisposable(); 14 | private bool disposed; 15 | 16 | ~ViewModelBase() 17 | { 18 | Dispose(false); 19 | } 20 | 21 | public virtual void Dispose() 22 | { 23 | Dispose(true); 24 | } 25 | 26 | public abstract void Init(); 27 | 28 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2213:DisposableFieldsShouldBeDisposed", MessageId = "Disposables")] 29 | protected virtual void Dispose(bool disposing) 30 | { 31 | if (disposed) 32 | return; 33 | 34 | Disposables?.Dispose(); 35 | Disposables = null; 36 | 37 | disposed = true; 38 | } 39 | 40 | [NotifyPropertyChangedInvocator] 41 | // ReSharper disable once InconsistentNaming 42 | protected void raisePropertyChanged([CallerMemberName] string propertyName = "") 43 | { 44 | this.RaisePropertyChanged(propertyName); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/AdaptersView.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/AdaptersView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace ProfinetTools.Gui.Views 17 | { 18 | /// 19 | /// Interaction logic for AdaptersView.xaml 20 | /// 21 | public partial class AdaptersView : UserControl 22 | { 23 | public AdaptersView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/DevicesView.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/DevicesView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace ProfinetTools.Gui.Views 17 | { 18 | /// 19 | /// Interaction logic for DevicesView.xaml 20 | /// 21 | public partial class DevicesView : UserControl 22 | { 23 | public DevicesView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/MainWindow.xaml: -------------------------------------------------------------------------------- 1 |  12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/MainWindow.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Windows; 4 | 5 | namespace ProfinetTools.Gui.Views 6 | { 7 | public partial class MainWindow : Window 8 | { 9 | public MainWindow() 10 | { 11 | InitializeComponent(); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/SettingsView.xaml: -------------------------------------------------------------------------------- 1 |  11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/Views/SettingsView.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Windows; 7 | using System.Windows.Controls; 8 | using System.Windows.Data; 9 | using System.Windows.Documents; 10 | using System.Windows.Input; 11 | using System.Windows.Media; 12 | using System.Windows.Media.Imaging; 13 | using System.Windows.Navigation; 14 | using System.Windows.Shapes; 15 | 16 | namespace ProfinetTools.Gui.Views 17 | { 18 | /// 19 | /// Interaction logic for SettingsView.xaml 20 | /// 21 | public partial class SettingsView : UserControl 22 | { 23 | public SettingsView() 24 | { 25 | InitializeComponent(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /ProfinetTools.Gui/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Commons/IInitializable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Interfaces.Commons 5 | { 6 | public interface IInitializable 7 | { 8 | void Init(); 9 | } 10 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Commons/IInstanceCreator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Ninject.Parameters; 4 | 5 | namespace ProfinetTools.Interfaces.Commons 6 | { 7 | public interface IInstanceCreator 8 | { 9 | T CreateInstance(ConstructorArgument[] arguments); 10 | } 11 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Commons/IViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Interfaces.Commons 5 | { 6 | public interface IViewModel 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Commons/IViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Interfaces.Commons 5 | { 6 | public interface IViewModelFactory 7 | { 8 | T Create(); 9 | 10 | TVm CreateViewModel(T model); 11 | 12 | TVm CreateViewModel(); 13 | } 14 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Commons/NotifyPropertyChanged.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | using System.Runtime.CompilerServices; 3 | using JetBrains.Annotations; 4 | 5 | namespace ProfinetTools.Interfaces.Commons 6 | { 7 | public abstract class NotifyPropertyChanged : INotifyPropertyChanged 8 | { 9 | public virtual event PropertyChangedEventHandler PropertyChanged; 10 | 11 | [NotifyPropertyChangedInvocator] 12 | protected virtual void raisePropertyChanged([CallerMemberName] string propertyName = null) 13 | { 14 | PropertyChangedEventHandler propertyChanged = this.PropertyChanged; 15 | if (propertyChanged == null) 16 | return; 17 | propertyChanged((object)this, new PropertyChangedEventArgs(propertyName)); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Extensions/DisposableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive.Disposables; 3 | 4 | namespace ProfinetTools.Interfaces.Extensions 5 | { 6 | public static class DisposableExtensions 7 | { 8 | public static T AddDisposableTo(this T obj, CompositeDisposable disposables) where T : IDisposable 9 | { 10 | disposables.Add(obj); 11 | return obj; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Models/Device.cs: -------------------------------------------------------------------------------- 1 | using ProfinetTools.Interfaces.Commons; 2 | 3 | namespace ProfinetTools.Interfaces.Models 4 | { 5 | public class Device : NotifyPropertyChanged 6 | { 7 | private string mac; 8 | private string name; 9 | private string type; 10 | private string role; 11 | private string ip; 12 | private string subnetMask; 13 | private string gateway; 14 | 15 | public string MAC 16 | { 17 | get { return mac; } 18 | set 19 | { 20 | if (value == mac) return; 21 | mac = value; 22 | raisePropertyChanged(); 23 | } 24 | } 25 | 26 | public string Name 27 | { 28 | get { return name; } 29 | set 30 | { 31 | if (value == name) return; 32 | name = value; 33 | raisePropertyChanged(); 34 | } 35 | } 36 | 37 | public string Type 38 | { 39 | get { return type; } 40 | set 41 | { 42 | if (value == type) return; 43 | type = value; 44 | raisePropertyChanged(); 45 | } 46 | } 47 | 48 | public string Role 49 | { 50 | get { return role; } 51 | set 52 | { 53 | if (value == role) return; 54 | role = value; 55 | raisePropertyChanged(); 56 | } 57 | } 58 | 59 | public string IP 60 | { 61 | get { return ip; } 62 | set 63 | { 64 | if (value == ip) return; 65 | ip = value; 66 | raisePropertyChanged(); 67 | } 68 | } 69 | 70 | public string SubnetMask 71 | { 72 | get { return subnetMask; } 73 | set 74 | { 75 | if (value == subnetMask) return; 76 | subnetMask = value; 77 | raisePropertyChanged(); 78 | } 79 | } 80 | 81 | public string Gateway 82 | { 83 | get { return gateway; } 84 | set 85 | { 86 | if (value == gateway) return; 87 | gateway = value; 88 | raisePropertyChanged(); 89 | } 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Models/SaveResult.cs: -------------------------------------------------------------------------------- 1 | namespace ProfinetTools.Interfaces.Models 2 | { 3 | public class SaveResult 4 | { 5 | public SaveResult(bool success, string errorMessage) 6 | { 7 | Success = success; 8 | ErrorMessage = errorMessage; 9 | } 10 | 11 | public bool Success { get; } 12 | public string ErrorMessage { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/ProfinetTools.Interfaces.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F} 8 | Library 9 | Properties 10 | ProfinetTools.Interfaces 11 | ProfinetTools.Interfaces 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\out\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\out\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\JetBrains.Annotations.10.2.1\lib\net\JetBrains.Annotations.dll 35 | 36 | 37 | ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll 38 | 39 | 40 | ..\packages\PacketDotNet.0.13.0\lib\net\PacketDotNet.dll 41 | 42 | 43 | ..\packages\SharpPcap.4.2.0\lib\net\SharpPcap.dll 44 | 45 | 46 | 47 | 48 | ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll 49 | 50 | 51 | ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProfinetTools.Interfaces")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProfinetTools.Interfaces")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("f23836b7-30f9-4a77-8ea1-8c57b7bc953f")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Serialization/IProfinetDeserialize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Interfaces.Serialization 5 | { 6 | public interface IProfinetDeserialize //Should be merged with IProfinetSerialize, at some point 7 | { 8 | int Deserialize(System.IO.Stream buffer); 9 | } 10 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Serialization/IProfinetSerialize.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Interfaces.Serialization 5 | { 6 | public interface IProfinetSerialize 7 | { 8 | int Serialize(System.IO.Stream buffer); 9 | } 10 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Services/IAdaptersService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using SharpPcap; 5 | 6 | namespace ProfinetTools.Interfaces.Services 7 | { 8 | public interface IAdaptersService 9 | { 10 | List GetAdapters(); 11 | 12 | IObservable SelectedAdapter { get; } 13 | void SelectAdapter(ICaptureDevice adapter); 14 | } 15 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Services/IDeviceService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using ProfinetTools.Interfaces.Models; 6 | using SharpPcap; 7 | 8 | namespace ProfinetTools.Interfaces.Services 9 | { 10 | public interface IDeviceService 11 | { 12 | Task> GetDevices(ICaptureDevice adapter, TimeSpan timeout); 13 | void SelectDevice(Device device); 14 | IObservable SelectedDevice { get; } 15 | } 16 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/Services/ISettingsService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using ProfinetTools.Interfaces.Models; 5 | using SharpPcap; 6 | 7 | namespace ProfinetTools.Interfaces.Services 8 | { 9 | public interface ISettingsService 10 | { 11 | Task FactoryReset(ICaptureDevice adapter, string deviceName); 12 | Task SendSettings(ICaptureDevice adapter, string macAddress, Device newSettings); 13 | bool TryParseNetworkConfiguration(Device device); 14 | } 15 | } -------------------------------------------------------------------------------- /ProfinetTools.Interfaces/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ProfinetTools.Logic/LogicModuleCatalog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using Ninject.Modules; 4 | using ProfinetTools.Interfaces.Services; 5 | using ProfinetTools.Logic.Services; 6 | 7 | namespace ProfinetTools.Logic 8 | { 9 | public class LogicModuleCatalog : NinjectModule 10 | { 11 | public override void Load() 12 | { 13 | Bind().To().InSingletonScope(); 14 | Bind().To().InSingletonScope(); 15 | Bind().To().InSingletonScope(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/ProfinetTools.Logic.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6} 8 | Library 9 | Properties 10 | ProfinetTools.Logic 11 | ProfinetTools.Logic 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | ..\out\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | ..\out\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll 35 | 36 | 37 | ..\packages\PacketDotNet.0.13.0\lib\net\PacketDotNet.dll 38 | 39 | 40 | ..\packages\SharpPcap.4.2.0\lib\net\SharpPcap.dll 41 | 42 | 43 | 44 | 45 | ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll 46 | 47 | 48 | ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll 49 | 50 | 51 | ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F} 81 | ProfinetTools.Interfaces 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /ProfinetTools.Logic/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ProfinetTools.Logic")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ProfinetTools.Logic")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6696f4a6-c9a5-49f3-8463-16a85bacb6e6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ProfinetTools.Logic/Protocols/DCP.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | using System.Text; 7 | using ProfinetTools.Interfaces.Serialization; 8 | 9 | namespace ProfinetTools.Logic.Protocols 10 | { 11 | public class DCP 12 | { 13 | [Flags] 14 | public enum ServiceIds : ushort 15 | { 16 | Get_Request = 0x0300, 17 | Get_Response = 0x0301, 18 | Set_Request = 0x0400, 19 | Set_Response = 0x0401, 20 | Identify_Request = 0x0500, 21 | Identify_Response = 0x0501, 22 | Hello_Request = 0x0600, 23 | ServiceIDNotSupported = 0x0004, 24 | } 25 | 26 | public enum BlockOptions : ushort 27 | { 28 | //IP 29 | IP_MACAddress = 0x0101, 30 | IP_IPParameter = 0x0102, 31 | IP_FullIPSuite = 0x0103, 32 | 33 | //DeviceProperties 34 | DeviceProperties_DeviceVendor = 0x0201, 35 | DeviceProperties_NameOfStation = 0x0202, 36 | DeviceProperties_DeviceID = 0x0203, 37 | DeviceProperties_DeviceRole = 0x0204, 38 | DeviceProperties_DeviceOptions = 0x0205, 39 | DeviceProperties_AliasName = 0x0206, 40 | DeviceProperties_DeviceInstance = 0x0207, 41 | DeviceProperties_OEMDeviceID = 0x0208, 42 | 43 | //DHCP 44 | DHCP_HostName = 0x030C, 45 | DHCP_VendorSpecificInformation = 0x032B, 46 | DHCP_ServerIdentifier = 0x0336, 47 | DHCP_ParameterRequestList = 0x0337, 48 | DHCP_ClassIdentifier = 0x033C, 49 | DHCP_DHCPClientIdentifier = 0x033D, 50 | DHCP_FullyQualifiedDomainName = 0x0351, 51 | DHCP_UUIDClientIdentifier = 0x0361, 52 | DHCP_DHCP = 0x03FF, 53 | 54 | //Control 55 | Control_Start = 0x0501, 56 | Control_Stop = 0x0502, 57 | Control_Signal = 0x0503, 58 | Control_Response = 0x0504, 59 | Control_FactoryReset = 0x0505, 60 | Control_ResetToFactory = 0x0506, 61 | 62 | //DeviceInitiative 63 | DeviceInitiative_DeviceInitiative = 0x0601, 64 | 65 | //AllSelector 66 | AllSelector_AllSelector = 0xFFFF, 67 | } 68 | 69 | public enum BlockQualifiers : ushort 70 | { 71 | Temporary = 0, 72 | Permanent = 1, 73 | 74 | ResetApplicationData = 2, 75 | ResetCommunicationParameter = 4, 76 | ResetEngineeringParameter = 6, 77 | ResetAllStoredData = 8, 78 | ResetDevice = 16, 79 | ResetAndRestoreData = 18, 80 | } 81 | 82 | [Flags] 83 | public enum BlockInfo : ushort 84 | { 85 | IpSet = 1, 86 | IpSetViaDhcp = 2, 87 | IpConflict = 0x80, 88 | } 89 | 90 | [Flags] 91 | public enum DeviceRoles : byte 92 | { 93 | Device = 1, 94 | Controller = 2, 95 | Multidevice = 4, 96 | Supervisor = 8, 97 | } 98 | 99 | public enum BlockErrors : byte 100 | { 101 | NoError = 0, 102 | OptionNotSupported = 1, 103 | SuboptionNotSupported = 2, 104 | SuboptionNotSet = 3, 105 | ResourceError = 4, 106 | SetNotPossible = 5, 107 | Busy = 6, 108 | } 109 | 110 | public static int EncodeU32(System.IO.Stream buffer, UInt32 value) 111 | { 112 | buffer.WriteByte((byte)((value & 0xFF000000) >> 24)); 113 | buffer.WriteByte((byte)((value & 0x00FF0000) >> 16)); 114 | buffer.WriteByte((byte)((value & 0x0000FF00) >> 08)); 115 | buffer.WriteByte((byte)((value & 0x000000FF) >> 00)); 116 | return 4; 117 | } 118 | 119 | public static int EncodeU16(System.IO.Stream buffer, UInt16 value) 120 | { 121 | buffer.WriteByte((byte)((value & 0xFF00) >> 08)); 122 | buffer.WriteByte((byte)((value & 0x00FF) >> 00)); 123 | return 2; 124 | } 125 | 126 | public static int EncodeU8(System.IO.Stream buffer, byte value) 127 | { 128 | buffer.WriteByte((byte)value); 129 | return 1; 130 | } 131 | 132 | public static int DecodeU16(System.IO.Stream buffer, out UInt16 value) 133 | { 134 | if (buffer.Position >= buffer.Length) 135 | { 136 | value = 0; 137 | return 0; 138 | } 139 | value = (UInt16)((buffer.ReadByte() << 8) | buffer.ReadByte()); 140 | return 2; 141 | } 142 | 143 | public static int DecodeU8(System.IO.Stream buffer, out byte value) 144 | { 145 | if (buffer.Position >= buffer.Length) 146 | { 147 | value = 0; 148 | return 0; 149 | } 150 | value = (byte)buffer.ReadByte(); 151 | return 1; 152 | } 153 | 154 | public static int DecodeU32(System.IO.Stream buffer, out UInt32 value) 155 | { 156 | if (buffer.Position >= buffer.Length) 157 | { 158 | value = 0; 159 | return 0; 160 | } 161 | value = (UInt32)((buffer.ReadByte() << 24) | (buffer.ReadByte() << 16) | (buffer.ReadByte() << 8) | buffer.ReadByte()); 162 | return 4; 163 | } 164 | 165 | public static int EncodeString(System.IO.Stream buffer, string value) 166 | { 167 | byte[] bytes = Encoding.ASCII.GetBytes(value); 168 | buffer.Write(bytes, 0, bytes.Length); 169 | return bytes.Length; 170 | } 171 | 172 | public static int DecodeString(System.IO.Stream buffer, int length, out string value) 173 | { 174 | byte[] tmp = new byte[length]; 175 | buffer.Read(tmp, 0, length); 176 | value = Encoding.ASCII.GetString(tmp); 177 | return tmp.Length; 178 | } 179 | 180 | public static int EncodeOctets(System.IO.Stream buffer, byte[] value) 181 | { 182 | if (value == null || value.Length == 0) return 0; 183 | buffer.Write(value, 0, value.Length); 184 | return value.Length; 185 | } 186 | 187 | public static int DecodeOctets(System.IO.Stream buffer, int length, out byte[] value) 188 | { 189 | if (length <= 0) 190 | { 191 | value = null; 192 | return 0; 193 | } 194 | value = new byte[length]; 195 | buffer.Read(value, 0, length); 196 | return value.Length; 197 | } 198 | 199 | public static int EncodeHeader(System.IO.Stream buffer, ServiceIds ServiceID, UInt32 Xid, UInt16 ResponseDelayFactor, UInt16 DCPDataLength) 200 | { 201 | long dummy; 202 | return EncodeHeader(buffer, ServiceID, Xid, ResponseDelayFactor, DCPDataLength, out dummy); 203 | } 204 | 205 | public static int EncodeHeader(System.IO.Stream buffer, ServiceIds ServiceID, UInt32 Xid, UInt16 ResponseDelayFactor, UInt16 DCPDataLength, out long DCPDataLength_pos) 206 | { 207 | EncodeU16(buffer, (ushort)ServiceID); 208 | 209 | //big endian uint32 210 | EncodeU32(buffer, Xid); 211 | 212 | //ResponseDelayFactor, 1 = Allowed value without spread, 2 – 0x1900 = Allowed value with spread 213 | EncodeU16(buffer, ResponseDelayFactor); 214 | 215 | DCPDataLength_pos = buffer.Position; 216 | EncodeU16(buffer, DCPDataLength); 217 | 218 | return 10; 219 | } 220 | 221 | public static void ReEncodeDCPDataLength(System.IO.Stream buffer, long DCPDataLength_pos) 222 | { 223 | long current_pos = buffer.Position; 224 | buffer.Position = DCPDataLength_pos; 225 | EncodeU16(buffer, (ushort)(current_pos - buffer.Position - 2)); 226 | buffer.Position = current_pos; 227 | } 228 | 229 | public static int DecodeHeader(System.IO.Stream buffer, out ServiceIds ServiceID, out UInt32 Xid, out UInt16 ResponseDelayFactor, out UInt16 DCPDataLength) 230 | { 231 | ushort val; 232 | DecodeU16(buffer, out val); 233 | ServiceID = (ServiceIds)val; 234 | 235 | //big endian uint32 236 | DecodeU32(buffer, out Xid); 237 | 238 | //ResponseDelayFactor, 1 = Allowed value without spread, 2 – 0x1900 = Allowed value with spread 239 | DecodeU16(buffer, out ResponseDelayFactor); 240 | 241 | DecodeU16(buffer, out DCPDataLength); 242 | 243 | return 10; 244 | } 245 | 246 | public static int EncodeBlock(System.IO.Stream buffer, BlockOptions options, UInt16 DCPBlockLength) 247 | { 248 | long dummy; 249 | return EncodeBlock(buffer, options, DCPBlockLength, out dummy); 250 | } 251 | 252 | public static int EncodeBlock(System.IO.Stream buffer, BlockOptions options, UInt16 DCPBlockLength, out long DCPBlockLength_pos) 253 | { 254 | EncodeU16(buffer, (ushort)options); 255 | DCPBlockLength_pos = buffer.Position; 256 | EncodeU16(buffer, DCPBlockLength); 257 | return 4; 258 | } 259 | 260 | public static int DecodeBlock(System.IO.Stream buffer, out BlockOptions options, out UInt16 DCPBlockLength) 261 | { 262 | ushort opt; 263 | DecodeU16(buffer, out opt); 264 | options = (BlockOptions)opt; 265 | DecodeU16(buffer, out DCPBlockLength); 266 | return 4; 267 | } 268 | 269 | public static int EncodeIdentifyResponse(System.IO.Stream buffer, UInt32 Xid, Dictionary blocks) 270 | { 271 | int ret = 0; 272 | long dcp_data_length_pos; 273 | 274 | //Header 275 | ret += EncodeHeader(buffer, ServiceIds.Identify_Response, Xid, 0, 0, out dcp_data_length_pos); 276 | 277 | //{ IdentifyResBlock, NameOfStationBlockRes,IPParameterBlockRes, DeviceIDBlockRes, DeviceVendorBlockRes,DeviceOptionsBlockRes, DeviceRoleBlockRes, [DeviceInitiativeBlockRes],[DeviceInstanceBlockRes], [OEMDeviceIDBlockRes] } 278 | 279 | foreach (KeyValuePair entry in blocks) 280 | { 281 | ret += EncodeNextBlock(buffer, entry); 282 | } 283 | 284 | //adjust dcp_length 285 | ReEncodeDCPDataLength(buffer, dcp_data_length_pos); 286 | 287 | return ret; 288 | } 289 | 290 | /// 291 | /// This is a helper class for the block options 292 | /// 293 | [TypeConverter(typeof(ExpandableObjectConverter)), Serializable] 294 | public class BlockOptionMeta 295 | { 296 | public string Name { get; set; } 297 | public bool IsReadable { get; set; } 298 | public bool IsWriteable { get; set; } 299 | 300 | [Browsable(false), System.Xml.Serialization.XmlIgnore] 301 | public BlockOptions BlockOption { get; set; } 302 | 303 | public byte Option 304 | { 305 | get 306 | { 307 | return (byte)((((UInt16)BlockOption) & 0xFF00) >> 8); 308 | } 309 | set 310 | { 311 | BlockOption = (BlockOptions)((((UInt16)BlockOption) & 0x00FF) | ((UInt16)value << 8)); 312 | } 313 | } 314 | 315 | public byte SubOption 316 | { 317 | get 318 | { 319 | return (byte)((((UInt16)BlockOption) & 0x00FF) >> 0); 320 | } 321 | set 322 | { 323 | BlockOption = (BlockOptions)((((UInt16)BlockOption) & 0xFF00) | ((UInt16)value << 0)); 324 | } 325 | } 326 | 327 | private BlockOptionMeta() //For XmlSerializer 328 | { 329 | } 330 | 331 | public BlockOptionMeta(string name, byte option, byte sub_option, bool is_readable, bool is_writeable) 332 | { 333 | this.BlockOption = 0; 334 | this.Name = name; 335 | this.Option = option; 336 | this.SubOption = sub_option; 337 | this.IsReadable = is_readable; 338 | this.IsWriteable = is_writeable; 339 | } 340 | 341 | public BlockOptionMeta(BlockOptions opt) 342 | { 343 | BlockOption = opt; 344 | Name = opt.ToString(); 345 | if (opt == BlockOptions.IP_MACAddress || 346 | opt == BlockOptions.DeviceProperties_DeviceID || 347 | opt == BlockOptions.DeviceProperties_DeviceVendor || 348 | opt == BlockOptions.DeviceProperties_DeviceRole || 349 | opt == BlockOptions.DeviceProperties_DeviceOptions || 350 | opt == BlockOptions.DeviceProperties_DeviceInstance || 351 | opt == BlockOptions.DeviceProperties_OEMDeviceID || 352 | opt == BlockOptions.DeviceInitiative_DeviceInitiative) 353 | { 354 | IsReadable = true; 355 | } 356 | else if (opt == BlockOptions.DeviceProperties_AliasName || 357 | opt == BlockOptions.Control_Response || 358 | opt == BlockOptions.AllSelector_AllSelector) 359 | { 360 | //none 361 | } 362 | else if (opt == BlockOptions.Control_Start || 363 | opt == BlockOptions.Control_Stop || 364 | opt == BlockOptions.Control_Signal || 365 | opt == BlockOptions.Control_FactoryReset || 366 | opt == BlockOptions.Control_ResetToFactory) 367 | { 368 | IsWriteable = true; 369 | } 370 | else 371 | { 372 | //default 373 | IsReadable = true; 374 | IsWriteable = true; 375 | } 376 | } 377 | } 378 | 379 | public class IpAddressConverter : TypeConverter 380 | { 381 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) 382 | { 383 | if (sourceType == typeof(string)) return true; 384 | return base.CanConvertFrom(context, sourceType); 385 | } 386 | public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value) 387 | { 388 | if (value is string) 389 | return System.Net.IPAddress.Parse((string)value); 390 | return base.ConvertFrom(context, culture, value); 391 | } 392 | } 393 | 394 | [TypeConverter(typeof(ExpandableObjectConverter))] 395 | public class IpInfo : IProfinetSerialize 396 | { 397 | public BlockInfo Info { get; set; } 398 | [TypeConverter(typeof(IpAddressConverter))] 399 | public System.Net.IPAddress Ip { get; set; } 400 | [TypeConverter(typeof(IpAddressConverter))] 401 | public System.Net.IPAddress SubnetMask { get; set; } 402 | [TypeConverter(typeof(IpAddressConverter))] 403 | public System.Net.IPAddress Gateway { get; set; } 404 | public IpInfo(BlockInfo info, byte[] ip, byte[] subnet, byte[] gateway) 405 | { 406 | Info = info; 407 | Ip = new System.Net.IPAddress(ip); 408 | SubnetMask = new System.Net.IPAddress(subnet); 409 | Gateway = new System.Net.IPAddress(gateway); 410 | } 411 | public override string ToString() 412 | { 413 | return "{" + Ip.ToString() + " - " + SubnetMask.ToString() + " - " + Gateway.ToString() + "}"; 414 | } 415 | 416 | public int Serialize(System.IO.Stream buffer) 417 | { 418 | int ret = 0; 419 | byte[] tmp; 420 | tmp = Ip.GetAddressBytes(); 421 | buffer.Write(tmp, 0, tmp.Length); 422 | ret += tmp.Length; 423 | tmp = SubnetMask.GetAddressBytes(); 424 | buffer.Write(tmp, 0, tmp.Length); 425 | ret += tmp.Length; 426 | tmp = Gateway.GetAddressBytes(); 427 | buffer.Write(tmp, 0, tmp.Length); 428 | ret += tmp.Length; 429 | return ret; 430 | } 431 | } 432 | 433 | [TypeConverter(typeof(ExpandableObjectConverter))] 434 | public class DeviceIdInfo : IProfinetSerialize 435 | { 436 | public UInt16 VendorId { get; set; } 437 | public UInt16 DeviceId { get; set; } 438 | public DeviceIdInfo(UInt16 vendor_id, UInt16 device_id) 439 | { 440 | VendorId = vendor_id; 441 | DeviceId = device_id; 442 | } 443 | public override string ToString() 444 | { 445 | return "Vendor 0x" + VendorId.ToString("X") + " - Device 0x" + DeviceId.ToString("X"); 446 | } 447 | 448 | public int Serialize(System.IO.Stream buffer) 449 | { 450 | int ret = 0; 451 | ret += EncodeU16(buffer, VendorId); 452 | ret += EncodeU16(buffer, DeviceId); 453 | return ret; 454 | } 455 | public override bool Equals(object obj) 456 | { 457 | if (!(obj is DeviceIdInfo)) return false; 458 | DeviceIdInfo o = (DeviceIdInfo)obj; 459 | return o.DeviceId == DeviceId && o.VendorId == VendorId; 460 | } 461 | public override int GetHashCode() 462 | { 463 | UInt32 tmp = (uint)(VendorId << 16); 464 | tmp |= DeviceId; 465 | return tmp.GetHashCode(); 466 | } 467 | } 468 | 469 | [TypeConverter(typeof(ExpandableObjectConverter))] 470 | public class DeviceRoleInfo : IProfinetSerialize 471 | { 472 | public DeviceRoles DeviceRole { get; set; } 473 | 474 | public DeviceRoleInfo(DeviceRoles device_role) 475 | { 476 | DeviceRole = device_role; 477 | } 478 | 479 | public int Serialize(System.IO.Stream buffer) 480 | { 481 | int ret = 0; 482 | ret += EncodeU8(buffer, (byte)DeviceRole); 483 | buffer.WriteByte(0); //padding 484 | ret++; 485 | return ret; 486 | } 487 | 488 | public override string ToString() 489 | { 490 | return DeviceRole.ToString(); 491 | } 492 | } 493 | 494 | [TypeConverter(typeof(ExpandableObjectConverter))] 495 | public class ResponseStatus 496 | { 497 | public BlockOptions Option { get; set; } 498 | public BlockErrors Error { get; set; } 499 | public ResponseStatus() 500 | { 501 | } 502 | public ResponseStatus(BlockOptions Option, BlockErrors Error) 503 | { 504 | this.Option = Option; 505 | this.Error = Error; 506 | } 507 | public override string ToString() 508 | { 509 | return Error.ToString(); 510 | } 511 | } 512 | 513 | private static int EncodeNextBlock(System.IO.Stream buffer, KeyValuePair block) 514 | { 515 | int ret = 0; 516 | int tmp = 0; 517 | long DCPBlockLength_pos; 518 | 519 | ret += EncodeBlock(buffer, block.Key, 0, out DCPBlockLength_pos); 520 | 521 | //block info 522 | if (block.Value != null) ret += EncodeU16(buffer, 0); 523 | else return ret; 524 | 525 | if (block.Value is ResponseStatus) 526 | { 527 | buffer.Position -= 2; 528 | EncodeU16(buffer, (ushort)((ResponseStatus)block.Value).Option); 529 | tmp += EncodeU8(buffer, (byte)((ResponseStatus)block.Value).Error); 530 | } 531 | else if (block.Value is IProfinetSerialize) 532 | { 533 | tmp += ((IProfinetSerialize)block.Value).Serialize(buffer); 534 | } 535 | else if (block.Value is string) 536 | { 537 | tmp += EncodeString(buffer, (string)block.Value); 538 | } 539 | else if (block.Value is byte[]) 540 | { 541 | tmp += EncodeOctets(buffer, (byte[])block.Value); 542 | } 543 | else if (block.Value is BlockOptions[]) 544 | { 545 | foreach (BlockOptions b in (BlockOptions[])block.Value) 546 | { 547 | tmp += EncodeU16(buffer, (ushort)b); 548 | } 549 | } 550 | else 551 | { 552 | throw new NotImplementedException(); 553 | } 554 | 555 | //adjust length 556 | ReEncodeDCPDataLength(buffer, DCPBlockLength_pos); 557 | 558 | //padding 559 | ret += tmp; 560 | if ((tmp % 2) != 0) 561 | { 562 | buffer.WriteByte(0); 563 | ret++; 564 | } 565 | 566 | return ret; 567 | } 568 | 569 | private static int DecodeNextBlock(System.IO.Stream buffer, ushort dcp_length, out KeyValuePair block) 570 | { 571 | int ret = 0; 572 | BlockOptions options; 573 | UInt16 dcp_block_length; 574 | UInt16 block_info = 0; 575 | UInt16 tmp, tmp2; 576 | string str; 577 | object content; 578 | ResponseStatus set_response; 579 | 580 | if (buffer.Position >= buffer.Length || dcp_length <= 0) 581 | { 582 | block = new KeyValuePair(0, null); 583 | return ret; 584 | } 585 | 586 | ret += DecodeBlock(buffer, out options, out dcp_block_length); 587 | if (dcp_block_length >= 2) ret += DecodeU16(buffer, out block_info); 588 | dcp_block_length -= 2; 589 | 590 | switch (options) 591 | { 592 | case BlockOptions.DeviceProperties_NameOfStation: 593 | ret += DecodeString(buffer, dcp_block_length, out str); 594 | content = str; 595 | break; 596 | case BlockOptions.IP_IPParameter: 597 | byte[] ip, subnet, gateway; 598 | ret += DecodeOctets(buffer, 4, out ip); 599 | ret += DecodeOctets(buffer, 4, out subnet); 600 | ret += DecodeOctets(buffer, 4, out gateway); 601 | content = new IpInfo((BlockInfo)block_info, ip, subnet, gateway); ; 602 | break; 603 | case BlockOptions.DeviceProperties_DeviceID: 604 | ret += DecodeU16(buffer, out tmp); 605 | ret += DecodeU16(buffer, out tmp2); 606 | content = new DeviceIdInfo(tmp, tmp2); 607 | break; 608 | case BlockOptions.DeviceProperties_DeviceOptions: 609 | BlockOptions[] option_list = new BlockOptions[dcp_block_length / 2]; 610 | for (int i = 0; i < option_list.Length; i++) 611 | { 612 | ret += DecodeU16(buffer, out tmp); 613 | option_list[i] = (BlockOptions)tmp; 614 | } 615 | content = option_list; 616 | break; 617 | case BlockOptions.DeviceProperties_DeviceRole: 618 | DeviceRoles roles = (DeviceRoles)buffer.ReadByte(); 619 | buffer.ReadByte(); //padding 620 | ret += 2; 621 | content = new DeviceRoleInfo(roles); 622 | break; 623 | case BlockOptions.DeviceProperties_DeviceVendor: 624 | ret += DecodeString(buffer, dcp_block_length, out str); 625 | content = str; 626 | break; 627 | case BlockOptions.Control_Response: 628 | set_response = new ResponseStatus(); 629 | set_response.Option = (BlockOptions)block_info; 630 | set_response.Error = (BlockErrors)buffer.ReadByte(); 631 | ret++; 632 | content = set_response; 633 | break; 634 | default: 635 | byte[] arr; 636 | ret += DecodeOctets(buffer, dcp_block_length, out arr); 637 | content = arr; 638 | break; 639 | } 640 | block = new KeyValuePair(options, content); 641 | 642 | //padding 643 | if ((dcp_block_length % 2) != 0) 644 | { 645 | buffer.ReadByte(); 646 | ret++; 647 | } 648 | 649 | return ret; 650 | } 651 | 652 | public static int DecodeAllBlocks(System.IO.Stream buffer, ushort dcp_length, out Dictionary blocks) 653 | { 654 | int ret = 0, r; 655 | KeyValuePair value; 656 | blocks = new Dictionary(); 657 | while ((r = DCP.DecodeNextBlock(buffer, (ushort)(dcp_length - ret), out value)) > 0) 658 | { 659 | ret += r; 660 | if (!blocks.ContainsKey(value.Key)) blocks.Add(value.Key, value.Value); 661 | else Trace.TraceError("Multiple blocks in reply: " + value.Key); 662 | } 663 | if (r < 0) return r; //error 664 | else return ret; 665 | } 666 | 667 | public static int EncodeIdentifyRequest(System.IO.Stream buffer, UInt32 Xid) 668 | { 669 | int ret = 0; 670 | 671 | //Header 672 | ret += EncodeHeader(buffer, ServiceIds.Identify_Request, Xid, 1, 4); 673 | 674 | //optional filter (instead of the ALL block) 675 | //[NameOfStationBlock] ^ [AliasNameBlock], IdentifyReqBlock 676 | 677 | //IdentifyReqBlock 678 | /* DeviceRoleBlock ^ DeviceVendorBlock ^ DeviceIDBlock ^ 679 | DeviceOptionsBlock ^ OEMDeviceIDBlock ^ MACAddressBlock ^ 680 | IPParameterBlock ^ DHCPParameterBlock ^ 681 | ManufacturerSpecificParameterBlock */ 682 | 683 | //AllSelectorType 684 | ret += EncodeBlock(buffer, BlockOptions.AllSelector_AllSelector, 0); 685 | 686 | return ret; 687 | } 688 | 689 | public static int EncodeSetRequest(System.IO.Stream buffer, UInt32 Xid, BlockOptions options, BlockQualifiers qualifiers, byte[] data) 690 | { 691 | int ret = 0; 692 | int data_length = 0; 693 | bool do_pad = false; 694 | 695 | if (data != null) data_length = data.Length; 696 | if ((data_length % 2) != 0) do_pad = true; 697 | 698 | //The following is modified by F.Chaxel. 699 | //TODO: Test that decode still work 700 | 701 | ret += EncodeHeader(buffer, ServiceIds.Set_Request, Xid, 0, (ushort)(12 + data_length + (do_pad ? 1 : 0))); 702 | ret += EncodeBlock(buffer, options, (ushort)(2 + data_length)); 703 | 704 | ret += EncodeU16(buffer, (ushort)0); // Don't care 705 | 706 | //data 707 | EncodeOctets(buffer, data); 708 | 709 | //pad (re-ordered by f.chaxel) 710 | if (do_pad) ret += EncodeU8(buffer, 0); 711 | 712 | //BlockQualifier 713 | ret += EncodeBlock(buffer, BlockOptions.Control_Stop, (ushort)(2)); 714 | ret += EncodeU16(buffer, (ushort)qualifiers); 715 | 716 | return ret; 717 | } 718 | 719 | public static int EncodeGetRequest(System.IO.Stream buffer, UInt32 Xid, BlockOptions options) 720 | { 721 | int ret = 0; 722 | 723 | ret += EncodeHeader(buffer, ServiceIds.Get_Request, Xid, 0, 2); 724 | ret += EncodeU16(buffer, (ushort)options); 725 | 726 | return ret; 727 | } 728 | 729 | public static int EncodeHelloRequest(System.IO.Stream buffer, UInt32 Xid) 730 | { 731 | throw new NotImplementedException(); 732 | } 733 | 734 | public static int EncodeGetResponse(System.IO.Stream buffer, UInt32 Xid, BlockOptions options, object data) 735 | { 736 | int ret = 0; 737 | long dcp_length; 738 | 739 | ret += EncodeHeader(buffer, ServiceIds.Get_Response, Xid, 0, 0, out dcp_length); 740 | ret += EncodeNextBlock(buffer, new KeyValuePair(options, data)); 741 | ReEncodeDCPDataLength(buffer, dcp_length); 742 | 743 | return ret; 744 | } 745 | 746 | public static int EncodeSetResponse(System.IO.Stream buffer, UInt32 Xid, BlockOptions options, BlockErrors status) 747 | { 748 | int ret = 0; 749 | long dcp_length; 750 | 751 | ret += EncodeHeader(buffer, ServiceIds.Set_Response, Xid, 0, 0, out dcp_length); 752 | ret += EncodeNextBlock(buffer, new KeyValuePair(BlockOptions.Control_Response, new ResponseStatus(options, status))); 753 | ReEncodeDCPDataLength(buffer, dcp_length); 754 | 755 | return ret; 756 | } 757 | } 758 | } 759 | -------------------------------------------------------------------------------- /ProfinetTools.Logic/Protocols/Ethernet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Logic.Protocols 5 | { 6 | public class Ethernet 7 | { 8 | public enum Type : ushort 9 | { 10 | None = 0, 11 | Loop = 96, 12 | Echo = 512, 13 | IpV4 = 2048, 14 | Arp = 2054, 15 | WakeOnLan = 2114, 16 | ReverseArp = 32821, 17 | AppleTalk = 32923, 18 | AppleTalkArp = 33011, 19 | VLanTaggedFrame = 33024, 20 | NovellInternetworkPacketExchange = 33079, 21 | Novell = 33080, 22 | IpV6 = 34525, 23 | MacControl = 34824, 24 | CobraNet = 34841, 25 | MultiprotocolLabelSwitchingUnicast = 34887, 26 | MultiprotocolLabelSwitchingMulticast = 34888, 27 | PointToPointProtocolOverEthernetDiscoveryStage = 34915, 28 | PointToPointProtocolOverEthernetSessionStage = 34916, 29 | ExtensibleAuthenticationProtocolOverLan = 34958, 30 | HyperScsi = 34970, 31 | AtaOverEthernet = 34978, 32 | EtherCatProtocol = 34980, 33 | ProviderBridging = 34984, 34 | AvbTransportProtocol = 34997, 35 | LLDP = 35020, 36 | SerialRealTimeCommunicationSystemIii = 35021, 37 | CircuitEmulationServicesOverEthernet = 35032, 38 | HomePlug = 35041, 39 | MacSecurity = 35045, 40 | PrecisionTimeProtocol = 35063, 41 | ConnectivityFaultManagementOrOperationsAdministrationManagement = 35074, 42 | FibreChannelOverEthernet = 35078, 43 | FibreChannelOverEthernetInitializationProtocol = 35092, 44 | QInQ = 37120, 45 | VeritasLowLatencyTransport = 51966, 46 | } 47 | 48 | public static int Encode(System.IO.Stream buffer, System.Net.NetworkInformation.PhysicalAddress destination, System.Net.NetworkInformation.PhysicalAddress source, Type type) 49 | { 50 | //destination 51 | DCP.EncodeOctets(buffer, destination.GetAddressBytes()); 52 | 53 | //source 54 | DCP.EncodeOctets(buffer, source.GetAddressBytes()); 55 | 56 | //type 57 | DCP.EncodeU16(buffer, (ushort)type); 58 | 59 | return 14; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Protocols/RPC.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Logic.Protocols 5 | { 6 | public class RPC 7 | { 8 | public static Guid UUID_IO_ObjectInstance_XYZ = Guid.Parse("DEA00000-6C97-11D1-8271-000000000000"); 9 | public static Guid UUID_IO_DeviceInterface = Guid.Parse("DEA00001-6C97-11D1-8271-00A02442DF7D"); 10 | public static Guid UUID_IO_ControllerInterface = Guid.Parse("DEA00002-6C97-11D1-8271-00A02442DF7D"); 11 | public static Guid UUID_IO_SupervisorInterface = Guid.Parse("DEA00003-6C97-11D1-8271-00A02442DF7D"); 12 | public static Guid UUID_IO_ParameterServerInterface = Guid.Parse("DEA00004-6C97-11D1-8271-00A02442DF7D"); 13 | public static Guid UUID_EPMap_Interface = Guid.Parse("E1AF8308-5D1F-11C9-91A4-08002B14A0FA"); 14 | public static Guid UUID_EPMap_Object = Guid.Parse("00000000-0000-0000-0000-000000000000"); 15 | 16 | public enum PacketTypes : byte 17 | { 18 | Request = 0, 19 | Ping = 1, 20 | Response = 2, 21 | Fault = 3, 22 | Working = 4, 23 | NoCall = 5, 24 | Reject = 6, 25 | Acknowledge = 7, 26 | ConnectionlessCancel = 8, 27 | FragmentAcknowledge = 9, 28 | CancelAcknowledge = 10, 29 | } 30 | 31 | [Flags] 32 | public enum Flags1 : byte 33 | { 34 | LastFragment = 2, 35 | Fragment = 4, 36 | NoFragmentAckRequested = 8, 37 | Maybe = 16, 38 | Idempotent = 32, 39 | Broadcast = 64, 40 | } 41 | 42 | [Flags] 43 | public enum Flags2 : byte 44 | { 45 | CancelPendingAtCallEnd = 2, 46 | } 47 | 48 | [Flags] 49 | public enum Encodings : ushort 50 | { 51 | ASCII = 0x000, 52 | EBCDIC = 0x100, 53 | BigEndian = 0x000, 54 | LittleEndian = 0x1000, 55 | IEEE_float = 0, 56 | VAX_float = 1, 57 | CRAY_float = 2, 58 | IBM_float = 3, 59 | } 60 | 61 | public enum Operations : ushort 62 | { 63 | //IO device 64 | Connect = 0, 65 | Release = 1, 66 | Read = 2, 67 | Write = 3, 68 | Control = 4, 69 | ReadImplicit = 5, 70 | 71 | //Endpoint mapper 72 | Insert = 0, 73 | Delete = 1, 74 | Lookup = 2, 75 | Map = 3, 76 | LookupHandleFree = 4, 77 | InqObject = 5, 78 | MgmtDelete = 6, 79 | } 80 | 81 | public static Guid GenerateObjectInstanceUUID(UInt16 InstanceNo, byte InterfaceNo, UInt16 DeviceId, UInt16 VendorId) 82 | { 83 | byte[] bytes = UUID_IO_ObjectInstance_XYZ.ToByteArray(); 84 | UInt32 Data1 = BitConverter.ToUInt32(bytes, 0); 85 | UInt16 Data2 = BitConverter.ToUInt16(bytes, 4); 86 | UInt16 Data3 = BitConverter.ToUInt16(bytes, 6); 87 | byte Data4 = bytes[8]; 88 | byte Data5 = bytes[9]; 89 | InstanceNo &= 0xFFF; 90 | InstanceNo |= (UInt16)(InterfaceNo << 12); 91 | Guid ret = new Guid(Data1, Data2, Data3, Data4, Data5, (byte)(InstanceNo >> 8), (byte)(InstanceNo & 0xFF), (byte)(DeviceId >> 8), (byte)(DeviceId & 0xFF), (byte)(VendorId >> 8), (byte)(VendorId & 0xFF)); 92 | return ret; 93 | } 94 | 95 | public static int EncodeU32(System.IO.Stream buffer, Encodings encoding, UInt32 value) 96 | { 97 | if ((encoding & Encodings.LittleEndian) == Encodings.BigEndian) 98 | { 99 | buffer.WriteByte((byte)((value & 0xFF000000) >> 24)); 100 | buffer.WriteByte((byte)((value & 0x00FF0000) >> 16)); 101 | buffer.WriteByte((byte)((value & 0x0000FF00) >> 08)); 102 | buffer.WriteByte((byte)((value & 0x000000FF) >> 00)); 103 | } 104 | else 105 | { 106 | buffer.WriteByte((byte)((value & 0x000000FF) >> 00)); 107 | buffer.WriteByte((byte)((value & 0x0000FF00) >> 08)); 108 | buffer.WriteByte((byte)((value & 0x00FF0000) >> 16)); 109 | buffer.WriteByte((byte)((value & 0xFF000000) >> 24)); 110 | } 111 | return 4; 112 | } 113 | 114 | public static int DecodeU32(System.IO.Stream buffer, Encodings encoding, out UInt32 value) 115 | { 116 | if ((encoding & Encodings.LittleEndian) == Encodings.BigEndian) 117 | { 118 | value = (UInt32)((buffer.ReadByte() << 24) | (buffer.ReadByte() << 16) | (buffer.ReadByte() << 8) | (buffer.ReadByte() << 0)); 119 | } 120 | else 121 | { 122 | value = (UInt32)((buffer.ReadByte() << 0) | (buffer.ReadByte() << 8) | (buffer.ReadByte() << 16) | (buffer.ReadByte() << 24)); 123 | } 124 | return 4; 125 | } 126 | 127 | public static int EncodeU16(System.IO.Stream buffer, Encodings encoding, UInt16 value) 128 | { 129 | if ((encoding & Encodings.LittleEndian) == Encodings.BigEndian) 130 | { 131 | buffer.WriteByte((byte)((value & 0x0000FF00) >> 08)); 132 | buffer.WriteByte((byte)((value & 0x000000FF) >> 00)); 133 | } 134 | else 135 | { 136 | buffer.WriteByte((byte)((value & 0x000000FF) >> 00)); 137 | buffer.WriteByte((byte)((value & 0x0000FF00) >> 08)); 138 | } 139 | return 2; 140 | } 141 | 142 | public static int DecodeU16(System.IO.Stream buffer, Encodings encoding, out UInt16 value) 143 | { 144 | if ((encoding & Encodings.LittleEndian) == Encodings.BigEndian) 145 | { 146 | value = (UInt16)((buffer.ReadByte() << 8) | (buffer.ReadByte() << 0)); 147 | } 148 | else 149 | { 150 | value = (UInt16)((buffer.ReadByte() << 0) | (buffer.ReadByte() << 8)); 151 | } 152 | return 2; 153 | } 154 | 155 | public static int EncodeGuid(System.IO.Stream buffer, Encodings encoding, Guid value) 156 | { 157 | int ret = 0; 158 | byte[] bytes = value.ToByteArray(); 159 | UInt32 Data1 = BitConverter.ToUInt32(bytes, 0); 160 | UInt16 Data2 = BitConverter.ToUInt16(bytes, 4); 161 | UInt16 Data3 = BitConverter.ToUInt16(bytes, 6); 162 | byte[] Data4 = new byte[8]; 163 | Array.Copy(bytes, 8, Data4, 0, 8); 164 | ret += EncodeU32(buffer, encoding, Data1); 165 | ret += EncodeU16(buffer, encoding, Data2); 166 | ret += EncodeU16(buffer, encoding, Data3); 167 | ret += DCP.EncodeOctets(buffer, Data4); 168 | return ret; 169 | } 170 | 171 | public static int DecodeGuid(System.IO.Stream buffer, Encodings encoding, out Guid value) 172 | { 173 | int ret = 0; 174 | UInt32 Data1; 175 | UInt16 Data2; 176 | UInt16 Data3; 177 | byte[] Data4 = new byte[8]; 178 | 179 | ret += DecodeU32(buffer, encoding, out Data1); 180 | ret += DecodeU16(buffer, encoding, out Data2); 181 | ret += DecodeU16(buffer, encoding, out Data3); 182 | buffer.Read(Data4, 0, Data4.Length); 183 | ret += Data4.Length; 184 | 185 | value = new Guid((int)Data1, (short)Data2, (short)Data3, Data4); 186 | 187 | return ret; 188 | } 189 | 190 | public static int EncodeHeader(System.IO.Stream buffer, PacketTypes type, Flags1 flags1, Flags2 flags2, Encodings encoding, UInt16 serial_high_low, Guid object_id, Guid interface_id, Guid activity_id, UInt32 server_boot_time, UInt32 sequence_no, Operations op, UInt16 body_length, UInt16 fragment_no, out long body_length_position) 191 | { 192 | int ret = 0; 193 | 194 | ret += DCP.EncodeU8(buffer, 4); //RPCVersion 195 | ret += DCP.EncodeU8(buffer, (byte)type); 196 | ret += DCP.EncodeU8(buffer, (byte)flags1); 197 | ret += DCP.EncodeU8(buffer, (byte)flags2); 198 | ret += DCP.EncodeU16(buffer, (ushort)encoding); 199 | ret += DCP.EncodeU8(buffer, 0); //pad 200 | ret += DCP.EncodeU8(buffer, (byte)(serial_high_low >> 8)); 201 | ret += EncodeGuid(buffer, encoding, object_id); 202 | ret += EncodeGuid(buffer, encoding, interface_id); 203 | ret += EncodeGuid(buffer, encoding, activity_id); 204 | ret += EncodeU32(buffer, encoding, server_boot_time); 205 | ret += EncodeU32(buffer, encoding, 1); //interface version 206 | ret += EncodeU32(buffer, encoding, sequence_no); 207 | ret += EncodeU16(buffer, encoding, (ushort)op); 208 | ret += EncodeU16(buffer, encoding, 0xFFFF); //interface hint 209 | ret += EncodeU16(buffer, encoding, 0xFFFF); //activity hint 210 | body_length_position = buffer.Position; 211 | ret += EncodeU16(buffer, encoding, body_length); 212 | ret += EncodeU16(buffer, encoding, fragment_no); 213 | ret += DCP.EncodeU8(buffer, 0); //authentication protocol 214 | ret += DCP.EncodeU8(buffer, (byte)(serial_high_low & 0xFF)); 215 | 216 | return ret; 217 | } 218 | 219 | public static int DecodeHeader(System.IO.Stream buffer, out PacketTypes type, out Flags1 flags1, out Flags2 flags2, out Encodings encoding, out UInt16 serial_high_low, out Guid object_id, out Guid interface_id, out Guid activity_id, out UInt32 server_boot_time, out UInt32 sequence_no, out Operations op, out UInt16 body_length, out UInt16 fragment_no) 220 | { 221 | int ret = 0; 222 | byte tmp1; 223 | UInt16 tmp2; 224 | UInt32 tmp3; 225 | 226 | serial_high_low = 0; 227 | 228 | ret += DCP.DecodeU8(buffer, out tmp1); //RPCVersion 229 | if (tmp1 != 4) throw new Exception("Wrong protocol"); 230 | ret += DCP.DecodeU8(buffer, out tmp1); 231 | type = (PacketTypes)tmp1; 232 | ret += DCP.DecodeU8(buffer, out tmp1); 233 | flags1 = (Flags1)tmp1; 234 | ret += DCP.DecodeU8(buffer, out tmp1); 235 | flags2 = (Flags2)tmp1; 236 | ret += DCP.DecodeU16(buffer, out tmp2); 237 | encoding = (Encodings)tmp2; 238 | ret += DCP.DecodeU8(buffer, out tmp1); //pad 239 | ret += DCP.DecodeU8(buffer, out tmp1); 240 | serial_high_low |= (UInt16)(tmp1 << 8); 241 | ret += DecodeGuid(buffer, encoding, out object_id); 242 | ret += DecodeGuid(buffer, encoding, out interface_id); 243 | ret += DecodeGuid(buffer, encoding, out activity_id); 244 | ret += DecodeU32(buffer, encoding, out server_boot_time); 245 | ret += DecodeU32(buffer, encoding, out tmp3); //interface version 246 | if ((tmp3 & 0xFFFF) != 1) throw new Exception("Wrong protocol version"); 247 | ret += DecodeU32(buffer, encoding, out sequence_no); 248 | ret += DecodeU16(buffer, encoding, out tmp2); 249 | op = (Operations)tmp2; 250 | ret += DecodeU16(buffer, encoding, out tmp2); //interface hint 251 | ret += DecodeU16(buffer, encoding, out tmp2); //activity hint 252 | ret += DecodeU16(buffer, encoding, out body_length); 253 | ret += DecodeU16(buffer, encoding, out fragment_no); 254 | ret += DCP.DecodeU8(buffer, out tmp1); //authentication protocol 255 | ret += DCP.DecodeU8(buffer, out tmp1); 256 | serial_high_low |= tmp1; 257 | 258 | return ret; 259 | } 260 | 261 | public static void ReEncodeHeaderLength(System.IO.Stream buffer, Encodings encoding, long body_length_position) 262 | { 263 | long current_pos = buffer.Position; 264 | UInt16 actual_length = (UInt16)(buffer.Position - body_length_position - 6); 265 | 266 | buffer.Position = body_length_position; 267 | EncodeU16(buffer, encoding, actual_length); 268 | 269 | buffer.Position = current_pos; 270 | } 271 | 272 | public static int EncodeNDRDataHeader(System.IO.Stream buffer, Encodings encoding, UInt32 ArgsMaximum_or_PNIOStatus, UInt32 ArgsLength, UInt32 MaximumCount, UInt32 Offset, UInt32 ActualCount, out long NDRDataHeader_position) 273 | { 274 | int ret = 0; 275 | 276 | NDRDataHeader_position = buffer.Position; 277 | ret += EncodeU32(buffer, encoding, ArgsMaximum_or_PNIOStatus); 278 | ret += EncodeU32(buffer, encoding, ArgsLength); 279 | ret += EncodeU32(buffer, encoding, MaximumCount); 280 | ret += EncodeU32(buffer, encoding, Offset); 281 | ret += EncodeU32(buffer, encoding, ActualCount); 282 | 283 | return ret; 284 | } 285 | 286 | public static int DecodeNDRDataHeader(System.IO.Stream buffer, Encodings encoding, out UInt32 ArgsMaximum_or_PNIOStatus, out UInt32 ArgsLength, out UInt32 MaximumCount, out UInt32 Offset, out UInt32 ActualCount) 287 | { 288 | int ret = 0; 289 | 290 | ret += DecodeU32(buffer, encoding, out ArgsMaximum_or_PNIOStatus); 291 | ret += DecodeU32(buffer, encoding, out ArgsLength); 292 | ret += DecodeU32(buffer, encoding, out MaximumCount); 293 | ret += DecodeU32(buffer, encoding, out Offset); 294 | ret += DecodeU32(buffer, encoding, out ActualCount); 295 | 296 | return ret; 297 | } 298 | 299 | public static void ReEncodeNDRDataHeaderLength(System.IO.Stream buffer, Encodings encoding, long NDRDataHeader_position, bool re_encode_pniostatus) 300 | { 301 | long current_pos = buffer.Position; 302 | UInt32 actual_length = (UInt32)(buffer.Position - NDRDataHeader_position - 20); 303 | 304 | buffer.Position = NDRDataHeader_position; 305 | if (re_encode_pniostatus) EncodeU32(buffer, encoding, actual_length); //ArgsMaximum/PNIOStatus 306 | else buffer.Position += 4; 307 | EncodeU32(buffer, encoding, actual_length); //ArgsLength 308 | EncodeU32(buffer, encoding, actual_length); //MaximumCount 309 | buffer.Position += 4; 310 | EncodeU32(buffer, encoding, actual_length); //ActualCount 311 | 312 | buffer.Position = current_pos; 313 | } 314 | } 315 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Protocols/RT.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Logic.Protocols 5 | { 6 | public class RT 7 | { 8 | public enum FrameIds : ushort 9 | { 10 | PTCP_RTSyncPDU_With_Follow_Up = 0x20, 11 | PTCP_RTSyncPDU = 0x80, 12 | Alarm_High = 0xFC01, 13 | Alarm_Low = 0xFE01, 14 | DCP_Hello_ReqPDU = 0xFEFC, 15 | DCP_Get_Set_PDU = 0xFEFD, 16 | DCP_Identify_ReqPDU = 0xFEFE, 17 | DCP_Identify_ResPDU = 0xFEFF, 18 | PTCP_AnnouncePDU = 0xFF00, 19 | PTCP_FollowUpPDU = 0xFF20, 20 | PTCP_DelayReqPDU = 0xFF40, 21 | PTCP_DelayResPDU_With_Follow_Up = 0xFF41, 22 | PTCP_DelayFuResPDU_With_Follow_Up = 0xFF42, 23 | PTCP_DelayResPDU = 0xFF43, 24 | RTC_Start = 0xC000, 25 | RTC_End = 0xF7FF, 26 | } 27 | 28 | public const string MulticastMACAdd_Identify_Address = "01-0E-CF-00-00-00"; 29 | public const string MulticastMACAdd_Hello_Address = "01-0E-CF-00-00-01"; 30 | public const string MulticastMACAdd_Range1_Destination_Address = "01-0E-CF-00-01-01"; 31 | public const string MulticastMACAdd_Range1_Invalid_Address = "01-0E-CF-00-01-02"; 32 | public const string PTCP_MulticastMACAdd_Range2_Clock_Synchronization_Address = "01-0E-CF-00-04-00"; 33 | public const string PTCP_MulticastMACAdd_Range3_Clock_Synchronization_Address = "01-0E-CF-00-04-20"; 34 | public const string PTCP_MulticastMACAdd_Range4_Clock_Synchronization_Address = "01-0E-CF-00-04-40"; 35 | public const string PTCP_MulticastMACAdd_Range6_Clock_Synchronization_Address = "01-0E-CF-00-04-80"; 36 | public const string PTCP_MulticastMACAdd_Range8_Address = "01-80-C2-00-00-0E"; 37 | public const string RTC_PDU_RT_CLASS_3_Destination_Address = "01-0E-CF-00-01-01"; 38 | public const string RTC_PDU_RT_CLASS_3_Invalid_Address = "01-0E-CF-00-01-02"; 39 | 40 | public static int EncodeFrameId(System.IO.Stream buffer, FrameIds value) 41 | { 42 | return DCP.EncodeU16(buffer, (ushort)value); 43 | } 44 | 45 | public static int DecodeFrameId(System.IO.Stream buffer, out FrameIds value) 46 | { 47 | ushort val; 48 | DCP.DecodeU16(buffer, out val); 49 | value = (FrameIds)val; 50 | return 2; 51 | } 52 | 53 | [Flags] 54 | public enum DataStatus : byte 55 | { 56 | State_Primary = 1, /* 0 is Backup */ 57 | Redundancy_Backup = 2, /* 0 is Primary */ 58 | DataItemValid = 4, /* 0 is invalid */ 59 | ProviderState_Run = 1 << 4, /* 0 is stop */ 60 | StationProblemIndicator_Normal = 1 << 5, /* 0 is Detected */ 61 | Ignore = 1 << 7, /* 0 is Evaluate */ 62 | } 63 | 64 | [Flags] 65 | public enum TransferStatus : byte 66 | { 67 | OK = 0, 68 | AlignmentOrFrameChecksumError = 1, 69 | WrongLengthError = 2, 70 | MACReceiveBufferOverflow = 4, 71 | RT_CLASS_3_Error = 8, 72 | } 73 | 74 | [Flags] 75 | public enum IOxS : byte 76 | { 77 | Extension_MoreIOxSOctetFollows = 1, 78 | Instance_DetectedBySubslot = 0 << 5, 79 | Instance_DetectedBySlot = 1 << 5, 80 | Instance_DetectedByIODevice = 2 << 5, 81 | Instance_DetectedByIOController = 3 << 5, 82 | DataState_Good = 1 << 7, 83 | } 84 | 85 | [Flags] 86 | public enum PDUTypes : byte 87 | { 88 | //0x00 Reserved — 89 | Data = 1, //Shall only be used to encode the DATA-RTA-PDU 90 | Nack = 2, //Shall only be used to encode the NACK-RTA-PDU 91 | Ack = 3, //Shall only be used to encode the ACK-RTA-PDU 92 | Err = 4, //Shall only be used to encode the ERR-RTA-PDU 93 | //0x05 – 0x0F Reserved — 94 | Version1 = 1 << 4, 95 | } 96 | 97 | [Flags] 98 | public enum AddFlags : byte 99 | { 100 | WindowSizeOne = 1, 101 | TACK_ImmediateAcknowledge = 1 << 4, 102 | } 103 | 104 | public static int DecodeRTCStatus(System.IO.Stream buffer, out UInt16 CycleCounter, out DataStatus DataStatus, out TransferStatus TransferStatus) 105 | { 106 | int ret = 0; 107 | byte tmp; 108 | 109 | ret += DCP.DecodeU16(buffer, out CycleCounter); 110 | ret += DCP.DecodeU8(buffer, out tmp); 111 | DataStatus = (DataStatus)tmp; 112 | ret += DCP.DecodeU8(buffer, out tmp); 113 | TransferStatus = (TransferStatus)tmp; 114 | 115 | return ret; 116 | } 117 | 118 | public static int EncodeRTCStatus(System.IO.Stream buffer, UInt16 CycleCounter, DataStatus DataStatus, TransferStatus TransferStatus) 119 | { 120 | int ret = 0; 121 | 122 | ret += DCP.EncodeU16(buffer, CycleCounter); 123 | ret += DCP.EncodeU8(buffer, (byte)DataStatus); 124 | ret += DCP.EncodeU8(buffer, (byte)TransferStatus); 125 | 126 | return ret; 127 | } 128 | 129 | public static int DecodeRTAHeader(System.IO.Stream buffer, out UInt16 AlarmDestinationEndpoint, out UInt16 AlarmSourceEndpoint, out PDUTypes PDUType, out AddFlags AddFlags, out UInt16 SendSeqNum, out UInt16 AckSeqNum, out UInt16 VarPartLen) 130 | { 131 | int ret = 0; 132 | byte tmp; 133 | 134 | ret += DCP.DecodeU16(buffer, out AlarmDestinationEndpoint); 135 | ret += DCP.DecodeU16(buffer, out AlarmSourceEndpoint); 136 | ret += DCP.DecodeU8(buffer, out tmp); 137 | PDUType = (PDUTypes)tmp; 138 | ret += DCP.DecodeU8(buffer, out tmp); 139 | AddFlags = (AddFlags)tmp; 140 | ret += DCP.DecodeU16(buffer, out SendSeqNum); 141 | ret += DCP.DecodeU16(buffer, out AckSeqNum); 142 | ret += DCP.DecodeU16(buffer, out VarPartLen); 143 | 144 | return ret; 145 | } 146 | } 147 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Protocols/VLAN.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace ProfinetTools.Logic.Protocols 5 | { 6 | public class VLAN 7 | { 8 | public enum Priorities 9 | { 10 | /// 11 | /// DCP, IP 12 | /// 13 | Priority0 = 0, 14 | /// 15 | /// Low prior RTA_CLASS_1 or RTA_CLASS_UDP 16 | /// 17 | Priority5 = 5, 18 | /// 19 | /// RT_CLASS_UDP, RT_CLASS_1, RT_CLASS_2, RT_CLASS_3, high prior RTA_CLASS_1 or RTA_CLASS_UDP 20 | /// 21 | Priority6 = 6, 22 | /// 23 | /// PTCP-AnnouncePDU 24 | /// 25 | Priority7 = 7, 26 | } 27 | 28 | public enum Type : ushort 29 | { 30 | /// 31 | /// UDP, RPC, SNMP, ICMP 32 | /// 33 | IP = 0x0800, 34 | ARP = 0x0806, 35 | TagControlInformation = 0x8100, 36 | /// 37 | /// RTC, RTA, DCP, PTCP, FRAG 38 | /// 39 | PN = 0x8892, 40 | IEEE_802_1AS = 0x88F7, 41 | LLDP = 0x88CC, 42 | MRP = 0x88E3, 43 | } 44 | 45 | public static int Encode(System.IO.Stream buffer, Priorities priority, Type type) 46 | { 47 | UInt16 tmp = 0; 48 | 49 | //Priority 50 | tmp |= (UInt16)((((UInt16)priority) & 0x7) << 13); 51 | 52 | //CanonicalFormatIdentificator 53 | tmp |= 0 << 12; 54 | 55 | //VLAN_Id 56 | tmp |= 0; 57 | 58 | DCP.EncodeU16(buffer, tmp); 59 | DCP.EncodeU16(buffer, (UInt16)type); 60 | 61 | return 4; 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Services/AdaptersService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Reactive.Linq; 4 | using System.Reactive.Subjects; 5 | using ProfinetTools.Interfaces.Services; 6 | using SharpPcap; 7 | 8 | namespace ProfinetTools.Logic.Services 9 | { 10 | public class AdaptersService : IAdaptersService 11 | { 12 | private readonly BehaviorSubject selectedAdapterSubject = new BehaviorSubject(null); 13 | public List GetAdapters() 14 | { 15 | var devices = new List(); 16 | 17 | try 18 | { 19 | foreach (ICaptureDevice dev in CaptureDeviceList.Instance) 20 | devices.Add(dev); 21 | } 22 | catch (Exception e) 23 | { 24 | Console.WriteLine(e); 25 | } 26 | 27 | return devices; 28 | } 29 | 30 | public void SelectAdapter(ICaptureDevice adapter) 31 | { 32 | selectedAdapterSubject.OnNext(adapter); 33 | } 34 | 35 | public IObservable SelectedAdapter => selectedAdapterSubject.AsObservable(); 36 | } 37 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Services/DeviceService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reactive.Disposables; 5 | using System.Reactive.Linq; 6 | using System.Reactive.Subjects; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using ProfinetTools.Interfaces.Extensions; 10 | using ProfinetTools.Interfaces.Models; 11 | using ProfinetTools.Interfaces.Services; 12 | using ProfinetTools.Logic.Protocols; 13 | using ProfinetTools.Logic.Transport; 14 | using SharpPcap; 15 | 16 | namespace ProfinetTools.Logic.Services 17 | { 18 | public class DeviceService : IDeviceService 19 | { 20 | public async Task> GetDevices(ICaptureDevice adapter, TimeSpan timeout) 21 | { 22 | var disposables = new CompositeDisposable(); 23 | var transport = new ProfinetEthernetTransport(adapter); 24 | transport.Open(); 25 | transport.AddDisposableTo(disposables); 26 | 27 | var devices = new List(); 28 | 29 | Observable.FromEventPattern(h => transport.OnDcpMessage += h, h => transport.OnDcpMessage -= h) 30 | .Select(x => ConvertEventToDevice(x.Sender, x.EventArgs)) 31 | .Where(device => devices!=null) 32 | .Do(device => devices.Add(device)) 33 | .Subscribe() 34 | .AddDisposableTo(disposables) 35 | ; 36 | 37 | transport.SendIdentifyBroadcast(); 38 | 39 | await Task.Delay(timeout); 40 | 41 | disposables.Dispose(); 42 | 43 | return devices; 44 | } 45 | 46 | private readonly BehaviorSubject selectedDeviceSubject = new BehaviorSubject(null); 47 | 48 | public void SelectDevice(Device device) 49 | { 50 | selectedDeviceSubject.OnNext(device); 51 | } 52 | 53 | public IObservable SelectedDevice => selectedDeviceSubject.AsObservable(); 54 | 55 | private Device ConvertEventToDevice(ConnectionInfoEthernet sender, DcpMessageArgs args) 56 | { 57 | try 58 | { 59 | var device = new Device() 60 | { 61 | MAC = sender.Source.ToString(), 62 | Name = (string)args.Blocks[DCP.BlockOptions.DeviceProperties_NameOfStation], 63 | IP = ((DCP.IpInfo)args.Blocks[DCP.BlockOptions.IP_IPParameter]).Ip.ToString(), 64 | SubnetMask = ((DCP.IpInfo)args.Blocks[DCP.BlockOptions.IP_IPParameter]).SubnetMask.ToString(), 65 | Gateway = ((DCP.IpInfo)args.Blocks[DCP.BlockOptions.IP_IPParameter]).Gateway.ToString(), 66 | Type = (string)args.Blocks[DCP.BlockOptions.DeviceProperties_DeviceVendor], 67 | Role = ((DCP.DeviceRoleInfo)args.Blocks[DCP.BlockOptions.DeviceProperties_DeviceRole]).ToString() 68 | }; 69 | return device; 70 | } 71 | catch (Exception e) 72 | { 73 | Console.WriteLine(e); 74 | return null; 75 | } 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Services/SettingsService.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reactive.Disposables; 3 | using System.Threading.Tasks; 4 | using ProfinetTools.Interfaces.Extensions; 5 | using ProfinetTools.Interfaces.Models; 6 | using ProfinetTools.Interfaces.Services; 7 | using ProfinetTools.Logic.Protocols; 8 | using ProfinetTools.Logic.Transport; 9 | using SharpPcap; 10 | 11 | namespace ProfinetTools.Logic.Services 12 | { 13 | public class SettingsService : ISettingsService 14 | { 15 | private readonly int timeoutInMilliseconds = 3000; 16 | private readonly int retries = 2; 17 | 18 | public bool TryParseNetworkConfiguration(Device device) 19 | { 20 | try 21 | { 22 | System.Net.IPAddress ip = System.Net.IPAddress.Parse(device.IP); 23 | System.Net.IPAddress subnet = System.Net.IPAddress.Parse(device.SubnetMask); 24 | System.Net.IPAddress gateway = System.Net.IPAddress.Parse(device.Gateway); 25 | 26 | return true; 27 | } 28 | catch (Exception e) 29 | { 30 | return false; 31 | } 32 | } 33 | 34 | public Task SendSettings(ICaptureDevice adapter, string macAddress, Device newSettings) 35 | { 36 | var disposables = new CompositeDisposable(); 37 | var transport = new ProfinetEthernetTransport(adapter); 38 | transport.Open(); 39 | transport.AddDisposableTo(disposables); 40 | 41 | 42 | try 43 | { 44 | System.Net.NetworkInformation.PhysicalAddress deviceAddress = System.Net.NetworkInformation.PhysicalAddress.Parse(macAddress); 45 | 46 | DCP.BlockErrors err = transport.SendSetNameRequest(deviceAddress, timeoutInMilliseconds, retries, newSettings.Name); 47 | if (err != DCP.BlockErrors.NoError) return Task.FromResult(new SaveResult(false, err.ToString())); 48 | 49 | System.Net.IPAddress ip = System.Net.IPAddress.Parse(newSettings.IP); 50 | System.Net.IPAddress subnet = System.Net.IPAddress.Parse(newSettings.SubnetMask); 51 | System.Net.IPAddress gateway = System.Net.IPAddress.Parse(newSettings.Gateway); 52 | err = transport.SendSetIpRequest(deviceAddress, timeoutInMilliseconds, retries, ip, subnet, gateway); 53 | if (err != DCP.BlockErrors.NoError) return Task.FromResult(new SaveResult(false, err.ToString())); 54 | 55 | return Task.FromResult(new SaveResult(true, err.ToString())); 56 | } 57 | catch (Exception e) 58 | { 59 | return Task.FromResult(new SaveResult(false, e.Message)); 60 | } 61 | finally 62 | { 63 | disposables.Dispose(); 64 | } 65 | } 66 | 67 | public Task FactoryReset(ICaptureDevice adapter, string deviceName) 68 | { 69 | var disposables = new CompositeDisposable(); 70 | var transport = new ProfinetEthernetTransport(adapter); 71 | transport.Open(); 72 | transport.AddDisposableTo(disposables); 73 | 74 | System.Net.NetworkInformation.PhysicalAddress deviceAddress = System.Net.NetworkInformation.PhysicalAddress.Parse(deviceName); 75 | 76 | try 77 | { 78 | DCP.BlockErrors err = transport.SendSetResetRequest(deviceAddress, timeoutInMilliseconds, retries); 79 | if (err != DCP.BlockErrors.NoError) return Task.FromResult(new SaveResult(false, err.ToString())); 80 | 81 | return Task.FromResult(new SaveResult(false, err.ToString())); 82 | } 83 | catch (Exception e) 84 | { 85 | return Task.FromResult(new SaveResult(false, e.Message)); 86 | } 87 | finally 88 | { 89 | disposables.Dispose(); 90 | } 91 | } 92 | } 93 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Transport/ConnectionInfoEthernet.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Net.NetworkInformation; 3 | 4 | namespace ProfinetTools.Logic.Transport 5 | { 6 | public class ConnectionInfoEthernet 7 | { 8 | public ProfinetEthernetTransport Adapter; 9 | public PhysicalAddress Destination; 10 | public PhysicalAddress Source; 11 | public ConnectionInfoEthernet(ProfinetEthernetTransport adapter, PhysicalAddress destination, PhysicalAddress source) 12 | { 13 | Adapter = adapter; 14 | Destination = destination; 15 | Source = source; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Transport/DcpMessageArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using ProfinetTools.Logic.Protocols; 5 | 6 | namespace ProfinetTools.Logic.Transport 7 | { 8 | public class DcpMessageArgs 9 | { 10 | public DCP.ServiceIds ServiceID { get; } 11 | public uint Xid { get; } 12 | public ushort ResponseDelayFactor { get; } 13 | public Dictionary Blocks { get; } 14 | 15 | public DcpMessageArgs(DCP.ServiceIds serviceID, uint xid, ushort responseDelayFactor, Dictionary blocks) 16 | { 17 | ServiceID = serviceID; 18 | Xid = xid; 19 | ResponseDelayFactor = responseDelayFactor; 20 | Blocks = blocks; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /ProfinetTools.Logic/Transport/ProfinetEthernetTransport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Net; 7 | using System.Net.NetworkInformation; 8 | using System.Text; 9 | using ProfinetTools.Logic.Protocols; 10 | using SharpPcap; 11 | 12 | namespace ProfinetTools.Logic.Transport 13 | { 14 | public class ProfinetEthernetTransport : IDisposable 15 | { 16 | private ICaptureDevice adapter; 17 | private UInt32 lastXid = 0; 18 | private bool isOpen = false; 19 | 20 | public delegate void OnDcpMessageHandler(ConnectionInfoEthernet sender, DcpMessageArgs args); 21 | public event OnDcpMessageHandler OnDcpMessage; 22 | public delegate void OnAcyclicMessageHandler(ConnectionInfoEthernet sender, UInt16 alarmDestinationEndpoint, UInt16 alarmSourceEndpoint, RT.PDUTypes pduType, RT.AddFlags addFlags, UInt16 sendSeqNum, UInt16 ackSeqNum, UInt16 varPartLen, Stream data); 23 | public event OnAcyclicMessageHandler OnAcyclicMessage; 24 | public delegate void OnCyclicMessageHandler(ConnectionInfoEthernet sender, UInt16 cycleCounter, RT.DataStatus dataStatus, RT.TransferStatus transferStatus, Stream data, int dataLength); 25 | public event OnCyclicMessageHandler OnCyclicMessage; 26 | 27 | public bool IsOpen => isOpen; 28 | public ICaptureDevice Adapter => adapter; 29 | 30 | public ProfinetEthernetTransport(ICaptureDevice adapter) 31 | { 32 | this.adapter = adapter; 33 | this.adapter.OnPacketArrival += new PacketArrivalEventHandler(m_adapter_OnPacketArrival); 34 | } 35 | 36 | /// 37 | /// Will return pcap version. Use this to validate installed pcap library 38 | /// 39 | public static string PcapVersion 40 | { 41 | get 42 | { 43 | try 44 | { 45 | return SharpPcap.Pcap.Version; 46 | } 47 | catch { } 48 | return ""; 49 | } 50 | } 51 | 52 | public void Open() 53 | { 54 | if (isOpen) return; 55 | if (adapter is SharpPcap.WinPcap.WinPcapDevice) 56 | ((SharpPcap.WinPcap.WinPcapDevice)adapter).Open(SharpPcap.WinPcap.OpenFlags.MaxResponsiveness | SharpPcap.WinPcap.OpenFlags.NoCaptureLocal, -1); 57 | else 58 | adapter.Open(DeviceMode.Normal); 59 | adapter.Filter = "ether proto 0x8892 or vlan 0"; 60 | adapter.StartCapture(); 61 | isOpen = true; 62 | System.Threading.Thread.Sleep(50); //let the pcap start up 63 | } 64 | 65 | public void Close() 66 | { 67 | if (!isOpen) return; 68 | try 69 | { 70 | adapter.StopCapture(); 71 | } 72 | catch 73 | { 74 | } 75 | isOpen = false; 76 | } 77 | 78 | public void Dispose() 79 | { 80 | if (adapter != null) 81 | { 82 | Close(); 83 | adapter.Close(); 84 | adapter = null; 85 | } 86 | } 87 | 88 | public static DCP.IpInfo GetPcapIp(SharpPcap.ICaptureDevice pcapDevice) 89 | { 90 | foreach (System.Net.NetworkInformation.NetworkInterface nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()) 91 | { 92 | PhysicalAddress mac = null; 93 | try 94 | { 95 | mac = nic.GetPhysicalAddress(); 96 | } 97 | catch (Exception) 98 | { 99 | //interface have no mac address 100 | } 101 | 102 | if (mac != null && mac.Equals(pcapDevice.MacAddress)) 103 | { 104 | IPInterfaceProperties ipp = nic.GetIPProperties(); 105 | foreach (var entry in ipp.UnicastAddresses) 106 | { 107 | if (entry.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 108 | { 109 | byte[] gw = new byte[] { 0, 0, 0, 0 }; 110 | if (ipp.GatewayAddresses.Count > 0) gw = ipp.GatewayAddresses[0].Address.GetAddressBytes(); 111 | return new DCP.IpInfo(DCP.BlockInfo.IpSet, entry.Address.GetAddressBytes(), entry.IPv4Mask.GetAddressBytes(), gw); 112 | } 113 | } 114 | } 115 | } 116 | return null; 117 | } 118 | 119 | public static PhysicalAddress GetDeviceMac(string interfaceIp) 120 | { 121 | IPAddress searchIp = IPAddress.Parse(interfaceIp); 122 | foreach (System.Net.NetworkInformation.NetworkInterface nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()) 123 | { 124 | PhysicalAddress mac = null; 125 | try 126 | { 127 | mac = nic.GetPhysicalAddress(); 128 | } 129 | catch (Exception) 130 | { 131 | //interface have no mac address 132 | continue; 133 | } 134 | foreach (var entry in nic.GetIPProperties().UnicastAddresses) 135 | { 136 | if (searchIp.Equals(entry.Address)) 137 | { 138 | return mac; 139 | } 140 | } 141 | } 142 | return null; 143 | } 144 | 145 | public static SharpPcap.ICaptureDevice GetPcapDevice(string localIp) 146 | { 147 | IPAddress searchIp = IPAddress.Parse(localIp); 148 | PhysicalAddress searchMac = null; 149 | Dictionary networks = new Dictionary(); 150 | 151 | //search all networks 152 | foreach (System.Net.NetworkInformation.NetworkInterface nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()) 153 | { 154 | PhysicalAddress mac = null; 155 | try 156 | { 157 | mac = nic.GetPhysicalAddress(); 158 | } 159 | catch (Exception) 160 | { 161 | //interface have no mac address 162 | continue; 163 | } 164 | foreach (var entry in nic.GetIPProperties().UnicastAddresses) 165 | { 166 | if (searchIp.Equals(entry.Address)) 167 | { 168 | searchMac = mac; 169 | break; 170 | } 171 | } 172 | if (searchMac != null) break; 173 | } 174 | 175 | //validate 176 | if (searchMac == null) return null; 177 | 178 | //search all pcap networks 179 | foreach (SharpPcap.ICaptureDevice dev in SharpPcap.CaptureDeviceList.Instance) 180 | { 181 | try 182 | { 183 | dev.Open(); 184 | networks.Add(dev.MacAddress, dev); 185 | dev.Close(); 186 | } 187 | catch { } 188 | } 189 | 190 | //find link 191 | if (networks.ContainsKey(searchMac)) return networks[searchMac]; 192 | else return null; 193 | } 194 | 195 | public static System.Net.IPAddress GetNetworkAddress(System.Net.IPAddress address, System.Net.IPAddress subnetMask) 196 | { 197 | byte[] ipAdressBytes = address.GetAddressBytes(); 198 | byte[] subnetMaskBytes = subnetMask.GetAddressBytes(); 199 | 200 | if (ipAdressBytes.Length != subnetMaskBytes.Length) 201 | throw new ArgumentException("Lengths of IP address and subnet mask do not match."); 202 | 203 | byte[] broadcastAddress = new byte[ipAdressBytes.Length]; 204 | for (int i = 0; i < broadcastAddress.Length; i++) 205 | broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i])); 206 | return new System.Net.IPAddress(broadcastAddress); 207 | } 208 | 209 | public static string GetLocalIpAddress(string ipMatch) 210 | { 211 | System.Net.IPAddress target = System.Net.IPAddress.Parse(ipMatch); 212 | foreach (System.Net.NetworkInformation.NetworkInterface nic in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces()) 213 | { 214 | foreach (var entry in nic.GetIPProperties().UnicastAddresses) 215 | { 216 | if (entry.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) 217 | { 218 | if (GetNetworkAddress(entry.Address, entry.IPv4Mask).Equals(GetNetworkAddress(target, entry.IPv4Mask))) 219 | return entry.Address.ToString(); 220 | } 221 | } 222 | } 223 | return ""; 224 | } 225 | 226 | private void m_adapter_OnProfinetArrival(ConnectionInfoEthernet sender, Stream stream) 227 | { 228 | RT.FrameIds frameID; 229 | 230 | //Real Time 231 | RT.DecodeFrameId(stream, out frameID); 232 | if (frameID == RT.FrameIds.DCP_Identify_ResPDU || frameID == RT.FrameIds.DCP_Identify_ReqPDU || frameID == RT.FrameIds.DCP_Get_Set_PDU || frameID == RT.FrameIds.DCP_Hello_ReqPDU) 233 | { 234 | DCP.ServiceIds serviceID; 235 | uint xid; 236 | ushort responseDelayFactor; 237 | ushort dcpDataLength; 238 | DCP.DecodeHeader(stream, out serviceID, out xid, out responseDelayFactor, out dcpDataLength); 239 | Dictionary blocks; 240 | DCP.DecodeAllBlocks(stream, dcpDataLength, out blocks); 241 | if (OnDcpMessage != null) OnDcpMessage(sender, new DcpMessageArgs(serviceID, xid, responseDelayFactor, blocks)); 242 | } 243 | else if (frameID == RT.FrameIds.PTCP_DelayReqPDU) 244 | { 245 | //ignore this for now 246 | } 247 | else if (frameID >= RT.FrameIds.RTC_Start && frameID <= RT.FrameIds.RTC_End) 248 | { 249 | long dataPos = stream.Position; 250 | stream.Position = stream.Length - 4; 251 | UInt16 cycleCounter; 252 | RT.DataStatus dataStatus; 253 | RT.TransferStatus transferStatus; 254 | RT.DecodeRTCStatus(stream, out cycleCounter, out dataStatus, out transferStatus); 255 | stream.Position = dataPos; 256 | if (OnCyclicMessage != null) OnCyclicMessage(sender, cycleCounter, dataStatus, transferStatus, stream, (int)(stream.Length - dataPos - 4)); 257 | } 258 | else if (frameID == RT.FrameIds.Alarm_Low || frameID == RT.FrameIds.Alarm_High) 259 | { 260 | UInt16 alarmDestinationEndpoint; 261 | UInt16 alarmSourceEndpoint; 262 | RT.PDUTypes pduType; 263 | RT.AddFlags addFlags; 264 | UInt16 sendSeqNum; 265 | UInt16 ackSeqNum; 266 | UInt16 varPartLen; 267 | RT.DecodeRTAHeader(stream, out alarmDestinationEndpoint, out alarmSourceEndpoint, out pduType, out addFlags, out sendSeqNum, out ackSeqNum, out varPartLen); 268 | if (OnAcyclicMessage != null) OnAcyclicMessage(sender, alarmDestinationEndpoint, alarmSourceEndpoint, pduType, addFlags, sendSeqNum, ackSeqNum, varPartLen, stream); 269 | } 270 | else 271 | { 272 | Trace.TraceWarning("Unclassified RT message"); 273 | } 274 | } 275 | 276 | private void m_adapter_OnPacketArrival(object sender, CaptureEventArgs e) 277 | { 278 | if (e.Packet.LinkLayerType != PacketDotNet.LinkLayers.Ethernet) return; 279 | PacketDotNet.Utils.ByteArraySegment bas = new PacketDotNet.Utils.ByteArraySegment(e.Packet.Data); 280 | PacketDotNet.EthernetPacket ethP = new PacketDotNet.EthernetPacket(bas); 281 | if (ethP.Type != (PacketDotNet.EthernetPacketType)0x8892 && ethP.Type != PacketDotNet.EthernetPacketType.VLanTaggedFrame) return; 282 | if (ethP.PayloadPacket != null && ethP.PayloadPacket is PacketDotNet.Ieee8021QPacket) 283 | { 284 | if (((PacketDotNet.Ieee8021QPacket)ethP.PayloadPacket).Type != (PacketDotNet.EthernetPacketType)0x8892) return; 285 | if (((PacketDotNet.Ieee8021QPacket)ethP.PayloadPacket).PayloadData == null) 286 | { 287 | Trace.TraceWarning("Empty vlan package"); 288 | return; 289 | } 290 | m_adapter_OnProfinetArrival(new ConnectionInfoEthernet(this, ethP.DestinationHwAddress, ethP.SourceHwAddress), new MemoryStream(((PacketDotNet.Ieee8021QPacket)ethP.PayloadPacket).PayloadData, false)); 291 | } 292 | else 293 | { 294 | if (ethP.PayloadData == null) 295 | { 296 | Trace.TraceWarning("Empty ethernet package"); 297 | return; 298 | } 299 | m_adapter_OnProfinetArrival(new ConnectionInfoEthernet(this, ethP.DestinationHwAddress, ethP.SourceHwAddress), new MemoryStream(ethP.PayloadData, false)); 300 | } 301 | } 302 | 303 | private void Send(MemoryStream stream) 304 | { 305 | byte[] buffer = stream.GetBuffer(); 306 | adapter.SendPacket(buffer, (int)stream.Position); 307 | } 308 | 309 | public void SendIdentifyBroadcast() 310 | { 311 | Trace.WriteLine("Sending identify broadcast", null); 312 | 313 | MemoryStream mem = new MemoryStream(); 314 | 315 | //ethernet 316 | PhysicalAddress ethernetDestinationHwAddress = PhysicalAddress.Parse(RT.MulticastMACAdd_Identify_Address); 317 | Ethernet.Encode(mem, ethernetDestinationHwAddress, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 318 | 319 | //VLAN 320 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 321 | 322 | //Profinet Real Time 323 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Identify_ReqPDU); 324 | 325 | //Profinet DCP 326 | DCP.EncodeIdentifyRequest(mem, ++lastXid); 327 | 328 | //Send 329 | Send(mem); 330 | } 331 | 332 | public void SendIdentifyResponse(PhysicalAddress destination, uint xid, Dictionary blocks) 333 | { 334 | Trace.WriteLine("Sending identify response", null); 335 | 336 | MemoryStream mem = new MemoryStream(); 337 | 338 | //ethernet 339 | Ethernet.Encode(mem, destination, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 340 | 341 | //VLAN 342 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 343 | 344 | //Profinet Real Time 345 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Identify_ResPDU); 346 | 347 | //Profinet DCP 348 | DCP.EncodeIdentifyResponse(mem, xid, blocks); 349 | 350 | //Send 351 | Send(mem); 352 | } 353 | 354 | public void SendCyclicData(PhysicalAddress destination, UInt16 frameID, UInt16 cycleCounter, byte[] userData) 355 | { 356 | Trace.WriteLine("Sending cyclic data", null); 357 | 358 | MemoryStream mem = new MemoryStream(); 359 | 360 | //ethernet 361 | Ethernet.Encode(mem, destination, adapter.MacAddress, (Ethernet.Type)0x8892); 362 | 363 | //Profinet Real Time 364 | RT.EncodeFrameId(mem, (RT.FrameIds)frameID); 365 | 366 | //user data 367 | if (userData == null) userData = new byte[40]; 368 | if (userData.Length < 40) Array.Resize(ref userData, 40); 369 | mem.Write(userData, 0, userData.Length); 370 | 371 | //RT footer 372 | RT.EncodeRTCStatus(mem, cycleCounter, RT.DataStatus.DataItemValid | 373 | RT.DataStatus.State_Primary | 374 | RT.DataStatus.ProviderState_Run | 375 | RT.DataStatus.StationProblemIndicator_Normal, 376 | RT.TransferStatus.OK); 377 | 378 | //Send 379 | Send(mem); 380 | } 381 | 382 | public class ProfinetAsyncDcpResult : IAsyncResult, IDisposable 383 | { 384 | private System.Threading.ManualResetEvent mWait = new System.Threading.ManualResetEvent(false); 385 | private uint mXid; 386 | private ProfinetEthernetTransport mConn = null; 387 | 388 | public object AsyncState { get; set; } 389 | public System.Threading.WaitHandle AsyncWaitHandle { get { return mWait; } } 390 | public bool CompletedSynchronously { get; private set; } //always false 391 | public bool IsCompleted { get; private set; } 392 | 393 | public Dictionary Result { get; private set; } 394 | 395 | public ProfinetAsyncDcpResult(ProfinetEthernetTransport conn, MemoryStream message, UInt32 xid) 396 | { 397 | mConn = conn; 398 | conn.OnDcpMessage += new OnDcpMessageHandler(conn_OnDcpMessage); 399 | mXid = xid; 400 | conn.Send(message); 401 | } 402 | 403 | private void conn_OnDcpMessage(ConnectionInfoEthernet sender, DcpMessageArgs args) 404 | { 405 | if (args.Xid == mXid) 406 | { 407 | Result = args.Blocks; 408 | IsCompleted = true; 409 | mWait.Set(); 410 | } 411 | } 412 | 413 | public void Dispose() 414 | { 415 | if (mConn != null) 416 | { 417 | mConn.OnDcpMessage -= conn_OnDcpMessage; 418 | mConn = null; 419 | } 420 | } 421 | } 422 | 423 | public IAsyncResult BeginGetRequest(PhysicalAddress destination, DCP.BlockOptions option) 424 | { 425 | Trace.WriteLine("Sending Get " + option.ToString() + " request", null); 426 | 427 | MemoryStream mem = new MemoryStream(); 428 | 429 | //ethernet 430 | Ethernet.Encode(mem, destination, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 431 | 432 | //VLAN 433 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 434 | 435 | //Profinet Real Time 436 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Get_Set_PDU); 437 | 438 | //Profinet DCP 439 | UInt32 xid = ++lastXid; 440 | DCP.EncodeGetRequest(mem, xid, option); 441 | //start Async 442 | return new ProfinetAsyncDcpResult(this, mem, xid); 443 | } 444 | 445 | public void SendGetResponse(PhysicalAddress destination, uint xid, DCP.BlockOptions option, object data) 446 | { 447 | Trace.WriteLine("Sending Get " + option.ToString() + " response", null); 448 | 449 | MemoryStream mem = new MemoryStream(); 450 | 451 | //ethernet 452 | Ethernet.Encode(mem, destination, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 453 | 454 | //VLAN 455 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 456 | 457 | //Profinet Real Time 458 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Get_Set_PDU); 459 | 460 | //Profinet DCP 461 | DCP.EncodeGetResponse(mem, xid, option, data); 462 | 463 | //send 464 | Send(mem); 465 | } 466 | 467 | public IAsyncResult BeginSetRequest(PhysicalAddress destination, DCP.BlockOptions option, DCP.BlockQualifiers qualifiers, byte[] data) 468 | { 469 | Trace.WriteLine("Sending Set " + option.ToString() + " request", null); 470 | 471 | MemoryStream mem = new MemoryStream(); 472 | 473 | //ethernet 474 | Ethernet.Encode(mem, destination, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 475 | 476 | //VLAN 477 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 478 | 479 | //Profinet Real Time 480 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Get_Set_PDU); 481 | 482 | //Profinet DCP 483 | UInt32 xid = ++lastXid; 484 | DCP.EncodeSetRequest(mem, xid, option, qualifiers, data); 485 | 486 | //start Async 487 | return new ProfinetAsyncDcpResult(this, mem, xid); 488 | } 489 | 490 | public void SendSetResponse(PhysicalAddress destination, uint xid, DCP.BlockOptions option, DCP.BlockErrors status) 491 | { 492 | Trace.WriteLine("Sending Set " + option.ToString() + " response", null); 493 | 494 | MemoryStream mem = new MemoryStream(); 495 | 496 | //ethernet 497 | Ethernet.Encode(mem, destination, adapter.MacAddress, Ethernet.Type.VLanTaggedFrame); 498 | 499 | //VLAN 500 | VLAN.Encode(mem, VLAN.Priorities.Priority0, VLAN.Type.PN); 501 | 502 | //Profinet Real Time 503 | RT.EncodeFrameId(mem, RT.FrameIds.DCP_Get_Set_PDU); 504 | 505 | //Profinet DCP 506 | DCP.EncodeSetResponse(mem, xid, option, status); 507 | 508 | //Send 509 | Send(mem); 510 | } 511 | 512 | public DCP.BlockErrors EndSetRequest(IAsyncResult result, int timeoutMs) 513 | { 514 | ProfinetAsyncDcpResult r = (ProfinetAsyncDcpResult)result; 515 | 516 | if (result.AsyncWaitHandle.WaitOne(timeoutMs)) 517 | { 518 | DCP.BlockErrors ret = r.Result.ContainsKey(DCP.BlockOptions.Control_Response) ? ((DCP.ResponseStatus)r.Result[DCP.BlockOptions.Control_Response]).Error : DCP.BlockErrors.NoError; 519 | r.Dispose(); 520 | return ret; 521 | } 522 | else 523 | { 524 | r.Dispose(); 525 | throw new TimeoutException("No response received"); 526 | } 527 | } 528 | 529 | public Dictionary EndGetRequest(IAsyncResult result, int timeoutMs) 530 | { 531 | ProfinetAsyncDcpResult r = (ProfinetAsyncDcpResult)result; 532 | 533 | if (result.AsyncWaitHandle.WaitOne(timeoutMs)) 534 | { 535 | Dictionary ret = r.Result; 536 | r.Dispose(); 537 | return ret; 538 | } 539 | else 540 | { 541 | r.Dispose(); 542 | throw new TimeoutException("No response received"); 543 | } 544 | } 545 | 546 | public IAsyncResult BeginSetSignalRequest(PhysicalAddress destination) 547 | { 548 | return BeginSetRequest(destination, DCP.BlockOptions.Control_Signal, DCP.BlockQualifiers.Temporary, BitConverter.GetBytes((ushort)0x100)); //SignalValue - Flash once 549 | } 550 | 551 | public IAsyncResult BeginSetResetRequest(PhysicalAddress destination) 552 | { 553 | return BeginSetRequest(destination, DCP.BlockOptions.Control_FactoryReset, DCP.BlockQualifiers.Permanent, null); 554 | } 555 | 556 | public IAsyncResult BeginSetNameRequest(PhysicalAddress destination, string name) 557 | { 558 | byte[] bytes = Encoding.ASCII.GetBytes(name); 559 | return BeginSetRequest(destination, DCP.BlockOptions.DeviceProperties_NameOfStation, DCP.BlockQualifiers.Permanent, bytes); 560 | } 561 | 562 | public IAsyncResult BeginSetIpRequest(PhysicalAddress destination, IPAddress ip, IPAddress subnetMask, IPAddress gateway) 563 | { 564 | byte[] bytes = new byte[12]; 565 | Array.Copy(ip.GetAddressBytes(), 0, bytes, 0, 4); 566 | Array.Copy(subnetMask.GetAddressBytes(), 0, bytes, 4, 4); 567 | Array.Copy(gateway.GetAddressBytes(), 0, bytes, 8, 4); 568 | return BeginSetRequest(destination, DCP.BlockOptions.IP_IPParameter, DCP.BlockQualifiers.Permanent, bytes); 569 | } 570 | 571 | public IAsyncResult BeginSetIpFullRequest(PhysicalAddress destination, IPAddress ip, IPAddress subnetMask, IPAddress gateway, IPAddress[] dns) 572 | { 573 | byte[] bytes = new byte[28]; 574 | Array.Copy(ip.GetAddressBytes(), 0, bytes, 0, 4); 575 | Array.Copy(subnetMask.GetAddressBytes(), 0, bytes, 4, 4); 576 | Array.Copy(gateway.GetAddressBytes(), 0, bytes, 8, 4); 577 | if (dns == null || dns.Length != 4) throw new ArgumentException("dns array length must be 4"); 578 | for (int i = 0; i < 4; i++) 579 | Array.Copy(dns[i].GetAddressBytes(), 0, bytes, 12 + i * 4, 4); 580 | return BeginSetRequest(destination, DCP.BlockOptions.IP_FullIPSuite, DCP.BlockQualifiers.Permanent, bytes); 581 | } 582 | 583 | public DCP.BlockErrors SendSetRequest(PhysicalAddress destination, int timeoutMs, int retries, DCP.BlockOptions option, DCP.BlockQualifiers qualifiers, byte[] data) 584 | { 585 | for (int r = 0; r < retries; r++) 586 | { 587 | IAsyncResult asyncResult = BeginSetRequest(destination, option, qualifiers, data); 588 | try 589 | { 590 | return EndSetRequest(asyncResult, timeoutMs); 591 | } 592 | catch (TimeoutException) 593 | { 594 | //continue 595 | } 596 | } 597 | throw new TimeoutException("No response received"); 598 | } 599 | 600 | public DCP.BlockErrors SendSetRequest(PhysicalAddress destination, int timeoutMs, int retries, DCP.BlockOptions option, byte[] data) 601 | { 602 | return SendSetRequest(destination, timeoutMs, retries, option, DCP.BlockQualifiers.Permanent, data); 603 | } 604 | 605 | public Dictionary SendGetRequest(PhysicalAddress destination, int timeoutMs, int retries, DCP.BlockOptions option) 606 | { 607 | for (int r = 0; r < retries; r++) 608 | { 609 | IAsyncResult asyncResult = BeginGetRequest(destination, option); 610 | try 611 | { 612 | return EndGetRequest(asyncResult, timeoutMs); 613 | } 614 | catch (TimeoutException) 615 | { 616 | //continue 617 | } 618 | } 619 | throw new TimeoutException("No response received"); 620 | } 621 | 622 | public DCP.BlockErrors SendSetSignalRequest(PhysicalAddress destination, int timeoutMs, int retries) 623 | { 624 | for (int r = 0; r < retries; r++) 625 | { 626 | IAsyncResult asyncResult = BeginSetSignalRequest(destination); 627 | try 628 | { 629 | return EndSetRequest(asyncResult, timeoutMs); 630 | } 631 | catch (TimeoutException) 632 | { 633 | //continue 634 | } 635 | } 636 | throw new TimeoutException("No response received"); 637 | } 638 | 639 | public DCP.BlockErrors SendSetResetRequest(PhysicalAddress destination, int timeoutMs, int retries) 640 | { 641 | for (int r = 0; r < retries; r++) 642 | { 643 | IAsyncResult asyncResult = BeginSetResetRequest(destination); 644 | try 645 | { 646 | return EndSetRequest(asyncResult, timeoutMs); 647 | } 648 | catch (TimeoutException) 649 | { 650 | //continue 651 | } 652 | } 653 | throw new TimeoutException("No response received"); 654 | } 655 | 656 | public DCP.BlockErrors SendSetNameRequest(PhysicalAddress destination, int timeoutMs, int retries, string name) 657 | { 658 | for (int r = 0; r < retries; r++) 659 | { 660 | IAsyncResult asyncResult = BeginSetNameRequest(destination, name); 661 | try 662 | { 663 | return EndSetRequest(asyncResult, timeoutMs); 664 | } 665 | catch (TimeoutException) 666 | { 667 | //continue 668 | } 669 | } 670 | throw new TimeoutException("No response received"); 671 | } 672 | 673 | public DCP.BlockErrors SendSetIpFullRequest(PhysicalAddress destination, int timeoutMs, int retries, IPAddress ip, IPAddress subnetMask, IPAddress gateway, IPAddress[] dns) 674 | { 675 | for (int r = 0; r < retries; r++) 676 | { 677 | IAsyncResult asyncResult = BeginSetIpFullRequest(destination, ip, subnetMask, gateway, dns); 678 | try 679 | { 680 | return EndSetRequest(asyncResult, timeoutMs); 681 | } 682 | catch (TimeoutException) 683 | { 684 | //continue 685 | } 686 | } 687 | throw new TimeoutException("No response received"); 688 | } 689 | 690 | public DCP.BlockErrors SendSetIpRequest(PhysicalAddress destination, int timeoutMs, int retries, IPAddress ip, IPAddress subnetMask, IPAddress gateway) 691 | { 692 | for (int r = 0; r < retries; r++) 693 | { 694 | IAsyncResult asyncResult = BeginSetIpRequest(destination, ip, subnetMask, gateway); 695 | try 696 | { 697 | return EndSetRequest(asyncResult, timeoutMs); 698 | } 699 | catch (TimeoutException) 700 | { 701 | //continue 702 | } 703 | } 704 | throw new TimeoutException("No response received"); 705 | } 706 | } 707 | } 708 | -------------------------------------------------------------------------------- /ProfinetTools.Logic/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ProfinetTools.Setup/Fragments/Fragments.wxs: -------------------------------------------------------------------------------- 1 |  2 | 3 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /ProfinetTools.Setup/Paraffin/Create.bat: -------------------------------------------------------------------------------- 1 | mkdir ..\Fragments 2 | Paraffin.exe -dir ..\..\out\Release ^ 3 | -NoRootDirectory ^ 4 | -alias $(var.SourcePath) ^ 5 | -GroupName ProfinetToolsFragments ..\Fragments\Fragments.wxs ^ 6 | -ext .json ^ 7 | -ext .sdf ^ 8 | -regExExclude "\.vshost\." ^ 9 | -regExExclude "\.dll\.conf" 10 | -------------------------------------------------------------------------------- /ProfinetTools.Setup/Paraffin/Update.bat: -------------------------------------------------------------------------------- 1 | Paraffin.exe -update -verbose ..\Fragments\Fragments.wxs 2 | move /Y ..\Fragments\Fragments.PARAFFIN ..\Fragments\Fragments.wxs -------------------------------------------------------------------------------- /ProfinetTools.Setup/Paraffin/Zen of Paraffin.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarresi/ProfinetTools/0315f0f698efd886809ba177edd7ee8e38b5166f/ProfinetTools.Setup/Paraffin/Zen of Paraffin.docx -------------------------------------------------------------------------------- /ProfinetTools.Setup/Product.wxs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 19 | 20 | 24 | 25 | 26 | 31 | 37 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 1 49 | 1 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 71 | 72 | 79 | 80 | 81 | 82 | 83 | 84 | 90 | 91 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 119 | 121 | 122 | 125 | 126 | 127 | 128 | 130 | NEWPRODUCTFOUND 131 | 132 | 133 | 134 | 135 | 138 | 139 | 141 | NEWPRODUCTFOUND 142 | 143 | 144 | 145 | 146 | 147 | -------------------------------------------------------------------------------- /ProfinetTools.Setup/ProfinetTools.Setup.wixproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | x86 6 | 3.10 7 | e6c11d5c-ed2c-43a9-8df9-15d36df77f6f 8 | 2.0 9 | ProfinetTools.Setup 10 | Package 11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets 12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets 13 | $(MSBuildProgramFiles32) 14 | $(ProgramFiles%28x86%29) 15 | $(ProgramFiles) (x86) 16 | $(ProgramFiles) 17 | 18 | 19 | bin\$(Configuration)\ 20 | obj\$(Configuration)\ 21 | Debug 22 | 23 | 24 | bin\$(Configuration)\ 25 | obj\$(Configuration)\ 26 | SourcePath=..\out\$(Configuration) 27 | VersionNumber=0.9.9.9; 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | $(WixExtDir)\WixUtilExtension.dll 52 | WixUtilExtension 53 | 54 | 55 | $(WixExtDir)\WixUIExtension.dll 56 | WixUIExtension 57 | 58 | 59 | $(WixExtDir)\WixNetFxExtension.dll 60 | WixNetFxExtension 61 | 62 | 63 | 64 | 72 | -------------------------------------------------------------------------------- /ProfinetTools.Setup/Resources/installer_background.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarresi/ProfinetTools/0315f0f698efd886809ba177edd7ee8e38b5166f/ProfinetTools.Setup/Resources/installer_background.bmp -------------------------------------------------------------------------------- /ProfinetTools.Setup/Resources/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarresi/ProfinetTools/0315f0f698efd886809ba177edd7ee8e38b5166f/ProfinetTools.Setup/Resources/logo.ico -------------------------------------------------------------------------------- /ProfinetTools.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27130.2024 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfinetTools", "ProfinetTools\ProfinetTools.csproj", "{8C9C17B3-A185-4D73-9645-A8871F7B17EC}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfinetTools.Gui", "ProfinetTools.Gui\ProfinetTools.Gui.csproj", "{F7D721A7-EB1B-4688-B535-63FCBEB12DAB}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfinetTools.Interfaces", "ProfinetTools.Interfaces\ProfinetTools.Interfaces.csproj", "{F23836B7-30F9-4A77-8EA1-8C57B7BC953F}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ProfinetTools.Logic", "ProfinetTools.Logic\ProfinetTools.Logic.csproj", "{6696F4A6-C9A5-49F3-8463-16A85BACB6E6}" 13 | EndProject 14 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ProfinetTools.Setup", "ProfinetTools.Setup\ProfinetTools.Setup.wixproj", "{E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}" 15 | EndProject 16 | Global 17 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 18 | Debug|Any CPU = Debug|Any CPU 19 | Debug|x86 = Debug|x86 20 | Release|Any CPU = Release|Any CPU 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 24 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Debug|x86.ActiveCfg = Debug|Any CPU 27 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Debug|x86.Build.0 = Debug|Any CPU 28 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Release|x86.ActiveCfg = Release|Any CPU 31 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC}.Release|x86.Build.0 = Release|Any CPU 32 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Debug|x86.ActiveCfg = Debug|Any CPU 35 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Debug|x86.Build.0 = Debug|Any CPU 36 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Release|x86.ActiveCfg = Release|Any CPU 39 | {F7D721A7-EB1B-4688-B535-63FCBEB12DAB}.Release|x86.Build.0 = Release|Any CPU 40 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Debug|x86.ActiveCfg = Debug|Any CPU 43 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Debug|x86.Build.0 = Debug|Any CPU 44 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Release|Any CPU.Build.0 = Release|Any CPU 46 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Release|x86.ActiveCfg = Release|Any CPU 47 | {F23836B7-30F9-4A77-8EA1-8C57B7BC953F}.Release|x86.Build.0 = Release|Any CPU 48 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 49 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Debug|Any CPU.Build.0 = Debug|Any CPU 50 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Debug|x86.ActiveCfg = Debug|Any CPU 51 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Debug|x86.Build.0 = Debug|Any CPU 52 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Release|Any CPU.ActiveCfg = Release|Any CPU 53 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Release|Any CPU.Build.0 = Release|Any CPU 54 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Release|x86.ActiveCfg = Release|Any CPU 55 | {6696F4A6-C9A5-49F3-8463-16A85BACB6E6}.Release|x86.Build.0 = Release|Any CPU 56 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Debug|Any CPU.ActiveCfg = Debug|x86 57 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Debug|x86.ActiveCfg = Debug|x86 58 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Debug|x86.Build.0 = Debug|x86 59 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Release|Any CPU.ActiveCfg = Release|x86 60 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Release|Any CPU.Build.0 = Release|x86 61 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Release|x86.ActiveCfg = Release|x86 62 | {E6C11D5C-ED2C-43A9-8DF9-15D36DF77F6F}.Release|x86.Build.0 = Release|x86 63 | EndGlobalSection 64 | GlobalSection(SolutionProperties) = preSolution 65 | HideSolutionNode = FALSE 66 | EndGlobalSection 67 | GlobalSection(ExtensibilityGlobals) = postSolution 68 | SolutionGuid = {83582AD7-A74F-4279-BE1A-C1272663677F} 69 | EndGlobalSection 70 | EndGlobal 71 | -------------------------------------------------------------------------------- /ProfinetTools/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /ProfinetTools/ProfinetTools.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8C9C17B3-A185-4D73-9645-A8871F7B17EC} 8 | WinExe 9 | ProfinetTools 10 | ProfinetTools 11 | v4.5.2 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | ..\out\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | ..\out\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | ..\packages\log4net.2.0.12\lib\net45\log4net.dll 39 | True 40 | 41 | 42 | ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 4.0 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Code 65 | 66 | 67 | True 68 | True 69 | Resources.resx 70 | 71 | 72 | True 73 | Settings.settings 74 | True 75 | 76 | 77 | ResXFileCodeGenerator 78 | Resources.Designer.cs 79 | 80 | 81 | 82 | SettingsSingleFileGenerator 83 | Settings.Designer.cs 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | {f7d721a7-eb1b-4688-b535-63fcbeb12dab} 92 | ProfinetTools.Gui 93 | 94 | 95 | {f23836b7-30f9-4a77-8ea1-8c57b7bc953f} 96 | ProfinetTools.Interfaces 97 | 98 | 99 | {6696f4a6-c9a5-49f3-8463-16a85bacb6e6} 100 | ProfinetTools.Logic 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /ProfinetTools/Program.cs: -------------------------------------------------------------------------------- 1 | using log4net; 2 | using log4net.Appender; 3 | using log4net.Config; 4 | using log4net.Layout; 5 | using Ninject; 6 | using ProfinetTools.Logic; 7 | using ProfinetTools.Gui; 8 | using ProfinetTools.Gui.ViewModels; 9 | using ProfinetTools.Gui.Views; 10 | using System; 11 | using System.Reflection; 12 | using System.Windows; 13 | using ProfinetTools.Interfaces.Commons; 14 | using App = ProfinetTools.Gui.App; 15 | 16 | namespace ProfinetTools 17 | { 18 | public static class ApplicationExtensions 19 | { 20 | public static void ReplaceViewModelLocator(this Application application, IViewModelFactory viewModelLocator, string locatorKey = "Locator") 21 | { 22 | if (application.Resources.Contains(locatorKey)) 23 | application.Resources.Remove(locatorKey); 24 | application.Resources.Add(locatorKey, viewModelLocator); 25 | } 26 | } 27 | 28 | internal class Program 29 | { 30 | private static ILog s_Logger; 31 | 32 | private static Application CreateApplication(IViewModelFactory viewModelLocator) 33 | { 34 | var application = new App(); 35 | 36 | application.InitializeComponent(); 37 | application.ReplaceViewModelLocator(viewModelLocator); 38 | 39 | return application; 40 | } 41 | 42 | private static void LoadModules(IKernel kernel) 43 | { 44 | kernel.Load(); 45 | kernel.Load(); 46 | } 47 | 48 | [STAThread] 49 | private static void Main() 50 | { 51 | using (IKernel kernel = new StandardKernel()) 52 | { 53 | LoadModules(kernel); 54 | 55 | var x = new ConsoleAppender { Layout = new SimpleLayout() }; 56 | BasicConfigurator.Configure(x); 57 | 58 | s_Logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 59 | 60 | var viewModelFactory = kernel.Get(); 61 | var application = CreateApplication(viewModelFactory); 62 | 63 | var mainWindowViewModel = viewModelFactory.CreateViewModel(); 64 | s_Logger.Info("Initializing application"); 65 | 66 | var mainWindow = kernel.Get(); 67 | mainWindow.DataContext = mainWindowViewModel; 68 | 69 | application.Run(mainWindow); 70 | application.Shutdown(); 71 | } 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /ProfinetTools/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Resources; 3 | using System.Runtime.CompilerServices; 4 | using System.Runtime.InteropServices; 5 | using System.Windows; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("ProfinetTools")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("")] 14 | [assembly: AssemblyProduct("ProfinetTools")] 15 | [assembly: AssemblyCopyright("Copyright © 2018")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | //In order to begin building localizable applications, set 25 | //CultureYouAreCodingWith in your .csproj file 26 | //inside a . For example, if you are using US english 27 | //in your source files, set the to en-US. Then uncomment 28 | //the NeutralResourceLanguage attribute below. Update the "en-US" in 29 | //the line below to match the UICulture setting in the project file. 30 | 31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] 32 | 33 | 34 | [assembly: ThemeInfo( 35 | ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located 36 | //(used if a resource is not found in the page, 37 | // or application resource dictionaries) 38 | ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located 39 | //(used if a resource is not found in the page, 40 | // app, or any theme specific resource dictionaries) 41 | )] 42 | 43 | 44 | // Version information for an assembly consists of the following four values: 45 | // 46 | // Major Version 47 | // Minor Version 48 | // Build Number 49 | // Revision 50 | // 51 | // You can specify all the values or you can default the Build and Revision Numbers 52 | // by using the '*' as shown below: 53 | // [assembly: AssemblyVersion("1.0.*")] 54 | [assembly: AssemblyVersion("1.0.0.0")] 55 | [assembly: AssemblyFileVersion("1.0.0.0")] 56 | -------------------------------------------------------------------------------- /ProfinetTools/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ProfinetTools.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ProfinetTools.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /ProfinetTools/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /ProfinetTools/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace ProfinetTools.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /ProfinetTools/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /ProfinetTools/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProfinetTools 2 | [![Build status](https://ci.appveyor.com/api/projects/status/4mi4rm9dnhgjg3cp?svg=true)](https://ci.appveyor.com/project/fbarresi/profinettools) 3 | 4 | Tools for profinet configuration 5 | 6 | # Requirements 7 | This software is based on the famouse *WinPcap* libraris. 8 | 9 | I suggest to use the [npcap](https://nmap.org/npcap/) improvement for better performace. 10 | 11 | Plese download it from [here](https://nmap.org/npcap/dist/npcap-0.98.exe) and install it. 12 | 13 | During the installation choose the option **WinPcap compatibility** 14 | 15 | # Installation 16 | 17 | Dowload the latest version of ProfinetTools from [here](https://github.com/fbarresi/ProfinetTools/releases/latest) 18 | you just need to execute the setup. 19 | 20 | # Usage 21 | 22 | ProfinetTools is an improvement of the opensource project [profinetexplorer](https://sourceforge.net/projects/profinetexplorer/) writte with modern WPF and reactive programming. 23 | 24 | It has a very simple user interface that allows you to scan your profinet network and assign names or ip configurations. 25 | 26 | ![alt text][screenshot] 27 | 28 | [screenshot]: https://github.com/fbarresi/ProfinetTools/blob/master/docs/screenshot.png "screenshot" 29 | -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fbarresi/ProfinetTools/0315f0f698efd886809ba177edd7ee8e38b5166f/docs/screenshot.png --------------------------------------------------------------------------------