diff --git a/.gitignore b/.gitignore index 7a7ca06..cf445f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,236 +1,8 @@ -## Ignore Visual Studio temporary files, build results, and -## files generated by popular Visual Studio add-ons. +### -# User-specific files -*.suo -*.user -*.userosscache -*.sln.docstates - -# User-specific files (MonoDevelop/Xamarin Studio) -*.userprefs - -# Build results -[Dd]ebug/ -[Dd]ebugPublic/ -[Rr]elease/ -[Rr]eleases/ -x64/ -x86/ -bld/ -[Bb]in/ [Oo]bj/ +[Bb]in/ -# Visual Studio 2015 cache/options directory -.vs/ -# Uncomment if you have tasks that create the project's static files in wwwroot -#wwwroot/ - -# MSTest test Results -[Tt]est[Rr]esult*/ -[Bb]uild[Ll]og.* - -# NUNIT -*.VisualState.xml -TestResult.xml - -# Build Results of an ATL Project -[Dd]ebugPS/ -[Rr]eleasePS/ -dlldata.c - -# DNX -project.lock.json -artifacts/ - -*_i.c -*_p.c -*_i.h -*.ilk -*.meta -*.obj -*.pch -*.pdb -*.pgc -*.pgd -*.rsp -*.sbr -*.tlb -*.tli -*.tlh -*.tmp -*.tmp_proj -*.log -*.vspscc -*.vssscc -.builds -*.pidb -*.svclog -*.scc - -# Chutzpah Test files -_Chutzpah* - -# Visual C++ cache files -ipch/ -*.aps -*.ncb -*.opendb -*.opensdf -*.sdf -*.cachefile - -# Visual Studio profiler -*.psess -*.vsp -*.vspx -*.sap - -# TFS 2012 Local Workspace -$tf/ - -# Guidance Automation Toolkit -*.gpState - -# ReSharper is a .NET coding add-in -_ReSharper*/ -*.[Rr]e[Ss]harper -*.DotSettings.user - -# JustCode is a .NET coding add-in -.JustCode - -# TeamCity is a build add-in -_TeamCity* - -# DotCover is a Code Coverage Tool -*.dotCover - -# NCrunch -_NCrunch_* -.*crunch*.local.xml -nCrunchTemp_* - -# MightyMoose -*.mm.* -AutoTest.Net/ - -# Web workbench (sass) -.sass-cache/ - -# Installshield output folder -[Ee]xpress/ - -# DocProject is a documentation generator add-in -DocProject/buildhelp/ -DocProject/Help/*.HxT -DocProject/Help/*.HxC -DocProject/Help/*.hhc -DocProject/Help/*.hhk -DocProject/Help/*.hhp -DocProject/Help/Html2 -DocProject/Help/html - -# Click-Once directory -publish/ - -# Publish Web Output -*.[Pp]ublish.xml -*.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings -# but database connection strings (with potential passwords) will be unencrypted -*.pubxml -*.publishproj - -# NuGet Packages -*.nupkg -# The packages folder can be ignored because of Package Restore -**/packages/* -# except build/, which is used as an MSBuild target. -!**/packages/build/ -# Uncomment if necessary however generally it will be regenerated when needed -#!**/packages/repositories.config -# NuGet v3's project.json files produces more ignoreable files -*.nuget.props -*.nuget.targets - -# Microsoft Azure Build Output -csx/ -*.build.csdef - -# Microsoft Azure Emulator -ecf/ -rcf/ - -# Microsoft Azure ApplicationInsights config file -ApplicationInsights.config - -# Windows Store app package directory -AppPackages/ -BundleArtifacts/ - -# Visual Studio cache files -# files ending in .cache can be ignored -*.[Cc]ache -# but keep track of directories ending in .cache -!*.[Cc]ache/ - -# Others -ClientBin/ -~$* -*~ -*.dbmdl -*.dbproj.schemaview -*.pfx -*.publishsettings -node_modules/ -orleans.codegen.cs - -# RIA/Silverlight projects -Generated_Code/ - -# Backup & report files from converting an old project file -# to a newer Visual Studio version. Backup files are not needed, -# because we have git ;-) -_UpgradeReport_Files/ -Backup*/ -UpgradeLog*.XML -UpgradeLog*.htm - -# SQL Server files -*.mdf -*.ldf - -# Business Intelligence projects -*.rdl.data -*.bim.layout -*.bim_*.settings - -# Microsoft Fakes -FakesAssemblies/ - -# GhostDoc plugin setting file -*.GhostDoc.xml - -# Node.js Tools for Visual Studio -.ntvs_analysis.dat - -# Visual Studio 6 build log -*.plg - -# Visual Studio 6 workspace options file -*.opt - -# Visual Studio LightSwitch build output -**/*.HTMLClient/GeneratedArtifacts -**/*.DesktopClient/GeneratedArtifacts -**/*.DesktopClient/ModelManifest.xml -**/*.Server/GeneratedArtifacts -**/*.Server/ModelManifest.xml -_Pvt_Extensions - -# Paket dependency manager -.paket/paket.exe - -# FAKE - F# Make -.fake/ +.vs +*.suo +*.user \ No newline at end of file diff --git a/README.md b/README.md index c1f3af9..a32d6a8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -A .NET wrapper around Beckhoff's TwinCAT.Ads API library. Project is not affiliated with Beckhoff. +High-level interface for Beckhoff's TwinCAT.Ads API library. Project is not affiliated with Beckhoff. Getting started =============== @@ -15,7 +15,7 @@ With help of Ads.Remote.PLC.Router you can add new route record into the remote Installation ------------ -TwinCAT 2 or 3 must be installed. +TwinCAT 2 or 3 have to be installed. Examples =============== @@ -47,11 +47,12 @@ private void Plc_DeviceReady(object sender, AdsDevice e) Create a copy of your PLC's variable then use it like an ordinary variable ```C# -Var main_count = plc.Var("MAIN.count"); -Var main_state = plc.Var("MAIN.state"); -Var frm0 = plc.Var("Inputs.Frm0InputToggle", 27907); -Var devState = plc.Var(0xF030, 0x5FE, 27907); -Var g_Version = plc.Var(".VERSION"); +Var main_count = plc.Var ("MAIN.count"); +Var main_state = plc.Var("MAIN.state"); +Var g_Version = plc.Var(".VERSION"); + +Var frm0 = plc.Var("Inputs.Frm0InputToggle", 27907); +Var devState = plc.Var(0xF030, 0x5FE, 27907); long framesTotal += frm0 / 2; // automatic type casting MessageBox.Show(frm0); // cast into the string type without call of the ToString() diff --git a/lib/TwinCAT.Ads.dll b/lib/TwinCAT.Ads.dll deleted file mode 100644 index 82b7654..0000000 Binary files a/lib/TwinCAT.Ads.dll and /dev/null differ diff --git a/src/AdsRemote/Ads.Remote.csproj b/src/AdsRemote/Ads.Remote.csproj index eb33b43..5d34735 100644 --- a/src/AdsRemote/Ads.Remote.csproj +++ b/src/AdsRemote/Ads.Remote.csproj @@ -23,7 +23,7 @@ 4 - pdbonly + none true ..\..\bin\Release\ @@ -33,9 +33,9 @@ - + False - ..\..\lib\TwinCAT.Ads.dll + C:\TwinCAT\AdsApi\.NET\v4.0.30319\TwinCAT.Ads.dll diff --git a/src/AdsRemote/AmsRouter.cs b/src/AdsRemote/AmsRouter.cs index 9accfb4..41ee28f 100644 --- a/src/AdsRemote/AmsRouter.cs +++ b/src/AdsRemote/AmsRouter.cs @@ -220,10 +220,8 @@ private static RemotePlcInfo ParseBroadcastSearchResponse(ResponseResult rr) // TCat type byte[] tcatType = rr.NextChunk(Segment.TCATTYPE_RUNTIME.Length); if (tcatType[0] == Segment.TCATTYPE_RUNTIME[0]) - { if (tcatType[2] == Segment.TCATTYPE_RUNTIME[2]) device.IsRuntime = true; - } // OS version byte[] osVer = rr.NextChunk(Segment.L_OSVERSION); @@ -239,7 +237,6 @@ private static RemotePlcInfo ParseBroadcastSearchResponse(ResponseResult rr) int ci = tail.Length - 4; for (int i = ci; i > 0; i -= 4) - { if (tail[i + 0] == 3 && tail[i + 2] == 4) { @@ -250,7 +247,6 @@ private static RemotePlcInfo ParseBroadcastSearchResponse(ResponseResult rr) device.TcVersion.Build = tail[i + 6] + tail[i + 7] * 256; break; } - } // Comment byte[] descMarker = rr.NextChunk(Segment.L_DESCRIPTIONMARKER); @@ -259,7 +255,6 @@ private static RemotePlcInfo ParseBroadcastSearchResponse(ResponseResult rr) if (descMarker[0] == 2) { if (isUnicode) - { for (int i = 0; i < c; i += 2) { if (rr.Buffer[rr.Shift + i] == 0 && @@ -267,32 +262,29 @@ private static RemotePlcInfo ParseBroadcastSearchResponse(ResponseResult rr) break; len += 2; } - } else - { for (int i = 0; i < c; i++) { if (rr.Buffer[rr.Shift + i] == 0) break; len++; } - } if (len > 0) { byte[] description = rr.NextChunk(len); - if (isUnicode) + if (!isUnicode) + device.Comment = ASCIIEncoding.Default.GetString(description); + else { byte[] asciiBytes = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, description); char[] asciiChars = new char[Encoding.ASCII.GetCharCount(asciiBytes, 0, asciiBytes.Length)]; Encoding.ASCII.GetChars(asciiBytes, 0, asciiBytes.Length, asciiChars, 0); device.Comment = new string(asciiChars); } - else - device.Comment = ASCIIEncoding.Default.GetString(description); } - } + } // if (descMarker[0] == 2) return device; } diff --git a/src/AdsRemote/Common/AdsDevice.cs b/src/AdsRemote/Common/AdsDevice.cs index 2eb3204..7439c44 100644 --- a/src/AdsRemote/Common/AdsDevice.cs +++ b/src/AdsRemote/Common/AdsDevice.cs @@ -21,7 +21,7 @@ internal AdsDevice(AmsNetId amsNetId, int port) internal void SetActive(bool isActive) { - this.isReady = isActive; + isReady = isActive; } } } diff --git a/src/AdsRemote/Common/VarBase.cs b/src/AdsRemote/Common/VarBase.cs index 2b4d8c3..7625620 100644 --- a/src/AdsRemote/Common/VarBase.cs +++ b/src/AdsRemote/Common/VarBase.cs @@ -38,9 +38,7 @@ public void Dispose() protected virtual void Dispose(bool disposing) { if (disposing) - { TryUnsubscribe(); - } } } } diff --git a/src/AdsRemote/IPHelper.cs b/src/AdsRemote/IPHelper.cs index 85ca362..38aece1 100644 --- a/src/AdsRemote/IPHelper.cs +++ b/src/AdsRemote/IPHelper.cs @@ -13,9 +13,7 @@ public static IPAddress GetBroadcastAddress(IPAddress localhost) IPAddress hostMask = GetHostMask(localhost); if (hostMask == null || localhost == null) - { return null; - } byte[] complementedMaskBytes = new byte[4]; byte[] broadcastIpBytes = new byte[4]; @@ -48,12 +46,8 @@ public static IPAddress GetHostMask(IPAddress localhost) UnicastIPAddressInformationCollection unicastInfos = netInterface.GetIPProperties().UnicastAddresses; foreach (UnicastIPAddressInformation info in unicastInfos) - { if (info.Address.ToString() == strLocalAddress) - { return info.IPv4Mask; - } - } } return null; @@ -70,31 +64,22 @@ public static List Localhosts public static List FilteredLocalhosts(List niTypes = null) { if (niTypes == null) - { - niTypes = new List - { - NetworkInterfaceType.Wireless80211, - NetworkInterfaceType.Ethernet - }; - } + niTypes = + new List + { + NetworkInterfaceType.Wireless80211, + NetworkInterfaceType.Ethernet + }; List localhosts = new List(); foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) - { if (niTypes.Contains(ni.NetworkInterfaceType)) - { foreach (UnicastIPAddressInformation unicastInfo in ni.GetIPProperties().UnicastAddresses) - { if (unicastInfo.Address.AddressFamily == AddressFamily.InterNetwork) - { localhosts.Add(unicastInfo.Address); - } - } - } - } return localhosts; } - } + } // class } diff --git a/src/AdsRemote/PLC.cs b/src/AdsRemote/PLC.cs index 16eff24..36776f4 100644 --- a/src/AdsRemote/PLC.cs +++ b/src/AdsRemote/PLC.cs @@ -120,9 +120,7 @@ private void PingThread(CancellationToken token, SynchronizationContext uiContex lock (_locker_dict_PortDevice) { if (devices.Count != dict_PortDevice.Values.Count) - { devices = new List(dict_PortDevice.Values); - } } foreach (AdsDevice device in devices) @@ -137,13 +135,10 @@ private void PingThread(CancellationToken token, SynchronizationContext uiContex { Var v = device.Vars[0]; if(v.IndexGroup > -1 && v.IndexOffset > -1) - { device.AdsClient.ReadAny(v.IndexGroup, v.IndexOffset, v.ValueType); - } else - { device.AdsClient.ReadSymbol(v.Name, v.ValueType, !device.Ready); - } + isActive = true; } catch { } @@ -157,9 +152,7 @@ private void PingThread(CancellationToken token, SynchronizationContext uiContex } // foreach (AdsDevice device in devices) if (!token.IsCancellationRequested) - { Thread.Sleep(updateList.Count > 0 ? Tune_ReinitInterval : Tune_PingSleepInterval); - } foreach(AdsDevice device in updateList) { @@ -208,9 +201,7 @@ protected virtual void OnDeviceLost(object obj_Device) AdsDevice device = (AdsDevice)obj_Device; foreach (Var v in device.Vars) - { v.TryUnsubscribe(); - } EventHandler handle = DeviceLost; handle?.Invoke(this, device); @@ -242,9 +233,7 @@ private Var CreateVariable(string varName, int Port, long IGrp = -1, long { Var v; if (dict_NameVar.TryGetValue(varName, out v)) - { return (Var)v; - } Var var; AdsDevice device; @@ -273,9 +262,7 @@ private Var CreateVariable(string varName, int Port, long IGrp = -1, long dict_NameVar.Add(varName, var); if (device.Ready) - { var.TrySubscribe(); - } return var; } @@ -307,9 +294,7 @@ public Var Var(string Variable, AmsPort3 Port) public T Class(T instance = default(T)) where T : new() { - T o = instance; - if (o == null) - o = new T(); + T o = instance == null ? new T() : instance; #region Properties PropertyInfo[] properties = o.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public); @@ -321,13 +306,9 @@ public Var Var(string Variable, AmsPort3 Port) Type t = null; if (pr.PropertyType.IsGenericType) - { t = pr.PropertyType.GetGenericArguments()[0]; - } else - { t = la.As; - } if (t != null) { @@ -345,8 +326,8 @@ public Var Var(string Variable, AmsPort3 Port) if (v != null) pr.SetValue(o, v); - } - } + } // if (t != null) + } // if (la != null) } //foreach(PropertyInfo pr in properties) #endregion @@ -360,13 +341,9 @@ public Var Var(string Variable, AmsPort3 Port) Type t = null; if (fi.FieldType.IsGenericType) - { t = fi.FieldType.GetGenericArguments()[0]; - } else - { t = la.As; - } if (t != null) { @@ -404,14 +381,10 @@ protected virtual void Dispose(bool disposing) if (disposing) { foreach (Var v in dict_NameVar.Values) - { v.TryUnsubscribe(); - } if (cancelTokenSource != null) - { cancelTokenSource.Cancel(); - } } } } diff --git a/src/AdsRemote/Properties/AssemblyInfo.cs b/src/AdsRemote/Properties/AssemblyInfo.cs index 6962a6c..fd2bac5 100644 --- a/src/AdsRemote/Properties/AssemblyInfo.cs +++ b/src/AdsRemote/Properties/AssemblyInfo.cs @@ -1,6 +1,6 @@ using System.Reflection; [assembly: AssemblyTitle("AdsRemote")] -[assembly: AssemblyDescription("Automation interface for TwinCAT.Ads API")] +[assembly: AssemblyDescription("High-level interface for TwinCAT.Ads API")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Nikolai Voronin")] [assembly: AssemblyProduct("AdsRemote")] diff --git a/src/AdsRemote/Var.cs b/src/AdsRemote/Var.cs index e1426fd..19bb820 100644 --- a/src/AdsRemote/Var.cs +++ b/src/AdsRemote/Var.cs @@ -65,9 +65,7 @@ internal override bool TryUnsubscribe() try { if (NotifyHandle > -1) - { Device.AdsClient.DeleteDeviceNotification(NotifyHandle); - } } catch { @@ -82,7 +80,6 @@ internal override bool TrySubscribe() try { if (IndexGroup == -1 && IndexOffset == -1) - { try { ITcAdsSymbol sym = Device.AdsClient.ReadSymbolInfo(RemoteName); @@ -90,10 +87,8 @@ internal override bool TrySubscribe() IndexOffset = sym.IndexOffset; } catch { } - } if (IndexGroup > -1 && IndexOffset > -1) - { NotifyHandle = Device.AdsClient.AddDeviceNotificationEx( IndexGroup, IndexOffset, @@ -101,9 +96,7 @@ internal override bool TrySubscribe() this, typeof(T) ); - } else - { NotifyHandle = Device.AdsClient.AddDeviceNotificationEx( RemoteName, @@ -111,7 +104,6 @@ internal override bool TrySubscribe() this, typeof(T) ); - } } catch { @@ -142,5 +134,5 @@ public override object GetValue() } public override Type ValueType { get { return typeof(T); } } - } + } // class } diff --git a/src/CxFinder/CxFinder.csproj b/src/CxFinder/CxFinder.csproj index 14c26e6..cfa6a36 100644 --- a/src/CxFinder/CxFinder.csproj +++ b/src/CxFinder/CxFinder.csproj @@ -39,9 +39,9 @@ - + False - ..\..\lib\TwinCAT.Ads.dll + C:\TwinCAT\AdsApi\.NET\v4.0.30319\TwinCAT.Ads.dll diff --git a/src/CxFinder/MainForm.cs b/src/CxFinder/MainForm.cs index 6e5126d..9224dca 100644 --- a/src/CxFinder/MainForm.cs +++ b/src/CxFinder/MainForm.cs @@ -33,7 +33,7 @@ private string AppShortVersion private void MainForm_Load(object sender, EventArgs e) { - this.Text = APP_NAME + AppShortVersion; + Text = APP_NAME + AppShortVersion; FormNiCombo(); statusStatusLabel.Text = STATUS_READY; @@ -99,23 +99,28 @@ private async void searchButton_Click(object sender, EventArgs e) niComboBox.Enabled = ethCheckBox.Enabled = wlanCheckBox.Enabled = lbCheckBox.Enabled = false; ComboBoxItem si = (ComboBoxItem)niComboBox.SelectedItem; - List di = await AmsRouter.BroadcastSearchAsync((IPAddress)si.Value, timeout * 1000); + List di = + await AmsRouter.BroadcastSearchAsync( + (IPAddress)si.Value, + timeout * 1000); cxListView.Items.Clear(); foreach(RemotePlcInfo info in di) { - ListViewItem lvi = new ListViewItem( new string[] - { - info.Name, - info.Address.ToString(), - info.AmsNetId.ToString(), - string.Concat( - info.TcVersion.Version.ToString(), ".", - info.TcVersion.Revision.ToString(), ".", - info.TcVersion.Build.ToString()), - info.OsVersion, - info.Comment - }); + ListViewItem lvi = + new ListViewItem( + new string[] + { + info.Name, + info.Address.ToString(), + info.AmsNetId.ToString(), + string.Concat( + info.TcVersion.Version.ToString(), ".", + info.TcVersion.Revision.ToString(), ".", + info.TcVersion.Build.ToString()), + info.OsVersion, + info.Comment + }); cxListView.Items.Add(lvi); } @@ -133,13 +138,9 @@ private async void searchButton_Click(object sender, EventArgs e) private void searchProgressTimer_Tick(object sender, EventArgs e) { if (searchStatusProgressBar.Value + 1 <= searchStatusProgressBar.Maximum) - { searchStatusProgressBar.Value++; - } else - { searchStatusProgressBar.Value = searchStatusProgressBar.Maximum; - } } } }